[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:
Peter Gal
2017-11-13 18:56:29 +01:00
committed by Baldur Karlsson
parent 9c84b7f716
commit ca95a9c3ab
5 changed files with 221 additions and 202 deletions
+1
View File
@@ -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()
+60 -135
View File
@@ -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;
+53
View File
@@ -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;
}
+89
View File
@@ -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;
};
+18 -67
View File
@@ -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;
}