Files
MobileGL/tools/trace_replay/apitrace_glproc_mobilegl.cpp
T

153 lines
4.3 KiB
C++

#include "glproc.hpp"
#if defined(__has_include)
#if __has_include(<GLES3/gl3.h>)
#include <GLES3/gl3.h>
#elif __has_include(<GLES3/gl32.h>)
#include <GLES3/gl32.h>
#else
#error "OpenGL ES 3 headers are required"
#endif
#else
#include <GLES3/gl3.h>
#endif
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <dlfcn.h>
void *_libGlHandle = nullptr;
namespace {
void *LookupSymbol(const char *procName);
void *GetMobileGlHandle() {
if (_libGlHandle != nullptr) {
return _libGlHandle;
}
const char *library = std::getenv("MOBILEGL_TRACE_LIBRARY");
if (library != nullptr && library[0] != '\0') {
_libGlHandle = dlopen(library, RTLD_NOW | RTLD_GLOBAL | RTLD_NOLOAD);
if (_libGlHandle == nullptr) {
_libGlHandle = dlopen(library, RTLD_NOW | RTLD_GLOBAL);
}
}
if (_libGlHandle == nullptr) {
_libGlHandle = dlopen("libMobileGL.so", RTLD_NOW | RTLD_GLOBAL | RTLD_NOLOAD);
}
if (_libGlHandle == nullptr) {
_libGlHandle = dlopen("libMobileGL.so", RTLD_NOW | RTLD_GLOBAL);
}
return _libGlHandle;
}
using GlReadBuffer = void (*)(GLenum mode);
using GlReadPixels = void (*)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void *pixels);
using GlGetIntegerv = void (*)(GLenum pname, GLint *data);
using GlGetError = GLenum (*)();
GlReadBuffer gRealGlReadBuffer = nullptr;
GlReadPixels gRealGlReadPixels = nullptr;
GlGetIntegerv gRealGlGetIntegerv = nullptr;
GlGetError gRealGlGetError = nullptr;
int gSuppressInvalidEnumCount = 0;
void MobileGLTraceReadBuffer(GLenum mode) {
if (mode == GL_BACK) {
++gSuppressInvalidEnumCount;
return;
}
if (gRealGlReadBuffer == nullptr) {
gRealGlReadBuffer = reinterpret_cast<GlReadBuffer>(LookupSymbol("glReadBuffer"));
}
if (gRealGlReadBuffer != nullptr) {
gRealGlReadBuffer(mode);
}
}
void MobileGLTraceReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void *pixels) {
if (gRealGlReadPixels == nullptr) {
gRealGlReadPixels = reinterpret_cast<GlReadPixels>(LookupSymbol("glReadPixels"));
}
if (gRealGlReadPixels != nullptr) {
gRealGlReadPixels(x, y, width, height, format, type, pixels);
}
}
void MobileGLTraceGetIntegerv(GLenum pname, GLint *data) {
if (pname == GL_READ_BUFFER) {
if (data != nullptr) {
*data = GL_BACK;
}
++gSuppressInvalidEnumCount;
return;
}
if (gRealGlGetIntegerv == nullptr) {
gRealGlGetIntegerv = reinterpret_cast<GlGetIntegerv>(LookupSymbol("glGetIntegerv"));
}
if (gRealGlGetIntegerv != nullptr) {
gRealGlGetIntegerv(pname, data);
}
}
GLenum MobileGLTraceGetError() {
if (gRealGlGetError == nullptr) {
gRealGlGetError = reinterpret_cast<GlGetError>(LookupSymbol("glGetError"));
}
if (gRealGlGetError == nullptr) {
return GL_NO_ERROR;
}
GLenum error = gRealGlGetError();
if (error == GL_INVALID_ENUM && gSuppressInvalidEnumCount > 0) {
--gSuppressInvalidEnumCount;
return GL_NO_ERROR;
}
return error;
}
void *LookupSymbol(const char *procName) {
void *mobileGl = GetMobileGlHandle();
if (mobileGl != nullptr) {
void *proc = dlsym(mobileGl, procName);
if (proc != nullptr) {
return proc;
}
}
return dlsym(RTLD_DEFAULT, procName);
}
} // namespace
void *_getPublicProcAddress(const char *procName) {
if (strcmp(procName, "glReadPixels") == 0) {
return reinterpret_cast<void *>(&MobileGLTraceReadPixels);
}
if (strcmp(procName, "glReadBuffer") == 0) {
return reinterpret_cast<void *>(&MobileGLTraceReadBuffer);
}
if (strcmp(procName, "glGetIntegerv") == 0) {
return reinterpret_cast<void *>(&MobileGLTraceGetIntegerv);
}
if (strcmp(procName, "glGetError") == 0) {
return reinterpret_cast<void *>(&MobileGLTraceGetError);
}
return LookupSymbol(procName);
}
void *_getPrivateProcAddress(const char *procName) {
void *proc = LookupSymbol(procName);
if (proc != nullptr) {
return proc;
}
if (_eglGetProcAddress != nullptr) {
return reinterpret_cast<void *>(_eglGetProcAddress(procName));
}
return nullptr;
}