mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 13:00:32 +00:00
Moved API-specific GLReplay code to GLPlatform.
ENABLE_GL & ENABLE_GLES can now both be ON without build errors on Linux.
This commit is contained in:
committed by
Baldur Karlsson
parent
2ee5f76185
commit
5a1ded7386
+1
-1
@@ -89,7 +89,7 @@ if(ANDROID)
|
|||||||
message(STATUS "Disabling GL driver on android and enabling GLES")
|
message(STATUS "Disabling GL driver on android and enabling GLES")
|
||||||
endif()
|
endif()
|
||||||
set(ENABLE_GL OFF CACHE BOOL "" FORCE)
|
set(ENABLE_GL OFF CACHE BOOL "" FORCE)
|
||||||
set(ENABLE_GLES ON CACHE BOOL "" FORCE)
|
set(ENABLE_GLES OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
# Android doesn't support the Qt UI for obvious reasons
|
# Android doesn't support the Qt UI for obvious reasons
|
||||||
message(STATUS "Disabling qrenderdoc for android build")
|
message(STATUS "Disabling qrenderdoc for android build")
|
||||||
|
|||||||
@@ -161,12 +161,20 @@ struct GLWindowingData
|
|||||||
#error "Unknown platform"
|
#error "Unknown platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "api/replay/renderdoc_replay.h"
|
||||||
|
|
||||||
struct GLPlatform
|
struct GLPlatform
|
||||||
{
|
{
|
||||||
// simple wrapper for OS functions to make/delete a context
|
// simple wrapper for OS functions to make/delete a context
|
||||||
virtual GLWindowingData MakeContext(GLWindowingData share) = 0;
|
virtual GLWindowingData MakeContext(GLWindowingData share) = 0;
|
||||||
virtual void DeleteContext(GLWindowingData context) = 0;
|
virtual void DeleteContext(GLWindowingData context) = 0;
|
||||||
|
virtual void DeleteReplayContext(GLWindowingData context) = 0;
|
||||||
virtual void MakeContextCurrent(GLWindowingData data) = 0;
|
virtual void MakeContextCurrent(GLWindowingData data) = 0;
|
||||||
|
virtual void SwapBuffers(GLWindowingData context) = 0;
|
||||||
|
virtual void GetOutputWindowDimensions(GLWindowingData context, int32_t &w, int32_t &h) = 0;
|
||||||
|
virtual bool IsOutputWindowVisible(GLWindowingData context) = 0;
|
||||||
|
virtual GLWindowingData MakeOutputWindow(WindowingSystem system, void *data, bool depth,
|
||||||
|
GLWindowingData share_context) = 0;
|
||||||
|
|
||||||
// for 'backwards compatible' overlay rendering
|
// for 'backwards compatible' overlay rendering
|
||||||
virtual bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices) = 0;
|
virtual bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices) = 0;
|
||||||
|
|||||||
@@ -49,7 +49,28 @@ public:
|
|||||||
return GLWindowingData();
|
return GLWindowingData();
|
||||||
}
|
}
|
||||||
virtual void DeleteContext(GLWindowingData context) { RDCUNIMPLEMENTED("DeleteContext"); }
|
virtual void DeleteContext(GLWindowingData context) { RDCUNIMPLEMENTED("DeleteContext"); }
|
||||||
|
virtual void DeleteReplayContext(GLWindowingData context)
|
||||||
|
{
|
||||||
|
RDCUNIMPLEMENTED("DeleteReplayContext");
|
||||||
|
}
|
||||||
virtual void MakeContextCurrent(GLWindowingData data) { RDCUNIMPLEMENTED("MakeContextCurrent"); }
|
virtual void MakeContextCurrent(GLWindowingData data) { RDCUNIMPLEMENTED("MakeContextCurrent"); }
|
||||||
|
virtual void SwapBuffers(GLWindowingData context) { RDCUNIMPLEMENTED("SwapBuffers"); }
|
||||||
|
virtual void GetOutputWindowDimensions(GLWindowingData context, int32_t &w, int32_t &h)
|
||||||
|
{
|
||||||
|
RDCUNIMPLEMENTED("GetOutputWindowDimensions");
|
||||||
|
}
|
||||||
|
virtual bool IsOutputWindowVisible(GLWindowingData context)
|
||||||
|
{
|
||||||
|
RDCUNIMPLEMENTED("IsOutputWindowVisible");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual GLWindowingData MakeOutputWindow(WindowingSystem system, void *data, bool depth,
|
||||||
|
GLWindowingData share_context)
|
||||||
|
{
|
||||||
|
RDCUNIMPLEMENTED("MakeOutputWindow");
|
||||||
|
return GLWindowingData();
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices)
|
virtual bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices)
|
||||||
{
|
{
|
||||||
RDCUNIMPLEMENTED("DrawQuads");
|
RDCUNIMPLEMENTED("DrawQuads");
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ typedef EGLContext (*PFN_eglCreateContext)(EGLDisplay dpy, EGLConfig config,
|
|||||||
typedef EGLBoolean (*PFN_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
typedef EGLBoolean (*PFN_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||||
typedef EGLSurface (*PFN_eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
|
typedef EGLSurface (*PFN_eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
|
||||||
const EGLint *attrib_list);
|
const EGLint *attrib_list);
|
||||||
|
typedef EGLSurface (*PFN_eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config,
|
||||||
|
EGLNativeWindowType win, const EGLint *attrib_list);
|
||||||
typedef EGLBoolean (*PFN_eglQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
|
typedef EGLBoolean (*PFN_eglQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
|
||||||
EGLint *value);
|
EGLint *value);
|
||||||
typedef EGLBoolean (*PFN_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
typedef EGLBoolean (*PFN_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||||
@@ -174,6 +176,110 @@ public:
|
|||||||
eglDestroyContext_real(context.egl_dpy, context.egl_ctx);
|
eglDestroyContext_real(context.egl_dpy, context.egl_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeleteReplayContext(GLWindowingData context)
|
||||||
|
{
|
||||||
|
if(eglDestroyContext_real)
|
||||||
|
{
|
||||||
|
eglMakeCurrent_real(context.egl_dpy, 0L, 0L, NULL);
|
||||||
|
eglDestroyContext_real(context.egl_dpy, context.egl_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapBuffers(GLWindowingData context)
|
||||||
|
{
|
||||||
|
eglSwapBuffers_real(context.egl_dpy, context.egl_wnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetOutputWindowDimensions(GLWindowingData context, int32_t &w, int32_t &h)
|
||||||
|
{
|
||||||
|
eglQuerySurface_real(context.egl_dpy, context.egl_wnd, EGL_WIDTH, &w);
|
||||||
|
eglQuerySurface_real(context.egl_dpy, context.egl_wnd, EGL_HEIGHT, &h);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOutputWindowVisible(GLWindowingData context) { return true; }
|
||||||
|
GLWindowingData MakeOutputWindow(WindowingSystem system, void *data, bool depth,
|
||||||
|
GLWindowingData share_context)
|
||||||
|
{
|
||||||
|
GLWindowingData ret;
|
||||||
|
EGLNativeWindowType window = 0;
|
||||||
|
|
||||||
|
if(system == eWindowingSystem_Xlib)
|
||||||
|
{
|
||||||
|
XlibWindowData *xlib = (XlibWindowData *)data;
|
||||||
|
window = (EGLNativeWindowType)xlib->window;
|
||||||
|
}
|
||||||
|
else if(system == eWindowingSystem_Unknown)
|
||||||
|
{
|
||||||
|
// allow undefined so that internally we can create a window-less context
|
||||||
|
Display *dpy = XOpenDisplay(NULL);
|
||||||
|
|
||||||
|
if(dpy == NULL)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RDCERR("Unexpected window system %u", system);
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLDisplay eglDisplay = eglGetDisplay_real(EGL_DEFAULT_DISPLAY);
|
||||||
|
RDCASSERT(eglDisplay);
|
||||||
|
|
||||||
|
static const EGLint configAttribs[] = {EGL_RED_SIZE,
|
||||||
|
8,
|
||||||
|
EGL_GREEN_SIZE,
|
||||||
|
8,
|
||||||
|
EGL_BLUE_SIZE,
|
||||||
|
8,
|
||||||
|
EGL_RENDERABLE_TYPE,
|
||||||
|
EGL_OPENGL_ES3_BIT,
|
||||||
|
EGL_SURFACE_TYPE,
|
||||||
|
EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
|
||||||
|
EGL_NONE};
|
||||||
|
|
||||||
|
PFN_eglChooseConfig eglChooseConfig = (PFN_eglChooseConfig)dlsym(RTLD_NEXT, "eglChooseConfig");
|
||||||
|
PFN_eglCreateWindowSurface eglCreateWindowSurface =
|
||||||
|
(PFN_eglCreateWindowSurface)dlsym(RTLD_NEXT, "eglCreateWindowSurfaceProc");
|
||||||
|
PFN_eglCreatePbufferSurface eglCreatePbufferSurface =
|
||||||
|
(PFN_eglCreatePbufferSurface)dlsym(RTLD_NEXT, "eglCreatePbufferSurface");
|
||||||
|
|
||||||
|
EGLint numConfigs;
|
||||||
|
EGLConfig config;
|
||||||
|
if(!eglChooseConfig(eglDisplay, configAttribs, &config, 1, &numConfigs))
|
||||||
|
{
|
||||||
|
RDCERR("Couldn't find a suitable EGL config");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_CONTEXT_FLAGS_KHR,
|
||||||
|
EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL_NONE};
|
||||||
|
|
||||||
|
EGLContext ctx = eglCreateContext_real(eglDisplay, config, EGL_NO_CONTEXT, ctxAttribs);
|
||||||
|
|
||||||
|
if(ctx == NULL)
|
||||||
|
{
|
||||||
|
RDCERR("Couldn't create GL ES context");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLSurface surface = 0;
|
||||||
|
|
||||||
|
if(window != 0)
|
||||||
|
{
|
||||||
|
surface = eglCreateWindowSurface(eglDisplay, config, window, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const EGLint pbAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
|
||||||
|
surface = eglCreatePbufferSurface(eglDisplay, config, pbAttribs);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.egl_dpy = eglDisplay;
|
||||||
|
ret.egl_ctx = ctx;
|
||||||
|
ret.egl_wnd = surface;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices);
|
bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices);
|
||||||
|
|
||||||
WrappedOpenGL *GetDriver()
|
WrappedOpenGL *GetDriver()
|
||||||
|
|||||||
@@ -153,22 +153,20 @@ public:
|
|||||||
bool is_direct = false;
|
bool is_direct = false;
|
||||||
|
|
||||||
PFNGLXISDIRECTPROC glXIsDirectProc = (PFNGLXISDIRECTPROC)dlsym(RTLD_NEXT, "glXIsDirect");
|
PFNGLXISDIRECTPROC glXIsDirectProc = (PFNGLXISDIRECTPROC)dlsym(RTLD_NEXT, "glXIsDirect");
|
||||||
PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfigProc =
|
|
||||||
(PFNGLXCHOOSEFBCONFIGPROC)dlsym(RTLD_NEXT, "glXChooseFBConfig");
|
|
||||||
PFNGLXCREATEPBUFFERPROC glXCreatePbufferProc =
|
PFNGLXCREATEPBUFFERPROC glXCreatePbufferProc =
|
||||||
(PFNGLXCREATEPBUFFERPROC)dlsym(RTLD_NEXT, "glXCreatePbuffer");
|
(PFNGLXCREATEPBUFFERPROC)dlsym(RTLD_NEXT, "glXCreatePbuffer");
|
||||||
|
|
||||||
if(glXIsDirectProc)
|
if(glXIsDirectProc)
|
||||||
is_direct = glXIsDirectProc(share.dpy, share.ctx);
|
is_direct = glXIsDirectProc(share.dpy, share.ctx);
|
||||||
|
|
||||||
if(glXChooseFBConfigProc && glXCreatePbufferProc)
|
if(glXChooseFBConfig_real && glXCreatePbufferProc)
|
||||||
{
|
{
|
||||||
// don't need to care about the fb config as we won't be using the default framebuffer
|
// don't need to care about the fb config as we won't be using the default framebuffer
|
||||||
// (backbuffer)
|
// (backbuffer)
|
||||||
int visAttribs[] = {0};
|
int visAttribs[] = {0};
|
||||||
int numCfgs = 0;
|
int numCfgs = 0;
|
||||||
GLXFBConfig *fbcfg =
|
GLXFBConfig *fbcfg =
|
||||||
glXChooseFBConfigProc(share.dpy, DefaultScreen(share.dpy), visAttribs, &numCfgs);
|
glXChooseFBConfig_real(share.dpy, DefaultScreen(share.dpy), visAttribs, &numCfgs);
|
||||||
|
|
||||||
// don't care about pbuffer properties as we won't render directly to this
|
// don't care about pbuffer properties as we won't render directly to this
|
||||||
int pbAttribs[] = {GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0};
|
int pbAttribs[] = {GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0};
|
||||||
@@ -197,6 +195,157 @@ public:
|
|||||||
glXDestroyContext_real(context.dpy, context.ctx);
|
glXDestroyContext_real(context.dpy, context.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeleteReplayContext(GLWindowingData context)
|
||||||
|
{
|
||||||
|
if(glXDestroyContext_real)
|
||||||
|
{
|
||||||
|
glXMakeContextCurrent_real(context.dpy, 0L, 0L, NULL);
|
||||||
|
glXDestroyContext_real(context.dpy, context.ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapBuffers(GLWindowingData context) { glXSwapBuffers_real(context.dpy, context.wnd); }
|
||||||
|
void GetOutputWindowDimensions(GLWindowingData context, int32_t &w, int32_t &h)
|
||||||
|
{
|
||||||
|
glXQueryDrawable_real(context.dpy, context.wnd, GLX_WIDTH, (unsigned int *)&w);
|
||||||
|
glXQueryDrawable_real(context.dpy, context.wnd, GLX_HEIGHT, (unsigned int *)&h);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOutputWindowVisible(GLWindowingData context)
|
||||||
|
{
|
||||||
|
GLNOTIMP("Optimisation missing - output window always returning true");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLWindowingData MakeOutputWindow(WindowingSystem system, void *data, bool depth,
|
||||||
|
GLWindowingData share_context)
|
||||||
|
{
|
||||||
|
GLWindowingData ret;
|
||||||
|
|
||||||
|
Display *dpy = NULL;
|
||||||
|
Drawable draw = 0;
|
||||||
|
|
||||||
|
if(system == eWindowingSystem_Xlib)
|
||||||
|
{
|
||||||
|
#if ENABLED(RDOC_XLIB)
|
||||||
|
XlibWindowData *xlib = (XlibWindowData *)data;
|
||||||
|
|
||||||
|
dpy = xlib->display;
|
||||||
|
draw = xlib->window;
|
||||||
|
#else
|
||||||
|
RDCERR(
|
||||||
|
"Xlib windowing system data passed in, but support is not compiled in. GL must have xlib "
|
||||||
|
"support compiled in");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if(system == eWindowingSystem_Unknown)
|
||||||
|
{
|
||||||
|
// allow undefined so that internally we can create a window-less context
|
||||||
|
dpy = XOpenDisplay(NULL);
|
||||||
|
|
||||||
|
if(dpy == NULL)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RDCERR("Unexpected window system %u", system);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int visAttribs[] = {GLX_X_RENDERABLE,
|
||||||
|
True,
|
||||||
|
GLX_DRAWABLE_TYPE,
|
||||||
|
GLX_WINDOW_BIT,
|
||||||
|
GLX_RENDER_TYPE,
|
||||||
|
GLX_RGBA_BIT,
|
||||||
|
GLX_X_VISUAL_TYPE,
|
||||||
|
GLX_TRUE_COLOR,
|
||||||
|
GLX_RED_SIZE,
|
||||||
|
8,
|
||||||
|
GLX_GREEN_SIZE,
|
||||||
|
8,
|
||||||
|
GLX_BLUE_SIZE,
|
||||||
|
8,
|
||||||
|
GLX_DOUBLEBUFFER,
|
||||||
|
True,
|
||||||
|
GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB,
|
||||||
|
True,
|
||||||
|
0};
|
||||||
|
int numCfgs = 0;
|
||||||
|
GLXFBConfig *fbcfg = glXChooseFBConfig_real(dpy, DefaultScreen(dpy), visAttribs, &numCfgs);
|
||||||
|
|
||||||
|
if(fbcfg == NULL)
|
||||||
|
{
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
RDCERR("Couldn't choose default framebuffer config");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(draw != 0)
|
||||||
|
{
|
||||||
|
// Choose FB config with a GLX_VISUAL_ID that matches the X screen.
|
||||||
|
VisualID visualid_correct = DefaultVisual(dpy, DefaultScreen(dpy))->visualid;
|
||||||
|
for(int i = 0; i < numCfgs; i++)
|
||||||
|
{
|
||||||
|
int visualid;
|
||||||
|
glXGetFBConfigAttrib(dpy, fbcfg[i], GLX_VISUAL_ID, &visualid);
|
||||||
|
if((VisualID)visualid == visualid_correct)
|
||||||
|
{
|
||||||
|
fbcfg[0] = fbcfg[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int attribs[64] = {0};
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
|
||||||
|
attribs[i++] = GLCoreVersion / 10;
|
||||||
|
attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
|
||||||
|
attribs[i++] = GLCoreVersion % 10;
|
||||||
|
attribs[i++] = GLX_CONTEXT_FLAGS_ARB;
|
||||||
|
#if ENABLED(RDOC_DEVEL)
|
||||||
|
attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB;
|
||||||
|
#else
|
||||||
|
attribs[i++] = 0;
|
||||||
|
#endif
|
||||||
|
attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB;
|
||||||
|
attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
|
||||||
|
GLXContext ctx = glXCreateContextAttribsARB_real(dpy, fbcfg[0], share_context.ctx, true, attribs);
|
||||||
|
|
||||||
|
if(ctx == NULL)
|
||||||
|
{
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
RDCERR("Couldn't create %d.%d context - something changed since creation", GLCoreVersion / 10,
|
||||||
|
GLCoreVersion % 10);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLXDrawable wnd = 0;
|
||||||
|
|
||||||
|
if(draw == 0)
|
||||||
|
{
|
||||||
|
// don't care about pbuffer properties as we won't render directly to this
|
||||||
|
int pbAttribs[] = {GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0};
|
||||||
|
|
||||||
|
wnd = glXCreatePbuffer(dpy, fbcfg[0], pbAttribs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wnd = glXCreateWindow(dpy, fbcfg[0], draw, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(fbcfg);
|
||||||
|
|
||||||
|
ret.dpy = dpy;
|
||||||
|
ret.ctx = ctx;
|
||||||
|
ret.wnd = wnd;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices);
|
bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices);
|
||||||
|
|
||||||
WrappedOpenGL *GetDriver()
|
WrappedOpenGL *GetDriver()
|
||||||
@@ -218,6 +367,8 @@ public:
|
|||||||
PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig_real;
|
PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig_real;
|
||||||
PFNGLXCREATEWINDOWPROC glXCreateWindow_real;
|
PFNGLXCREATEWINDOWPROC glXCreateWindow_real;
|
||||||
PFNGLXDESTROYWINDOWPROC glXDestroyWindow_real;
|
PFNGLXDESTROYWINDOWPROC glXDestroyWindow_real;
|
||||||
|
PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfig_real;
|
||||||
|
PFNGLXQUERYDRAWABLEPROC glXQueryDrawable_real;
|
||||||
|
|
||||||
set<GLXContext> m_Contexts;
|
set<GLXContext> m_Contexts;
|
||||||
|
|
||||||
@@ -258,6 +409,11 @@ public:
|
|||||||
glXCreateWindow_real = (PFNGLXCREATEWINDOWPROC)dlsym(libGLdlsymHandle, "glXCreateWindow");
|
glXCreateWindow_real = (PFNGLXCREATEWINDOWPROC)dlsym(libGLdlsymHandle, "glXCreateWindow");
|
||||||
if(glXDestroyWindow_real == NULL)
|
if(glXDestroyWindow_real == NULL)
|
||||||
glXDestroyWindow_real = (PFNGLXDESTROYWINDOWPROC)dlsym(libGLdlsymHandle, "glXDestroyWindow");
|
glXDestroyWindow_real = (PFNGLXDESTROYWINDOWPROC)dlsym(libGLdlsymHandle, "glXDestroyWindow");
|
||||||
|
if(glXChooseFBConfig_real == NULL)
|
||||||
|
glXChooseFBConfig_real =
|
||||||
|
(PFNGLXCHOOSEFBCONFIGPROC)dlsym(libGLdlsymHandle, "glXChooseFBConfig");
|
||||||
|
if(glXQueryDrawable_real == NULL)
|
||||||
|
glXQueryDrawable_real = (PFNGLXQUERYDRAWABLEPROC)dlsym(RTLD_NEXT, "glXQueryDrawable");
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -305,6 +305,9 @@
|
|||||||
|
|
||||||
Threading::CriticalSection glLock;
|
Threading::CriticalSection glLock;
|
||||||
|
|
||||||
|
extern PFNWGLCREATECONTEXTATTRIBSARBPROC createContextAttribs;
|
||||||
|
extern PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttrib;
|
||||||
|
|
||||||
class OpenGLHook : LibraryHook, public GLPlatform
|
class OpenGLHook : LibraryHook, public GLPlatform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -391,6 +394,159 @@ public:
|
|||||||
wglDeleteContext_hook()(context.ctx);
|
wglDeleteContext_hook()(context.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeleteReplayContext(GLWindowingData context)
|
||||||
|
{
|
||||||
|
if(wglDeleteContext_hook())
|
||||||
|
{
|
||||||
|
wglMakeCurrent_hook()(NULL, NULL);
|
||||||
|
wglDeleteContext_hook()(context.ctx);
|
||||||
|
ReleaseDC(context.wnd, context.DC);
|
||||||
|
::DestroyWindow(context.wnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapBuffers(GLWindowingData context) { ::SwapBuffers(context.DC); }
|
||||||
|
void GetOutputWindowDimensions(GLWindowingData context, int32_t &w, int32_t &h)
|
||||||
|
{
|
||||||
|
RECT rect = {0};
|
||||||
|
GetClientRect(context.wnd, &rect);
|
||||||
|
w = rect.right - rect.left;
|
||||||
|
h = rect.bottom - rect.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOutputWindowVisible(GLWindowingData context)
|
||||||
|
{
|
||||||
|
return (IsWindowVisible(context.wnd) == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLWindowingData GLPlatform::MakeOutputWindow(WindowingSystem system, void *data, bool depth,
|
||||||
|
GLWindowingData share_context)
|
||||||
|
{
|
||||||
|
GLWindowingData ret;
|
||||||
|
|
||||||
|
RDCASSERT(system == eWindowingSystem_Win32 || system == eWindowingSystem_Unknown, system);
|
||||||
|
|
||||||
|
HWND w = (HWND)data;
|
||||||
|
|
||||||
|
if(w == NULL)
|
||||||
|
w = CreateWindowEx(WS_EX_CLIENTEDGE, L"renderdocGLclass", L"", WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
|
||||||
|
GetModuleHandle(NULL), NULL);
|
||||||
|
|
||||||
|
HDC DC = GetDC(w);
|
||||||
|
|
||||||
|
PIXELFORMATDESCRIPTOR pfd = {0};
|
||||||
|
|
||||||
|
int attrib = eWGL_NUMBER_PIXEL_FORMATS_ARB;
|
||||||
|
int value = 1;
|
||||||
|
|
||||||
|
getPixelFormatAttrib(DC, 1, 0, 1, &attrib, &value);
|
||||||
|
|
||||||
|
int pf = 0;
|
||||||
|
|
||||||
|
int numpfs = value;
|
||||||
|
for(int i = 1; i <= numpfs; i++)
|
||||||
|
{
|
||||||
|
// verify that we have the properties we want
|
||||||
|
attrib = eWGL_DRAW_TO_WINDOW_ARB;
|
||||||
|
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
||||||
|
if(value == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
attrib = eWGL_ACCELERATION_ARB;
|
||||||
|
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
||||||
|
if(value == eWGL_NO_ACCELERATION_ARB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
attrib = eWGL_SUPPORT_OPENGL_ARB;
|
||||||
|
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
||||||
|
if(value == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
attrib = eWGL_DOUBLE_BUFFER_ARB;
|
||||||
|
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
||||||
|
if(value == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
attrib = eWGL_PIXEL_TYPE_ARB;
|
||||||
|
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
||||||
|
if(value != eWGL_TYPE_RGBA_ARB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// we have an opengl-capable accelerated RGBA context.
|
||||||
|
// we use internal framebuffers to do almost all rendering, so we just need
|
||||||
|
// RGB (color bits > 24) and SRGB buffer.
|
||||||
|
|
||||||
|
attrib = eWGL_COLOR_BITS_ARB;
|
||||||
|
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
||||||
|
if(value < 24)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
attrib = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
|
||||||
|
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
||||||
|
if(value == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// this one suits our needs, choose it
|
||||||
|
pf = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pf == 0)
|
||||||
|
{
|
||||||
|
ReleaseDC(w, DC);
|
||||||
|
RDCERR("Couldn't choose pixel format");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL res = DescribePixelFormat(DC, pf, sizeof(pfd), &pfd);
|
||||||
|
if(res == FALSE)
|
||||||
|
{
|
||||||
|
ReleaseDC(w, DC);
|
||||||
|
RDCERR("Couldn't describe pixel format");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = SetPixelFormat(DC, pf, &pfd);
|
||||||
|
if(res == FALSE)
|
||||||
|
{
|
||||||
|
ReleaseDC(w, DC);
|
||||||
|
RDCERR("Couldn't set pixel format");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int attribs[64] = {0};
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
|
||||||
|
attribs[i++] = GLCoreVersion / 10;
|
||||||
|
attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||||
|
attribs[i++] = GLCoreVersion % 10;
|
||||||
|
attribs[i++] = WGL_CONTEXT_FLAGS_ARB;
|
||||||
|
#if ENABLED(RDOC_DEVEL)
|
||||||
|
attribs[i++] = WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||||
|
#else
|
||||||
|
attribs[i++] = 0;
|
||||||
|
#endif
|
||||||
|
attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||||
|
attribs[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
|
||||||
|
HGLRC rc = createContextAttribs(DC, share_context.ctx, attribs);
|
||||||
|
if(rc == NULL)
|
||||||
|
{
|
||||||
|
ReleaseDC(w, DC);
|
||||||
|
RDCERR("Couldn't create %d.%d context - something changed since creation", GLCoreVersion / 10,
|
||||||
|
GLCoreVersion % 10);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.DC = DC;
|
||||||
|
ret.ctx = rc;
|
||||||
|
ret.wnd = w;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices);
|
bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -3203,6 +3203,83 @@ ShaderDebugTrace GLReplay::DebugThread(uint32_t eventID, uint32_t groupid[3], ui
|
|||||||
return ShaderDebugTrace();
|
return ShaderDebugTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLReplay::MakeCurrentReplayContext(GLWindowingData *ctx)
|
||||||
|
{
|
||||||
|
static GLWindowingData *prev = NULL;
|
||||||
|
|
||||||
|
if(ctx && ctx != prev)
|
||||||
|
{
|
||||||
|
m_pDriver->m_Platform.MakeContextCurrent(*ctx);
|
||||||
|
prev = ctx;
|
||||||
|
m_pDriver->ActivateContext(*ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLReplay::SwapBuffers(GLWindowingData *ctx)
|
||||||
|
{
|
||||||
|
m_pDriver->m_Platform.SwapBuffers(*ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLReplay::CloseReplayContext()
|
||||||
|
{
|
||||||
|
m_pDriver->m_Platform.DeleteReplayContext(m_ReplayCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GLReplay::MakeOutputWindow(WindowingSystem system, void *data, bool depth)
|
||||||
|
{
|
||||||
|
OutputWindow win = m_pDriver->m_Platform.MakeOutputWindow(system, data, depth, m_ReplayCtx);
|
||||||
|
if(!win.wnd)
|
||||||
|
return eReplayCreate_APIInitFailed;
|
||||||
|
|
||||||
|
m_pDriver->m_Platform.GetOutputWindowDimensions(win, win.width, win.height);
|
||||||
|
|
||||||
|
MakeCurrentReplayContext(&win);
|
||||||
|
InitOutputWindow(win);
|
||||||
|
CreateOutputWindowBackbuffer(win, depth);
|
||||||
|
|
||||||
|
uint64_t ret = m_OutputWindowID++;
|
||||||
|
|
||||||
|
m_OutputWindows[ret] = win;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLReplay::DestroyOutputWindow(uint64_t id)
|
||||||
|
{
|
||||||
|
auto it = m_OutputWindows.find(id);
|
||||||
|
if(id == 0 || it == m_OutputWindows.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
OutputWindow &outw = it->second;
|
||||||
|
|
||||||
|
MakeCurrentReplayContext(&outw);
|
||||||
|
|
||||||
|
WrappedOpenGL &gl = *m_pDriver;
|
||||||
|
gl.glDeleteFramebuffers(1, &outw.BlitData.readFBO);
|
||||||
|
|
||||||
|
m_pDriver->m_Platform.DeleteReplayContext(outw);
|
||||||
|
|
||||||
|
m_OutputWindows.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
|
||||||
|
{
|
||||||
|
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
OutputWindow &outw = m_OutputWindows[id];
|
||||||
|
|
||||||
|
m_pDriver->m_Platform.GetOutputWindowDimensions(outw, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLReplay::IsOutputWindowVisible(uint64_t id)
|
||||||
|
{
|
||||||
|
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_pDriver->m_Platform.IsOutputWindowVisible(m_OutputWindows[id]);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(RENDERDOC_SUPPORT_GL)
|
#if defined(RENDERDOC_SUPPORT_GL)
|
||||||
|
|
||||||
// defined in gl_replay_<platform>.cpp
|
// defined in gl_replay_<platform>.cpp
|
||||||
|
|||||||
@@ -243,6 +243,8 @@ private:
|
|||||||
|
|
||||||
struct OutputWindow : public GLWindowingData
|
struct OutputWindow : public GLWindowingData
|
||||||
{
|
{
|
||||||
|
OutputWindow(const GLWindowingData &data) : GLWindowingData(data) {}
|
||||||
|
OutputWindow() {}
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
// used to blit from defined FBO (VAOs not shared)
|
// used to blit from defined FBO (VAOs not shared)
|
||||||
|
|||||||
@@ -26,43 +26,6 @@
|
|||||||
#include "gl_driver.h"
|
#include "gl_driver.h"
|
||||||
#include "gl_resources.h"
|
#include "gl_resources.h"
|
||||||
|
|
||||||
void GLReplay::MakeCurrentReplayContext(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
RDCUNIMPLEMENTED("GLReplay::MakeCurrentReplayContext");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::SwapBuffers(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
RDCUNIMPLEMENTED("GLReplay::SwapBuffers");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::CloseReplayContext()
|
|
||||||
{
|
|
||||||
RDCUNIMPLEMENTED("GLReplay::CloseReplayContext");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GLReplay::MakeOutputWindow(WindowingSystem system, void *data, bool depth)
|
|
||||||
{
|
|
||||||
RDCUNIMPLEMENTED("GLReplay::MakeOutputWindow");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::DestroyOutputWindow(uint64_t id)
|
|
||||||
{
|
|
||||||
RDCUNIMPLEMENTED("GLReplay::DestroyOutputWindow");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
|
|
||||||
{
|
|
||||||
RDCUNIMPLEMENTED("GLReplay::GetOutputWindowDimensions");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLReplay::IsOutputWindowVisible(uint64_t id)
|
|
||||||
{
|
|
||||||
RDCUNIMPLEMENTED("GLReplay::IsOutputWindowVisible");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
|
ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
|
||||||
{
|
{
|
||||||
RDCUNIMPLEMENTED("GL_CreateReplayDevice");
|
RDCUNIMPLEMENTED("GL_CreateReplayDevice");
|
||||||
|
|||||||
@@ -61,161 +61,6 @@ PFN_eglCreateWindowSurface eglCreateWindowSurfaceProc = NULL;
|
|||||||
PFN_eglChooseConfig eglChooseConfigProc = NULL;
|
PFN_eglChooseConfig eglChooseConfigProc = NULL;
|
||||||
PFN_eglGetProcAddress eglGetProcAddressProc = NULL;
|
PFN_eglGetProcAddress eglGetProcAddressProc = NULL;
|
||||||
|
|
||||||
void GLReplay::MakeCurrentReplayContext(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
static GLWindowingData *prev = NULL;
|
|
||||||
|
|
||||||
if(eglMakeCurrentProc && ctx && ctx != prev)
|
|
||||||
{
|
|
||||||
prev = ctx;
|
|
||||||
eglMakeCurrentProc(ctx->egl_dpy, ctx->egl_wnd, ctx->egl_wnd, ctx->egl_ctx);
|
|
||||||
m_pDriver->ActivateContext(*ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::SwapBuffers(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
eglSwapBuffersProc(ctx->egl_dpy, ctx->egl_wnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::CloseReplayContext()
|
|
||||||
{
|
|
||||||
if(eglDestroyContextProc)
|
|
||||||
{
|
|
||||||
eglMakeCurrentProc(m_ReplayCtx.egl_dpy, 0L, 0L, NULL);
|
|
||||||
eglDestroyContextProc(m_ReplayCtx.egl_dpy, m_ReplayCtx.egl_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GLReplay::MakeOutputWindow(WindowingSystem system, void *data, bool depth)
|
|
||||||
{
|
|
||||||
EGLNativeWindowType window = 0;
|
|
||||||
|
|
||||||
if(system == eWindowingSystem_Xlib)
|
|
||||||
{
|
|
||||||
XlibWindowData *xlib = (XlibWindowData *)data;
|
|
||||||
window = (EGLNativeWindowType)xlib->window;
|
|
||||||
}
|
|
||||||
else if(system == eWindowingSystem_Unknown)
|
|
||||||
{
|
|
||||||
// allow undefined so that internally we can create a window-less context
|
|
||||||
Display *dpy = XOpenDisplay(NULL);
|
|
||||||
|
|
||||||
if(dpy == NULL)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RDCERR("Unexpected window system %u", system);
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLDisplay eglDisplay = eglGetDisplayProc(EGL_DEFAULT_DISPLAY);
|
|
||||||
RDCASSERT(eglDisplay);
|
|
||||||
|
|
||||||
static const EGLint configAttribs[] = {EGL_RED_SIZE,
|
|
||||||
8,
|
|
||||||
EGL_GREEN_SIZE,
|
|
||||||
8,
|
|
||||||
EGL_BLUE_SIZE,
|
|
||||||
8,
|
|
||||||
EGL_RENDERABLE_TYPE,
|
|
||||||
EGL_OPENGL_ES3_BIT,
|
|
||||||
EGL_SURFACE_TYPE,
|
|
||||||
EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
|
|
||||||
EGL_NONE};
|
|
||||||
EGLint numConfigs;
|
|
||||||
EGLConfig config;
|
|
||||||
|
|
||||||
if(!eglChooseConfigProc(eglDisplay, configAttribs, &config, 1, &numConfigs))
|
|
||||||
{
|
|
||||||
RDCERR("Couldn't find a suitable EGL config");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_CONTEXT_FLAGS_KHR,
|
|
||||||
EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL_NONE};
|
|
||||||
|
|
||||||
EGLContext ctx = eglCreateContextProc(eglDisplay, config, EGL_NO_CONTEXT, ctxAttribs);
|
|
||||||
|
|
||||||
if(ctx == NULL)
|
|
||||||
{
|
|
||||||
RDCERR("Couldn't create GL ES context");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLSurface surface = 0;
|
|
||||||
|
|
||||||
if(window != 0)
|
|
||||||
{
|
|
||||||
surface = eglCreateWindowSurfaceProc(eglDisplay, config, window, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static const EGLint pbAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
|
|
||||||
surface = eglCreatePbufferSurfaceProc(eglDisplay, config, pbAttribs);
|
|
||||||
}
|
|
||||||
|
|
||||||
RDCASSERT(surface != NULL);
|
|
||||||
|
|
||||||
OutputWindow win;
|
|
||||||
win.egl_dpy = eglDisplay;
|
|
||||||
win.egl_ctx = ctx;
|
|
||||||
win.egl_wnd = surface;
|
|
||||||
|
|
||||||
eglQuerySurfaceProc(eglDisplay, surface, EGL_WIDTH, &win.width);
|
|
||||||
eglQuerySurfaceProc(eglDisplay, surface, EGL_HEIGHT, &win.height);
|
|
||||||
|
|
||||||
MakeCurrentReplayContext(&win);
|
|
||||||
InitOutputWindow(win);
|
|
||||||
CreateOutputWindowBackbuffer(win, depth);
|
|
||||||
|
|
||||||
uint64_t ret = m_OutputWindowID++;
|
|
||||||
|
|
||||||
m_OutputWindows[ret] = win;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::DestroyOutputWindow(uint64_t id)
|
|
||||||
{
|
|
||||||
auto it = m_OutputWindows.find(id);
|
|
||||||
if(id == 0 || it == m_OutputWindows.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
OutputWindow &outw = it->second;
|
|
||||||
|
|
||||||
MakeCurrentReplayContext(&outw);
|
|
||||||
|
|
||||||
WrappedOpenGL &gl = *m_pDriver;
|
|
||||||
gl.glDeleteFramebuffers(1, &outw.BlitData.readFBO);
|
|
||||||
|
|
||||||
eglMakeCurrentProc(outw.egl_dpy, 0L, 0L, NULL);
|
|
||||||
eglDestroyContextProc(outw.egl_dpy, outw.egl_ctx);
|
|
||||||
|
|
||||||
m_OutputWindows.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
|
|
||||||
{
|
|
||||||
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
OutputWindow &outw = m_OutputWindows[id];
|
|
||||||
|
|
||||||
eglQuerySurfaceProc(outw.egl_dpy, outw.egl_wnd, EGL_WIDTH, &w);
|
|
||||||
eglQuerySurfaceProc(outw.egl_dpy, outw.egl_wnd, EGL_HEIGHT, &h);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLReplay::IsOutputWindowVisible(uint64_t id)
|
|
||||||
{
|
|
||||||
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
GLNOTIMP("Optimisation missing - output window always returning true");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GLHookSet &GetRealGLFunctionsEGL();
|
const GLHookSet &GetRealGLFunctionsEGL();
|
||||||
GLPlatform &GetGLPlatformEGL();
|
GLPlatform &GetGLPlatformEGL();
|
||||||
|
|
||||||
|
|||||||
@@ -42,215 +42,6 @@ PFNGLXQUERYDRAWABLEPROC glXQueryDrawableProc = NULL;
|
|||||||
PFNGLXDESTROYCONTEXTPROC glXDestroyCtxProc = NULL;
|
PFNGLXDESTROYCONTEXTPROC glXDestroyCtxProc = NULL;
|
||||||
PFNGLXSWAPBUFFERSPROC glXSwapProc = NULL;
|
PFNGLXSWAPBUFFERSPROC glXSwapProc = NULL;
|
||||||
|
|
||||||
void GLReplay::MakeCurrentReplayContext(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
static GLWindowingData *prev = NULL;
|
|
||||||
|
|
||||||
if(glXMakeContextCurrentProc && ctx && ctx != prev)
|
|
||||||
{
|
|
||||||
prev = ctx;
|
|
||||||
glXMakeContextCurrentProc(ctx->dpy, ctx->wnd, ctx->wnd, ctx->ctx);
|
|
||||||
m_pDriver->ActivateContext(*ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::SwapBuffers(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
glXSwapProc(ctx->dpy, ctx->wnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::CloseReplayContext()
|
|
||||||
{
|
|
||||||
if(glXDestroyCtxProc)
|
|
||||||
{
|
|
||||||
glXMakeContextCurrentProc(m_ReplayCtx.dpy, 0L, 0L, NULL);
|
|
||||||
glXDestroyCtxProc(m_ReplayCtx.dpy, m_ReplayCtx.ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GLReplay::MakeOutputWindow(WindowingSystem system, void *data, bool depth)
|
|
||||||
{
|
|
||||||
Display *dpy = NULL;
|
|
||||||
Drawable draw = 0;
|
|
||||||
|
|
||||||
if(system == eWindowingSystem_Xlib)
|
|
||||||
{
|
|
||||||
#if ENABLED(RDOC_XLIB)
|
|
||||||
XlibWindowData *xlib = (XlibWindowData *)data;
|
|
||||||
|
|
||||||
dpy = xlib->display;
|
|
||||||
draw = xlib->window;
|
|
||||||
#else
|
|
||||||
RDCERR(
|
|
||||||
"Xlib windowing system data passed in, but support is not compiled in. GL must have xlib "
|
|
||||||
"support compiled in");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if(system == eWindowingSystem_Unknown)
|
|
||||||
{
|
|
||||||
// allow undefined so that internally we can create a window-less context
|
|
||||||
dpy = XOpenDisplay(NULL);
|
|
||||||
|
|
||||||
if(dpy == NULL)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RDCERR("Unexpected window system %u", system);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int visAttribs[] = {GLX_X_RENDERABLE,
|
|
||||||
True,
|
|
||||||
GLX_DRAWABLE_TYPE,
|
|
||||||
GLX_WINDOW_BIT,
|
|
||||||
GLX_RENDER_TYPE,
|
|
||||||
GLX_RGBA_BIT,
|
|
||||||
GLX_X_VISUAL_TYPE,
|
|
||||||
GLX_TRUE_COLOR,
|
|
||||||
GLX_RED_SIZE,
|
|
||||||
8,
|
|
||||||
GLX_GREEN_SIZE,
|
|
||||||
8,
|
|
||||||
GLX_BLUE_SIZE,
|
|
||||||
8,
|
|
||||||
GLX_DOUBLEBUFFER,
|
|
||||||
True,
|
|
||||||
GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB,
|
|
||||||
True,
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(draw != 0)
|
|
||||||
{
|
|
||||||
// Choose FB config with a GLX_VISUAL_ID that matches the X screen.
|
|
||||||
VisualID visualid_correct = DefaultVisual(dpy, DefaultScreen(dpy))->visualid;
|
|
||||||
for(int i = 0; i < numCfgs; i++)
|
|
||||||
{
|
|
||||||
int visualid;
|
|
||||||
glXGetFBConfigAttrib(dpy, fbcfg[i], GLX_VISUAL_ID, &visualid);
|
|
||||||
if((VisualID)visualid == visualid_correct)
|
|
||||||
{
|
|
||||||
fbcfg[0] = fbcfg[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int attribs[64] = {0};
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
|
|
||||||
attribs[i++] = GLCoreVersion / 10;
|
|
||||||
attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
|
|
||||||
attribs[i++] = GLCoreVersion % 10;
|
|
||||||
attribs[i++] = GLX_CONTEXT_FLAGS_ARB;
|
|
||||||
#if ENABLED(RDOC_DEVEL)
|
|
||||||
attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB;
|
|
||||||
#else
|
|
||||||
attribs[i++] = 0;
|
|
||||||
#endif
|
|
||||||
attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB;
|
|
||||||
attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
|
||||||
|
|
||||||
GLXContext ctx = glXCreateContextAttribsProc(dpy, fbcfg[0], m_ReplayCtx.ctx, true, attribs);
|
|
||||||
|
|
||||||
if(ctx == NULL)
|
|
||||||
{
|
|
||||||
XCloseDisplay(dpy);
|
|
||||||
RDCERR("Couldn't create %d.%d context - something changed since creation", GLCoreVersion / 10,
|
|
||||||
GLCoreVersion % 10);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLXDrawable wnd = 0;
|
|
||||||
|
|
||||||
if(draw == 0)
|
|
||||||
{
|
|
||||||
// don't care about pbuffer properties as we won't render directly to this
|
|
||||||
int pbAttribs[] = {GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0};
|
|
||||||
|
|
||||||
wnd = glXCreatePbufferProc(dpy, fbcfg[0], pbAttribs);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// on NV and AMD creating this window causes problems rendering to any widgets in Qt, with the
|
|
||||||
// width/height queries failing to return any values and the framebuffer blitting not working.
|
|
||||||
// For the moment, we use the passed-in drawable directly as this works in testing on
|
|
||||||
// renderdoccmd and qrenderdoc
|
|
||||||
wnd = draw;
|
|
||||||
// glXCreateWindow(dpy, fbcfg[0], draw, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(fbcfg);
|
|
||||||
|
|
||||||
OutputWindow win;
|
|
||||||
win.dpy = dpy;
|
|
||||||
win.ctx = ctx;
|
|
||||||
win.wnd = wnd;
|
|
||||||
|
|
||||||
glXQueryDrawableProc(dpy, wnd, GLX_WIDTH, (unsigned int *)&win.width);
|
|
||||||
glXQueryDrawableProc(dpy, wnd, GLX_HEIGHT, (unsigned int *)&win.height);
|
|
||||||
|
|
||||||
MakeCurrentReplayContext(&win);
|
|
||||||
|
|
||||||
InitOutputWindow(win);
|
|
||||||
CreateOutputWindowBackbuffer(win, depth);
|
|
||||||
|
|
||||||
uint64_t ret = m_OutputWindowID++;
|
|
||||||
|
|
||||||
m_OutputWindows[ret] = win;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::DestroyOutputWindow(uint64_t id)
|
|
||||||
{
|
|
||||||
auto it = m_OutputWindows.find(id);
|
|
||||||
if(id == 0 || it == m_OutputWindows.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
OutputWindow &outw = it->second;
|
|
||||||
|
|
||||||
MakeCurrentReplayContext(&outw);
|
|
||||||
|
|
||||||
WrappedOpenGL &gl = *m_pDriver;
|
|
||||||
gl.glDeleteFramebuffers(1, &outw.BlitData.readFBO);
|
|
||||||
|
|
||||||
glXMakeContextCurrentProc(outw.dpy, 0L, 0L, NULL);
|
|
||||||
glXDestroyCtxProc(outw.dpy, outw.ctx);
|
|
||||||
|
|
||||||
m_OutputWindows.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
|
|
||||||
{
|
|
||||||
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
OutputWindow &outw = m_OutputWindows[id];
|
|
||||||
|
|
||||||
glXQueryDrawableProc(outw.dpy, outw.wnd, GLX_WIDTH, (unsigned int *)&w);
|
|
||||||
glXQueryDrawableProc(outw.dpy, outw.wnd, GLX_HEIGHT, (unsigned int *)&h);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLReplay::IsOutputWindowVisible(uint64_t id)
|
|
||||||
{
|
|
||||||
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
GLNOTIMP("Optimisation missing - output window always returning true");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool X11ErrorSeen = false;
|
static bool X11ErrorSeen = false;
|
||||||
|
|
||||||
int NonFatalX11ErrorHandler(Display *display, XErrorEvent *error)
|
int NonFatalX11ErrorHandler(Display *display, XErrorEvent *error)
|
||||||
|
|||||||
@@ -40,215 +40,6 @@ WGLCREATECONTEXTPROC wglCreateRC = NULL;
|
|||||||
WGLMAKECURRENTPROC wglMakeCurrentProc = NULL;
|
WGLMAKECURRENTPROC wglMakeCurrentProc = NULL;
|
||||||
WGLDELETECONTEXTPROC wglDeleteRC = NULL;
|
WGLDELETECONTEXTPROC wglDeleteRC = NULL;
|
||||||
|
|
||||||
void GLReplay::MakeCurrentReplayContext(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
static GLWindowingData *prev = NULL;
|
|
||||||
|
|
||||||
if(wglMakeCurrentProc && ctx && ctx != prev)
|
|
||||||
{
|
|
||||||
prev = ctx;
|
|
||||||
wglMakeCurrentProc(ctx->DC, ctx->ctx);
|
|
||||||
m_pDriver->ActivateContext(*ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::SwapBuffers(GLWindowingData *ctx)
|
|
||||||
{
|
|
||||||
::SwapBuffers(ctx->DC);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::CloseReplayContext()
|
|
||||||
{
|
|
||||||
if(wglDeleteRC)
|
|
||||||
{
|
|
||||||
wglMakeCurrentProc(NULL, NULL);
|
|
||||||
wglDeleteRC(m_ReplayCtx.ctx);
|
|
||||||
ReleaseDC(m_ReplayCtx.wnd, m_ReplayCtx.DC);
|
|
||||||
::DestroyWindow(m_ReplayCtx.wnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GLReplay::MakeOutputWindow(WindowingSystem system, void *data, bool depth)
|
|
||||||
{
|
|
||||||
RDCASSERT(system == eWindowingSystem_Win32 || system == eWindowingSystem_Unknown, system);
|
|
||||||
|
|
||||||
HWND w = (HWND)data;
|
|
||||||
|
|
||||||
if(w == NULL)
|
|
||||||
w = CreateWindowEx(WS_EX_CLIENTEDGE, L"renderdocGLclass", L"", WS_OVERLAPPEDWINDOW,
|
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
|
|
||||||
GetModuleHandle(NULL), NULL);
|
|
||||||
|
|
||||||
HDC DC = GetDC(w);
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pfd = {0};
|
|
||||||
|
|
||||||
int attrib = eWGL_NUMBER_PIXEL_FORMATS_ARB;
|
|
||||||
int value = 1;
|
|
||||||
|
|
||||||
getPixelFormatAttrib(DC, 1, 0, 1, &attrib, &value);
|
|
||||||
|
|
||||||
int pf = 0;
|
|
||||||
|
|
||||||
int numpfs = value;
|
|
||||||
for(int i = 1; i <= numpfs; i++)
|
|
||||||
{
|
|
||||||
// verify that we have the properties we want
|
|
||||||
attrib = eWGL_DRAW_TO_WINDOW_ARB;
|
|
||||||
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
|
||||||
if(value == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
attrib = eWGL_ACCELERATION_ARB;
|
|
||||||
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
|
||||||
if(value == eWGL_NO_ACCELERATION_ARB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
attrib = eWGL_SUPPORT_OPENGL_ARB;
|
|
||||||
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
|
||||||
if(value == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
attrib = eWGL_DOUBLE_BUFFER_ARB;
|
|
||||||
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
|
||||||
if(value == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
attrib = eWGL_PIXEL_TYPE_ARB;
|
|
||||||
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
|
||||||
if(value != eWGL_TYPE_RGBA_ARB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// we have an opengl-capable accelerated RGBA context.
|
|
||||||
// we use internal framebuffers to do almost all rendering, so we just need
|
|
||||||
// RGB (color bits > 24) and SRGB buffer.
|
|
||||||
|
|
||||||
attrib = eWGL_COLOR_BITS_ARB;
|
|
||||||
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
|
||||||
if(value < 24)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
attrib = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
|
|
||||||
getPixelFormatAttrib(DC, i, 0, 1, &attrib, &value);
|
|
||||||
if(value == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// this one suits our needs, choose it
|
|
||||||
pf = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pf == 0)
|
|
||||||
{
|
|
||||||
ReleaseDC(w, DC);
|
|
||||||
RDCERR("Couldn't choose pixel format");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL res = DescribePixelFormat(DC, pf, sizeof(pfd), &pfd);
|
|
||||||
if(res == FALSE)
|
|
||||||
{
|
|
||||||
ReleaseDC(w, DC);
|
|
||||||
RDCERR("Couldn't describe pixel format");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = SetPixelFormat(DC, pf, &pfd);
|
|
||||||
if(res == FALSE)
|
|
||||||
{
|
|
||||||
ReleaseDC(w, DC);
|
|
||||||
RDCERR("Couldn't set pixel format");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int attribs[64] = {0};
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
|
|
||||||
attribs[i++] = GLCoreVersion / 10;
|
|
||||||
attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
|
|
||||||
attribs[i++] = GLCoreVersion % 10;
|
|
||||||
attribs[i++] = WGL_CONTEXT_FLAGS_ARB;
|
|
||||||
#if ENABLED(RDOC_DEVEL)
|
|
||||||
attribs[i++] = WGL_CONTEXT_DEBUG_BIT_ARB;
|
|
||||||
#else
|
|
||||||
attribs[i++] = 0;
|
|
||||||
#endif
|
|
||||||
attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
|
|
||||||
attribs[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
|
||||||
|
|
||||||
HGLRC rc = createContextAttribs(DC, m_ReplayCtx.ctx, attribs);
|
|
||||||
if(rc == NULL)
|
|
||||||
{
|
|
||||||
ReleaseDC(w, DC);
|
|
||||||
RDCERR("Couldn't create %d.%d context - something changed since creation", GLCoreVersion / 10,
|
|
||||||
GLCoreVersion % 10);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputWindow win;
|
|
||||||
win.DC = DC;
|
|
||||||
win.ctx = rc;
|
|
||||||
win.wnd = w;
|
|
||||||
|
|
||||||
RECT rect = {0};
|
|
||||||
GetClientRect(w, &rect);
|
|
||||||
win.width = rect.right - rect.left;
|
|
||||||
win.height = rect.bottom - rect.top;
|
|
||||||
|
|
||||||
m_pDriver->RegisterContext(win, m_ReplayCtx.ctx, true, true);
|
|
||||||
|
|
||||||
InitOutputWindow(win);
|
|
||||||
CreateOutputWindowBackbuffer(win, depth);
|
|
||||||
|
|
||||||
uint64_t ret = m_OutputWindowID++;
|
|
||||||
|
|
||||||
m_OutputWindows[ret] = win;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::DestroyOutputWindow(uint64_t id)
|
|
||||||
{
|
|
||||||
auto it = m_OutputWindows.find(id);
|
|
||||||
if(id == 0 || it == m_OutputWindows.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
OutputWindow &outw = it->second;
|
|
||||||
|
|
||||||
MakeCurrentReplayContext(&outw);
|
|
||||||
|
|
||||||
WrappedOpenGL &gl = *m_pDriver;
|
|
||||||
gl.glDeleteFramebuffers(1, &outw.BlitData.readFBO);
|
|
||||||
|
|
||||||
wglMakeCurrentProc(NULL, NULL);
|
|
||||||
wglDeleteRC(outw.ctx);
|
|
||||||
ReleaseDC(outw.wnd, outw.DC);
|
|
||||||
|
|
||||||
m_OutputWindows.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
|
|
||||||
{
|
|
||||||
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
OutputWindow &outw = m_OutputWindows[id];
|
|
||||||
|
|
||||||
RECT rect = {0};
|
|
||||||
GetClientRect(outw.wnd, &rect);
|
|
||||||
w = rect.right - rect.left;
|
|
||||||
h = rect.bottom - rect.top;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLReplay::IsOutputWindowVisible(uint64_t id)
|
|
||||||
{
|
|
||||||
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return (IsWindowVisible(m_OutputWindows[id].wnd) == TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
|
ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
|
||||||
{
|
{
|
||||||
RDCDEBUG("Creating an OpenGL replay device");
|
RDCDEBUG("Creating an OpenGL replay device");
|
||||||
|
|||||||
@@ -389,10 +389,10 @@ void sig_handler(int signo)
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
|
volatile bool never_run = false;
|
||||||
|
|
||||||
#if defined(RENDERDOC_SUPPORT_GL)
|
#if defined(RENDERDOC_SUPPORT_GL)
|
||||||
|
|
||||||
volatile bool never_run = false;
|
|
||||||
if(never_run)
|
if(never_run)
|
||||||
glXWaitX();
|
glXWaitX();
|
||||||
|
|
||||||
@@ -400,7 +400,6 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
#if defined(RENDERDOC_SUPPORT_GLES)
|
#if defined(RENDERDOC_SUPPORT_GLES)
|
||||||
|
|
||||||
volatile bool never_run = false;
|
|
||||||
if(never_run)
|
if(never_run)
|
||||||
eglWaitGL();
|
eglWaitGL();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user