[Feat|Fix](...): Process EGL, GL_TEXTURE_LOD_BIAS. Add glUnmapBuffer, glMapBuffer. Process more GL functions.

This commit is contained in:
BZLZHH 2025-01-28 23:17:50 +08:00
parent b982f7c7c1
commit 6be9c4438d
17 changed files with 339 additions and 269 deletions

View File

@ -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

View File

@ -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");
}

View File

@ -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
View 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), &current_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
View 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
View 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
View 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

View File

@ -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);
//}

View File

@ -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)

View File

@ -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;
}

View File

@ -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")
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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_

View File

@ -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;
}

View File

@ -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

View File

@ -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);