From 21724ddbf884632214cb6267393bea71e1cd552b Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 6 Jan 2012 21:43:39 +0000 Subject: [PATCH] gsdx-ogl: add a loader to replay gs file. Quite shaky but probably enough for debug :) git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@5052 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/CMakeLists.txt | 31 ++++-- plugins/GSdx/GS.cpp | 187 ++++++++++++++++++++++++++++++++++ plugins/GSdx/GSDeviceOGL.cpp | 2 +- plugins/GSdx/GSWnd.cpp | 167 ++++++++++++++++++++---------- plugins/GSdx/GSWnd.h | 10 +- plugins/GSdx/linux_replay.cpp | 41 ++++++++ 6 files changed, 370 insertions(+), 68 deletions(-) create mode 100644 plugins/GSdx/linux_replay.cpp diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt index ef836d6a98..ebb5585f4b 100644 --- a/plugins/GSdx/CMakeLists.txt +++ b/plugins/GSdx/CMakeLists.txt @@ -8,6 +8,8 @@ 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 @@ -179,38 +181,47 @@ set(GSdxHeaders xbyak/xbyak_util.h ) -# add additional include directories include_directories(.) -# add library -add_library(${Output} SHARED - ${GSdxSources} - ${GSdxHeaders} - ) +add_library(${Output} SHARED ${GSdxSources} ${GSdxHeaders}) + +add_library(${Static} STATIC ${GSdxSources} ${GSdxHeaders}) + +add_executable(${Replay} linux_replay.cpp) -# link target with X11 target_link_libraries(${Output} ${X11_LIBRARIES}) +target_link_libraries(${Output} ${GLEW_LIBRARY}) +target_link_libraries(${Output} ${OPENGL_LIBRARIES}) if(projectSDL) target_link_libraries(${Output} ${SDL_LIBRARY}) endif(projectSDL) -# link target with glew -target_link_libraries(${Output} ${GLEW_LIBRARY}) +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}) + -# User flags options 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) diff --git a/plugins/GSdx/GS.cpp b/plugins/GSdx/GS.cpp index c0baf6196c..7133ae4280 100644 --- a/plugins/GSdx/GS.cpp +++ b/plugins/GSdx/GS.cpp @@ -1084,3 +1084,190 @@ EXPORT_C GSBenchmark(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow } #endif + +#ifdef _LINUX + +// Note +EXPORT_C GSReplay(char* lpszCmdLine, int renderer) +{ + + +// lpszCmdLine: +// First parameter is the renderer. +// Second parameter is the gs file to load and run. + +//EXPORT_C GSReplay(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) +#if 0 + int renderer = -1; + + { + char* start = lpszCmdLine; + char* end = NULL; + long n = strtol(lpszCmdLine, &end, 10); + if(end > start) {renderer = n; lpszCmdLine = end;} + } + + while(*lpszCmdLine == ' ') lpszCmdLine++; + + ::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS); +#endif + + if(FILE* fp = fopen(lpszCmdLine, "rb")) + { + //Console console("GSdx", true); + + GSinit(); + + uint8 regs[0x2000]; + GSsetBaseMem(regs); + + s_vsync = !!theApp.GetConfig("vsync", 0); + + void* hWnd = NULL; + + _GSopen((void**)&hWnd, "", renderer); + + uint32 crc; + fread(&crc, 4, 1, fp); + GSsetGameCRC(crc, 0); + + GSFreezeData fd; + fread(&fd.size, 4, 1, fp); + fd.data = new uint8[fd.size]; + fread(fd.data, fd.size, 1, fp); + GSfreeze(FREEZE_LOAD, &fd); + delete [] fd.data; + + fread(regs, 0x2000, 1, fp); + + long start = ftell(fp); + + GSvsync(1); + + struct Packet {uint8 type, param; uint32 size, addr; vector buff;}; + + list packets; + vector buff; + int type; + + while((type = fgetc(fp)) != EOF) + { + Packet* p = new Packet(); + + p->type = (uint8)type; + + switch(type) + { + case 0: + + p->param = (uint8)fgetc(fp); + + fread(&p->size, 4, 1, fp); + + switch(p->param) + { + case 0: + p->buff.resize(0x4000); + p->addr = 0x4000 - p->size; + fread(&p->buff[p->addr], p->size, 1, fp); + break; + case 1: + case 2: + case 3: + p->buff.resize(p->size); + fread(&p->buff[0], p->size, 1, fp); + break; + } + + break; + + case 1: + + p->param = (uint8)fgetc(fp); + + break; + + case 2: + + fread(&p->size, 4, 1, fp); + + break; + + case 3: + + p->buff.resize(0x2000); + + fread(&p->buff[0], 0x2000, 1, fp); + + break; + } + + packets.push_back(p); + } + + sleep(30); + // FIXME too slow :p + // sleep(100); + + //while(IsWindowVisible(hWnd)) + //FIXME map? + while(true) + { + for(auto i = packets.begin(); i != packets.end(); i++) + { + Packet* p = *i; + + switch(p->type) + { + case 0: + + switch(p->param) + { + case 0: GSgifTransfer1(&p->buff[0], p->addr); break; + case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break; + case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break; + case 3: GSgifTransfer(&p->buff[0], p->size / 16); break; + } + + break; + + case 1: + + GSvsync(p->param); + + break; + + case 2: + + if(buff.size() < p->size) buff.resize(p->size); + + GSreadFIFO2(&buff[0], p->size / 16); + + break; + + case 3: + + memcpy(regs, &p->buff[0], 0x2000); + + break; + } + } + } + + for(auto i = packets.begin(); i != packets.end(); i++) + { + delete *i; + } + + packets.clear(); + + sleep(100); + + GSclose(); + GSshutdown(); + + fclose(fp); + } +} +#endif + diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 57aa9b8966..742b9b078c 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -195,7 +195,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) s = glGetString(GL_VERSION); if (s == NULL) return false; - GLuint dot; + GLuint dot = 0; while (s[dot] != '\0' && s[dot] != '.') dot++; if (dot == 0) return false; diff --git a/plugins/GSdx/GSWnd.cpp b/plugins/GSdx/GSWnd.cpp index d3ec81e6f1..75147c4eb6 100644 --- a/plugins/GSdx/GSWnd.cpp +++ b/plugins/GSdx/GSWnd.cpp @@ -331,6 +331,74 @@ GSWnd::~GSWnd() } } +bool GSWnd::CreateContext(int major, int minor) +{ + if ( !m_XDisplay || !m_Xwindow ) + { + fprintf( stderr, "Wrong X11 display/window\n" ); + exit(1); + } + + // Get visual information + static int attrListDbl[] = + { + GLX_X_RENDERABLE , True, + GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, + GLX_RENDER_TYPE , GLX_RGBA_BIT, + GLX_RED_SIZE , 8, + GLX_GREEN_SIZE , 8, + GLX_BLUE_SIZE , 8, + GLX_DEPTH_SIZE , 24, + GLX_DOUBLEBUFFER , True, + 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; + + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB"); + if (!glXCreateContextAttribsARB) return false; + + // Create a context + int context_attribs[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, major, + GLX_CONTEXT_MINOR_VERSION_ARB, minor, + // FIXME : Request a debug context to ease opengl development + // Note: don't support deprecated feature (pre openg 3.1) + //GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, + None + }; + + m_context = glXCreateContextAttribsARB(m_XDisplay, fbc[0], 0, true, context_attribs); + if (!m_context) return false; + + XSync( m_XDisplay, false); +} + +void GSWnd::AttachContext() +{ + glXMakeCurrent(m_XDisplay, m_Xwindow, m_context); +} + +void GSWnd::DetachContext() +{ + glXMakeCurrent(m_XDisplay, None, NULL); +} + +void GSWnd::CheckContext() +{ + 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); +} + bool GSWnd::Attach(void* handle, bool managed) { m_Xwindow = *(Window*)handle; @@ -340,60 +408,12 @@ bool GSWnd::Attach(void* handle, bool managed) if (m_renderer != 2) { m_XDisplay = XOpenDisplay(NULL); - if ( !m_XDisplay ) - { - fprintf( stderr, "Failed to open X display\n" ); - exit(1); - } - - // Get visual information - static int attrListDbl[] = - { - GLX_X_RENDERABLE , True, - GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, - GLX_RENDER_TYPE , GLX_RGBA_BIT, - GLX_RED_SIZE , 8, - GLX_GREEN_SIZE , 8, - GLX_BLUE_SIZE , 8, - GLX_DEPTH_SIZE , 24, - GLX_DOUBLEBUFFER , True, - 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; + // Note: 4.2 crash on latest nvidia drivers! + if (!CreateContext(3, 3)) return false; - PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB"); - if (!glXCreateContextAttribsARB) return false; - - // Create a context - int context_attribs[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - // Note: 4.2 crash on latest nvidia drivers! - GLX_CONTEXT_MINOR_VERSION_ARB, 3, - // FIXME : Request a debug context to ease opengl development - // Note: don't support deprecated feature (pre openg 3.1) - //GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, - None - }; - 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); + AttachContext(); + CheckContext(); } return true; @@ -412,7 +432,7 @@ void GSWnd::Detach() } #endif } else { - glXMakeCurrent(m_XDisplay, None, NULL); + DetachContext(); if (m_context) glXDestroyContext(m_XDisplay, m_context); } if (m_XDisplay) { @@ -462,7 +482,43 @@ bool GSWnd::Create(const string& title, int w, int h) return (m_window != NULL); #else - return false; + + // 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 } @@ -480,7 +536,8 @@ Display* GSWnd::GetDisplay() return wminfo.subsystem == SDL_SYSWM_X11 ? wminfo.info.x11.display : NULL; #else - return NULL; + // note this part must be only executed when replaying .gs debug file + return m_XDisplay; #endif } diff --git a/plugins/GSdx/GSWnd.h b/plugins/GSdx/GSWnd.h index 6e85a3aef5..6e2967fad0 100644 --- a/plugins/GSdx/GSWnd.h +++ b/plugins/GSdx/GSWnd.h @@ -100,8 +100,9 @@ class GSWnd #else void* m_window; #endif - Window m_Xwindow; - Display* m_XDisplay; + Window m_Xwindow; + Display* m_XDisplay; + bool m_managed; int m_renderer; GLXContext m_context; @@ -123,6 +124,11 @@ public: void SetWindow(SDL_Window* current_window) { if (current_window) m_window = current_window; } #endif + bool CreateContext(int major, int minor); + void AttachContext(); + void DetachContext(); + void CheckContext(); + void Show(); void Hide(); void HideFrame(); diff --git a/plugins/GSdx/linux_replay.cpp b/plugins/GSdx/linux_replay.cpp new file mode 100644 index 0000000000..f2d25ab8c9 --- /dev/null +++ b/plugins/GSdx/linux_replay.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 20011-2012 Hainaut gregory + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" + +EXPORT_C GSsetSettingsDir(const char* dir); +EXPORT_C GSReplay(char* lpszCmdLine, int renderer); + + +void help() +{ + fprintf(stderr, "Loader gs file\n"); + fprintf(stderr, "ARG1 Ini directory\n"); + fprintf(stderr, "ARG2 .gs file\n"); + exit(1); +} + +int main ( int argc, char *argv[] ) +{ + if ( argc != 3 ) help(); + + GSsetSettingsDir(argv[1]); + GSReplay(argv[2], 12); +}