mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-15 14:30:35 +00:00
216 lines
5.7 KiB
C++
216 lines
5.7 KiB
C++
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2018-2019 Baldur Karlsson
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
#include <dlfcn.h>
|
|
#include "hooks/hooks.h"
|
|
#include "cgl_dispatch_table.h"
|
|
#include "gl_driver.h"
|
|
|
|
class CGLHook : LibraryHook
|
|
{
|
|
public:
|
|
CGLHook() : driver(GetGLPlatform()) {}
|
|
void RegisterHooks();
|
|
|
|
// default to RTLD_NEXT for CGL lookups if we haven't gotten a more specific library handle
|
|
void *handle = RTLD_NEXT;
|
|
WrappedOpenGL driver;
|
|
std::set<CGLContextObj> contexts;
|
|
} cglhook;
|
|
|
|
CGLError GL_EXPORT_NAME(CGLCreateContext)(CGLPixelFormatObj pix, CGLContextObj share,
|
|
CGLContextObj *ctx)
|
|
{
|
|
if(RenderDoc::Inst().IsReplayApp())
|
|
{
|
|
if(!CGL.CGLCreateContext)
|
|
CGL.PopulateForReplay();
|
|
|
|
return CGL.CGLCreateContext(pix, share, ctx);
|
|
}
|
|
|
|
CGLError ret = CGL.CGLCreateContext(pix, share, ctx);
|
|
|
|
if(ret != kCGLNoError)
|
|
return ret;
|
|
|
|
GLInitParams init = {};
|
|
|
|
init.width = 0;
|
|
init.height = 0;
|
|
|
|
GLint value = 0;
|
|
|
|
CGLError err = kCGLNoError;
|
|
|
|
CGL.CGLDescribePixelFormat(pix, 0, kCGLPFAColorSize, &value);
|
|
init.colorBits = (uint32_t)value;
|
|
CGL.CGLDescribePixelFormat(pix, 0, kCGLPFADepthSize, &value);
|
|
init.depthBits = (uint32_t)value;
|
|
CGL.CGLDescribePixelFormat(pix, 0, kCGLPFAStencilSize, &value);
|
|
init.stencilBits = (uint32_t)value;
|
|
// TODO: is macOS sRGB?
|
|
init.isSRGB = 1;
|
|
CGL.CGLDescribePixelFormat(pix, 0, kCGLPFASamples, &value);
|
|
init.multiSamples = RDCMAX(1, value);
|
|
|
|
GLWindowingData data;
|
|
data.wnd = NULL;
|
|
data.ctx = *ctx;
|
|
data.cfg = pix;
|
|
|
|
{
|
|
SCOPED_LOCK(glLock);
|
|
cglhook.driver.CreateContext(data, share, init, true, true);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
CGLError GL_EXPORT_NAME(CGLSetCurrentContext)(CGLContextObj ctx)
|
|
{
|
|
if(RenderDoc::Inst().IsReplayApp())
|
|
{
|
|
if(!CGL.CGLSetCurrentContext)
|
|
CGL.PopulateForReplay();
|
|
|
|
return CGL.CGLSetCurrentContext(ctx);
|
|
}
|
|
|
|
CGLError ret = CGL.CGLSetCurrentContext(ctx);
|
|
|
|
if(ret == kCGLNoError)
|
|
{
|
|
SCOPED_LOCK(glLock);
|
|
|
|
SetDriverForHooks(&cglhook.driver);
|
|
|
|
if(ctx && cglhook.contexts.find(ctx) == cglhook.contexts.end())
|
|
{
|
|
cglhook.contexts.insert(ctx);
|
|
|
|
FetchEnabledExtensions();
|
|
|
|
// see gl_emulated.cpp
|
|
GL.EmulateUnsupportedFunctions();
|
|
GL.EmulateRequiredExtensions();
|
|
GL.DriverForEmulation(&cglhook.driver);
|
|
}
|
|
|
|
CGRect rect = {};
|
|
|
|
GLWindowingData data;
|
|
data.wnd = NULL;
|
|
data.ctx = ctx;
|
|
data.cfg = NULL;
|
|
|
|
if(data.ctx)
|
|
{
|
|
CGSConnectionID conn = 0;
|
|
CGSWindowID window = 0;
|
|
CGSSurfaceID surface = 0;
|
|
|
|
CGL.CGLGetSurface(ctx, &conn, &window, &surface);
|
|
|
|
data.wnd = (void *)(uintptr_t)window;
|
|
|
|
CGL.CGSGetSurfaceBounds(conn, window, surface, &rect);
|
|
}
|
|
|
|
cglhook.driver.ActivateContext(data);
|
|
|
|
if(data.ctx)
|
|
{
|
|
GLInitParams ¶ms = cglhook.driver.GetInitParams(data);
|
|
params.width = (uint32_t)rect.size.width;
|
|
params.height = (uint32_t)rect.size.height;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
CGLError GL_EXPORT_NAME(CGLFlushDrawable)(CGLContextObj ctx)
|
|
{
|
|
if(RenderDoc::Inst().IsReplayApp())
|
|
{
|
|
if(!CGL.CGLFlushDrawable)
|
|
CGL.PopulateForReplay();
|
|
|
|
return CGL.CGLFlushDrawable(ctx);
|
|
}
|
|
|
|
{
|
|
SCOPED_LOCK(glLock);
|
|
|
|
CGSConnectionID conn = 0;
|
|
CGSWindowID window = 0;
|
|
CGSSurfaceID surface = 0;
|
|
|
|
CGL.CGLGetSurface(ctx, &conn, &window, &surface);
|
|
|
|
cglhook.driver.SwapBuffers((void *)(uintptr_t)window);
|
|
}
|
|
|
|
return CGL.CGLFlushDrawable(ctx);
|
|
}
|
|
|
|
DECL_GL_HOOK_EXPORT(CGLCreateContext);
|
|
DECL_GL_HOOK_EXPORT(CGLSetCurrentContext);
|
|
DECL_GL_HOOK_EXPORT(CGLFlushDrawable);
|
|
|
|
static void CGLHooked(void *handle)
|
|
{
|
|
RDCDEBUG("CGL library hooked");
|
|
|
|
// store the handle for any pass-through implementations that need to look up their onward
|
|
// pointers
|
|
cglhook.handle = handle;
|
|
|
|
// as a hook callback this is only called while capturing
|
|
RDCASSERT(!RenderDoc::Inst().IsReplayApp());
|
|
|
|
// fetch non-hooked functions into our dispatch table
|
|
#define CGL_FETCH(func) CGL.func = &func;
|
|
CGL_NONHOOKED_SYMBOLS(CGL_FETCH)
|
|
#undef CGL_FETCH
|
|
}
|
|
|
|
void CGLHook::RegisterHooks()
|
|
{
|
|
RDCLOG("Registering CGL hooks");
|
|
|
|
// register library hooks
|
|
LibraryHooks::RegisterLibraryHook(
|
|
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", &CGLHooked);
|
|
LibraryHooks::RegisterLibraryHook("libGL.dylib", NULL);
|
|
|
|
// register CGL hooks
|
|
#define CGL_REGISTER(func) \
|
|
LibraryHooks::RegisterFunctionHook( \
|
|
"OpenGL", FunctionHook(STRINGIZE(func), (void **)&CGL.func, (void *)&GL_EXPORT_NAME(func)));
|
|
CGL_HOOKED_SYMBOLS(CGL_REGISTER)
|
|
#undef CGL_REGISTER
|
|
}
|