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:
Michael Rennie
2017-02-22 12:09:27 +00:00
committed by Baldur Karlsson
parent 2ee5f76185
commit 5a1ded7386
13 changed files with 532 additions and 617 deletions
+1 -1
View File
@@ -89,7 +89,7 @@ if(ANDROID)
message(STATUS "Disabling GL driver on android and enabling GLES")
endif()
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
message(STATUS "Disabling qrenderdoc for android build")
+8
View File
@@ -161,12 +161,20 @@ struct GLWindowingData
#error "Unknown platform"
#endif
#include "api/replay/renderdoc_replay.h"
struct GLPlatform
{
// simple wrapper for OS functions to make/delete a context
virtual GLWindowingData MakeContext(GLWindowingData share) = 0;
virtual void DeleteContext(GLWindowingData context) = 0;
virtual void DeleteReplayContext(GLWindowingData context) = 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
virtual bool DrawQuads(float width, float height, const std::vector<Vec4f> &vertices) = 0;
+21
View File
@@ -49,7 +49,28 @@ public:
return GLWindowingData();
}
virtual void DeleteContext(GLWindowingData context) { RDCUNIMPLEMENTED("DeleteContext"); }
virtual void DeleteReplayContext(GLWindowingData context)
{
RDCUNIMPLEMENTED("DeleteReplayContext");
}
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)
{
RDCUNIMPLEMENTED("DrawQuads");
+106
View File
@@ -41,6 +41,8 @@ typedef EGLContext (*PFN_eglCreateContext)(EGLDisplay dpy, EGLConfig config,
typedef EGLBoolean (*PFN_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
typedef EGLSurface (*PFN_eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
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,
EGLint *value);
typedef EGLBoolean (*PFN_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
@@ -174,6 +176,110 @@ public:
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);
WrappedOpenGL *GetDriver()
+160 -4
View File
@@ -153,22 +153,20 @@ public:
bool is_direct = false;
PFNGLXISDIRECTPROC glXIsDirectProc = (PFNGLXISDIRECTPROC)dlsym(RTLD_NEXT, "glXIsDirect");
PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfigProc =
(PFNGLXCHOOSEFBCONFIGPROC)dlsym(RTLD_NEXT, "glXChooseFBConfig");
PFNGLXCREATEPBUFFERPROC glXCreatePbufferProc =
(PFNGLXCREATEPBUFFERPROC)dlsym(RTLD_NEXT, "glXCreatePbuffer");
if(glXIsDirectProc)
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
// (backbuffer)
int visAttribs[] = {0};
int numCfgs = 0;
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
int pbAttribs[] = {GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0};
@@ -197,6 +195,157 @@ public:
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);
WrappedOpenGL *GetDriver()
@@ -218,6 +367,8 @@ public:
PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig_real;
PFNGLXCREATEWINDOWPROC glXCreateWindow_real;
PFNGLXDESTROYWINDOWPROC glXDestroyWindow_real;
PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfig_real;
PFNGLXQUERYDRAWABLEPROC glXQueryDrawable_real;
set<GLXContext> m_Contexts;
@@ -258,6 +409,11 @@ public:
glXCreateWindow_real = (PFNGLXCREATEWINDOWPROC)dlsym(libGLdlsymHandle, "glXCreateWindow");
if(glXDestroyWindow_real == NULL)
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;
}
+156
View File
@@ -305,6 +305,9 @@
Threading::CriticalSection glLock;
extern PFNWGLCREATECONTEXTATTRIBSARBPROC createContextAttribs;
extern PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttrib;
class OpenGLHook : LibraryHook, public GLPlatform
{
public:
@@ -391,6 +394,159 @@ public:
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);
private:
+77
View File
@@ -3203,6 +3203,83 @@ ShaderDebugTrace GLReplay::DebugThread(uint32_t eventID, uint32_t groupid[3], ui
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)
// defined in gl_replay_<platform>.cpp
+2
View File
@@ -243,6 +243,8 @@ private:
struct OutputWindow : public GLWindowingData
{
OutputWindow(const GLWindowingData &data) : GLWindowingData(data) {}
OutputWindow() {}
struct
{
// used to blit from defined FBO (VAOs not shared)
-37
View File
@@ -26,43 +26,6 @@
#include "gl_driver.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)
{
RDCUNIMPLEMENTED("GL_CreateReplayDevice");
-155
View File
@@ -61,161 +61,6 @@ PFN_eglCreateWindowSurface eglCreateWindowSurfaceProc = NULL;
PFN_eglChooseConfig eglChooseConfigProc = 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();
GLPlatform &GetGLPlatformEGL();
-209
View File
@@ -42,215 +42,6 @@ PFNGLXQUERYDRAWABLEPROC glXQueryDrawableProc = NULL;
PFNGLXDESTROYCONTEXTPROC glXDestroyCtxProc = 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;
int NonFatalX11ErrorHandler(Display *display, XErrorEvent *error)
-209
View File
@@ -40,215 +40,6 @@ WGLCREATECONTEXTPROC wglCreateRC = NULL;
WGLMAKECURRENTPROC wglMakeCurrentProc = 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)
{
RDCDEBUG("Creating an OpenGL replay device");
+1 -2
View File
@@ -389,10 +389,10 @@ void sig_handler(int signo)
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "");
volatile bool never_run = false;
#if defined(RENDERDOC_SUPPORT_GL)
volatile bool never_run = false;
if(never_run)
glXWaitX();
@@ -400,7 +400,6 @@ int main(int argc, char *argv[])
#if defined(RENDERDOC_SUPPORT_GLES)
volatile bool never_run = false;
if(never_run)
eglWaitGL();