gsdx-ogl:

* fix bad setup issue for constant blend factor
* Use a read framebuffer to read back the texture (less disruptive)
* cmake separate the loader to the main plugins


git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@5064 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2012-01-08 21:59:42 +00:00
parent 47985bc4fa
commit 14b0572b61
7 changed files with 104 additions and 95 deletions

View File

@ -8,8 +8,6 @@ endif(NOT TOP_CMAKE_WAS_SOURCED)
# plugin name # plugin name
set(Output GSdx-0.1.16) set(Output GSdx-0.1.16)
set(Replay pcsx2_GSReplayLoader)
set(Static GSdx-static)
set(CommonFlags set(CommonFlags
-D_LINUX -D_LINUX
@ -186,10 +184,6 @@ include_directories(.)
add_library(${Output} SHARED ${GSdxSources} ${GSdxHeaders}) add_library(${Output} SHARED ${GSdxSources} ${GSdxHeaders})
add_library(${Static} STATIC ${GSdxSources} ${GSdxHeaders})
add_executable(${Replay} linux_replay.cpp)
target_link_libraries(${Output} ${X11_LIBRARIES}) target_link_libraries(${Output} ${X11_LIBRARIES})
target_link_libraries(${Output} ${GLEW_LIBRARY}) target_link_libraries(${Output} ${GLEW_LIBRARY})
target_link_libraries(${Output} ${OPENGL_LIBRARIES}) target_link_libraries(${Output} ${OPENGL_LIBRARIES})
@ -197,14 +191,37 @@ if(projectSDL)
target_link_libraries(${Output} ${SDL_LIBRARY}) target_link_libraries(${Output} ${SDL_LIBRARY})
endif(projectSDL) endif(projectSDL)
target_link_libraries(${Replay} ${OPENGL_LIBRARIES}) if(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
target_link_libraries(${Replay} ${X11_LIBRARIES}) target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}")
target_link_libraries(${Replay} ${GLEW_LIBRARY}) endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
target_link_libraries(${Replay} ${GTK2_LIBRARIES})
target_link_libraries(${Replay} ${Static}) if(PACKAGE_MODE)
if(projectSDL) install(TARGETS ${Output} DESTINATION ${PLUGIN_DIR})
target_link_libraries(${Replay} ${SDL_LIBRARY})
endif(projectSDL) 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})
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.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)
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
endif(PACKAGE_MODE)
################################### Replay Loader
set(Replay pcsx2_GSReplayLoader)
set(Static GSdx-static)
# We can have separate option for gsdx inside the player. It will only
# cost a 2nd rebuild of gsdx...
#add_definitions(${CommonFlags} ${SDLFlags} ${OptimizationFlags} -W)
add_library(${Static} STATIC ${GSdxSources} ${GSdxHeaders})
add_executable(${Replay} linux_replay.cpp)
target_link_libraries(${Static} ${OPENGL_LIBRARIES}) target_link_libraries(${Static} ${OPENGL_LIBRARIES})
target_link_libraries(${Static} ${X11_LIBRARIES}) target_link_libraries(${Static} ${X11_LIBRARIES})
@ -214,26 +231,23 @@ if(projectSDL)
target_link_libraries(${Static} ${SDL_LIBRARY}) target_link_libraries(${Static} ${SDL_LIBRARY})
endif(projectSDL) endif(projectSDL)
target_link_libraries(${Replay} ${Static})
# Warning others lib must be linked after GSdx...
target_link_libraries(${Replay} ${OPENGL_LIBRARIES})
target_link_libraries(${Replay} ${X11_LIBRARIES})
target_link_libraries(${Replay} ${GLEW_LIBRARY})
target_link_libraries(${Replay} ${GTK2_LIBRARIES})
if(projectSDL)
target_link_libraries(${Replay} ${SDL_LIBRARY})
endif(projectSDL)
if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") if(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}")
endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
if(PACKAGE_MODE) if(PACKAGE_MODE)
install(TARGETS ${Replay} DESTINATION bin) install(TARGETS ${Replay} DESTINATION bin)
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})
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.glsl DESTINATION ${PLUGIN_DIR})
else(PACKAGE_MODE) else(PACKAGE_MODE)
install(TARGETS ${Replay} DESTINATION ${CMAKE_SOURCE_DIR}/bin) install(TARGETS ${Replay} DESTINATION ${CMAKE_SOURCE_DIR}/bin)
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)
install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
endif(PACKAGE_MODE) endif(PACKAGE_MODE)

View File

@ -1205,13 +1205,14 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
packets.push_back(p); packets.push_back(p);
} }
sleep(10); sleep(1);
// FIXME too slow :p // FIXME too slow :p
// sleep(100); // sleep(100);
//while(IsWindowVisible(hWnd)) //while(IsWindowVisible(hWnd))
//FIXME map? //FIXME map?
while(true) bool finished = false;
while(!finished)
{ {
for(auto i = packets.begin(); i != packets.end(); i++) for(auto i = packets.begin(); i != packets.end(); i++)
{ {
@ -1252,6 +1253,9 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
break; break;
} }
} }
sleep(5);
finished = true;
} }
for(auto i = packets.begin(); i != packets.end(); i++) for(auto i = packets.begin(); i != packets.end(); i++)
@ -1261,7 +1265,7 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
packets.clear(); packets.clear();
sleep(100); sleep(1);
GSclose(); GSclose();
GSshutdown(); GSshutdown();

View File

@ -45,22 +45,16 @@
//GL EXT: recompiling and managing multiple shaders, while still retaining most of //GL EXT: recompiling and managing multiple shaders, while still retaining most of
//GL EXT: the performance of specialized shaders. //GL EXT: the performance of specialized shaders.
// //
// ************************** Uniform buffer
// // Note don't know how to chose block_binding_point (probably managed like texture unit
// maybe any number will be fine)
// index=glGetUniformBlockIndex(program, "BlockName");
// glBindBufferBase(GL_UNIFORM_BUFFER, block_binding_point, some_buffer_object);
// glUniformBlockBinding(program, block_index, block_binding_point);
//#define LOUD_DEBUGGING #define LOUD_DEBUGGING
#define SHADER_DEBUG #define SHADER_DEBUG
//#define DUMP_START (70) #define DUMP_START (500)
//#define DUMP_LENGTH (130) #define DUMP_LENGTH (5)
//#define PRINT_FRAME_NUMBER //#define PRINT_FRAME_NUMBER
//#define ONLY_LINES //#define ONLY_LINES
// It seems dual blending does not work on AMD !!! // It seems dual blending does not work on AMD !!!
//#define DISABLE_DUAL_BLEND #define DISABLE_DUAL_BLEND
#ifdef DUMP_START #ifdef DUMP_START
static uint32 g_draw_count = 0; static uint32 g_draw_count = 0;
@ -73,13 +67,14 @@ GSDeviceOGL::GSDeviceOGL()
, m_window(NULL) , m_window(NULL)
, m_pipeline(0) , m_pipeline(0)
, m_fbo(0) , m_fbo(0)
, m_fbo_read(0)
, m_vb_sr(NULL) , m_vb_sr(NULL)
, m_srv_changed(false) , m_srv_changed(false)
, m_ss_changed(false) , m_ss_changed(false)
{ {
m_msaa = theApp.GetConfig("msaa", 0); m_msaa = theApp.GetConfig("msaa", 0);
memset(&m_merge, 0, sizeof(m_merge)); memset(&m_merge_obj, 0, sizeof(m_merge_obj));
memset(&m_interlace, 0, sizeof(m_interlace)); memset(&m_interlace, 0, sizeof(m_interlace));
memset(&m_convert, 0, sizeof(m_convert)); memset(&m_convert, 0, sizeof(m_convert));
memset(&m_date, 0, sizeof(m_date)); memset(&m_date, 0, sizeof(m_date));
@ -91,11 +86,11 @@ GSDeviceOGL::~GSDeviceOGL()
// Clean vertex buffer state // Clean vertex buffer state
delete (m_vb_sr); delete (m_vb_sr);
// Clean m_merge // Clean m_merge_obj
for (uint i = 0; i < 2; i++) for (uint i = 0; i < 2; i++)
glDeleteProgram(m_merge.ps[i]); glDeleteProgram(m_merge_obj.ps[i]);
delete (m_merge.cb); delete (m_merge_obj.cb);
delete (m_merge.bs); delete (m_merge_obj.bs);
// Clean m_interlace // Clean m_interlace
for (uint i = 0; i < 2; i++) for (uint i = 0; i < 2; i++)
@ -118,6 +113,7 @@ GSDeviceOGL::~GSDeviceOGL()
// Clean various opengl allocation // Clean various opengl allocation
glDeleteProgramPipelines(1, &m_pipeline); glDeleteProgramPipelines(1, &m_pipeline);
glDeleteFramebuffers(1, &m_fbo); glDeleteFramebuffers(1, &m_fbo);
glDeleteFramebuffers(1, &m_fbo_read);
// Delete HW FX // Delete HW FX
delete m_vs_cb; delete m_vs_cb;
@ -141,7 +137,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for
{ {
// A wrapper to call GSTextureOGL, with the different kind of parameter // A wrapper to call GSTextureOGL, with the different kind of parameter
GSTextureOGL* t = NULL; GSTextureOGL* t = NULL;
t = new GSTextureOGL(type, w, h, msaa, format); t = new GSTextureOGL(type, w, h, msaa, format, m_fbo_read);
switch(type) switch(type)
{ {
@ -234,6 +230,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
glBindProgramPipeline(m_pipeline); glBindProgramPipeline(m_pipeline);
glGenFramebuffers(1, &m_fbo); glGenFramebuffers(1, &m_fbo);
glGenFramebuffers(1, &m_fbo_read);
// Setup FBO fragment output // Setup FBO fragment output
// OMSetFBO(m_fbo); // OMSetFBO(m_fbo);
// glDrawBuffer(GL_COLOR_ATTACHMENT0); // glDrawBuffer(GL_COLOR_ATTACHMENT0);
@ -312,14 +309,14 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
// **************************************************************** // ****************************************************************
// merge // merge
// **************************************************************** // ****************************************************************
m_merge.cb = new GSUniformBufferOGL(1, sizeof(MergeConstantBuffer)); m_merge_obj.cb = new GSUniformBufferOGL(1, sizeof(MergeConstantBuffer));
for(int i = 0; i < countof(m_merge.ps); i++) for(int i = 0; i < countof(m_merge_obj.ps); i++)
CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge.ps[i]); CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge_obj.ps[i]);
m_merge.bs = new GSBlendStateOGL(); m_merge_obj.bs = new GSBlendStateOGL();
m_merge.bs->EnableBlend(); m_merge_obj.bs->EnableBlend();
m_merge.bs->SetRGB(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); m_merge_obj.bs->SetRGB(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// **************************************************************** // ****************************************************************
// interlace // interlace
@ -508,7 +505,7 @@ bool GSDeviceOGL::Reset(int w, int h)
// Opengl allocate the backbuffer with the window. The render is done in the backbuffer when // Opengl allocate the backbuffer with the window. The render is done in the backbuffer when
// there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done // there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done
// in the backbuffer // in the backbuffer
m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, false, 0); m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, false, 0, m_fbo_read);
return true; return true;
} }
@ -542,7 +539,8 @@ void GSDeviceOGL::DrawPrimitive()
m_state.ps_srv[i]->Save(format("/tmp/in_%d__%d.bmp", g_draw_count, i)); m_state.ps_srv[i]->Save(format("/tmp/in_%d__%d.bmp", g_draw_count, i));
} }
} }
if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_in_%d.bmp", g_draw_count)); if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/in_current_out_%d.bmp", g_draw_count));
//if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_in_%d.bmp", g_draw_count));
fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count); fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count);
fprintf(stderr, "vs: %d ; gs: %d ; ps: %d\n", m_state.vs, m_state.gs, m_state.ps); fprintf(stderr, "vs: %d ; gs: %d ; ps: %d\n", m_state.vs, m_state.gs, m_state.ps);
@ -558,7 +556,7 @@ void GSDeviceOGL::DrawPrimitive()
#ifdef DUMP_START #ifdef DUMP_START
if ( dump_me ) { if ( dump_me ) {
if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/out_%d.bmp", g_draw_count)); if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/out_%d.bmp", g_draw_count));
if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_out_%d.bmp", g_draw_count)); //if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_out_%d.bmp", g_draw_count));
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@ -849,15 +847,15 @@ void GSDeviceOGL::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVect
if(st[1] && !slbg) if(st[1] && !slbg)
{ {
StretchRect(st[1], sr[1], dt, dr[1], m_merge.ps[0]); StretchRect(st[1], sr[1], dt, dr[1], m_merge_obj.ps[0]);
} }
if(st[0]) if(st[0])
{ {
SetUniformBuffer(m_merge.cb); SetUniformBuffer(m_merge_obj.cb);
m_merge.cb->upload(&c.v); m_merge_obj.cb->upload(&c.v);
StretchRect(st[0], sr[0], dt, dr[0], m_merge.ps[mmod ? 1 : 0], m_merge.bs); StretchRect(st[0], sr[0], dt, dr[0], m_merge_obj.ps[mmod ? 1 : 0], m_merge_obj.bs);
} }
} }

View File

@ -41,6 +41,7 @@ class GSBlendStateOGL {
bool m_g_msk; bool m_g_msk;
bool m_a_msk; bool m_a_msk;
bool constant_factor; bool constant_factor;
float debug_factor;
public: public:
@ -55,7 +56,7 @@ public:
, m_b_msk(GL_TRUE) , m_b_msk(GL_TRUE)
, m_g_msk(GL_TRUE) , m_g_msk(GL_TRUE)
, m_a_msk(GL_TRUE) , m_a_msk(GL_TRUE)
, constant_factor(true) , constant_factor(false)
{} {}
void SetRGB(GLenum op, GLenum src, GLenum dst) void SetRGB(GLenum op, GLenum src, GLenum dst)
@ -100,7 +101,10 @@ public:
if (m_enable) { if (m_enable) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
if (HasConstantFactor()) glBlendColor(factor, factor, factor, 0); if (HasConstantFactor()) {
debug_factor = factor;
glBlendColor(factor, factor, factor, 0);
}
glBlendEquationSeparate(m_equation_RGB, m_equation_ALPHA); glBlendEquationSeparate(m_equation_RGB, m_equation_ALPHA);
glBlendFuncSeparate(m_func_sRGB, m_func_dRGB, m_func_sALPHA, m_func_dALPHA); glBlendFuncSeparate(m_func_sRGB, m_func_dRGB, m_func_sALPHA, m_func_dALPHA);
@ -135,6 +139,7 @@ public:
{ {
if (!m_enable) return; if (!m_enable) return;
fprintf(stderr,"Blend op: %s; src:%s; dst:%s\n", NameOfParam(m_equation_RGB), NameOfParam(m_func_sRGB), NameOfParam(m_func_dRGB)); fprintf(stderr,"Blend op: %s; src:%s; dst:%s\n", NameOfParam(m_equation_RGB), NameOfParam(m_func_sRGB), NameOfParam(m_func_dRGB));
if (HasConstantFactor()) fprintf(stderr, "Blend constant: %f\n", debug_factor);
fprintf(stderr,"Mask. R:%d B:%d G:%d A:%d\n", m_r_msk, m_b_msk, m_g_msk, m_a_msk); fprintf(stderr,"Mask. R:%d B:%d G:%d A:%d\n", m_r_msk, m_b_msk, m_g_msk, m_a_msk);
} }
}; };
@ -315,10 +320,12 @@ public:
void upload(const void* src, uint32 count) void upload(const void* src, uint32 count)
{ {
#ifdef OGL_DEBUG
GLint b_size = -1; GLint b_size = -1;
glGetBufferParameteriv(m_target, GL_BUFFER_SIZE, &b_size); glGetBufferParameteriv(m_target, GL_BUFFER_SIZE, &b_size);
if (b_size <= 0) return; if (b_size <= 0) return;
#endif
m_count = count; m_count = count;
@ -345,10 +352,12 @@ public:
// Upload the data to the buffer // Upload the data to the buffer
uint8* dst = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags); uint8* dst = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags);
#ifdef OGL_DEBUG
if (dst == NULL) { if (dst == NULL) {
fprintf(stderr, "CRITICAL ERROR map failed for vb!!!\n"); fprintf(stderr, "CRITICAL ERROR map failed for vb!!!\n");
return; return;
} }
#endif
memcpy(dst, src, m_stride*m_count); memcpy(dst, src, m_stride*m_count);
glUnmapBuffer(m_target); glUnmapBuffer(m_target);
} }
@ -412,7 +421,7 @@ public:
topo = "triangle strip"; topo = "triangle strip";
break; break;
} }
fprintf(stderr, "%d elements of %s\n", element, topo.c_str()); fprintf(stderr, "%d primitives of %s\n", element, topo.c_str());
} }
}; };
@ -661,6 +670,7 @@ class GSDeviceOGL : public GSDevice
GLuint m_pipeline; // pipeline to attach program shader GLuint m_pipeline; // pipeline to attach program shader
GLuint m_fbo; // frame buffer container GLuint m_fbo; // frame buffer container
GLuint m_fbo_read; // frame buffer container only for reading
GSVertexBufferStateOGL* m_vb; // vb_state for HW renderer GSVertexBufferStateOGL* m_vb; // vb_state for HW renderer
GSVertexBufferStateOGL* m_vb_sr; // vb_state for StretchRect GSVertexBufferStateOGL* m_vb_sr; // vb_state for StretchRect
@ -669,7 +679,7 @@ class GSDeviceOGL : public GSDevice
GLuint ps[2]; // program object GLuint ps[2]; // program object
GSUniformBufferOGL* cb; // uniform buffer object GSUniformBufferOGL* cb; // uniform buffer object
GSBlendStateOGL* bs; GSBlendStateOGL* bs;
} m_merge; } m_merge_obj;
struct { struct {
GLuint ps[4]; // program object GLuint ps[4]; // program object

View File

@ -25,23 +25,13 @@
static int g_state_texture_unit = -1; static int g_state_texture_unit = -1;
static int g_state_texture_id = -1; static int g_state_texture_id = -1;
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format) GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read)
: m_extra_buffer_id(0), : m_extra_buffer_id(0),
m_pbo_size(0) m_pbo_size(0)
{ {
// ************************************************************* // *************************************************************
// Opengl world // Opengl world
// http://www.opengl.org/wiki/Renderbuffer_Object
// render: constructor -> glGenRenderbuffers, glDeleteRenderbuffers
// info -> glGetRenderbufferParameteriv, glIsRenderbuffer
// binding -> glBindRenderbuffer (only 1 target), glFramebufferRenderbuffer (attach actually)
// setup param -> glRenderbufferStorageMultisample (after this call the buffer is unitialized)
//
// the only way to use a renderbuffer object is to attach it to a Framebuffer Object. After you bind that
// FBO to the context, and set up the draw or read buffers appropriately, you can use pixel transfer operations
// to read and write to it. Of course, you can also render to it. The standard glClear function will also clear the appropriate buffer.
//
// Render work in parallal with framebuffer object (FBO) http://www.opengl.org/wiki/Framebuffer_Objects // Render work in parallal with framebuffer object (FBO) http://www.opengl.org/wiki/Framebuffer_Objects
// render are attached to FBO through : glFramebufferRenderbuffer. You can query the number of colorattachement with GL_MAX_COLOR_ATTACHMENTS // render are attached to FBO through : glFramebufferRenderbuffer. You can query the number of colorattachement with GL_MAX_COLOR_ATTACHMENTS
// FBO : constructor -> glGenFramebuffers, glDeleteFramebuffers // FBO : constructor -> glGenFramebuffers, glDeleteFramebuffers
@ -57,28 +47,13 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
// glReadBuffer // glReadBuffer
// glBlitFramebuffer // glBlitFramebuffer
// TODO: we can render directly into a texture so I'm not sure rendertarget are useful anymore !!!
// ************************************************************* // *************************************************************
m_size.x = w; m_size.x = w;
m_size.y = h; m_size.y = h;
m_format = format; m_format = format;
m_type = type; m_type = type;
m_msaa = msaa; m_msaa = msaa;
m_fbo_read = fbo_read;
// == Then generate the texture or buffer.
// D3D11_BIND_RENDER_TARGET: Bind a texture as a render target for the output-merger stage.
// => glGenRenderbuffers with GL_COLOR_ATTACHMENTi (Hum glGenTextures might work too)
// D3D11_BIND_DEPTH_STENCIL: Bind a texture as a depth-stencil target for the output-merger stage.
// => glGenRenderbuffers with GL_DEPTH_STENCIL_ATTACHMENT
// D3D11_BIND_SHADER_RESOURCE: Bind a buffer or texture to a shader stage
// => glGenTextures
// D3D11_USAGE_STAGING: A resource that supports data transfer (copy) from the GPU to the CPU.
// glGenTextures
// glReadPixels seems to use a framebuffer. In this case you can setup the source
// with glReadBuffer(GL_COLOR_ATTACHMENTi)
// glGetTexImage: read pixels of a bound texture
// => To allow map/unmap. I think we can use a pixel buffer (target GL_PIXEL_UNPACK_BUFFER)
// http://www.opengl.org/wiki/Pixel_Buffer_Objects
// Generate the buffer // Generate the buffer
switch (m_type) { switch (m_type) {
@ -396,8 +371,15 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
EnableUnit(1); EnableUnit(1);
glGetTexImage(m_texture_target, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, image); glGetTexImage(m_texture_target, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, image);
} else { } else {
EnableUnit(0); glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
glGetTexImage(m_texture_target, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
EnableUnit(1);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, m_texture_target, m_texture_id, 0);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
} }
Save(fn, image, pitch); Save(fn, image, pitch);

View File

@ -30,9 +30,10 @@ class GSTextureOGL : public GSTexture
GLuint m_texture_id; // the texture id GLuint m_texture_id; // the texture id
uint m_extra_buffer_id; uint m_extra_buffer_id;
int m_pbo_size; int m_pbo_size;
GLuint m_fbo_read;
public: public:
explicit GSTextureOGL(int type, int w, int h, bool msaa, int format); explicit GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read);
virtual ~GSTextureOGL(); virtual ~GSTextureOGL();
bool Update(const GSVector4i& r, const void* data, int pitch); bool Update(const GSVector4i& r, const void* data, int pitch);

View File

@ -572,7 +572,7 @@ GSVector4i GSWnd::GetClientRect()
bool GSWnd::SetWindowText(const char* title) bool GSWnd::SetWindowText(const char* title)
{ {
#if ENABLE_SDL_DEV #ifdef ENABLE_SDL_DEV
if (!m_managed) return true; if (!m_managed) return true;
// Do not find anyway to check the current fullscreen status // Do not find anyway to check the current fullscreen status