mirror of
https://github.com/libretro/pcsx2.git
synced 2024-11-24 17:59:47 +00:00
gsdx-ogl: LINUX-ONLY
* implement the saving of texture (take bmp SW code) * fix the missing "enable attribute code" and the typo in glsl. It works now !!! * rework a little texture to pack texture into a temporay buffer when src pitch != dst pitch * try to replace sdl with pure xlib (not yet enabled by default but it seems to work) Note there still a minor issue, coordinate are different between DX and OGL (upper-left vs lower-left) so the image is inversed. git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@4981 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
eb3eafa090
commit
a835de0af7
@ -119,7 +119,7 @@ set(CMAKE_SHARED_LIBRARY_CXX_FLAGS "")
|
||||
#-------------------------------------------------------------------------------
|
||||
# Set some default compiler flags
|
||||
#-------------------------------------------------------------------------------
|
||||
set(DEFAULT_WARNINGS "-Wno-write-strings -Wno-format -Wno-unused-parameter -Wno-unused-value -Wstrict-aliasing")
|
||||
set(DEFAULT_WARNINGS "-w -Wno-write-strings -Wno-format -Wno-unused-parameter -Wno-unused-value -Wstrict-aliasing")
|
||||
set(DEFAULT_GCC_FLAG "-m32 -msse -msse2 -march=i686 -pthread ${DEFAULT_WARNINGS}")
|
||||
set(DEFAULT_CPP_FLAG "${DEFAULT_GCC_FLAG} -Wno-invalid-offsetof")
|
||||
|
||||
|
@ -16,6 +16,7 @@ set(CommonFlags
|
||||
-mfpmath=sse
|
||||
#-Wstrict-aliasing # Allow to track strict aliasing issue.
|
||||
-Wunused-variable
|
||||
-DKEEP_SDL
|
||||
)
|
||||
|
||||
set(OptimizationFlags
|
||||
@ -196,6 +197,12 @@ endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
|
||||
|
||||
if(PACKAGE_MODE)
|
||||
install(TARGETS ${Output} DESTINATION ${PLUGIN_DIR})
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/convert.glsl DESTINATION ${PLUGIN_DIR})
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/interlace.glsl DESTINATION ${PLUGIN_DIR})
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/merge.glsl DESTINATION ${PLUGIN_DIR})
|
||||
else(PACKAGE_MODE)
|
||||
install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/convert.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/interlace.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/merge.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
endif(PACKAGE_MODE)
|
||||
|
@ -62,8 +62,13 @@ GSDeviceOGL::GSDeviceOGL()
|
||||
, m_pipeline(0)
|
||||
, m_srv_changed(false)
|
||||
, m_ss_changed(false)
|
||||
, m_vb_changed(false)
|
||||
{
|
||||
m_msaa = theApp.GetConfig("msaa", 0);
|
||||
|
||||
m_frag_back_buffer[0] = GL_BACK_LEFT;
|
||||
m_frag_rt_buffer[0] = GL_COLOR_ATTACHMENT0;
|
||||
|
||||
memset(&m_merge, 0, sizeof(m_merge));
|
||||
memset(&m_interlace, 0, sizeof(m_interlace));
|
||||
memset(&m_convert, 0, sizeof(m_convert));
|
||||
@ -102,13 +107,17 @@ GSDeviceOGL::~GSDeviceOGL()
|
||||
glDeleteProgramPipelines(1, &m_pipeline);
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
|
||||
// glXMakeCurrent(m_XDisplay, m_Xwindow, 0);
|
||||
// if (m_context) glXDestroyContext(m_XDisplay, m_context);
|
||||
// if(m_context)
|
||||
// SDL_GL_DeleteContext(m_context);
|
||||
#ifdef KEEP_SDL
|
||||
if(m_dummy_renderer)
|
||||
SDL_DestroyRenderer(m_dummy_renderer);
|
||||
|
||||
if(m_window != NULL && m_free_window)
|
||||
SDL_DestroyWindow(m_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int format)
|
||||
@ -149,11 +158,8 @@ PFNGLTEXSTORAGE2DPROC glTexStorage2D_glew17 = NULL;
|
||||
bool GSDeviceOGL::Create(GSWnd* wnd)
|
||||
{
|
||||
if (m_window == NULL) {
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
#ifdef KEEP_SDL
|
||||
m_window = SDL_CreateWindowFrom(wnd->GetHandle());
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
m_free_window = true;
|
||||
|
||||
// If the user request OpenGL acceleration, we take recent OGL version (4.2)
|
||||
@ -168,7 +174,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
||||
// Ask for an advance opengl version
|
||||
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 4 );
|
||||
// FIXME AMD does not support yet 4.2...
|
||||
//SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
|
||||
//SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
|
||||
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
|
||||
|
||||
// Window must be recreated to gain Opengl feature...
|
||||
@ -177,7 +183,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
||||
m_dummy_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED); // SDL_RENDERER_PRESENTVSYNC
|
||||
// At least create the opengl context
|
||||
// m_context = SDL_GL_CreateContext(m_window);
|
||||
|
||||
#endif
|
||||
|
||||
// FIXME......
|
||||
// GLEW's problem is that it calls glGetString(GL_EXTENSIONS) which causes GL_INVALID_ENUM on GL 3.2 forward compatible context as soon as glewInit() is called. It also doesn't fetch the function pointers. The solution is for GLEW to use glGetStringi instead.
|
||||
@ -202,10 +208,12 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
||||
glTexStorage2D_glew17 = (PFNGLTEXSTORAGE2DPROC)glXGetProcAddressARB((const GLubyte*)"glTexStorage2D");
|
||||
}
|
||||
|
||||
#ifdef __LINUX__
|
||||
#ifdef KEEP_SDL
|
||||
// In GSopen2, sdl failed to received any resize event. GSWnd::GetClientRect need to manually
|
||||
// set the window size... So we send the m_window to the wnd object to allow some manipulation on it.
|
||||
wnd->SetWindow(m_window);
|
||||
#else
|
||||
m_window = wnd;
|
||||
#endif
|
||||
|
||||
// FIXME disable it when code is ready
|
||||
@ -529,13 +537,7 @@ void GSDeviceOGL::Flip()
|
||||
{
|
||||
// FIXME: disable it when code is working
|
||||
CheckDebugLog();
|
||||
// Warning it is not OGL dependent but application dependant (glx and so not portable)
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
SDL_GL_SwapWindow(m_window);
|
||||
#else
|
||||
SDL_GL_SwapBuffers();
|
||||
#endif
|
||||
|
||||
m_wnd->Flip();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::DrawPrimitive()
|
||||
@ -546,18 +548,29 @@ void GSDeviceOGL::DrawPrimitive()
|
||||
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
|
||||
{
|
||||
GSTextureOGL* t_ogl = (GSTextureOGL*)t;
|
||||
// FIXME I need to clarify this FBO attachment stuff
|
||||
// I would like to avoid FBO for a basic clean operation
|
||||
//glClearBufferfv(GL_COLOR, t_ogl->attachment(), c.v);
|
||||
if (t == m_backbuffer) {
|
||||
// FIXME need an assert
|
||||
if (m_state.fbo) {
|
||||
m_state.fbo = 0;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
glClearBufferfv(GL_COLOR, GL_BACK, c.v);
|
||||
} else {
|
||||
// FIXME I need to clarify this FBO attachment stuff
|
||||
// I would like to avoid FBO for a basic clean operation
|
||||
if (!m_state.fbo) {
|
||||
m_state.fbo = m_fbo;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
}
|
||||
t_ogl->Attach(GL_COLOR_ATTACHMENT0);
|
||||
glClearBufferfv(GL_COLOR, 0, c.v);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c)
|
||||
{
|
||||
GSTextureOGL* t_ogl = (GSTextureOGL*)t;
|
||||
GSVector4 color = GSVector4::rgba32(c) * (1.0f / 255);
|
||||
// FIXME I need to clarify this FBO attachment stuff
|
||||
// I would like to avoid FBO for a basic clean operation
|
||||
//glClearBufferfv(GL_COLOR, t_ogl->attachment(), color.v);
|
||||
ClearRenderTarget(t, color);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
|
||||
@ -691,9 +704,9 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
||||
StretchRect(st, sr, dt, dr, ps, ps_cb, m_convert.bs, linear);
|
||||
}
|
||||
|
||||
// probably no difficult to convert when all helpers function will be done
|
||||
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL* ps_cb, GSBlendStateOGL* bs, bool linear)
|
||||
{
|
||||
|
||||
if(!st || !dt)
|
||||
{
|
||||
ASSERT(0);
|
||||
@ -717,8 +730,7 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
||||
float right = dr.z * 2 / ds.x - 1.0f;
|
||||
float bottom = 1.0f - dr.w * 2 / ds.y;
|
||||
|
||||
//FIXME aligment issue
|
||||
GSVertexPT1 vertices[] __attribute__ ((aligned (16))) =
|
||||
GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(left, top, 0.5f, 1.0f), GSVector2(sr.x, sr.y)},
|
||||
{GSVector4(right, top, 0.5f, 1.0f), GSVector2(sr.z, sr.y)},
|
||||
@ -745,6 +757,12 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
||||
PSSetShader(ps, ps_cb);
|
||||
|
||||
//
|
||||
// FIXME: disable it when code is working
|
||||
glValidateProgramPipeline(m_pipeline);
|
||||
GLint status;
|
||||
glGetProgramPipelineiv(m_pipeline, GL_VALIDATE_STATUS, &status);
|
||||
if (status != GL_TRUE)
|
||||
fprintf(stderr, "Failed to validate the pipeline\n");
|
||||
|
||||
DrawPrimitive();
|
||||
|
||||
@ -797,7 +815,6 @@ void GSDeviceOGL::DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool lin
|
||||
m_state.cb = m_interlace.cb->buffer;
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, m_interlace.cb->buffer);
|
||||
}
|
||||
// FIXME I'm not sure it will be happy with InterlaceConstantBuffer type
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, m_interlace.cb->byte_size, &cb);
|
||||
#if 0
|
||||
m_ctx->UpdateSubresource(m_interlace.cb, 0, NULL, &cb, 0, 0);
|
||||
@ -842,6 +859,7 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
|
||||
m_vertices.start = 0;
|
||||
m_vertices.count = 0;
|
||||
m_vertices.limit = std::max<int>(count * 3 / 2, 11000);
|
||||
|
||||
}
|
||||
|
||||
if(!m_vb)
|
||||
@ -850,6 +868,7 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
|
||||
// FIXME: GL_DYNAMIC_DRAW vs GL_STREAM_DRAW !!!
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vb);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.limit * stride, NULL, GL_DYNAMIC_DRAW);
|
||||
m_vb_changed = true;
|
||||
}
|
||||
|
||||
// append data or go back to the beginning
|
||||
@ -867,12 +886,21 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
|
||||
|
||||
void GSDeviceOGL::IASetInputLayout(GSInputLayout* layout, int layout_nbr)
|
||||
{
|
||||
if(m_state.layout != layout)
|
||||
if(m_state.layout != layout || m_state.layout_nbr != layout_nbr || m_vb_changed)
|
||||
{
|
||||
m_state.layout = layout;
|
||||
// Remove old configuration.
|
||||
for (int i = m_state.layout_nbr ; i > (m_state.layout_nbr - layout_nbr) ; i--) {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < layout_nbr; i++)
|
||||
glVertexAttribPointer(layout->index, layout->size, layout->type, GL_FALSE, layout->stride, layout->offset);
|
||||
for (int i = 0; i < layout_nbr; i++) {
|
||||
glEnableVertexAttribArray(layout[i].index);
|
||||
glVertexAttribPointer(layout[i].index, layout[i].size, layout[i].type, GL_FALSE, layout[i].stride, layout[i].offset);
|
||||
}
|
||||
|
||||
m_vb_changed = false;
|
||||
m_state.layout = layout;
|
||||
m_state.layout_nbr = layout_nbr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1066,6 +1094,7 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
|
||||
if (m_state.fbo) {
|
||||
m_state.fbo = 0;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // render in the backbuffer
|
||||
glDrawBuffers(1, m_frag_back_buffer);
|
||||
}
|
||||
|
||||
assert(ds_ogl == NULL); // no depth-stencil without FBO
|
||||
@ -1073,6 +1102,7 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
|
||||
if (m_state.fbo != m_fbo) {
|
||||
m_state.fbo = m_fbo;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
glDrawBuffers(1, m_frag_rt_buffer);
|
||||
}
|
||||
|
||||
assert(rt_ogl != NULL); // a render target must exists
|
||||
@ -1094,12 +1124,7 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
|
||||
if(!m_state.scissor.eq(r))
|
||||
{
|
||||
m_state.scissor = r;
|
||||
// FIXME check position
|
||||
// x = 0,
|
||||
// y = 0,
|
||||
// z = 512,
|
||||
// w = 512
|
||||
glScissor(r.x, r.y, r.z-r.x, r.w-r.y);
|
||||
glScissor( r.x, r.y, r.width(), r.height() );
|
||||
#if 0
|
||||
m_ctx->RSSetScissorRects(1, r);
|
||||
#endif
|
||||
@ -1187,7 +1212,8 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st
|
||||
char* log = (char*)malloc(log_length);
|
||||
glGetProgramInfoLog(*program, log_length, NULL, log);
|
||||
|
||||
fprintf(stderr, "%s", log);
|
||||
fprintf(stderr, "%s (%s) :", glsl_file.c_str(), entry.c_str());
|
||||
fprintf(stderr, "%s\n", log);
|
||||
free(log);
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,11 @@ class GSDeviceOGL : public GSDevice
|
||||
uint32 m_msaa; // Level of Msaa
|
||||
|
||||
bool m_free_window;
|
||||
#ifdef KEEP_SDL
|
||||
SDL_Window* m_window; // pointer to the SDL window
|
||||
#else
|
||||
GSWnd* m_window; // pointer to the SDL window
|
||||
#endif
|
||||
//SDL_GLContext m_context; // current opengl context
|
||||
SDL_Renderer* m_dummy_renderer; // ... crappy API ...
|
||||
|
||||
@ -111,6 +115,9 @@ class GSDeviceOGL : public GSDevice
|
||||
GLuint m_pipeline; // pipeline to attach program shader
|
||||
GLuint m_fbo; // frame buffer container
|
||||
|
||||
GLenum m_frag_back_buffer[1];
|
||||
GLenum m_frag_rt_buffer[1];
|
||||
|
||||
struct {
|
||||
GLuint ps[2]; // program object
|
||||
GSUniformBufferOGL* cb; // uniform buffer object
|
||||
@ -170,6 +177,7 @@ class GSDeviceOGL : public GSDevice
|
||||
// size_t vb_stride;
|
||||
// ID3D11InputLayout* layout;
|
||||
GSInputLayout* layout;
|
||||
uint32 layout_nbr;
|
||||
GLenum topology; // (ie GL_TRIANGLES...)
|
||||
GLuint vs; // program
|
||||
GLuint cb; // uniform current buffer
|
||||
@ -197,6 +205,7 @@ class GSDeviceOGL : public GSDevice
|
||||
|
||||
bool m_srv_changed;
|
||||
bool m_ss_changed;
|
||||
bool m_vb_changed;
|
||||
|
||||
#if 0
|
||||
CComPtr<ID3D11Device> m_dev;
|
||||
@ -229,6 +238,8 @@ class GSDeviceOGL : public GSDevice
|
||||
PSConstantBuffer m_ps_cb_cache;
|
||||
#endif
|
||||
|
||||
//GLenum frag_back[1] = { GL_BACK };
|
||||
//GLenum frag_target[1] = { GL_COLOR_ATTACHMENT0 }:
|
||||
|
||||
void CheckDebugLog();
|
||||
void DebugOutputToFile(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, const char* message);
|
||||
|
@ -24,7 +24,9 @@
|
||||
#include "GSTextureOGL.h"
|
||||
|
||||
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
|
||||
: m_texture_unit(0)
|
||||
: m_texture_unit(0),
|
||||
m_extra_buffer_id(0),
|
||||
m_extra_buffer_allocated(false)
|
||||
{
|
||||
// *************************************************************
|
||||
// Opengl world
|
||||
@ -123,8 +125,11 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
|
||||
// gvec texelFetch(gsampler sampler, ivec texCoord, int lod[, int sample]);
|
||||
// corollary we can maybe use it for multisample stuff
|
||||
break;
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Extra buffer to handle various pixel transfer
|
||||
glGenBuffers(1, &m_extra_buffer_id);
|
||||
|
||||
uint msaa_level;
|
||||
if (m_msaa) {
|
||||
@ -178,31 +183,51 @@ void GSTextureOGL::Attach(GLenum attachment)
|
||||
|
||||
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
|
||||
{
|
||||
// static int update_count = 0;
|
||||
// update_count++;
|
||||
// To update only a part of the texture you can use:
|
||||
// glTexSubImage2D — specify a two-dimensional texture subimage
|
||||
switch (m_type) {
|
||||
case GSTexture::RenderTarget:
|
||||
case GSTexture::Texture:
|
||||
// glTexSubImage2D specifies a two-dimensional subtexture for the current texture unit, specified with glActiveTexture.
|
||||
// If a non-zero named buffer object is bound to the GL_PIXEL_UNPACK_BUFFER target
|
||||
//(see glBindBuffer) while a texture image is
|
||||
// specified, data is treated as a byte offset into the buffer object's data store
|
||||
// FIXME warning order of the y axis
|
||||
// FIXME I'm not confident with GL_UNSIGNED_BYTE type
|
||||
// FIXME add a state check
|
||||
glBindTexture(m_texture_target, m_texture_id);
|
||||
//void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * data);
|
||||
// fprintf(stderr, "texture coord %d, %d, %d, %d\n", r.x, r.y, r.z, r.w);
|
||||
if (m_format == GL_RGBA8)
|
||||
glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.z-r.x, r.w-r.y, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
else
|
||||
assert(0);
|
||||
break;
|
||||
case GSTexture::DepthStencil:
|
||||
case GSTexture::Offscreen:
|
||||
assert(0);
|
||||
break;
|
||||
if (m_type == GSTexture::DepthStencil || m_type == GSTexture::Offscreen) assert(0);
|
||||
|
||||
// glTexSubImage2D specifies a two-dimensional subtexture for the current texture unit, specified with glActiveTexture.
|
||||
// If a non-zero named buffer object is bound to the GL_PIXEL_UNPACK_BUFFER target
|
||||
//(see glBindBuffer) while a texture image is
|
||||
// specified, data is treated as a byte offset into the buffer object's data store
|
||||
// FIXME warning order of the y axis
|
||||
// FIXME I'm not confident with GL_UNSIGNED_BYTE type
|
||||
// FIXME add a state check
|
||||
|
||||
EnableUnit(0);
|
||||
|
||||
if (m_format != GL_RGBA8) assert(0);
|
||||
|
||||
// FIXME. That suck but I don't know how to do better for now. I think we need to create a texture buffer and directly upload the copy
|
||||
// The case appears on SW mode. Src pitch is 2x dst pitch.
|
||||
int rowbytes = r.width() << 2;
|
||||
if (pitch != rowbytes) {
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_extra_buffer_id);
|
||||
|
||||
if (!m_extra_buffer_allocated) {
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, m_size.x * m_size.y * 4, NULL, GL_STREAM_DRAW);
|
||||
m_extra_buffer_allocated = true;
|
||||
}
|
||||
|
||||
uint8* src = (uint8*) data;
|
||||
uint8* dst = (uint8*) glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||
for(int h = r.height(); h > 0; h--, src += pitch, dst += rowbytes)
|
||||
{
|
||||
memcpy(dst, src, rowbytes);
|
||||
}
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE, 0 /* offset in UNPACK BUFFER */);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
} else {
|
||||
glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(m_dev && m_texture)
|
||||
{
|
||||
@ -283,10 +308,107 @@ void GSTextureOGL::Unmap()
|
||||
#endif
|
||||
}
|
||||
|
||||
// If I'm correct, this function only dump some buffer. Debug only, still very useful!
|
||||
// Note: check zzogl implementation
|
||||
#ifndef _WINDOWS
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct BITMAPFILEHEADER
|
||||
{
|
||||
uint16 bfType;
|
||||
uint32 bfSize;
|
||||
uint16 bfReserved1;
|
||||
uint16 bfReserved2;
|
||||
uint32 bfOffBits;
|
||||
};
|
||||
|
||||
struct BITMAPINFOHEADER
|
||||
{
|
||||
uint32 biSize;
|
||||
int32 biWidth;
|
||||
int32 biHeight;
|
||||
uint16 biPlanes;
|
||||
uint16 biBitCount;
|
||||
uint32 biCompression;
|
||||
uint32 biSizeImage;
|
||||
int32 biXPelsPerMeter;
|
||||
int32 biYPelsPerMeter;
|
||||
uint32 biClrUsed;
|
||||
uint32 biClrImportant;
|
||||
};
|
||||
|
||||
#define BI_RGB 0
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
||||
bool GSTextureOGL::Save(const string& fn, bool dds)
|
||||
{
|
||||
switch (m_type) {
|
||||
case GSTexture::DepthStencil:
|
||||
case GSTexture::Offscreen:
|
||||
ASSERT(0);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Collect the texture data
|
||||
char* image = (char*)malloc(4 * m_size.x * m_size.y);
|
||||
if (m_type) {
|
||||
EnableUnit(0);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
} else {
|
||||
// TODO backbuffer
|
||||
glReadBuffer(GL_BACK);
|
||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
|
||||
// Build a BMP file
|
||||
if(FILE* fp = fopen(fn.c_str(), "wb"))
|
||||
{
|
||||
BITMAPINFOHEADER bih;
|
||||
|
||||
memset(&bih, 0, sizeof(bih));
|
||||
|
||||
bih.biSize = sizeof(bih);
|
||||
bih.biWidth = m_size.x;
|
||||
bih.biHeight = m_size.y;
|
||||
bih.biPlanes = 1;
|
||||
bih.biBitCount = 32;
|
||||
bih.biCompression = BI_RGB;
|
||||
bih.biSizeImage = m_size.x * m_size.y << 2;
|
||||
|
||||
BITMAPFILEHEADER bfh;
|
||||
|
||||
memset(&bfh, 0, sizeof(bfh));
|
||||
|
||||
uint8* bfType = (uint8*)&bfh.bfType;
|
||||
|
||||
// bfh.bfType = 'MB';
|
||||
bfType[0] = 0x42;
|
||||
bfType[1] = 0x4d;
|
||||
bfh.bfOffBits = sizeof(bfh) + sizeof(bih);
|
||||
bfh.bfSize = bfh.bfOffBits + bih.biSizeImage;
|
||||
bfh.bfReserved1 = bfh.bfReserved2 = 0;
|
||||
|
||||
fwrite(&bfh, 1, sizeof(bfh), fp);
|
||||
fwrite(&bih, 1, sizeof(bih), fp);
|
||||
|
||||
uint32 pitch = 4 * m_size.x;
|
||||
uint8* data = (uint8*)image + (m_size.y - 1) * pitch;
|
||||
|
||||
for(int h = m_size.y; h > 0; h--, data -= pitch)
|
||||
{
|
||||
fwrite(data, 1, m_size.x << 2, fp); // TODO: swap red-blue?
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
free(image);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#if 0
|
||||
CComPtr<ID3D11Resource> res;
|
||||
|
||||
|
@ -29,6 +29,8 @@ class GSTextureOGL : public GSTexture
|
||||
GLenum m_texture_target; // texture target: 2D, rectangle etc...
|
||||
GLuint m_texture_id; // the texture id
|
||||
uint m_texture_unit; // the texture unit offset
|
||||
uint m_extra_buffer_id;
|
||||
bool m_extra_buffer_allocated;
|
||||
|
||||
public:
|
||||
explicit GSTextureOGL(int type, int w, int h, bool msaa, int format);
|
||||
|
@ -46,14 +46,10 @@ struct GSVertexP
|
||||
GSVector4 p;
|
||||
};
|
||||
|
||||
struct GSVertexPT1
|
||||
__aligned(struct, 32) GSVertexPT1
|
||||
{
|
||||
GSVector4 p;
|
||||
GSVector2 t;
|
||||
#ifdef _LINUX
|
||||
//FIXME aligment issue
|
||||
GSVector2 pad;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct GSVertexPT2
|
||||
|
@ -314,6 +314,11 @@ void GSWnd::HideFrame()
|
||||
GSWnd::GSWnd()
|
||||
: m_window(NULL), m_Xwindow(0), m_XDisplay(NULL)
|
||||
{
|
||||
#ifdef KEEP_SDL
|
||||
m_renderer = 2;
|
||||
#else
|
||||
m_renderer = theApp.GetConfig("renderer", 0) / 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
GSWnd::~GSWnd()
|
||||
@ -334,6 +339,53 @@ bool GSWnd::Attach(void* handle, bool managed)
|
||||
m_Xwindow = *(Window*)handle;
|
||||
m_managed = managed;
|
||||
|
||||
if (m_renderer != 2) {
|
||||
m_XDisplay = XOpenDisplay(NULL);
|
||||
|
||||
// Get visual information
|
||||
int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
None
|
||||
};
|
||||
|
||||
PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
|
||||
int fbcount = 0;
|
||||
GLXFBConfig *fbc = glXChooseFBConfig(m_XDisplay, DefaultScreen(m_XDisplay), attrListDbl, &fbcount);
|
||||
if (!fbc || fbcount < 1) return false;
|
||||
|
||||
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
|
||||
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB");
|
||||
if (!glXCreateContextAttribsARB) return false;
|
||||
|
||||
// Create a context
|
||||
int context_attribs[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
// FIXME : Request a debug context to ease opengl development
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
0
|
||||
};
|
||||
m_context = glXCreateContextAttribsARB(m_XDisplay, fbc[0], 0, true, context_attribs);
|
||||
XSync( m_XDisplay, false);
|
||||
|
||||
if (!m_context) return false;
|
||||
glXMakeCurrent(m_XDisplay, m_Xwindow, m_context);
|
||||
|
||||
// Check the status
|
||||
int glxMajorVersion, glxMinorVersion;
|
||||
glXQueryVersion(m_XDisplay, &glxMajorVersion, &glxMinorVersion);
|
||||
if (glXIsDirect(m_XDisplay, m_context))
|
||||
fprintf(stderr, "glX-Version %d.%d with Direct Rendering\n", glxMajorVersion, glxMinorVersion);
|
||||
else
|
||||
fprintf(stderr, "glX-Version %d.%d with Indirect Rendering !!! It will be slow\n", glxMajorVersion, glxMinorVersion);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -341,10 +393,15 @@ void GSWnd::Detach()
|
||||
{
|
||||
// Actually the destructor is not called when there is only a GSclose/GSshutdown
|
||||
// The window still need to be closed
|
||||
if(m_window != NULL && m_managed)
|
||||
{
|
||||
SDL_DestroyWindow(m_window);
|
||||
m_window = NULL;
|
||||
if (m_renderer == 2) {
|
||||
if(m_window != NULL && m_managed)
|
||||
{
|
||||
SDL_DestroyWindow(m_window);
|
||||
m_window = NULL;
|
||||
}
|
||||
} else {
|
||||
glXMakeCurrent(m_XDisplay, m_Xwindow, 0);
|
||||
if (m_context) glXDestroyContext(m_XDisplay, m_context);
|
||||
}
|
||||
if (m_XDisplay) {
|
||||
XCloseDisplay(m_XDisplay);
|
||||
@ -425,7 +482,8 @@ GSVector4i GSWnd::GetClientRect()
|
||||
// In real world...:
|
||||
if (!m_XDisplay) m_XDisplay = XOpenDisplay(NULL);
|
||||
XGetGeometry(m_XDisplay, m_Xwindow, &winDummy, &xDummy, &yDummy, &w, &h, &borderDummy, &depthDummy);
|
||||
SDL_SetWindowSize(m_window, w, h);
|
||||
if (m_renderer == 2)
|
||||
SDL_SetWindowSize(m_window, w, h);
|
||||
|
||||
return GSVector4i(0, 0, (int)w, (int)h);
|
||||
}
|
||||
@ -445,23 +503,48 @@ bool GSWnd::SetWindowText(const char* title)
|
||||
// but we not use this function anyway.
|
||||
// FIXME: it does not feel a good solution -- Gregory
|
||||
// NOte: it might be more thread safe to use a call to XGetGeometry
|
||||
SDL_PumpEvents();
|
||||
int x,y = 0;
|
||||
SDL_GetWindowPosition(m_window, &x, &y);
|
||||
if ( x && y )
|
||||
SDL_SetWindowTitle(m_window, title);
|
||||
if (m_renderer == 2) {
|
||||
SDL_PumpEvents();
|
||||
SDL_GetWindowPosition(m_window, &x, &y);
|
||||
if ( x && y )
|
||||
SDL_SetWindowTitle(m_window, title);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSWnd::Flip()
|
||||
{
|
||||
if (m_renderer == 2) {
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
SDL_GL_SwapWindow(m_window);
|
||||
#else
|
||||
SDL_GL_SwapBuffers();
|
||||
#endif
|
||||
} else {
|
||||
glXSwapBuffers(m_XDisplay, m_Xwindow);
|
||||
}
|
||||
}
|
||||
|
||||
void GSWnd::Show()
|
||||
{
|
||||
SDL_ShowWindow(m_window);
|
||||
if (m_renderer == 2) {
|
||||
SDL_ShowWindow(m_window);
|
||||
} else {
|
||||
XMapRaised(m_XDisplay, m_Xwindow);
|
||||
XFlush(m_XDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
void GSWnd::Hide()
|
||||
{
|
||||
SDL_HideWindow(m_window);
|
||||
if (m_renderer == 2) {
|
||||
SDL_HideWindow(m_window);
|
||||
} else {
|
||||
XUnmapWindow(m_XDisplay, m_Xwindow);
|
||||
XFlush(m_XDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
void GSWnd::HideFrame()
|
||||
|
@ -91,12 +91,16 @@ public:
|
||||
#include "../../3rdparty/SDL-1.3.0-5387/include/SDL.h"
|
||||
#include "../../3rdparty/SDL-1.3.0-5387/include/SDL_syswm.h"
|
||||
|
||||
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, bool, const int*);
|
||||
|
||||
class GSWnd
|
||||
{
|
||||
SDL_Window* m_window;
|
||||
Window m_Xwindow;
|
||||
Display* m_XDisplay;
|
||||
bool m_managed;
|
||||
int m_renderer;
|
||||
GLXContext m_context;
|
||||
|
||||
public:
|
||||
GSWnd();
|
||||
@ -116,6 +120,7 @@ public:
|
||||
void Show();
|
||||
void Hide();
|
||||
void HideFrame();
|
||||
void Flip();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,12 @@
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
float gl_ClipDistance[];
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 POSITION;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
|
||||
@ -20,7 +26,7 @@ smooth layout(location = 1) out vec2 TEXCOORD0_OUT;
|
||||
void vs_main()
|
||||
{
|
||||
POSITION_OUT = POSITION;
|
||||
TEXCOORD0_OUT = TEXCOORD0_OUT;
|
||||
TEXCOORD0_OUT = TEXCOORD0;
|
||||
gl_Position = POSITION; // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
}
|
||||
|
||||
@ -32,7 +38,7 @@ void vs_main()
|
||||
layout(location = 0) in vec4 SV_Position;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
|
||||
out vec4 SV_Target0;
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
@ -88,6 +94,21 @@ void ps_main6() // diagonal
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
//void ps_main1()
|
||||
//{
|
||||
// vec4 c = sample_c(TEXCOORD);
|
||||
//
|
||||
// c.a *= 256.0f / 127; // hm, 0.5 won't give us 1.0 if we just multiply with 2
|
||||
//
|
||||
// uvec4 i = uvec4(c * vec4(0x001f, 0x03e0, 0x7c00, 0x8000));
|
||||
//
|
||||
//#ifdef DEBUG_FRAG
|
||||
// SV_Target0 = vec4(0.5,0.5,0.5,1.0);
|
||||
//#else
|
||||
// SV_Target0 = (i.x & 0x001f) | (i.y & 0x03e0) | (i.z & 0x7c00) | (i.w & 0x8000);
|
||||
//#endif
|
||||
//}
|
||||
|
||||
// Texture2D Texture;
|
||||
// SamplerState TextureSampler;
|
||||
//
|
||||
|
@ -4,7 +4,7 @@
|
||||
layout(location = 0) in vec4 SV_Position;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
|
||||
out vec4 SV_Target0;
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
layout(std140, binding = 1) uniform cb0
|
||||
{
|
||||
|
@ -1,11 +1,10 @@
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec4 SV_Position;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
|
||||
out vec4 SV_Target0;
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
layout(std140, binding = 1) uniform cb0
|
||||
{
|
||||
@ -16,8 +15,9 @@ layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
void ps_main0()
|
||||
{
|
||||
|
||||
vec4 c = texture(TextureSampler, TEXCOORD0);
|
||||
c.a = min(c.a * 2, 1);
|
||||
c.a = min(c.a * 2, 1.0);
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user