ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) { RDCDEBUG("Creating an OpenGL replay device"); if(glXCreateContextAttribsProc == NULL) { glXGetFuncProc = (PFNGLXGETPROCADDRESSPROC)dlsym(RTLD_NEXT, "glXGetProcAddress"); glXDestroyCtxProc = (PFNGLXDESTROYCONTEXTPROC)dlsym(RTLD_NEXT, "glXDestroyContext"); glXSwapProc = (PFNGLXSWAPBUFFERSPROC)dlsym(RTLD_NEXT, "glXSwapBuffers"); glXChooseFBConfigProc = (PFNGLXCHOOSEFBCONFIGPROC)dlsym(RTLD_NEXT, "glXChooseFBConfig"); glXCreatePbufferProc = (PFNGLXCREATEPBUFFERPROC)dlsym(RTLD_NEXT, "glXCreatePbuffer"); glXDestroyPbufferProc = (PFNGLXDESTROYPBUFFERPROC)dlsym(RTLD_NEXT, "glXDestroyPbuffer"); glXQueryDrawableProc = (PFNGLXQUERYDRAWABLEPROC)dlsym(RTLD_NEXT, "glXQueryDrawable"); if(glXGetFuncProc == NULL || glXDestroyCtxProc == NULL || glXSwapProc == NULL || glXChooseFBConfigProc == NULL || glXCreatePbufferProc == NULL || glXDestroyPbufferProc == NULL || glXQueryDrawableProc == NULL) { RDCERR("Couldn't find required entry points, glXGetProcAddress glXDestroyContext glXSwapBuffers"); return eReplayCreate_APIInitFailed; } glXCreateContextAttribsProc = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetFuncProc((const GLubyte*)"glXCreateContextAttribsARB"); glXMakeContextCurrentProc = (PFNGLXMAKECONTEXTCURRENTPROC)glXGetFuncProc((const GLubyte*)"glXMakeContextCurrent"); if(glXCreateContextAttribsProc == NULL || glXMakeContextCurrentProc == NULL) { RDCERR("Couldn't get glx function addresses, glXCreateContextAttribsARB glXMakeContextCurrent"); return eReplayCreate_APIInitFailed; } } GLInitParams initParams; RDCDriver driverType = RDC_OpenGL; string driverName = "OpenGL"; if(logfile) RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, (RDCInitParams *)&initParams); if(initParams.SerialiseVersion != GLInitParams::GL_SERIALISE_VERSION) { RDCERR("Incompatible OpenGL serialise version, expected %d got %d", GLInitParams::GL_SERIALISE_VERSION, initParams.SerialiseVersion); return eReplayCreate_APIIncompatibleVersion; } int attribs[64] = {0}; int i=0; GLReplay::PreContextInitCounters(); attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB; attribs[i++] = 4; attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB; attribs[i++] = 3; attribs[i++] = GLX_CONTEXT_FLAGS_ARB; attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB; attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; Display *dpy = XOpenDisplay(NULL); if(dpy == NULL) { RDCERR("Couldn't open default X display"); return eReplayCreate_APIInitFailed; } // don't need to care about the fb config as we won't be using the default framebuffer (backbuffer) static int visAttribs[] = { 0 }; int numCfgs = 0; GLXFBConfig *fbcfg = glXChooseFBConfigProc(dpy, DefaultScreen(dpy), visAttribs, &numCfgs); if(fbcfg == NULL) { XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); RDCERR("Couldn't choose default framebuffer config"); return eReplayCreate_APIInitFailed; } GLXContext ctx = glXCreateContextAttribsProc(dpy, fbcfg[0], 0, true, attribs); if(ctx == NULL) { XFree(fbcfg); XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); RDCERR("Couldn't create 4.3 context - RenderDoc requires OpenGL 4.3 availability"); return eReplayCreate_APIHardwareUnsupported; } // don't care about pbuffer properties for same reason as backbuffer int pbAttribs[] = { GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0 }; GLXPbuffer pbuffer = glXCreatePbufferProc(dpy, fbcfg[0], pbAttribs); XFree(fbcfg); Bool res = glXMakeContextCurrentProc(dpy, pbuffer, pbuffer, ctx); if(!res) { glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XFree(fbcfg); XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); RDCERR("Couldn't make pbuffer & context current"); return eReplayCreate_APIInitFailed; } PFNGLGETINTEGERVPROC getInt = (PFNGLGETINTEGERVPROC)glXGetFuncProc((const GLubyte *)"glGetIntegerv"); PFNGLGETSTRINGIPROC getStr = (PFNGLGETSTRINGIPROC)glXGetFuncProc((const GLubyte *)"glGetStringi"); if(getInt == NULL || getStr == NULL) { RDCERR("Couldn't get glGetIntegerv (%p) or glGetStringi (%p) entry points", getInt, getStr); glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XFree(fbcfg); XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); return eReplayCreate_APIInitFailed; } else { // eventually we want to emulate EXT_dsa on replay if it isn't present, but for // now we just require it. bool found = false; GLint numExts = 0; getInt(eGL_NUM_EXTENSIONS, &numExts); for(GLint i=0; i < numExts; i++) { const char *ext = (const char *)getStr(eGL_EXTENSIONS, (GLuint)i); if(!strcmp(ext, "GL_EXT_direct_state_access")) { found = true; break; } } if(!found) { RDCERR("RenderDoc requires EXT_direct_state_access availability, and it is not reported. Try updating your drivers."); glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XFree(fbcfg); XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); return eReplayCreate_APIHardwareUnsupported; } } WrappedOpenGL *gl = new WrappedOpenGL(logfile, GetRealFunctions()); gl->Initialise(initParams); RDCLOG("Created device."); GLReplay *replay = gl->GetReplay(); replay->SetProxy(logfile == NULL); GLWindowingData data; data.dpy = dpy; data.ctx = ctx; data.wnd = pbuffer; replay->SetReplayData(data); *driver = (IReplayDriver *)replay; return eReplayCreate_Success; }
ReplayCreateStatus GL_CreateReplayDevice(const wchar_t *logfile, IReplayDriver **driver) { RDCDEBUG("Creating an OpenGL replay device"); if(glXCreateContextAttribsProc == NULL) { glXGetFuncProc = (PFNGLXGETPROCADDRESSPROC)dlsym(RTLD_NEXT, "glXGetProcAddress"); glXDestroyCtxProc = (PFNGLXDESTROYCONTEXTPROC)dlsym(RTLD_NEXT, "glXDestroyContext"); glXSwapProc = (PFNGLXSWAPBUFFERSPROC)dlsym(RTLD_NEXT, "glXSwapBuffers"); glXChooseFBConfigProc = (PFNGLXCHOOSEFBCONFIGPROC)dlsym(RTLD_NEXT, "glXChooseFBConfig"); glXCreatePbufferProc = (PFNGLXCREATEPBUFFERPROC)dlsym(RTLD_NEXT, "glXCreatePbuffer"); glXDestroyPbufferProc = (PFNGLXDESTROYPBUFFERPROC)dlsym(RTLD_NEXT, "glXDestroyPbuffer"); glXQueryDrawableProc = (PFNGLXQUERYDRAWABLEPROC)dlsym(RTLD_NEXT, "glXQueryDrawable"); if(glXGetFuncProc == NULL || glXDestroyCtxProc == NULL || glXSwapProc == NULL || glXChooseFBConfigProc == NULL || glXCreatePbufferProc == NULL || glXDestroyPbufferProc == NULL || glXQueryDrawableProc == NULL) { RDCERR("Couldn't find required entry points, glXGetProcAddress glXDestroyContext glXSwapBuffers"); return eReplayCreate_APIInitFailed; } glXCreateContextAttribsProc = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetFuncProc((const GLubyte*)"glXCreateContextAttribsARB"); glXMakeContextCurrentProc = (PFNGLXMAKECONTEXTCURRENTPROC)glXGetFuncProc((const GLubyte*)"glXMakeContextCurrent"); if(glXCreateContextAttribsProc == NULL || glXMakeContextCurrentProc == NULL) { RDCERR("Couldn't get glx function addresses, glXCreateContextAttribsARB glXMakeContextCurrent"); return eReplayCreate_APIInitFailed; } } GLInitParams initParams; RDCDriver driverType = RDC_OpenGL; wstring driverName = L"OpenGL"; if(logfile) RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, (RDCInitParams *)&initParams); if(initParams.SerialiseVersion != GLInitParams::GL_SERIALISE_VERSION) { RDCERR("Incompatible OpenGL serialise version, expected %d got %d", GLInitParams::GL_SERIALISE_VERSION, initParams.SerialiseVersion); return eReplayCreate_APIIncompatibleVersion; } int attribs[64] = {0}; int i=0; attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB; attribs[i++] = 4; attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB; attribs[i++] = 3; attribs[i++] = GLX_CONTEXT_FLAGS_ARB; attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB; Display *dpy = XOpenDisplay(NULL); if(dpy == NULL) { RDCERR("Couldn't open default X display"); return eReplayCreate_APIInitFailed; } // don't need to care about the fb config as we won't be using the default framebuffer (backbuffer) static int visAttribs[] = { 0 }; int numCfgs = 0; GLXFBConfig *fbcfg = glXChooseFBConfigProc(dpy, DefaultScreen(dpy), visAttribs, &numCfgs); if(fbcfg == NULL) { XCloseDisplay(dpy); RDCERR("Couldn't choose default framebuffer config"); return eReplayCreate_APIInitFailed; } GLXContext ctx = glXCreateContextAttribsProc(dpy, fbcfg[0], 0, true, attribs); if(ctx == NULL) { XCloseDisplay(dpy); RDCERR("Couldn't create 4.3 context - RenderDoc requires OpenGL 4.3 availability"); return eReplayCreate_APIHardwareUnsupported; } // don't care about pbuffer properties for same reason as backbuffer int pbAttribs[] = { GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0 }; GLXPbuffer pbuffer = glXCreatePbufferProc(dpy, fbcfg[0], pbAttribs); XFree(fbcfg); Bool res = glXMakeContextCurrentProc(dpy, pbuffer, pbuffer, ctx); if(!res) { glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XCloseDisplay(dpy); RDCERR("Couldn't make pbuffer & context current"); return eReplayCreate_APIInitFailed; } WrappedOpenGL *gl = new WrappedOpenGL(logfile, GetRealFunctions()); gl->Initialise(initParams); RDCLOG("Created device."); GLReplay *replay = gl->GetReplay(); replay->SetProxy(logfile == NULL); GLWindowingData data; data.dpy = dpy; data.ctx = ctx; data.wnd = pbuffer; replay->SetReplayData(data); *driver = (IReplayDriver *)replay; return eReplayCreate_Success; }