mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 09:00:44 +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")
|
||||
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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user