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
set(Output GSdx-0.1.16)
set(Replay pcsx2_GSReplayLoader)
set(Static GSdx-static)
set(CommonFlags
-D_LINUX
@ -186,10 +184,6 @@ include_directories(.)
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} ${GLEW_LIBRARY})
target_link_libraries(${Output} ${OPENGL_LIBRARIES})
@ -197,14 +191,37 @@ if(projectSDL)
target_link_libraries(${Output} ${SDL_LIBRARY})
endif(projectSDL)
target_link_libraries(${Replay} ${OPENGL_LIBRARIES})
target_link_libraries(${Replay} ${X11_LIBRARIES})
target_link_libraries(${Replay} ${GLEW_LIBRARY})
target_link_libraries(${Replay} ${GTK2_LIBRARIES})
target_link_libraries(${Replay} ${Static})
if(projectSDL)
target_link_libraries(${Replay} ${SDL_LIBRARY})
endif(projectSDL)
if(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}")
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})
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} ${X11_LIBRARIES})
@ -214,26 +231,23 @@ if(projectSDL)
target_link_libraries(${Static} ${SDL_LIBRARY})
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 "")
target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}")
endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
if(PACKAGE_MODE)
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)
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)

View File

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

View File

@ -45,22 +45,16 @@
//GL EXT: recompiling and managing multiple shaders, while still retaining most of
//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 DUMP_START (70)
//#define DUMP_LENGTH (130)
#define DUMP_START (500)
#define DUMP_LENGTH (5)
//#define PRINT_FRAME_NUMBER
//#define ONLY_LINES
// It seems dual blending does not work on AMD !!!
//#define DISABLE_DUAL_BLEND
#define DISABLE_DUAL_BLEND
#ifdef DUMP_START
static uint32 g_draw_count = 0;
@ -73,13 +67,14 @@ GSDeviceOGL::GSDeviceOGL()
, m_window(NULL)
, m_pipeline(0)
, m_fbo(0)
, m_fbo_read(0)
, m_vb_sr(NULL)
, m_srv_changed(false)
, m_ss_changed(false)
{
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_convert, 0, sizeof(m_convert));
memset(&m_date, 0, sizeof(m_date));
@ -91,11 +86,11 @@ GSDeviceOGL::~GSDeviceOGL()
// Clean vertex buffer state
delete (m_vb_sr);
// Clean m_merge
// Clean m_merge_obj
for (uint i = 0; i < 2; i++)
glDeleteProgram(m_merge.ps[i]);
delete (m_merge.cb);
delete (m_merge.bs);
glDeleteProgram(m_merge_obj.ps[i]);
delete (m_merge_obj.cb);
delete (m_merge_obj.bs);
// Clean m_interlace
for (uint i = 0; i < 2; i++)
@ -118,6 +113,7 @@ GSDeviceOGL::~GSDeviceOGL()
// Clean various opengl allocation
glDeleteProgramPipelines(1, &m_pipeline);
glDeleteFramebuffers(1, &m_fbo);
glDeleteFramebuffers(1, &m_fbo_read);
// Delete HW FX
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
GSTextureOGL* t = NULL;
t = new GSTextureOGL(type, w, h, msaa, format);
t = new GSTextureOGL(type, w, h, msaa, format, m_fbo_read);
switch(type)
{
@ -234,6 +230,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
glBindProgramPipeline(m_pipeline);
glGenFramebuffers(1, &m_fbo);
glGenFramebuffers(1, &m_fbo_read);
// Setup FBO fragment output
// OMSetFBO(m_fbo);
// glDrawBuffer(GL_COLOR_ATTACHMENT0);
@ -312,14 +309,14 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
// ****************************************************************
// 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++)
CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &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_obj.ps[i]);
m_merge.bs = new GSBlendStateOGL();
m_merge.bs->EnableBlend();
m_merge.bs->SetRGB(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
m_merge_obj.bs = new GSBlendStateOGL();
m_merge_obj.bs->EnableBlend();
m_merge_obj.bs->SetRGB(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// ****************************************************************
// 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
// there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done
// 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;
}
@ -542,7 +539,8 @@ void GSDeviceOGL::DrawPrimitive()
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, "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
if ( dump_me ) {
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");
@ -849,15 +847,15 @@ void GSDeviceOGL::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVect
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])
{
SetUniformBuffer(m_merge.cb);
m_merge.cb->upload(&c.v);
SetUniformBuffer(m_merge_obj.cb);
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_a_msk;
bool constant_factor;
float debug_factor;
public:
@ -55,7 +56,7 @@ public:
, m_b_msk(GL_TRUE)
, m_g_msk(GL_TRUE)
, m_a_msk(GL_TRUE)
, constant_factor(true)
, constant_factor(false)
{}
void SetRGB(GLenum op, GLenum src, GLenum dst)
@ -100,7 +101,10 @@ public:
if (m_enable) {
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);
glBlendFuncSeparate(m_func_sRGB, m_func_dRGB, m_func_sALPHA, m_func_dALPHA);
@ -135,6 +139,7 @@ public:
{
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));
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);
}
};
@ -315,10 +320,12 @@ public:
void upload(const void* src, uint32 count)
{
#ifdef OGL_DEBUG
GLint b_size = -1;
glGetBufferParameteriv(m_target, GL_BUFFER_SIZE, &b_size);
if (b_size <= 0) return;
#endif
m_count = count;
@ -345,10 +352,12 @@ public:
// Upload the data to the buffer
uint8* dst = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags);
#ifdef OGL_DEBUG
if (dst == NULL) {
fprintf(stderr, "CRITICAL ERROR map failed for vb!!!\n");
return;
}
#endif
memcpy(dst, src, m_stride*m_count);
glUnmapBuffer(m_target);
}
@ -412,7 +421,7 @@ public:
topo = "triangle strip";
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_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_sr; // vb_state for StretchRect
@ -669,7 +679,7 @@ class GSDeviceOGL : public GSDevice
GLuint ps[2]; // program object
GSUniformBufferOGL* cb; // uniform buffer object
GSBlendStateOGL* bs;
} m_merge;
} m_merge_obj;
struct {
GLuint ps[4]; // program object

View File

@ -25,23 +25,13 @@
static int g_state_texture_unit = -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_pbo_size(0)
{
// *************************************************************
// 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 are attached to FBO through : glFramebufferRenderbuffer. You can query the number of colorattachement with GL_MAX_COLOR_ATTACHMENTS
// FBO : constructor -> glGenFramebuffers, glDeleteFramebuffers
@ -57,28 +47,13 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
// glReadBuffer
// glBlitFramebuffer
// TODO: we can render directly into a texture so I'm not sure rendertarget are useful anymore !!!
// *************************************************************
m_size.x = w;
m_size.y = h;
m_format = format;
m_type = type;
m_msaa = msaa;
// == 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
m_fbo_read = fbo_read;
// Generate the buffer
switch (m_type) {
@ -396,8 +371,15 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
EnableUnit(1);
glGetTexImage(m_texture_target, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, image);
} else {
EnableUnit(0);
glGetTexImage(m_texture_target, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
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);

View File

@ -30,9 +30,10 @@ class GSTextureOGL : public GSTexture
GLuint m_texture_id; // the texture id
uint m_extra_buffer_id;
int m_pbo_size;
GLuint m_fbo_read;
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();
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)
{
#if ENABLE_SDL_DEV
#ifdef ENABLE_SDL_DEV
if (!m_managed) return true;
// Do not find anyway to check the current fullscreen status