mirror of
https://github.com/MobileGL-Dev/MobileGlues.git
synced 2025-09-23 11:14:14 -04:00
[Feat|Fix](...): Process EGL, GL_TEXTURE_LOD_BIAS. Add glUnmapBuffer, glMapBuffer. Process more GL functions.
This commit is contained in:
parent
b982f7c7c1
commit
6be9c4438d
@ -28,6 +28,8 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
gl/shader.c
|
||||
gl/texture.c
|
||||
gl/mg.c
|
||||
gl/buffer.c
|
||||
gl/getter.c
|
||||
gl/glsl/glsl_for_es.cpp
|
||||
glx/lookup.c
|
||||
egl/egl.c
|
||||
|
@ -8,50 +8,41 @@
|
||||
#include "../includes.h"
|
||||
#include "../gl/log.h"
|
||||
#include "../gl/envvars.h"
|
||||
|
||||
#define LOAD_CORE_FUNC(handle, name) \
|
||||
g_egl_func.name = _mglues_dlsym(handle, #name); \
|
||||
if (!g_egl_func.name) { \
|
||||
LOG_F("Failed to load core function: %s", #name); \
|
||||
}
|
||||
#include "../gles/loader.h"
|
||||
|
||||
void init_target_egl() {
|
||||
LOG_V("Initializing %s @ %s", RENDERERNAME, __FUNCTION__);
|
||||
char* egl_name = GetEnvVar("LIBGL_EGL") ? GetEnvVar("LIBGL_EGL") : "libEGL.so";
|
||||
void* handle = _mglues_dlopen(egl_name);
|
||||
if (!handle) LOG_F("Cannot load system %s!", egl_name);
|
||||
|
||||
LOAD_CORE_FUNC(handle, eglGetProcAddress);
|
||||
LOAD_CORE_FUNC(handle, eglBindAPI);
|
||||
LOAD_CORE_FUNC(handle, eglInitialize);
|
||||
LOAD_CORE_FUNC(handle, eglGetDisplay);
|
||||
LOAD_CORE_FUNC(handle, eglCreatePbufferSurface);
|
||||
LOAD_CORE_FUNC(handle, eglDestroySurface);
|
||||
LOAD_CORE_FUNC(handle, eglDestroyContext);
|
||||
LOAD_CORE_FUNC(handle, eglMakeCurrent);
|
||||
LOAD_CORE_FUNC(handle, eglChooseConfig);
|
||||
LOAD_CORE_FUNC(handle, eglCreateContext);
|
||||
LOAD_CORE_FUNC(handle, eglQueryString);
|
||||
LOAD_CORE_FUNC(handle, eglTerminate);
|
||||
LOAD_CORE_FUNC(handle, eglGetError);
|
||||
|
||||
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
|
||||
EGLSurface eglSurface = EGL_NO_SURFACE;
|
||||
EGLContext eglContext = EGL_NO_CONTEXT;
|
||||
|
||||
eglDisplay = g_egl_func.eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
LOAD_EGL(eglGetProcAddress);
|
||||
LOAD_EGL(eglBindAPI);
|
||||
LOAD_EGL(eglInitialize);
|
||||
LOAD_EGL(eglGetDisplay);
|
||||
LOAD_EGL(eglCreatePbufferSurface);
|
||||
LOAD_EGL(eglDestroySurface);
|
||||
LOAD_EGL(eglDestroyContext);
|
||||
LOAD_EGL(eglMakeCurrent);
|
||||
LOAD_EGL(eglChooseConfig);
|
||||
LOAD_EGL(eglCreateContext);
|
||||
LOAD_EGL(eglQueryString);
|
||||
LOAD_EGL(eglTerminate);
|
||||
LOAD_EGL(eglGetError);
|
||||
|
||||
eglDisplay = egl_eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (eglDisplay == EGL_NO_DISPLAY) {
|
||||
LOG_E("eglGetDisplay failed (0x%x)", g_egl_func.eglGetError());
|
||||
LOG_E("eglGetDisplay failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (g_egl_func.eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE) {
|
||||
LOG_E("eglInitialize failed (0x%x)", g_egl_func.eglGetError());
|
||||
if (egl_eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE) {
|
||||
LOG_E("eglInitialize failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (g_egl_func.eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) {
|
||||
LOG_E("eglBindAPI failed (0x%x)", g_egl_func.eglGetError());
|
||||
if (egl_eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) {
|
||||
LOG_E("eglBindAPI failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -67,15 +58,15 @@ void init_target_egl() {
|
||||
|
||||
EGLConfig pbufConfig;
|
||||
EGLint configsFound = 0;
|
||||
if (g_egl_func.eglChooseConfig(eglDisplay, configAttribs, &pbufConfig, 1, &configsFound) != EGL_TRUE) {
|
||||
LOG_E("eglChooseConfig failed (0x%x)", g_egl_func.eglGetError());
|
||||
if (egl_eglChooseConfig(eglDisplay, configAttribs, &pbufConfig, 1, &configsFound) != EGL_TRUE) {
|
||||
LOG_E("eglChooseConfig failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (configsFound == 0) {
|
||||
configAttribs[6] = 0;
|
||||
if (g_egl_func.eglChooseConfig(eglDisplay, configAttribs, &pbufConfig, 1, &configsFound) != EGL_TRUE) {
|
||||
LOG_E("Retry eglChooseConfig failed (0x%x)", g_egl_func.eglGetError());
|
||||
if (egl_eglChooseConfig(eglDisplay, configAttribs, &pbufConfig, 1, &configsFound) != EGL_TRUE) {
|
||||
LOG_E("Retry eglChooseConfig failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
if (configsFound) {
|
||||
@ -87,21 +78,21 @@ void init_target_egl() {
|
||||
}
|
||||
|
||||
EGLint ctxAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
||||
eglContext = g_egl_func.eglCreateContext(eglDisplay, pbufConfig, EGL_NO_CONTEXT, ctxAttribs);
|
||||
eglContext = egl_eglCreateContext(eglDisplay, pbufConfig, EGL_NO_CONTEXT, ctxAttribs);
|
||||
if (eglContext == EGL_NO_CONTEXT) {
|
||||
LOG_E("eglCreateContext failed (0x%x)", g_egl_func.eglGetError());
|
||||
LOG_E("eglCreateContext failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
EGLint pbAttribs[] = { EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE };
|
||||
eglSurface = g_egl_func.eglCreatePbufferSurface(eglDisplay, pbufConfig, pbAttribs);
|
||||
eglSurface = egl_eglCreatePbufferSurface(eglDisplay, pbufConfig, pbAttribs);
|
||||
if (eglSurface == EGL_NO_SURFACE) {
|
||||
LOG_E("eglCreatePbufferSurface failed (0x%x)", g_egl_func.eglGetError());
|
||||
LOG_E("eglCreatePbufferSurface failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (g_egl_func.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE) {
|
||||
LOG_E("eglMakeCurrent failed (0x%x)", g_egl_func.eglGetError());
|
||||
if (egl_eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE) {
|
||||
LOG_E("eglMakeCurrent failed (0x%x)", egl_eglGetError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -110,13 +101,13 @@ void init_target_egl() {
|
||||
|
||||
cleanup:
|
||||
if (eglSurface != EGL_NO_SURFACE) {
|
||||
g_egl_func.eglDestroySurface(eglDisplay, eglSurface);
|
||||
egl_eglDestroySurface(eglDisplay, eglSurface);
|
||||
}
|
||||
if (eglContext != EGL_NO_CONTEXT) {
|
||||
g_egl_func.eglDestroyContext(eglDisplay, eglContext);
|
||||
egl_eglDestroyContext(eglDisplay, eglContext);
|
||||
}
|
||||
if (eglDisplay != EGL_NO_DISPLAY) {
|
||||
g_egl_func.eglTerminate(eglDisplay);
|
||||
egl_eglTerminate(eglDisplay);
|
||||
}
|
||||
LOG_E("EGL initialization failed");
|
||||
}
|
@ -7,6 +7,46 @@
|
||||
|
||||
#include "egl.h"
|
||||
|
||||
typedef EGLBoolean (*eglBindAPI_PTR)(EGLenum api);
|
||||
typedef EGLBoolean (*eglBindTexImage_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (*eglChooseConfig_PTR)(EGLDisplay dpy, const EGLint * attrib_list, EGLConfig * configs, EGLint config_size, EGLint * num_config);
|
||||
typedef EGLBoolean (*eglCopyBuffers_PTR)(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
|
||||
typedef EGLContext (*eglCreateContext_PTR)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint * attrib_list);
|
||||
typedef EGLSurface (*eglCreatePbufferFromClientBuffer_PTR)(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint * attrib_list);
|
||||
typedef EGLSurface (*eglCreatePbufferSurface_PTR)(EGLDisplay dpy, EGLConfig config, const EGLint * attrib_list);
|
||||
typedef EGLSurface (*eglCreatePixmapSurface_PTR)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint * attrib_list);
|
||||
typedef EGLSurface (*eglCreatePlatformWindowSurface_PTR)(EGLDisplay display, EGLConfig config, void * native_window, const EGLint * attrib_list);
|
||||
typedef EGLSurface (*eglCreateWindowSurface_PTR)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint * attrib_list);
|
||||
typedef EGLBoolean (*eglDestroyContext_PTR)(EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (*eglDestroySurface_PTR)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (*eglGetConfigAttrib_PTR)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint * value);
|
||||
typedef EGLBoolean (*eglGetConfigs_PTR)(EGLDisplay dpy, EGLConfig * configs, EGLint config_size, EGLint * num_config);
|
||||
typedef EGLContext (*eglGetCurrentContext_PTR)();
|
||||
typedef EGLDisplay (*eglGetCurrentDisplay_PTR)();
|
||||
typedef EGLSurface (*eglGetCurrentSurface_PTR)(EGLint readdraw);
|
||||
typedef EGLDisplay (*eglGetDisplay_PTR)(EGLNativeDisplayType display_id);
|
||||
typedef EGLDisplay (*eglGetPlatformDisplay_PTR)(EGLenum platform, void * native_display, const EGLint * attrib_list);
|
||||
typedef EGLint (*eglGetError_PTR)();
|
||||
typedef __eglMustCastToProperFunctionPointerType (*eglGetProcAddress_PTR)(const char * procname);
|
||||
typedef EGLBoolean (*eglInitialize_PTR)(EGLDisplay dpy, EGLint * major, EGLint * minor);
|
||||
typedef EGLBoolean (*eglMakeCurrent_PTR)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
typedef EGLenum (*eglQueryAPI_PTR)();
|
||||
typedef EGLBoolean (*eglQueryContext_PTR)(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint * value);
|
||||
typedef const char * (*eglQueryString_PTR)(EGLDisplay dpy, EGLint name);
|
||||
typedef EGLBoolean (*eglQuerySurface_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint * value);
|
||||
typedef EGLBoolean (*eglReleaseTexImage_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (*eglReleaseThread_PTR)();
|
||||
typedef EGLBoolean (*eglSurfaceAttrib_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
|
||||
typedef EGLBoolean (*eglSwapBuffers_PTR)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (*eglSwapBuffersWithDamageEXT_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint * rects, EGLint n_rects);
|
||||
typedef EGLBoolean (*eglSwapInterval_PTR)(EGLDisplay dpy, EGLint interval);
|
||||
typedef EGLBoolean (*eglTerminate_PTR)(EGLDisplay dpy);
|
||||
typedef EGLBoolean (*eglUnlockSurfaceKHR_PTR)(EGLDisplay display, EGLSurface surface);
|
||||
typedef EGLBoolean (*eglWaitClient_PTR)();
|
||||
typedef EGLBoolean (*eglWaitGL_PTR)();
|
||||
typedef EGLBoolean (*eglWaitNative_PTR)(EGLint engine);
|
||||
|
||||
/*
|
||||
struct egl_func_t {
|
||||
EGLGETPROCADDRESSPROCP eglGetProcAddress;
|
||||
EGLCREATECONTEXTPROCP eglCreateContext;
|
||||
@ -21,14 +61,13 @@ struct egl_func_t {
|
||||
EGLCREATEPBUFFERSURFACEPROCP eglCreatePbufferSurface;
|
||||
EGLDESTROYSURFACEPROCP eglDestroySurface;
|
||||
EGLGETERRORPROCP eglGetError;
|
||||
EGLCREATEWINDOWSURFACEPROCP eglCreateWindowSurface;
|
||||
};
|
||||
|
||||
|
||||
void init_target_egl();
|
||||
|
||||
EGLContext mglues_eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
EGLBoolean mglues_eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
|
||||
EGLBoolean mglues_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
*/
|
||||
|
||||
void init_target_egl();
|
||||
|
||||
#endif //FOLD_CRAFT_LAUNCHER_EGL_LOADER_H
|
||||
|
111
src/main/cpp/gl/buffer.c
Normal file
111
src/main/cpp/gl/buffer.c
Normal file
@ -0,0 +1,111 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/1/28.
|
||||
//
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
static GLenum get_binding_query(GLenum target) {
|
||||
switch(target) {
|
||||
case GL_ARRAY_BUFFER: return GL_ARRAY_BUFFER_BINDING;
|
||||
case GL_ELEMENT_ARRAY_BUFFER: return GL_ELEMENT_ARRAY_BUFFER_BINDING;
|
||||
case GL_PIXEL_PACK_BUFFER: return GL_PIXEL_PACK_BUFFER_BINDING;
|
||||
case GL_PIXEL_UNPACK_BUFFER: return GL_PIXEL_UNPACK_BUFFER_BINDING;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* glMapBuffer(GLenum target, GLenum access) {
|
||||
if (get_binding_query(target) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
GLint current_buffer;
|
||||
glGetIntegerv(get_binding_query(target), ¤t_buffer);
|
||||
if (current_buffer == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (g_active_mapping.mapped_ptr != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
GLint buffer_size;
|
||||
glGetBufferParameteriv(target, GL_BUFFER_SIZE, &buffer_size);
|
||||
if (buffer_size <= 0 || glGetError() != GL_NO_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
GLbitfield flags = 0;
|
||||
switch (access) {
|
||||
case GL_READ_ONLY: flags = GL_MAP_READ_BIT; break;
|
||||
case GL_WRITE_ONLY: flags = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT; break;
|
||||
case GL_READ_WRITE: flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
void* ptr = glMapBufferRange(target, 0, buffer_size, flags);
|
||||
if (!ptr) return NULL;
|
||||
g_active_mapping.target = target;
|
||||
g_active_mapping.buffer_id = (GLuint)current_buffer;
|
||||
g_active_mapping.mapped_ptr = ptr;
|
||||
g_active_mapping.size = buffer_size;
|
||||
g_active_mapping.flags = flags;
|
||||
g_active_mapping.is_dirty = (flags & GL_MAP_WRITE_BIT) ? GL_TRUE : GL_FALSE;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void force_unmap(GLenum target, GLuint original_buffer) {
|
||||
GLint prev_buffer;
|
||||
glGetIntegerv(get_binding_query(target), &prev_buffer);
|
||||
GLuint temp_buffer;
|
||||
glGenBuffers(1, &temp_buffer);
|
||||
glBindBuffer(target, temp_buffer);
|
||||
glBindBuffer(target, 0);
|
||||
glDeleteBuffers(1, &temp_buffer);
|
||||
if (target == GL_ARRAY_BUFFER) {
|
||||
GLint prev_element_array;
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prev_element_array);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prev_element_array);
|
||||
} else {
|
||||
GLint prev_array;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, prev_array);
|
||||
}
|
||||
glBindBuffer(target, original_buffer);
|
||||
}
|
||||
|
||||
GLboolean glUnmapBuffer(GLenum target) {
|
||||
if (g_active_mapping.mapped_ptr == NULL ||
|
||||
g_active_mapping.target != target ||
|
||||
g_active_mapping.buffer_id == 0)
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
GLint buffer_size;
|
||||
glGetBufferParameteriv(target, GL_BUFFER_SIZE, &buffer_size);
|
||||
if (glGetError() != GL_NO_ERROR || buffer_size <= 0) {
|
||||
memset(&g_active_mapping, 0, sizeof(BufferMapping));
|
||||
return GL_FALSE;
|
||||
}
|
||||
glBindBuffer(target, g_active_mapping.buffer_id);
|
||||
force_unmap(target, g_active_mapping.buffer_id);
|
||||
if (g_active_mapping.is_dirty) {
|
||||
GLuint temp_pbo;
|
||||
glGenBuffers(1, &temp_pbo);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, temp_pbo);
|
||||
glBufferData(GL_COPY_WRITE_BUFFER, g_active_mapping.size,
|
||||
g_active_mapping.mapped_ptr, GL_STREAM_COPY);
|
||||
glBindBuffer(target, g_active_mapping.buffer_id);
|
||||
GLint is_mapped;
|
||||
glGetBufferParameteriv(target, GL_BUFFER_MAPPED, &is_mapped);
|
||||
if (is_mapped) {
|
||||
glBufferData(target, g_active_mapping.size, NULL, GL_STATIC_DRAW);
|
||||
} else {
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, temp_pbo);
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, target, 0, 0, g_active_mapping.size);
|
||||
}
|
||||
|
||||
glDeleteBuffers(1, &temp_pbo);
|
||||
}
|
||||
memset(&g_active_mapping, 0, sizeof(BufferMapping));
|
||||
return GL_TRUE;
|
||||
}
|
34
src/main/cpp/gl/buffer.h
Normal file
34
src/main/cpp/gl/buffer.h
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/1/28.
|
||||
//
|
||||
|
||||
#ifndef MOBILEGLUES_BUFFER_H
|
||||
|
||||
#include "../includes.h"
|
||||
#include "gl.h"
|
||||
#include "glcorearb.h"
|
||||
#include "log.h"
|
||||
#include "loader.h"
|
||||
#include "../gles/loader.h"
|
||||
#include "mg.h"
|
||||
|
||||
typedef struct {
|
||||
GLenum target;
|
||||
GLuint buffer_id;
|
||||
void* mapped_ptr;
|
||||
GLsizeiptr size;
|
||||
GLbitfield flags;
|
||||
GLboolean is_dirty;
|
||||
} BufferMapping;
|
||||
|
||||
static BufferMapping g_active_mapping = {0};
|
||||
|
||||
static GLenum get_binding_query(GLenum target);
|
||||
static void force_unmap(GLenum target, GLuint original_buffer);
|
||||
|
||||
GLAPI GLAPIENTRY GLboolean glUnmapBuffer(GLenum target);
|
||||
GLAPI GLAPIENTRY void *glMapBuffer(GLenum target, GLenum access);
|
||||
|
||||
#define MOBILEGLUES_BUFFER_H
|
||||
|
||||
#endif //MOBILEGLUES_BUFFER_H
|
20
src/main/cpp/gl/getter.c
Normal file
20
src/main/cpp/gl/getter.c
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/1/28.
|
||||
//
|
||||
|
||||
#include "getter.h"
|
||||
|
||||
GLAPI GLAPIENTRY void glGetIntegerv(GLenum pname, GLint *params) {
|
||||
LOG();
|
||||
LOG_D("glGetIntegerv, pname: %d",pname);
|
||||
if (pname == GL_CONTEXT_PROFILE_MASK) {
|
||||
(*params) = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
|
||||
return;
|
||||
}
|
||||
LOAD_GLES(glGetIntegerv, void, GLenum pname, GLint *params);
|
||||
gles_glGetIntegerv(pname, params);
|
||||
LOAD_GLES(glGetError, GLenum)
|
||||
GLenum ERR = gles_glGetError();
|
||||
if (ERR != GL_NO_ERROR)
|
||||
LOG_E("ERROR: %d", ERR)
|
||||
}
|
16
src/main/cpp/gl/getter.h
Normal file
16
src/main/cpp/gl/getter.h
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/1/28.
|
||||
//
|
||||
|
||||
#include "../includes.h"
|
||||
#include "gl.h"
|
||||
#include "glcorearb.h"
|
||||
#include "log.h"
|
||||
#include "loader.h"
|
||||
#include "../gles/loader.h"
|
||||
#include "mg.h"
|
||||
|
||||
#ifndef MOBILEGLUES_GETTER_H
|
||||
#define MOBILEGLUES_GETTER_H
|
||||
|
||||
#endif //MOBILEGLUES_GETTER_H
|
@ -1,3 +1,7 @@
|
||||
//
|
||||
// Created by Swung0x48 on 2024/10/8.
|
||||
//
|
||||
|
||||
#include "../includes.h"
|
||||
#include "gl.h"
|
||||
#include "glcorearb.h"
|
||||
@ -6,176 +10,27 @@
|
||||
#include "../gles/loader.h"
|
||||
#include "mg.h"
|
||||
|
||||
void glClearError() {
|
||||
LOAD_GLES(glGetError, GLenum)
|
||||
GLenum err = gles_glGetError();
|
||||
while (err != GL_NO_ERROR) {
|
||||
err = gles_glGetError();
|
||||
}
|
||||
}
|
||||
|
||||
void glCheckError() {
|
||||
LOAD_GLES(glGetError, GLenum)
|
||||
GLenum err = gles_glGetError();
|
||||
while (err != GL_NO_ERROR) {
|
||||
err = gles_glGetError();
|
||||
LOG_E("GL ERROR: %d", err)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Miscellaneous
|
||||
*/
|
||||
|
||||
GLAPI GLAPIENTRY void glGetIntegerv(GLenum pname, GLint *params) {
|
||||
LOG();
|
||||
LOG_D("glGetIntegerv, pname: %d",pname);
|
||||
if (pname == GL_CONTEXT_PROFILE_MASK) {
|
||||
(*params) = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
|
||||
return;
|
||||
}
|
||||
LOAD_GLES(glGetIntegerv, void, GLenum pname, GLint *params);
|
||||
gles_glGetIntegerv(pname, params);
|
||||
LOAD_GLES(glGetError, GLenum)
|
||||
GLenum ERR = gles_glGetError();
|
||||
if (ERR != GL_NO_ERROR)
|
||||
LOG_E("ERROR: %d", ERR)
|
||||
}
|
||||
|
||||
GLAPI GLAPIENTRY GLenum glGetError() {
|
||||
LOG();
|
||||
LOAD_GLES(glGetError, GLenum);
|
||||
return gles_glGetError();
|
||||
LOG();
|
||||
LOAD_GLES(glGetError, GLenum);
|
||||
return gles_glGetError();
|
||||
}
|
||||
|
||||
GLAPI GLAPIENTRY const GLubyte * glGetString( GLenum name ) {
|
||||
LOG();
|
||||
switch (name) {
|
||||
case GL_VENDOR:
|
||||
return (const GLubyte *)"Swung0x48, BZLZHH";
|
||||
case GL_RENDERER:
|
||||
return (const GLubyte *)"2.1 MobileGlues";
|
||||
case GL_VERSION:
|
||||
return (const GLubyte *)"2.1.0";
|
||||
}
|
||||
return (const GLubyte *)"NotSupported_GLenum";
|
||||
LOG();
|
||||
switch (name) {
|
||||
case GL_VENDOR:
|
||||
return (const GLubyte *)"Swung0x48, BZLZHH";
|
||||
case GL_RENDERER:
|
||||
return (const GLubyte *)"2.1 MobileGlues";
|
||||
case GL_VERSION:
|
||||
return (const GLubyte *)"2.1.0";
|
||||
}
|
||||
return (const GLubyte *)"NotSupported_GLenum";
|
||||
}
|
||||
|
||||
/*
|
||||
* Depth Buffer
|
||||
*/
|
||||
|
||||
GLAPI GLAPIENTRY void glClearDepth(GLclampd depth) {
|
||||
LOG();
|
||||
glClearDepthf(depth);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
LOG();
|
||||
glClearDepthf(depth);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// OpenGL 3.1
|
||||
|
||||
GLAPI GLAPIENTRY GLenum glCheckFramebufferStatus(GLenum target) {
|
||||
LOG();
|
||||
LOAD_GLES(glCheckFramebufferStatus, GLenum, GLenum target);
|
||||
GLenum result = gles_glCheckFramebufferStatus(target);
|
||||
LOG_D("Result: %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GLAPI GLAPIENTRY void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
|
||||
LOG();
|
||||
LOG_D("glFramebufferTexture2D, target: %d, attachment: %d, textarget: %d, texture: %d, level: %d",target,attachment,textarget,texture,level);
|
||||
LOAD_GLES(glFramebufferTexture2D, void, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
gles_glFramebufferTexture2D(target,attachment,textarget,texture,level);
|
||||
LOAD_GLES(glGetError, GLenum)
|
||||
GLenum ERR = gles_glGetError();
|
||||
if (ERR != GL_NO_ERROR)
|
||||
LOG_E("ERROR: %d", ERR)
|
||||
}
|
||||
|
||||
|
||||
GLbitfield gl_to_es_access(GLenum access) {
|
||||
switch (access) {
|
||||
case GL_READ_ONLY:
|
||||
LOG_V("GL_READ_ONLY -> GL_MAP_READ_BIT");
|
||||
return GL_MAP_READ_BIT;
|
||||
case GL_WRITE_ONLY:
|
||||
LOG_V("GL_WRITE_ONLY -> GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT");
|
||||
return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
case GL_READ_WRITE:
|
||||
LOG_V("GL_READ_WRITE -> GL_MAP_READ_BIT | GL_MAP_WRITE_BIT");
|
||||
return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
|
||||
default:
|
||||
LOG_E("Invalid glMapBuffer access parameter: 0x%x!", access);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLAPI void *APIENTRY glMapBuffer (GLenum target, GLenum access) {
|
||||
LOG();
|
||||
LOAD_GLES(glGetBufferParameteriv,void, GLenum target, GLenum pname, GLint* params);
|
||||
LOAD_GLES(glMapBufferRange,void*, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||
|
||||
GLbitfield flags = gl_to_es_access(access);
|
||||
if (flags == 0) {
|
||||
flags = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
}
|
||||
|
||||
GLint buffer_size = 0;
|
||||
gles_glGetBufferParameteriv(target, GL_BUFFER_SIZE, &buffer_size);
|
||||
|
||||
void* ptr = gles_glMapBufferRange(target, 0, buffer_size, flags);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//NATIVE_FUNCTION_HEAD(void,glBufferData,GLenum target, GLsizeiptr size, const void* data, GLenum usage); NATIVE_FUNCTION_END_NO_RETURN(void,glBufferData,target,size,data,usage)
|
||||
|
||||
__attribute__((visibility("default")))void
|
||||
glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
|
||||
LOG_D("glBufferData(0x%x, %ld, 0x%lx, 0x%x)", target, size, data, usage);
|
||||
|
||||
typedef void(*glBufferData_PTR)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
glBufferData_PTR gles_glBufferData = ((void *) 0);
|
||||
__android_log_print(ANDROID_LOG_DEBUG, "MobileGlues", "Use native function: %s @ %s(...)",
|
||||
"MobileGlues", __func__);;
|
||||
{
|
||||
static _Bool first = 1;
|
||||
if (first) {
|
||||
first = 0;
|
||||
if (gles != ((void *) 0)) {
|
||||
gles_glBufferData = (glBufferData_PTR) proc_address(gles, "glBufferData");
|
||||
}
|
||||
if (gles_glBufferData == ((void *) 0)) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "MobileGlues",
|
||||
"%s line %d function %s: " "gles_glBufferData" " is NULL\n",
|
||||
"_file_name_", 112, "_function_name_");;
|
||||
};
|
||||
}
|
||||
};
|
||||
gles_glBufferData(target, size, data, usage);
|
||||
typedef GLenum(*glGetError_PTR)();
|
||||
glGetError_PTR gles_glGetError = ((void *) 0);
|
||||
{
|
||||
static _Bool first = 1;
|
||||
if (first) {
|
||||
first = 0;
|
||||
if (gles != ((void *) 0)) {
|
||||
gles_glGetError = (glGetError_PTR) proc_address(gles, "glGetError");
|
||||
}
|
||||
if (gles_glGetError == ((void *) 0)) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "MobileGlues",
|
||||
"%s line %d function %s: " "gles_glGetError" " is NULL\n",
|
||||
"_file_name_", 112, "_function_name_");;
|
||||
};
|
||||
}
|
||||
}
|
||||
GLenum ERR = gles_glGetError();
|
||||
if (ERR != 0)__android_log_print(ANDROID_LOG_ERROR, "MobileGlues", "ERROR: %d", ERR);
|
||||
|
||||
}
|
||||
|
||||
//GLAPI void APIENTRY glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
|
||||
// LOG();
|
||||
// LOAD_GLES(glBufferData, void, GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
// LOG_D("glBufferData(0x%x, %ld, 0x%lx, 0x%x)", target, size, data, usage);
|
||||
// gles_glBufferData(target, size, data, usage);
|
||||
//}
|
||||
|
@ -693,11 +693,11 @@ NATIVE_FUNCTION_HEAD(GLboolean, glIsFramebuffer,GLuint framebuffer) NATIVE_FUNCT
|
||||
NATIVE_FUNCTION_HEAD(void, glBindFramebuffer,GLenum target, GLuint framebuffer) NATIVE_FUNCTION_END_NO_RETURN(void,glBindFramebuffer,target,framebuffer)
|
||||
NATIVE_FUNCTION_HEAD(void, glDeleteFramebuffers,GLsizei n, const GLuint *framebuffers) NATIVE_FUNCTION_END_NO_RETURN(void,glDeleteFramebuffers,n,framebuffers)
|
||||
NATIVE_FUNCTION_HEAD(void, glGenFramebuffers,GLsizei n, GLuint *framebuffers) NATIVE_FUNCTION_END_NO_RETURN(void,glGenFramebuffers,n,framebuffers)
|
||||
//NATIVE_FUNCTION_HEAD(GLenum, glCheckFramebufferStatus,GLenum target) NATIVE_FUNCTION_END(GLenum,glCheckFramebufferStatus,target)
|
||||
NATIVE_FUNCTION_HEAD(GLenum, glCheckFramebufferStatus,GLenum target) NATIVE_FUNCTION_END(GLenum,glCheckFramebufferStatus,target)
|
||||
|
||||
|
||||
NATIVE_FUNCTION_HEAD(void, glFramebufferTexture1D,GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) NATIVE_FUNCTION_END_NO_RETURN(void,glFramebufferTexture1D,target,attachment,textarget,texture,level)
|
||||
//NATIVE_FUNCTION_HEAD(void, glFramebufferTexture2D,GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) NATIVE_FUNCTION_END_NO_RETURN(void,glFramebufferTexture2D,target,attachment,textarget,texture,level)
|
||||
NATIVE_FUNCTION_HEAD(void, glFramebufferTexture2D,GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) NATIVE_FUNCTION_END_NO_RETURN(void,glFramebufferTexture2D,target,attachment,textarget,texture,level)
|
||||
|
||||
NATIVE_FUNCTION_HEAD(void, glFramebufferTexture3D,GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) NATIVE_FUNCTION_END_NO_RETURN(void,glFramebufferTexture3D,target,attachment,textarget,texture,level,zoffset)
|
||||
NATIVE_FUNCTION_HEAD(void, glFramebufferRenderbuffer,GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) NATIVE_FUNCTION_END_NO_RETURN(void,glFramebufferRenderbuffer,target,attachment,renderbuffertarget,renderbuffer)
|
||||
|
@ -9,9 +9,7 @@ gl_state_t gl_state;
|
||||
|
||||
GLenum pname_convert(GLenum pname){
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
LOG_D("pnameConvert: GL_TEXTURE_LOD_BIAS -> GL_TEXTURE_LOD_BIAS_QCOM");
|
||||
return GL_TEXTURE_LOD_BIAS_QCOM;
|
||||
//useless now
|
||||
}
|
||||
return pname;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "glsl/glsl_for_es.h"
|
||||
|
||||
bool can_run_essl3(int esversion, const char *glsl) {
|
||||
int glsl_version = 0;
|
||||
int glsl_version;
|
||||
|
||||
if (strncmp(glsl, "#version 100", 12) == 0) {
|
||||
return true;
|
||||
@ -63,9 +63,11 @@ void glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, c
|
||||
}
|
||||
LOAD_GLES2(glShaderSource, void, GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
if (gles_glShaderSource) {
|
||||
if(is_direct_shader(source))
|
||||
if(is_direct_shader(source)){
|
||||
LOG_D("[INFO] [Shader] Direct shader source: ");
|
||||
LOG_D("%s", source);
|
||||
converted = strdup(source);
|
||||
else{
|
||||
} else {
|
||||
int glsl_version = getGLSLVersion(source);
|
||||
LOG_D("[INFO] [Shader] Shader source: ");
|
||||
LOG_D("%s", source);
|
||||
@ -75,13 +77,14 @@ void glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, c
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
converted = GLSLtoGLSLES(source, shaderType, 320);
|
||||
}
|
||||
LOG_D("\n[INFO] [Shader] Converted Shader source: \n%s", converted);
|
||||
}
|
||||
|
||||
gles_glShaderSource(shader, count, (const GLchar * const*)((converted)?(&converted):(&source)), length);
|
||||
gles_glShaderSource(shader, count, (const GLchar * const*)&converted, length);
|
||||
} else {
|
||||
LOG_E("No gles_glShaderSource")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,11 +40,9 @@ GLenum internal_convert(GLenum internal_format, GLenum type) {
|
||||
|
||||
void glTexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
||||
LOG();
|
||||
if (pname == GL_TEXTURE_LOD_BIAS && -1e-6 < param && param < 1e-6) {
|
||||
LOG_D("glTexParameterf: GL_TEXTURE_LOD_BIAS = 0");
|
||||
pname = pname_convert(pname);
|
||||
if(pname == GL_TEXTURE_LOD_BIAS)
|
||||
return;
|
||||
}
|
||||
// pname = pname_convert(pname);
|
||||
LOG_D("glTexParameterf, target: %d, pname: %d, param: %f",target, pname, param);
|
||||
LOAD_GLES(glTexParameterf, void, GLenum target, GLenum pname, GLfloat param);
|
||||
gles_glTexParameterf(target,pname, param);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "../gl/envvars.h"
|
||||
#include "../gl/log.h"
|
||||
#include "../gl/mg.h"
|
||||
#include "../gl/buffer.h"
|
||||
|
||||
void *gles = NULL, *egl = NULL;
|
||||
|
||||
@ -42,6 +43,14 @@ static const char *gles3_lib[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *egl_lib[] = {
|
||||
#if defined(BCMHOST)
|
||||
"libbrcmEGL",
|
||||
#endif
|
||||
"libEGL",
|
||||
NULL
|
||||
};
|
||||
|
||||
void *open_lib(const char **names, const char *override) {
|
||||
void *lib = NULL;
|
||||
|
||||
@ -74,14 +83,14 @@ void load_libs() {
|
||||
if (! first) return;
|
||||
first = 0;
|
||||
const char *gles_override = GetEnvVar("LIBGL_GLES");
|
||||
const char *egl_override = GetEnvVar("LIBGL_EGL");
|
||||
gles = open_lib(gles3_lib, gles_override);
|
||||
egl = open_lib(egl_lib, egl_override);
|
||||
}
|
||||
|
||||
void *(*gles_getProcAddress)(const char *name);
|
||||
|
||||
void *proc_address(void *lib, const char *name) {
|
||||
if (gles_getProcAddress)
|
||||
return gles_getProcAddress(name);
|
||||
return dlsym(lib, name);
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern void *(*gles_getProcAddress)(const char *name);
|
||||
|
||||
void *proc_address(void *lib, const char *name);
|
||||
|
||||
extern void *gles, *egl;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -27,27 +26,13 @@ void init_target_gles();
|
||||
|
||||
#define WARN_NULL(name) if (name == NULL) { LOG_W("%s line %d function %s: " #name " is NULL\n", __FILE__, __LINE__, __func__); }
|
||||
|
||||
#define PUSH_IF_COMPILING_EXT(nam, ...) \
|
||||
if (glstate->list.active) { \
|
||||
if (!glstate->list.pending) { \
|
||||
NewStage(glstate->list.active, STAGE_GLCALL); \
|
||||
push_##nam(__VA_ARGS__); \
|
||||
noerrorShim(); \
|
||||
return (nam##_RETURN)0; \
|
||||
} \
|
||||
else gl4es_flush(); \
|
||||
}
|
||||
|
||||
void *open_lib(const char **names, const char *override);
|
||||
#define LOAD_RAW_GLES(name, type, ...) \
|
||||
{ \
|
||||
static bool first = true; \
|
||||
if (first) { \
|
||||
first = false; \
|
||||
if (gles != NULL) { \
|
||||
gles_##name = (name##_PTR)proc_address(gles, #name); \
|
||||
} \
|
||||
WARN_NULL(gles_##name); \
|
||||
if (gles != NULL) { \
|
||||
gles_##name = (name##_PTR)proc_address(gles, #name); \
|
||||
} \
|
||||
WARN_NULL(gles_##name); \
|
||||
}
|
||||
|
||||
#define LOAD_LIB(type, name, ...) \
|
||||
@ -58,15 +43,19 @@ void init_target_gles();
|
||||
#define LOAD_GLES(name,type, ...) LOAD_LIB(type, name, __VA_ARGS__)
|
||||
#define LOAD_GLES2(name,type, ...) LOAD_LIB(type, name, __VA_ARGS__)
|
||||
#define LOAD_GLES3(name,type, ...) LOAD_LIB(type, name, __VA_ARGS__)
|
||||
#define LOAD_EGL(name) \
|
||||
static name##_PTR egl_##name = NULL; \
|
||||
{ \
|
||||
static bool first = true; \
|
||||
if (first) { \
|
||||
first = false; \
|
||||
if (egl != NULL) { \
|
||||
egl_##name = (name##_PTR)proc_address(egl, #name); \
|
||||
} \
|
||||
WARN_NULL(egl_##name); \
|
||||
} \
|
||||
}
|
||||
|
||||
void glClearError();
|
||||
void glCheckError();
|
||||
|
||||
#define GL_CHECKERROR(stmt) do { \
|
||||
glClearError(); \
|
||||
stmt; \
|
||||
glCheckError(); \
|
||||
} while (0)
|
||||
|
||||
#define NATIVE_FUNCTION_HEAD(type,name,...) \
|
||||
GLAPI GLAPIENTRY type name(__VA_ARGS__) { \
|
||||
@ -89,6 +78,4 @@ GLAPI GLAPIENTRY type name(__VA_ARGS__) { \
|
||||
LOG_E("ERROR: %d", ERR) \
|
||||
}
|
||||
|
||||
#define LOAD_EGL(name) LOAD_LIB(egl, name)
|
||||
|
||||
#endif // _MOBILEGLUES_LOADER_H_
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Created by BZLZHH on 2025/1/27.
|
||||
//
|
||||
|
||||
#include "lookup.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <EGL/egl.h>
|
||||
@ -21,3 +23,15 @@ void *glXGetProcAddress(const char *name) {
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
void *glXGetProcAddressARB(const char *name) {
|
||||
void* proc = dlsym(RTLD_DEFAULT, (const char*)name);
|
||||
|
||||
if (!proc) {
|
||||
fprintf(stderr, "Failed to get OpenGL function %s: %s\n", name, dlerror());
|
||||
LOG_W("Failed to get OpenGL function: %s", (const char*)name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return proc;
|
||||
}
|
@ -6,5 +6,6 @@
|
||||
#define MOBILEGLUES_LOOKUP_H
|
||||
|
||||
void *glXGetProcAddress(const char *name) __attribute__((visibility("default")));
|
||||
void *glXGetProcAddressARB(const char *name) __attribute__((visibility("default")));
|
||||
|
||||
#endif //MOBILEGLUES_LOOKUP_H
|
||||
|
@ -14,15 +14,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct egl_func_t g_egl_func;
|
||||
|
||||
__eglMustCastToProperFunctionPointerType prehook(const char *procname);
|
||||
__eglMustCastToProperFunctionPointerType posthook(const char *procname);
|
||||
|
||||
void proc_init() {
|
||||
LOG_V("Initializing %s @ %s", RENDERERNAME, __FUNCTION__);
|
||||
init_target_egl();
|
||||
init_target_gles();
|
||||
init_target_egl();
|
||||
|
||||
g_initialized = 1;
|
||||
}
|
||||
@ -493,12 +491,6 @@ __eglMustCastToProperFunctionPointerType posthook(const char *procname) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY glXGetProcAddress (const char *procname) {
|
||||
// __android_log_print(ANDROID_LOG_VERBOSE, RENDERERNAME,
|
||||
// "%s @ %s(%s)", RENDERERNAME, __FUNCTION__, procname);
|
||||
// return eglGetProcAddress(procname);
|
||||
//}
|
||||
|
||||
EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, RENDERERNAME,
|
||||
"%s @ %s(%s)", RENDERERNAME, __FUNCTION__, procname);
|
||||
|
Loading…
x
Reference in New Issue
Block a user