From cfedf41441c16ef217388555144218dafa4650d0 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 12 Jan 2012 07:29:31 +0000 Subject: [PATCH] gsdx-ogl: linux only * Fix some issue on wnd management, mix between sdl/ogl render * create new gsdx option for ogl debug + debug_ogl_dump: start frame to dump when not 0 + debug_ogl_dump_length: length of the dump + debug_ogl_shader: print shader debug Note current dump option must be fixed to use linux path. git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@5067 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/CMakeLists.txt | 2 +- plugins/GSdx/GS.cpp | 22 +++- plugins/GSdx/GSDeviceOGL.cpp | 105 ++++----------- plugins/GSdx/GSWnd.cpp | 245 ++++++++++++----------------------- plugins/GSdx/res/tfx.glsl | 8 +- 5 files changed, 132 insertions(+), 250 deletions(-) diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt index cac8bfee05..0cbc9f0131 100644 --- a/plugins/GSdx/CMakeLists.txt +++ b/plugins/GSdx/CMakeLists.txt @@ -243,7 +243,7 @@ endif(projectSDL) if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") - target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") + target_link_libraries(${Replay} "${USER_CMAKE_LD_FLAGS}") endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") if(PACKAGE_MODE) diff --git a/plugins/GSdx/GS.cpp b/plugins/GSdx/GS.cpp index c65df40ef3..5f74ddba22 100644 --- a/plugins/GSdx/GS.cpp +++ b/plugins/GSdx/GS.cpp @@ -1087,6 +1087,17 @@ EXPORT_C GSBenchmark(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow #ifdef _LINUX +#include +#include // ftime(), struct timeb + +inline unsigned long timeGetTime() +{ + timeb t; + ftime(&t); + + return (unsigned long)(t.time*1000 + t.millitm); +} + // Note EXPORT_C GSReplay(char* lpszCmdLine, int renderer) { @@ -1206,14 +1217,14 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer) } sleep(1); - // FIXME too slow :p - // sleep(100); //while(IsWindowVisible(hWnd)) //FIXME map? bool finished = false; while(!finished) { + unsigned long start = timeGetTime(); + unsigned long frame_number = 0; for(auto i = packets.begin(); i != packets.end(); i++) { Packet* p = *i; @@ -1235,6 +1246,7 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer) case 1: GSvsync(p->param); + frame_number++; break; @@ -1253,11 +1265,15 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer) break; } } + unsigned long end = timeGetTime(); + fprintf(stderr, "The %d frames of the scene was render on %dms\n", frame_number, end - start); + fprintf(stderr, "A means of %fms by frame\n", (float)(end - start)/(float)frame_number); - sleep(5); + sleep(1); finished = true; } + for(auto i = packets.begin(); i != packets.end(); i++) { delete *i; diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 8f6753e718..8131d591bc 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -21,45 +21,15 @@ #include "GSDeviceOGL.h" -// Various Note: separate build of shader -// ************************** BUILD METHOD 1 -// 1/ create a stand alone prog -// uint CreateShaderProgramv( enum type, sizei count, const char **strings ); -// 2/ Create various prog pipeline (maybe 1 foreach combination or only 1) -// glGenProgramPipelines -// 3/ Attach a program to a pipeline -// void UseProgramStages( uint pipeline, bitfield stages, uint program ); -// ... -// ... -// 5/ Before the use of the program, we can validate it. (mandatory or not ?) -// glValidateProgramPipeline -// -// ************************** BUILD METHOD 2 -// Humm, there is another solutions. You can setup function pointer in GLSL and configure them with OPENGL. shader_subroutine. glUseProgram must be replace with glUseProgramInstance in this case (and instance must be managed) -//GL EXT: Overview -//GL EXT: -//GL EXT: This extension adds support to shaders for "indirect subroutine calls", -//GL EXT: where a single shader can include many subroutines and dynamically select -//GL EXT: through the API which subroutine is called from each call site. -//GL EXT: Switching subroutines dynamically in this fashion can avoid the cost of -//GL EXT: recompiling and managing multiple shaders, while still retaining most of -//GL EXT: the performance of specialized shaders. -// - -#define LOUD_DEBUGGING -#define SHADER_DEBUG -#define DUMP_START (500) -#define DUMP_LENGTH (5) +//#define LOUD_DEBUGGING //#define PRINT_FRAME_NUMBER //#define ONLY_LINES // It seems dual blending does not work on AMD !!! #define DISABLE_DUAL_BLEND -#ifdef DUMP_START static uint32 g_draw_count = 0; -static uint32 g_frame_count = 0; -#endif +static uint32 g_frame_count = 1; GSDeviceOGL::GSDeviceOGL() @@ -231,10 +201,6 @@ bool GSDeviceOGL::Create(GSWnd* wnd) glGenFramebuffers(1, &m_fbo); glGenFramebuffers(1, &m_fbo_read); - // Setup FBO fragment output - // OMSetFBO(m_fbo); - // glDrawBuffer(GL_COLOR_ATTACHMENT0); - // OMSetFBO(0); // **************************************************************** // Vertex buffer state @@ -518,28 +484,30 @@ void GSDeviceOGL::Flip() #ifdef PRINT_FRAME_NUMBER fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count); #endif -#ifdef DUMP_START - g_frame_count++; +#ifdef OGL_DEBUG + if (theApp.GetConfig("debug_ogl_dump", 0) != 0) + g_frame_count++; #endif } void GSDeviceOGL::DrawPrimitive() { -#ifdef DUMP_START +#ifdef OGL_DEBUG bool dump_me = false; - if ( (g_frame_count > DUMP_START && g_frame_count < (DUMP_START+DUMP_LENGTH)) ) - dump_me = true; + uint32 start = theApp.GetConfig("debug_ogl_dump", 0); + uint32 length = theApp.GetConfig("debug_ogl_dump_length", 5); + if ( (start != 0 && g_frame_count >= start && g_frame_count < (start + length)) ) dump_me = true; #endif // DUMP INPUT -#ifdef DUMP_START +#ifdef OGL_DEBUG if ( dump_me ) { for (auto i = 0 ; i < 3 ; i++) { if (m_state.ps_srv[i] != NULL) { - 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_f%d__d%d__%d.bmp", g_frame_count, g_draw_count, i)); } } - if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/in_current_out_%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); @@ -553,9 +521,9 @@ void GSDeviceOGL::DrawPrimitive() m_state.vb->draw_arrays(); // DUMP OUTPUT -#ifdef DUMP_START +#ifdef OGL_DEBUG 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_f%d__d%d.bmp", g_frame_count, g_draw_count)); //if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_out_%d.bmp", g_draw_count)); fprintf(stderr, "\n"); @@ -926,9 +894,6 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver // -#ifdef DUMP_START - fprintf(stderr, "draw date!!!\n"); -#endif DrawPrimitive(); // @@ -1067,21 +1032,6 @@ void GSDeviceOGL::PSSetShader(GLuint ps) } } } -#if 0 - if (m_srv_changed) - { - m_ctx->PSSetShaderResources(0, 3, m_state.ps_srv); - - m_srv_changed = false; - } - - if(m_ss_changed) - { - m_ctx->PSSetSamplers(0, 3, m_state.ps_ss); - - m_ss_changed = false; - } -#endif } void GSDeviceOGL::OMSetFBO(GLuint fbo) @@ -1164,9 +1114,6 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto { m_state.scissor = r; glScissor( r.x, r.y, r.width(), r.height() ); -#if 0 - m_ctx->RSSetScissorRects(1, r); -#endif } } @@ -1176,7 +1123,7 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st // Build a header string // ***************************************************** // First select the version (must be the first line so we need to generate it - std::string version = "#version 330\n#extension GL_ARB_shading_language_420pack: enable\n#extension GL_ARB_separate_shader_objects : enable\n"; + std::string version = "#version 330\n#extension GL_ARB_shading_language_420pack: require\n#extension GL_ARB_separate_shader_objects : require\n"; //std::string version = "#version 420\n"; // Allow to puts several shader in 1 files @@ -1248,19 +1195,19 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st free(header_str); free(sources_array); -#ifdef SHADER_DEBUG - // Print a nice debug log - GLint log_length = 0; - glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &log_length); + if (theApp.GetConfig("debug_ogl_shader", 1) == 1) { + // Print a nice debug log + GLint log_length = 0; + glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &log_length); - char* log = (char*)malloc(log_length); - glGetProgramInfoLog(*program, log_length, NULL, log); + char* log = (char*)malloc(log_length); + glGetProgramInfoLog(*program, log_length, NULL, log); - fprintf(stderr, "%s (entry %s, prog %d) :", glsl_file.c_str(), entry.c_str(), *program); - fprintf(stderr, "\n%s", macro_sel.c_str()); - fprintf(stderr, "%s\n", log); - free(log); -#endif + fprintf(stderr, "%s (entry %s, prog %d) :", glsl_file.c_str(), entry.c_str(), *program); + fprintf(stderr, "\n%s", macro_sel.c_str()); + fprintf(stderr, "%s\n", log); + free(log); + } } void GSDeviceOGL::CheckDebugLog() diff --git a/plugins/GSdx/GSWnd.cpp b/plugins/GSdx/GSWnd.cpp index c4a17a1920..aee95c24ba 100644 --- a/plugins/GSdx/GSWnd.cpp +++ b/plugins/GSdx/GSWnd.cpp @@ -212,105 +212,6 @@ void GSWnd::HideFrame() #else -/* -GSWnd::GSWnd() - : m_display(NULL) - , m_window(0) - , m_managed(true) - , m_frame(true) -{ -} - -GSWnd::~GSWnd() -{ - if(m_display != NULL) - { - if(m_window != 0) - { - XDestroyWindow(m_display, m_window); - } - - XCloseDisplay(m_display); - } -} - -bool GSWnd::Create(const string& title, int w, int h) -{ - if(m_display != NULL) return false; - - if(!XInitThreads()) return false; - - m_display = XOpenDisplay(0); - - if(m_display == NULL) return false; - - m_window = XCreateSimpleWindow(m_display, RootWindow(m_display, 0), 0, 0, 640, 480, 0, BlackPixel(m_display, 0), BlackPixel(m_display, 0)); - - XFlush(m_display); - - return true; -} - -GSVector4i GSWnd::GetClientRect() -{ - int x, y; - unsigned int w, h; - unsigned int border, depth; - Window root; - - XLockDisplay(m_display); - XGetGeometry(m_display, m_window, &root, &x, &y, &w, &h, &border, &depth); - XUnlockDisplay(m_display); - - return GSVector4i(0, 0, w, h); -} - -// Returns FALSE if the window has no title, or if th window title is under the strict -// management of the emulator. - -bool GSWnd::SetWindowText(const char* title) -{ - if(!m_managed) return false; - - XTextProperty p; - - p.value = (unsigned char*)title; - p.encoding = XA_STRING; - p.format = 8; - p.nitems = strlen(title); - - XSetWMName(m_display, m_window, &p); - XFlush(m_display); - - return m_frame; -} - -void GSWnd::Show() -{ - if(!m_managed) return; - - XMapWindow(m_display, m_window); - XFlush(m_display); -} - -void GSWnd::Hide() -{ - if(!m_managed) return; - - XUnmapWindow(m_display, m_window); - XFlush(m_display); -} - -void GSWnd::HideFrame() -{ - if(!m_managed) return; - - // TODO - - m_frame = false; -} -*/ - GSWnd::GSWnd() : m_window(NULL), m_Xwindow(0), m_XDisplay(NULL) { @@ -443,7 +344,6 @@ void GSWnd::Detach() bool GSWnd::Create(const string& title, int w, int h) { -#ifdef ENABLE_SDL_DEV if(m_window != NULL) return false; if(w <= 0 || h <= 0) { @@ -451,75 +351,78 @@ bool GSWnd::Create(const string& title, int w, int h) h = theApp.GetConfig("ModeHeight", 480); } + m_managed = true; + + if (m_renderer == 2) { +#ifdef ENABLE_SDL_DEV + #ifdef _LINUX - // When you reconfigure the plugins during the play, SDL is shutdown so SDL_GetNumVideoDisplays return 0 - // and the plugins is badly closed. NOTE: SDL is initialized in SDL_CreateWindow. - // - // I'm not sure this sanity check is still useful, normally (I hope) SDL_CreateWindow will return a null - // hence a false for this current function. - // For the moment do an init -- Gregory - if(!SDL_WasInit(SDL_INIT_VIDEO)) - if(SDL_Init(SDL_INIT_VIDEO) < 0) return false; + // When you reconfigure the plugins during the play, SDL is shutdown so SDL_GetNumVideoDisplays return 0 + // and the plugins is badly closed. NOTE: SDL is initialized in SDL_CreateWindow. + // + // I'm not sure this sanity check is still useful, normally (I hope) SDL_CreateWindow will return a null + // hence a false for this current function. + // For the moment do an init -- Gregory + if(!SDL_WasInit(SDL_INIT_VIDEO)) + if(SDL_Init(SDL_INIT_VIDEO) < 0) return false; - // Sanity check; if there aren't any video displays available, we can't create a window. - if (SDL_GetNumVideoDisplays() <= 0) return false; + // Sanity check; if there aren't any video displays available, we can't create a window. + if (SDL_GetNumVideoDisplays() <= 0) return false; #endif - m_managed = true; + m_window = SDL_CreateWindow(title.c_str(), 100, 100, w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); - m_window = SDL_CreateWindow(title.c_str(), 100, 100, w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + // Get the X window from the newly created window + // It would be needed to get the current size + SDL_SysWMinfo wminfo; + memset(&wminfo, 0, sizeof(wminfo)); - // Get the X window from the newly created window - // It would be needed to get the current size - SDL_SysWMinfo wminfo; - memset(&wminfo, 0, sizeof(wminfo)); + wminfo.version.major = SDL_MAJOR_VERSION; + wminfo.version.minor = SDL_MINOR_VERSION; - wminfo.version.major = SDL_MAJOR_VERSION; - wminfo.version.minor = SDL_MINOR_VERSION; + SDL_GetWindowWMInfo(m_window, &wminfo); + m_Xwindow = wminfo.info.x11.window; - SDL_GetWindowWMInfo(m_window, &wminfo); - m_Xwindow = wminfo.info.x11.window; - - return (m_window != NULL); -#else - - // note this part must be only executed when replaying .gs debug file - m_managed = true; - - m_XDisplay = XOpenDisplay(NULL); - - int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_DEPTH_SIZE, 24, - None - }; - XVisualInfo* vi = glXChooseVisual(m_XDisplay, DefaultScreen(m_XDisplay), attrListDbl); - - /* create a color map */ - XSetWindowAttributes attr; - attr.colormap = XCreateColormap(m_XDisplay, RootWindow(m_XDisplay, vi->screen), - vi->visual, AllocNone); - attr.border_pixel = 0; - attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | - StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | - EnterWindowMask | LeaveWindowMask | FocusChangeMask ; - - // Create a window at the last position/size - m_Xwindow = XCreateWindow(m_XDisplay, RootWindow(m_XDisplay, vi->screen), - 0 , 0 , w, h, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, &attr); - - XMapWindow (m_XDisplay, m_Xwindow); - XFree(vi); - - if (!CreateContext(3, 3)) return false; - - AttachContext(); - - return (m_Xwindow != 0); #endif + return (m_window != NULL); + + } else { + + // note this part must be only executed when replaying .gs debug file + m_XDisplay = XOpenDisplay(NULL); + + int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None + }; + XVisualInfo* vi = glXChooseVisual(m_XDisplay, DefaultScreen(m_XDisplay), attrListDbl); + + /* create a color map */ + XSetWindowAttributes attr; + attr.colormap = XCreateColormap(m_XDisplay, RootWindow(m_XDisplay, vi->screen), + vi->visual, AllocNone); + attr.border_pixel = 0; + attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | + StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | + EnterWindowMask | LeaveWindowMask | FocusChangeMask ; + + // Create a window at the last position/size + m_Xwindow = XCreateWindow(m_XDisplay, RootWindow(m_XDisplay, vi->screen), + 0 , 0 , w, h, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &attr); + + XMapWindow (m_XDisplay, m_Xwindow); + XFree(vi); + + if (!CreateContext(3, 3)) return false; + + AttachContext(); + + return (m_Xwindow != 0); + } } Display* GSWnd::GetDisplay() @@ -572,9 +475,11 @@ GSVector4i GSWnd::GetClientRect() bool GSWnd::SetWindowText(const char* title) { -#ifdef ENABLE_SDL_DEV if (!m_managed) return true; + if (m_renderer == 2) { +#ifdef ENABLE_SDL_DEV + // Do not find anyway to check the current fullscreen status // Better than nothing heuristic, check the window position. Fullscreen = (0,0) // if(!(m_window->flags & SDL_WINDOW_FULLSCREEN) ) // Do not compile @@ -583,15 +488,27 @@ 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 - int x,y = 0; - if (m_renderer == 2) { + int x,y = 0; SDL_PumpEvents(); SDL_GetWindowPosition(m_window, &x, &y); if ( x && y ) SDL_SetWindowTitle(m_window, title); - } #endif + } else { + XTextProperty prop; + + memset(&prop, 0, sizeof(prop)); + + char* ptitle = (char*)title; + if (XStringListToTextProperty(&ptitle, 1, &prop)) { + XSetWMName(m_XDisplay, m_Xwindow, &prop); + } + + XFree(prop.value); + XFlush(m_XDisplay); + } + return true; } diff --git a/plugins/GSdx/res/tfx.glsl b/plugins/GSdx/res/tfx.glsl index 2bf22ca9ff..e836be3c29 100644 --- a/plugins/GSdx/res/tfx.glsl +++ b/plugins/GSdx/res/tfx.glsl @@ -623,9 +623,8 @@ void ps_main() // FIXME: I'm not sure about the value of others field // output.c1 = c.a * 2; // used for alpha blending -#ifndef DISABLE_DUAL_BLEND - SV_Target0 = vec4(c.a*2, c.a*2, c.a*2, c.a * 2); -#endif + + float alpha = c.a * 2; if(PS_AOUT != 0) // 16 bit output { @@ -638,6 +637,9 @@ void ps_main() if(c.a < 0.5) c.a += 0.5; } +#ifndef DISABLE_DUAL_BLEND + SV_Target0 = vec4(alpha, alpha, alpha, alpha); +#endif SV_Target1 = c; } #endif