mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 09:30:44 +00:00
[EGL] Move symbol loading into one file
The EGL function pointer loading was scattered in two files thus it is hard to keep track where the symbols were loaded. Introduced a class which holds all internally used EGL function pointers with a helper method to load the required pointers. Not all EGL pointers are loaded just the used ones (just like before).
This commit is contained in:
committed by
Baldur Karlsson
parent
9c84b7f716
commit
ca95a9c3ab
@@ -60,6 +60,7 @@ else()
|
||||
list(APPEND sources
|
||||
gl_hooks_egl.cpp
|
||||
gl_hooks_egl_pass.cpp
|
||||
gl_library_egl.cpp
|
||||
gl_replay_egl.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -30,30 +30,7 @@
|
||||
#include "hooks/hooks.h"
|
||||
#include "strings/string_utils.h"
|
||||
#include "gl_hooks_linux_shared.h"
|
||||
|
||||
typedef __eglMustCastToProperFunctionPointerType (*PFN_eglGetProcAddress)(const char *procname);
|
||||
typedef EGLBoolean (*PFN_eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute,
|
||||
EGLint *value);
|
||||
typedef EGLBoolean (*PFN_eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLContext (*PFN_eglCreateContext)(EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_context, const EGLint *attrib_list);
|
||||
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);
|
||||
typedef EGLBoolean (*PFN_eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
|
||||
EGLContext ctx);
|
||||
typedef EGLBoolean (*PFN_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLDisplay (*PFN_eglGetDisplay)(EGLNativeDisplayType display_id);
|
||||
typedef EGLContext (*PFN_eglGetCurrentContext)(void);
|
||||
typedef EGLDisplay (*PFN_eglGetCurrentDisplay)(void);
|
||||
typedef EGLSurface (*PFN_eglGetCurrentSurface)(EGLint readdraw);
|
||||
typedef EGLint (*PFN_eglGetError)(void);
|
||||
#include "gl_library_egl.h"
|
||||
|
||||
class EGLHook : LibraryHook, public GLPlatform
|
||||
{
|
||||
@@ -116,14 +93,15 @@ public:
|
||||
|
||||
void MakeContextCurrent(GLWindowingData data)
|
||||
{
|
||||
if(eglMakeCurrent_real)
|
||||
eglMakeCurrent_real(data.egl_dpy, data.egl_wnd, data.egl_wnd, data.egl_ctx);
|
||||
if(real.MakeCurrent)
|
||||
real.MakeCurrent(data.egl_dpy, data.egl_wnd, data.egl_wnd, data.egl_ctx);
|
||||
}
|
||||
|
||||
GLWindowingData MakeContext(GLWindowingData share)
|
||||
{
|
||||
GLWindowingData ret;
|
||||
if(eglCreateContext_real)
|
||||
|
||||
if(real.CreateContext && real.ChooseConfig && real.CreatePbufferSurface)
|
||||
{
|
||||
const EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_CONTEXT_FLAGS_KHR,
|
||||
EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL_NONE};
|
||||
@@ -144,24 +122,16 @@ public:
|
||||
EGL_RGB_BUFFER,
|
||||
EGL_NONE};
|
||||
|
||||
PFN_eglChooseConfig eglChooseConfig =
|
||||
(PFN_eglChooseConfig)dlsym(RTLD_NEXT, "eglChooseConfig");
|
||||
PFN_eglCreatePbufferSurface eglCreatePbufferSurface =
|
||||
(PFN_eglCreatePbufferSurface)dlsym(RTLD_NEXT, "eglCreatePbufferSurface");
|
||||
EGLConfig config;
|
||||
EGLint numConfigs;
|
||||
EGLBoolean configFound = real.ChooseConfig(share.egl_dpy, attribs, &config, 1, &numConfigs);
|
||||
|
||||
if(eglChooseConfig && eglCreatePbufferSurface)
|
||||
if(configFound)
|
||||
{
|
||||
EGLConfig config;
|
||||
EGLint numConfigs;
|
||||
EGLBoolean configFound = eglChooseConfig(share.egl_dpy, attribs, &config, 1, &numConfigs);
|
||||
|
||||
if(configFound)
|
||||
{
|
||||
const EGLint pbAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
|
||||
ret.egl_wnd = eglCreatePbufferSurface(share.egl_dpy, config, pbAttribs);
|
||||
ret.egl_dpy = share.egl_dpy;
|
||||
ret.egl_ctx = eglCreateContext_real(share.egl_dpy, config, share.ctx, ctxAttribs);
|
||||
}
|
||||
const EGLint pbAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
|
||||
ret.egl_wnd = real.CreatePbufferSurface(share.egl_dpy, config, pbAttribs);
|
||||
ret.egl_dpy = share.egl_dpy;
|
||||
ret.egl_ctx = real.CreateContext(share.egl_dpy, config, share.ctx, ctxAttribs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,30 +140,23 @@ public:
|
||||
|
||||
void DeleteContext(GLWindowingData context)
|
||||
{
|
||||
PFN_eglDestroySurface eglDestroySurface =
|
||||
(PFN_eglDestroySurface)dlsym(RTLD_NEXT, "eglDestroySurface");
|
||||
if(context.wnd && real.DestroySurface)
|
||||
real.DestroySurface(context.egl_dpy, context.egl_wnd);
|
||||
|
||||
if(context.wnd && eglDestroySurface)
|
||||
eglDestroySurface(context.egl_dpy, context.egl_wnd);
|
||||
|
||||
if(context.ctx && eglDestroyContext_real)
|
||||
eglDestroyContext_real(context.egl_dpy, context.egl_ctx);
|
||||
if(context.ctx && real.DestroyContext)
|
||||
real.DestroyContext(context.egl_dpy, context.egl_ctx);
|
||||
}
|
||||
|
||||
void DeleteReplayContext(GLWindowingData context)
|
||||
{
|
||||
if(eglDestroyContext_real)
|
||||
if(real.DestroyContext)
|
||||
{
|
||||
eglMakeCurrent_real(context.egl_dpy, 0L, 0L, NULL);
|
||||
eglDestroyContext_real(context.egl_dpy, context.egl_ctx);
|
||||
real.MakeCurrent(context.egl_dpy, 0L, 0L, NULL);
|
||||
real.DestroyContext(context.egl_dpy, context.egl_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void SwapBuffers(GLWindowingData context)
|
||||
{
|
||||
eglSwapBuffers_real(context.egl_dpy, context.egl_wnd);
|
||||
}
|
||||
|
||||
void SwapBuffers(GLWindowingData context) { real.SwapBuffers(context.egl_dpy, context.egl_wnd); }
|
||||
void GetOutputWindowDimensions(GLWindowingData context, int32_t &w, int32_t &h)
|
||||
{
|
||||
// On some Linux systems the surface seems to be context dependant.
|
||||
@@ -201,17 +164,17 @@ public:
|
||||
// To avoid any problems because of the context change we'll save the old
|
||||
// context information so we can switch back to it after the surface query is done.
|
||||
GLWindowingData oldContext;
|
||||
oldContext.egl_ctx = eglGetCurrentContext_real();
|
||||
oldContext.egl_dpy = eglGetCurrentDisplay_real();
|
||||
oldContext.egl_wnd = eglGetCurrentSurface_real(EGL_READ);
|
||||
oldContext.egl_ctx = real.GetCurrentContext();
|
||||
oldContext.egl_dpy = real.GetCurrentDisplay();
|
||||
oldContext.egl_wnd = real.GetCurrentSurface(EGL_READ);
|
||||
MakeContextCurrent(context);
|
||||
|
||||
EGLBoolean width_ok = eglQuerySurface_real(context.egl_dpy, context.egl_wnd, EGL_WIDTH, &w);
|
||||
EGLBoolean height_ok = eglQuerySurface_real(context.egl_dpy, context.egl_wnd, EGL_HEIGHT, &h);
|
||||
EGLBoolean width_ok = real.QuerySurface(context.egl_dpy, context.egl_wnd, EGL_WIDTH, &w);
|
||||
EGLBoolean height_ok = real.QuerySurface(context.egl_dpy, context.egl_wnd, EGL_HEIGHT, &h);
|
||||
|
||||
if(!width_ok || !height_ok)
|
||||
{
|
||||
RDCGLenum error_code = (RDCGLenum)eglGetError_real();
|
||||
RDCGLenum error_code = (RDCGLenum)real.GetError();
|
||||
RDCWARN("Unable to query the surface size. Error: (0x%x) %s", error_code,
|
||||
ToStr(error_code).c_str());
|
||||
}
|
||||
@@ -244,7 +207,7 @@ public:
|
||||
default: RDCERR("Unexpected window system %u", system); break;
|
||||
}
|
||||
|
||||
EGLDisplay eglDisplay = eglGetDisplay_real(EGL_DEFAULT_DISPLAY);
|
||||
EGLDisplay eglDisplay = real.GetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
RDCASSERT(eglDisplay);
|
||||
|
||||
static const EGLint configAttribs[] = {EGL_RED_SIZE,
|
||||
@@ -259,15 +222,9 @@ public:
|
||||
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, "eglCreateWindowSurface");
|
||||
PFN_eglCreatePbufferSurface eglCreatePbufferSurface =
|
||||
(PFN_eglCreatePbufferSurface)dlsym(RTLD_NEXT, "eglCreatePbufferSurface");
|
||||
|
||||
EGLint numConfigs;
|
||||
EGLConfig config;
|
||||
if(!eglChooseConfig(eglDisplay, configAttribs, &config, 1, &numConfigs))
|
||||
if(!real.ChooseConfig(eglDisplay, configAttribs, &config, 1, &numConfigs))
|
||||
{
|
||||
RDCERR("Couldn't find a suitable EGL config");
|
||||
return ret;
|
||||
@@ -276,7 +233,7 @@ public:
|
||||
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, share_context.ctx, ctxAttribs);
|
||||
EGLContext ctx = real.CreateContext(eglDisplay, config, share_context.ctx, ctxAttribs);
|
||||
|
||||
if(ctx == NULL)
|
||||
{
|
||||
@@ -288,12 +245,12 @@ public:
|
||||
|
||||
if(window != 0)
|
||||
{
|
||||
surface = eglCreateWindowSurface(eglDisplay, config, window, NULL);
|
||||
surface = real.CreateWindowSurface(eglDisplay, config, window, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
static const EGLint pbAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
|
||||
surface = eglCreatePbufferSurface(eglDisplay, config, pbAttribs);
|
||||
surface = real.CreatePbufferSurface(eglDisplay, config, pbAttribs);
|
||||
}
|
||||
|
||||
ret.egl_dpy = eglDisplay;
|
||||
@@ -316,19 +273,7 @@ public:
|
||||
return m_GLDriver;
|
||||
}
|
||||
|
||||
PFN_eglCreateContext eglCreateContext_real;
|
||||
PFN_eglDestroyContext eglDestroyContext_real;
|
||||
PFN_eglGetProcAddress eglGetProcAddress_real;
|
||||
PFN_eglSwapBuffers eglSwapBuffers_real;
|
||||
PFN_eglMakeCurrent eglMakeCurrent_real;
|
||||
PFN_eglQuerySurface eglQuerySurface_real;
|
||||
PFN_eglGetConfigAttrib eglGetConfigAttrib_real;
|
||||
PFN_eglGetDisplay eglGetDisplay_real;
|
||||
PFN_eglGetCurrentContext eglGetCurrentContext_real;
|
||||
PFN_eglGetCurrentDisplay eglGetCurrentDisplay_real;
|
||||
PFN_eglGetCurrentSurface eglGetCurrentSurface_real;
|
||||
PFN_eglGetError eglGetError_real;
|
||||
|
||||
EGLPointers real;
|
||||
set<EGLContext> m_Contexts;
|
||||
|
||||
bool m_PopulatedHooks;
|
||||
@@ -339,35 +284,15 @@ public:
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
if(eglGetProcAddress_real == NULL)
|
||||
eglGetProcAddress_real = (PFN_eglGetProcAddress)dlsym(libGLdlsymHandle, "eglGetProcAddress");
|
||||
if(eglCreateContext_real == NULL)
|
||||
eglCreateContext_real = (PFN_eglCreateContext)dlsym(libGLdlsymHandle, "eglCreateContext");
|
||||
if(eglDestroyContext_real == NULL)
|
||||
eglDestroyContext_real = (PFN_eglDestroyContext)dlsym(libGLdlsymHandle, "eglDestroyContext");
|
||||
if(eglMakeCurrent_real == NULL)
|
||||
eglMakeCurrent_real = (PFN_eglMakeCurrent)dlsym(libGLdlsymHandle, "eglMakeCurrent");
|
||||
if(eglSwapBuffers_real == NULL)
|
||||
eglSwapBuffers_real = (PFN_eglSwapBuffers)dlsym(libGLdlsymHandle, "eglSwapBuffers");
|
||||
if(eglQuerySurface_real == NULL)
|
||||
eglQuerySurface_real = (PFN_eglQuerySurface)dlsym(libGLdlsymHandle, "eglQuerySurface");
|
||||
if(eglGetConfigAttrib_real == NULL)
|
||||
eglGetConfigAttrib_real =
|
||||
(PFN_eglGetConfigAttrib)dlsym(libGLdlsymHandle, "eglGetConfigAttrib");
|
||||
if(eglGetDisplay_real == NULL)
|
||||
eglGetDisplay_real = (PFN_eglGetDisplay)dlsym(libGLdlsymHandle, "eglGetDisplay");
|
||||
if(eglGetCurrentContext_real == NULL)
|
||||
eglGetCurrentContext_real =
|
||||
(PFN_eglGetCurrentContext)dlsym(libGLdlsymHandle, "eglGetCurrentContext");
|
||||
if(eglGetCurrentDisplay_real == NULL)
|
||||
eglGetCurrentDisplay_real =
|
||||
(PFN_eglGetCurrentDisplay)dlsym(libGLdlsymHandle, "eglGetCurrentDisplay");
|
||||
if(eglGetCurrentSurface_real == NULL)
|
||||
eglGetCurrentSurface_real =
|
||||
(PFN_eglGetCurrentSurface)dlsym(libGLdlsymHandle, "eglGetCurrentSurface");
|
||||
if(eglGetError_real == NULL)
|
||||
eglGetError_real = (PFN_eglGetError)dlsym(libGLdlsymHandle, "eglGetError");
|
||||
|
||||
if(!real.IsInitialized())
|
||||
{
|
||||
bool symbols_ok = real.LoadSymbolsFrom(libGLdlsymHandle);
|
||||
if(!symbols_ok)
|
||||
{
|
||||
RDCWARN("Unable to load some of the EGL API functions, may cause problems");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -386,14 +311,14 @@ extern "C" {
|
||||
|
||||
__attribute__((visibility("default"))) EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
|
||||
{
|
||||
if(eglhooks.eglGetDisplay_real == NULL)
|
||||
if(eglhooks.real.GetDisplay == NULL)
|
||||
eglhooks.SetupExportedFunctions();
|
||||
|
||||
#if DISABLED(RDOC_ANDROID)
|
||||
Keyboard::CloneDisplay(display);
|
||||
#endif
|
||||
|
||||
return eglhooks.eglGetDisplay_real(display);
|
||||
return eglhooks.real.GetDisplay(display);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) EGLContext eglCreateContext(EGLDisplay display,
|
||||
@@ -440,10 +365,10 @@ __attribute__((visibility("default"))) EGLContext eglCreateContext(EGLDisplay di
|
||||
attribs = &attribVec[0];
|
||||
}
|
||||
|
||||
if(eglhooks.eglCreateContext_real == NULL)
|
||||
if(eglhooks.real.CreateContext == NULL)
|
||||
eglhooks.SetupExportedFunctions();
|
||||
|
||||
EGLContext ret = eglhooks.eglCreateContext_real(display, config, shareContext, attribs);
|
||||
EGLContext ret = eglhooks.real.CreateContext(display, config, shareContext, attribs);
|
||||
|
||||
// don't continue if context creation failed
|
||||
if(!ret)
|
||||
@@ -455,11 +380,11 @@ __attribute__((visibility("default"))) EGLContext eglCreateContext(EGLDisplay di
|
||||
init.height = 0;
|
||||
|
||||
EGLint value;
|
||||
eglhooks.eglGetConfigAttrib_real(display, config, EGL_BUFFER_SIZE, &value);
|
||||
eglhooks.real.GetConfigAttrib(display, config, EGL_BUFFER_SIZE, &value);
|
||||
init.colorBits = value;
|
||||
eglhooks.eglGetConfigAttrib_real(display, config, EGL_DEPTH_SIZE, &value);
|
||||
eglhooks.real.GetConfigAttrib(display, config, EGL_DEPTH_SIZE, &value);
|
||||
init.depthBits = value;
|
||||
eglhooks.eglGetConfigAttrib_real(display, config, EGL_STENCIL_SIZE, &value);
|
||||
eglhooks.real.GetConfigAttrib(display, config, EGL_STENCIL_SIZE, &value);
|
||||
init.stencilBits = value;
|
||||
// We will set isSRGB when we see the surface.
|
||||
init.isSRGB = 0;
|
||||
@@ -480,7 +405,7 @@ __attribute__((visibility("default"))) EGLContext eglCreateContext(EGLDisplay di
|
||||
|
||||
__attribute__((visibility("default"))) EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
|
||||
{
|
||||
if(eglhooks.eglDestroyContext_real == NULL)
|
||||
if(eglhooks.real.DestroyContext == NULL)
|
||||
eglhooks.SetupExportedFunctions();
|
||||
|
||||
eglhooks.GetDriver()->SetDriverType(RDC_OpenGLES);
|
||||
@@ -489,16 +414,16 @@ __attribute__((visibility("default"))) EGLBoolean eglDestroyContext(EGLDisplay d
|
||||
eglhooks.GetDriver()->DeleteContext(ctx);
|
||||
}
|
||||
|
||||
return eglhooks.eglDestroyContext_real(dpy, ctx);
|
||||
return eglhooks.real.DestroyContext(dpy, ctx);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) EGLBoolean eglMakeCurrent(EGLDisplay display, EGLSurface draw,
|
||||
EGLSurface read, EGLContext ctx)
|
||||
{
|
||||
if(eglhooks.eglMakeCurrent_real == NULL)
|
||||
if(eglhooks.real.MakeCurrent == NULL)
|
||||
eglhooks.SetupExportedFunctions();
|
||||
|
||||
EGLBoolean ret = eglhooks.eglMakeCurrent_real(display, draw, read, ctx);
|
||||
EGLBoolean ret = eglhooks.real.MakeCurrent(display, draw, read, ctx);
|
||||
|
||||
SCOPED_LOCK(glLock);
|
||||
|
||||
@@ -522,18 +447,18 @@ __attribute__((visibility("default"))) EGLBoolean eglMakeCurrent(EGLDisplay disp
|
||||
|
||||
__attribute__((visibility("default"))) EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
|
||||
{
|
||||
if(eglhooks.eglSwapBuffers_real == NULL)
|
||||
if(eglhooks.real.SwapBuffers == NULL)
|
||||
eglhooks.SetupExportedFunctions();
|
||||
|
||||
SCOPED_LOCK(glLock);
|
||||
|
||||
int height, width;
|
||||
eglhooks.eglQuerySurface_real(dpy, surface, EGL_HEIGHT, &height);
|
||||
eglhooks.eglQuerySurface_real(dpy, surface, EGL_WIDTH, &width);
|
||||
eglhooks.real.QuerySurface(dpy, surface, EGL_HEIGHT, &height);
|
||||
eglhooks.real.QuerySurface(dpy, surface, EGL_WIDTH, &width);
|
||||
|
||||
GLInitParams &init = eglhooks.GetDriver()->GetInitParams();
|
||||
int colorspace = 0;
|
||||
eglhooks.eglQuerySurface_real(dpy, surface, EGL_GL_COLORSPACE, &colorspace);
|
||||
eglhooks.real.QuerySurface(dpy, surface, EGL_GL_COLORSPACE, &colorspace);
|
||||
// GL_SRGB8_ALPHA8 is specified as color-renderable, unlike GL_SRGB8.
|
||||
init.isSRGB = init.colorBits == 32 && colorspace == EGL_GL_COLORSPACE_SRGB;
|
||||
|
||||
@@ -541,16 +466,16 @@ __attribute__((visibility("default"))) EGLBoolean eglSwapBuffers(EGLDisplay dpy,
|
||||
eglhooks.GetDriver()->WindowSize(surface, width, height);
|
||||
eglhooks.GetDriver()->SwapBuffers(surface);
|
||||
|
||||
return eglhooks.eglSwapBuffers_real(dpy, surface);
|
||||
return eglhooks.real.SwapBuffers(dpy, surface);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) __eglMustCastToProperFunctionPointerType eglGetProcAddress(
|
||||
const char *func)
|
||||
{
|
||||
if(eglhooks.eglGetProcAddress_real == NULL)
|
||||
if(eglhooks.real.GetProcAddress == NULL)
|
||||
eglhooks.SetupExportedFunctions();
|
||||
|
||||
__eglMustCastToProperFunctionPointerType realFunc = eglhooks.eglGetProcAddress_real(func);
|
||||
__eglMustCastToProperFunctionPointerType realFunc = eglhooks.real.GetProcAddress(func);
|
||||
|
||||
if(!strcmp(func, "eglCreateContext"))
|
||||
return (__eglMustCastToProperFunctionPointerType)&eglCreateContext;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 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 "gl_library_egl.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
bool EGLPointers::LoadSymbolsFrom(void *lib_handle)
|
||||
{
|
||||
if(m_initialized)
|
||||
{
|
||||
RDCDEBUG("EGL function pointers already loaded, skipping");
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
bool symbols_ok = true;
|
||||
#define LOAD_SYM(SYMBOL_NAME) \
|
||||
do \
|
||||
{ \
|
||||
this->SYMBOL_NAME = (PFN_egl##SYMBOL_NAME)dlsym(lib_handle, "egl" #SYMBOL_NAME); \
|
||||
if(this->SYMBOL_NAME == NULL) \
|
||||
{ \
|
||||
symbols_ok = false; \
|
||||
RDCWARN("Unable to load symbol: %s", #SYMBOL_NAME); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
EGL_SYMBOLS(LOAD_SYM)
|
||||
|
||||
#undef LOAD_SYM
|
||||
m_initialized = symbols_ok;
|
||||
return symbols_ok;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 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.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gl_common.h"
|
||||
|
||||
typedef EGLBoolean (*PFN_eglBindAPI)(EGLenum api);
|
||||
typedef EGLDisplay (*PFN_eglGetDisplay)(EGLNativeDisplayType display_id);
|
||||
typedef EGLContext (*PFN_eglCreateContext)(EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_context, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (*PFN_eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
|
||||
EGLContext ctx);
|
||||
typedef EGLBoolean (*PFN_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (*PFN_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (*PFN_eglQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
|
||||
EGLint *value);
|
||||
typedef EGLBoolean (*PFN_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
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_eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef __eglMustCastToProperFunctionPointerType (*PFN_eglGetProcAddress)(const char *procname);
|
||||
typedef EGLBoolean (*PFN_eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
typedef EGLContext (*PFN_eglGetCurrentContext)(void);
|
||||
typedef EGLDisplay (*PFN_eglGetCurrentDisplay)(void);
|
||||
typedef EGLSurface (*PFN_eglGetCurrentSurface)(EGLint readdraw);
|
||||
typedef EGLint (*PFN_eglGetError)(void);
|
||||
typedef EGLBoolean (*PFN_eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute,
|
||||
EGLint *value);
|
||||
|
||||
#define EGL_SYMBOLS(FUNC) \
|
||||
FUNC(BindAPI); \
|
||||
FUNC(ChooseConfig); \
|
||||
FUNC(CreateContext); \
|
||||
FUNC(CreatePbufferSurface); \
|
||||
FUNC(CreateWindowSurface); \
|
||||
FUNC(DestroyContext); \
|
||||
FUNC(DestroySurface); \
|
||||
FUNC(GetConfigAttrib); \
|
||||
FUNC(GetCurrentContext); \
|
||||
FUNC(GetCurrentDisplay); \
|
||||
FUNC(GetCurrentSurface); \
|
||||
FUNC(GetDisplay); \
|
||||
FUNC(GetError); \
|
||||
FUNC(GetProcAddress); \
|
||||
FUNC(Initialize); \
|
||||
FUNC(MakeCurrent); \
|
||||
FUNC(QuerySurface); \
|
||||
FUNC(SwapBuffers);
|
||||
|
||||
class EGLPointers
|
||||
{
|
||||
public:
|
||||
EGLPointers() : m_initialized(false) {}
|
||||
bool IsInitialized() const { return m_initialized; }
|
||||
bool LoadSymbolsFrom(void *lib_handle);
|
||||
|
||||
// Generate the EGL function pointers
|
||||
#define EGL_PTR_GEN(SYMBOL_NAME) PFN_egl##SYMBOL_NAME SYMBOL_NAME = NULL;
|
||||
EGL_SYMBOLS(EGL_PTR_GEN)
|
||||
#undef EGL_PTR_GEN
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
};
|
||||
@@ -23,44 +23,14 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "gl_replay.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include "serialise/rdcfile.h"
|
||||
#include "gl_driver.h"
|
||||
#include "gl_library_egl.h"
|
||||
#include "gl_resources.h"
|
||||
|
||||
typedef EGLBoolean (*PFN_eglBindAPI)(EGLenum api);
|
||||
typedef EGLDisplay (*PFN_eglGetDisplay)(EGLNativeDisplayType display_id);
|
||||
typedef EGLContext (*PFN_eglCreateContext)(EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_context, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (*PFN_eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
|
||||
EGLContext ctx);
|
||||
typedef EGLBoolean (*PFN_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (*PFN_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (*PFN_eglQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
|
||||
EGLint *value);
|
||||
typedef EGLBoolean (*PFN_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
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_eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef __eglMustCastToProperFunctionPointerType (*PFN_eglGetProcAddress)(const char *procname);
|
||||
typedef EGLBoolean (*PFN_eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
|
||||
PFN_eglBindAPI eglBindAPIProc = NULL;
|
||||
PFN_eglInitialize eglInitializeProc = NULL;
|
||||
PFN_eglGetDisplay eglGetDisplayProc = NULL;
|
||||
PFN_eglCreateContext eglCreateContextProc = NULL;
|
||||
PFN_eglMakeCurrent eglMakeCurrentProc = NULL;
|
||||
PFN_eglSwapBuffers eglSwapBuffersProc = NULL;
|
||||
PFN_eglDestroyContext eglDestroyContextProc = NULL;
|
||||
PFN_eglQuerySurface eglQuerySurfaceProc = NULL;
|
||||
PFN_eglDestroySurface eglDestroySurfaceProc = NULL;
|
||||
PFN_eglCreatePbufferSurface eglCreatePbufferSurfaceProc = NULL;
|
||||
PFN_eglCreateWindowSurface eglCreateWindowSurfaceProc = NULL;
|
||||
PFN_eglChooseConfig eglChooseConfigProc = NULL;
|
||||
PFN_eglGetProcAddress eglGetProcAddressProc = NULL;
|
||||
static EGLPointers egl;
|
||||
|
||||
const GLHookSet &GetRealGLFunctionsEGL();
|
||||
GLPlatform &GetGLPlatformEGL();
|
||||
@@ -69,30 +39,11 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
{
|
||||
RDCDEBUG("Creating an OpenGL ES replay device");
|
||||
|
||||
// Query the required EGL functions
|
||||
if(eglCreateContextProc == NULL)
|
||||
if(!egl.IsInitialized())
|
||||
{
|
||||
eglGetProcAddressProc = (PFN_eglGetProcAddress)dlsym(RTLD_NEXT, "eglGetProcAddress");
|
||||
eglChooseConfigProc = (PFN_eglChooseConfig)dlsym(RTLD_NEXT, "eglChooseConfig");
|
||||
eglInitializeProc = (PFN_eglInitialize)dlsym(RTLD_NEXT, "eglInitialize");
|
||||
eglBindAPIProc = (PFN_eglBindAPI)dlsym(RTLD_NEXT, "eglBindAPI");
|
||||
eglGetDisplayProc = (PFN_eglGetDisplay)dlsym(RTLD_NEXT, "eglGetDisplay");
|
||||
eglCreateContextProc = (PFN_eglCreateContext)dlsym(RTLD_NEXT, "eglCreateContext");
|
||||
eglMakeCurrentProc = (PFN_eglMakeCurrent)dlsym(RTLD_NEXT, "eglMakeCurrent");
|
||||
eglSwapBuffersProc = (PFN_eglSwapBuffers)dlsym(RTLD_NEXT, "eglSwapBuffers");
|
||||
eglDestroyContextProc = (PFN_eglDestroyContext)dlsym(RTLD_NEXT, "eglDestroyContext");
|
||||
eglDestroySurfaceProc = (PFN_eglDestroySurface)dlsym(RTLD_NEXT, "eglDestroySurface");
|
||||
eglQuerySurfaceProc = (PFN_eglQuerySurface)dlsym(RTLD_NEXT, "eglQuerySurface");
|
||||
eglCreatePbufferSurfaceProc =
|
||||
(PFN_eglCreatePbufferSurface)dlsym(RTLD_NEXT, "eglCreatePbufferSurface");
|
||||
eglCreateWindowSurfaceProc =
|
||||
(PFN_eglCreateWindowSurface)dlsym(RTLD_NEXT, "eglCreateWindowSurface");
|
||||
bool load_ok = egl.LoadSymbolsFrom(RTLD_NEXT);
|
||||
|
||||
if(eglGetProcAddressProc == NULL || eglBindAPIProc == NULL || eglGetDisplayProc == NULL ||
|
||||
eglCreateContextProc == NULL || eglMakeCurrentProc == NULL || eglSwapBuffersProc == NULL ||
|
||||
eglDestroyContextProc == NULL || eglDestroySurfaceProc == NULL ||
|
||||
eglQuerySurfaceProc == NULL || eglCreatePbufferSurfaceProc == NULL ||
|
||||
eglCreateWindowSurfaceProc == NULL || eglChooseConfigProc == NULL)
|
||||
if(!load_ok)
|
||||
{
|
||||
RDCERR(
|
||||
"Couldn't find required function addresses, eglGetProcAddress eglCreateContext"
|
||||
@@ -146,9 +97,9 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
initParams.isSRGB = 0;
|
||||
#endif
|
||||
|
||||
eglBindAPIProc(EGL_OPENGL_ES_API);
|
||||
egl.BindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
EGLDisplay eglDisplay = eglGetDisplayProc(EGL_DEFAULT_DISPLAY);
|
||||
EGLDisplay eglDisplay = egl.GetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(!eglDisplay)
|
||||
{
|
||||
RDCERR("Couldn't open default EGL display");
|
||||
@@ -156,7 +107,7 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
}
|
||||
|
||||
int major, minor;
|
||||
eglInitializeProc(eglDisplay, &major, &minor);
|
||||
egl.Initialize(eglDisplay, &major, &minor);
|
||||
|
||||
static const EGLint configAttribs[] = {EGL_RED_SIZE,
|
||||
8,
|
||||
@@ -172,7 +123,7 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
EGLint numConfigs;
|
||||
EGLConfig config;
|
||||
|
||||
if(!eglChooseConfigProc(eglDisplay, configAttribs, &config, 1, &numConfigs))
|
||||
if(!egl.ChooseConfig(eglDisplay, configAttribs, &config, 1, &numConfigs))
|
||||
{
|
||||
RDCERR("Couldn't find a suitable EGL config");
|
||||
return ReplayStatus::APIInitFailed;
|
||||
@@ -183,7 +134,7 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
|
||||
GLReplay::PreContextInitCounters();
|
||||
|
||||
EGLContext ctx = eglCreateContextProc(eglDisplay, config, EGL_NO_CONTEXT, ctxAttribs);
|
||||
EGLContext ctx = egl.CreateContext(eglDisplay, config, EGL_NO_CONTEXT, ctxAttribs);
|
||||
if(ctx == NULL)
|
||||
{
|
||||
GLReplay::PostContextShutdownCounters();
|
||||
@@ -192,22 +143,22 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
}
|
||||
|
||||
static const EGLint pbAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
|
||||
EGLSurface pbuffer = eglCreatePbufferSurfaceProc(eglDisplay, config, pbAttribs);
|
||||
EGLSurface pbuffer = egl.CreatePbufferSurface(eglDisplay, config, pbAttribs);
|
||||
|
||||
if(pbuffer == NULL)
|
||||
{
|
||||
RDCERR("Couldn't create a suitable PBuffer");
|
||||
eglDestroySurfaceProc(eglDisplay, pbuffer);
|
||||
egl.DestroySurface(eglDisplay, pbuffer);
|
||||
GLReplay::PostContextShutdownCounters();
|
||||
return ReplayStatus::APIInitFailed;
|
||||
}
|
||||
|
||||
EGLBoolean res = eglMakeCurrentProc(eglDisplay, pbuffer, pbuffer, ctx);
|
||||
EGLBoolean res = egl.MakeCurrent(eglDisplay, pbuffer, pbuffer, ctx);
|
||||
if(!res)
|
||||
{
|
||||
RDCERR("Couldn't active the created GL ES context");
|
||||
eglDestroySurfaceProc(eglDisplay, pbuffer);
|
||||
eglDestroyContextProc(eglDisplay, ctx);
|
||||
egl.DestroySurface(eglDisplay, pbuffer);
|
||||
egl.DestroyContext(eglDisplay, ctx);
|
||||
GLReplay::PostContextShutdownCounters();
|
||||
return ReplayStatus::APIInitFailed;
|
||||
}
|
||||
@@ -218,8 +169,8 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
|
||||
bool extensionsValidated = ValidateFunctionPointers(real);
|
||||
if(!extensionsValidated)
|
||||
{
|
||||
eglDestroySurfaceProc(eglDisplay, pbuffer);
|
||||
eglDestroyContextProc(eglDisplay, ctx);
|
||||
egl.DestroySurface(eglDisplay, pbuffer);
|
||||
egl.DestroyContext(eglDisplay, ctx);
|
||||
GLReplay::PostContextShutdownCounters();
|
||||
return ReplayStatus::APIHardwareUnsupported;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user