Skip to content

Commit

Permalink
allow gles+gles2 linking at the same time (v3)
Browse files Browse the repository at this point in the history
Compile both GLESv1 and GLESv2 hooks at the same time, load symbols
that intersect between GLESv1 and GLESv2 dynamically on GLESv2 side
from correct lib. There is still possibility to compile GLESv1 or
GLESv2-only version by modifying the makefile.

Osmos is linked to both libGLESv1_CM.so and libGLESv2.so and
uses symbols from both, so old GLES=x way was not enough.
  • Loading branch information
notaz committed Jun 14, 2013
1 parent b6f60c3 commit 8d624db
Show file tree
Hide file tree
Showing 15 changed files with 226 additions and 73 deletions.
22 changes: 19 additions & 3 deletions apkenv.c
Expand Up @@ -47,6 +47,7 @@
#include "apklib/keycodes.h"
#include "debug/debug.h"
#include "compat/gles_wrappers.h"
#include "compat/gles2_wrappers.h"
#include "linker/linker.h"
#include "compat/hooks.h"

Expand Down Expand Up @@ -365,7 +366,7 @@ operation(const char *operation, const char *filename)


static int
system_init()
system_init(int gles_version)
{
int i, j;

Expand All @@ -374,12 +375,13 @@ system_init()
return 0;
}

if ( !platform_init() ) {
if ( !platform_init(gles_version) ) {
printf("platform_init failed.\n");
return 0;
}

gles_extensions_init();
gles2_init();

SDL_ShowCursor(0);

Expand Down Expand Up @@ -635,7 +637,21 @@ int main(int argc, char **argv)
goto finish;
}

if (!system_init()) {
/* figure out GLES version to use */
int gles_version = 1;

if (global.loader_seen_glesv1 && global.loader_seen_glesv2) {
printf("Warning: app uses both GLESv1 and GLESv2 libs\n");
/* TODO: perhaps consult the module what to use here? */
} else if (global.loader_seen_glesv2) {
gles_version = 2;
}
#if !defined(APKENV_GLES)
gles_version = 2;
#endif
printf("Using GLES version %d\n", gles_version);

if (!system_init(gles_version)) {
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions apkenv.h
Expand Up @@ -116,6 +116,9 @@ struct GlobalState {

struct ResourceStrings resource_strings;

int loader_seen_glesv1;
int loader_seen_glesv2;

lookup_symbol_t lookup_symbol;
lookup_lib_symbol_t lookup_lib_symbol;
foreach_file_t foreach_file;
Expand Down
43 changes: 43 additions & 0 deletions compat/gl_types.h
@@ -0,0 +1,43 @@
#ifndef __apkenv_gl_types_h_
#define __apkenv_gl_types_h_

#include <GLES/glplatform.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
* This document is licensed under the SGI Free Software B License Version
* 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
*/

typedef void GLvoid;
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef unsigned int GLbitfield;
typedef khronos_int8_t GLbyte;
typedef short GLshort;
typedef int GLint;
typedef int GLsizei;
typedef khronos_uint8_t GLubyte;
typedef unsigned short GLushort;
typedef unsigned int GLuint;
typedef khronos_float_t GLfloat;
typedef khronos_float_t GLclampf;
typedef khronos_int32_t GLfixed;
typedef khronos_int32_t GLclampx;

typedef khronos_intptr_t GLintptr;
typedef khronos_ssize_t GLsizeiptr;

/* GL_OES_EGL_image */
#ifndef GL_OES_EGL_image
typedef void* GLeglImageOES;
#endif

#ifdef __cplusplus
}
#endif

#endif /* __apkenv_gl_types_h_ */
8 changes: 8 additions & 0 deletions compat/gles2_wrappers.c
@@ -1,6 +1,11 @@
#ifdef APKENV_GLES2
#include <GLES2/gl2.h>
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2ext.h>
#define IN_GLES2_WRAPPERS
#include "gles2_wrappers.h"
#include <assert.h>

#ifdef APKENV_DEBUG
# define WRAPPERS_DEBUG_PRINTF(...) printf("%d %s", pthread_self(), __VA_ARGS__)
#else
Expand Down Expand Up @@ -1012,12 +1017,14 @@ my_gles2_glMapBufferOES(GLenum target, GLenum access)
{
WRAPPERS_DEBUG_PRINTF("glMapBufferOES()\n", target, access);
/* No CALL */ printf("UNIMPLEMENTED: glMapBufferOES\n");
return NULL;
}
GLboolean
my_gles2_glUnmapBufferOES(GLenum target)
{
WRAPPERS_DEBUG_PRINTF("glUnmapBufferOES()\n", target);
/* No CALL */ printf("UNIMPLEMENTED: glUnmapBufferOES\n");
return GL_FALSE;
}
void
my_gles2_glGetBufferPointervOES(GLenum target, GLenum pname, void **params)
Expand Down Expand Up @@ -1090,6 +1097,7 @@ my_gles2_glGetTexStreamDeviceNameIMG(GLint device)
{
WRAPPERS_DEBUG_PRINTF("glGetTexStreamDeviceNameIMG()\n", device);
/* No CALL */ printf("UNIMPLEMENTED: glGetTexStreamDeviceNameIMG\n");
return NULL;
}
void
my_gles2_glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
Expand Down
8 changes: 4 additions & 4 deletions compat/gles2_wrappers.h
@@ -1,9 +1,9 @@
#ifdef APKENV_GLES2
#include <GLES2/gl2.h>
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2ext.h>

#include "../apkenv.h"
#ifndef IN_GLES2_WRAPPERS
#include "gl_types.h"
#endif

void
my_gles2_glActiveTexture(GLenum texture) SOFTFP;
void
Expand Down
5 changes: 5 additions & 0 deletions compat/gles_wrappers.c
@@ -1,7 +1,12 @@
#ifdef APKENV_GLES
#include <GLES/gl.h>
#define GL_GLEXT_PROTOTYPES
#include <GLES/glext.h>
#define IN_GLES_WRAPPERS
#include "gles_wrappers.h"
#include <assert.h>
#include <EGL/egl.h>

#ifdef APKENV_DEBUG
# define WRAPPERS_DEBUG_PRINTF(...) printf(__VA_ARGS__)
# define GL_TEST_ERROR if (glGetError()!=GL_NO_ERROR) { printf("GL ERROR near %s\n", __FUNCTION__); }
Expand Down
11 changes: 7 additions & 4 deletions compat/gles_wrappers.h
@@ -1,9 +1,9 @@
#ifdef APKENV_GLES
#include <GLES/gl.h>
#define GL_GLEXT_PROTOTYPES
#include <GLES/glext.h>

#include "../apkenv.h"
#ifndef IN_GLES_WRAPPERS
#include "gl_types.h"
#endif

void
my_glAlphaFunc(GLenum func, GLclampf ref) SOFTFP;
void
Expand Down Expand Up @@ -524,5 +524,8 @@ my_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, const
void
gles_extensions_init();

#else

#define gles_extensions_init()

#endif /* APKENV_GLES */
131 changes: 116 additions & 15 deletions compat/hooks.c
Expand Up @@ -43,26 +43,48 @@
#include "gles2_wrappers.h"
#include "pthread_wrappers.h"

extern struct GlobalState global;

char my___sF[SIZEOF_SF * 3];

static struct _hook hooks[] = {
#define HOOKS_MAX 1024

static struct _hook hooks[HOOKS_MAX] = {
#include "libc_mapping.h"
#include "liblog_mapping.h"
#include "egl_mapping.h"
#include "gles_mapping.h"
#include "gles2_mapping.h"
#include "pthread_mapping.h"

{"__sF", my___sF},
};
static int hooks_count;

#ifdef APKENV_GLES
static struct _hook hooks_gles1[] = {
#include "gles_mapping.h"
};
#define HOOKS_GLES1_COUNT (sizeof(hooks_gles1) / (HOOK_SIZE))
#endif

#ifdef APKENV_GLES2
static struct _hook hooks_gles2[] = {
#include "gles2_mapping.h"
};
#define HOOKS_GLES2_COUNT (sizeof(hooks_gles2) / (HOOK_SIZE))
#endif

/* fully wrapped or harmful libs that should not be loaded
* even if provided by user (like 3D driver libs) */
enum builtin_library_id {
BUILTIN_LIB_EGL = 0,
BUILTIN_LIB_GLESV1 = 1,
BUILTIN_LIB_GLESV2 = 2,
};

static const char *builtin_libs[] = {
"libEGL.so",
"libGLESv1_CM.so",
"libGLESv2.so",
[BUILTIN_LIB_EGL] = "libEGL.so",
[BUILTIN_LIB_GLESV1] = "libGLESv1_CM.so",
[BUILTIN_LIB_GLESV2] = "libGLESv2.so",
};

/* this is just to not log errors if those libs are missing */
Expand All @@ -83,15 +105,14 @@ hook_cmp(const void *p1, const void *p2)
}

#define HOOK_SIZE (sizeof(struct _hook))
#define HOOKS_COUNT (sizeof(hooks) / (HOOK_SIZE))

void *get_hooked_symbol(const char *sym)
{
struct _hook target;
target.name = sym;

struct _hook *result = bsearch(&target, &(hooks[0]),
HOOKS_COUNT, HOOK_SIZE, hook_cmp);
hooks_count, HOOK_SIZE, hook_cmp);

if (result != NULL) {
return result->func;
Expand All @@ -105,18 +126,85 @@ void *get_hooked_symbol(const char *sym)
return NULL;
}

int is_lib_builtin(const char *name)
void *get_hooked_symbol_dlfcn(void *handle, const char *sym)
{
struct _hook *result;
struct _hook target;
target.name = sym;

if (is_builtin_lib_handle(handle)) {
enum builtin_library_id builtin_lib_id = (const char **)handle - builtin_libs;
#ifdef APKENV_GLES
if (builtin_lib_id == BUILTIN_LIB_GLESV1) {
result = bsearch(&target, hooks_gles1, HOOKS_GLES1_COUNT,
HOOK_SIZE, hook_cmp);
if (result != NULL)
return result->func;
return NULL;
}
#endif
#ifdef APKENV_GLES2
if (builtin_lib_id == BUILTIN_LIB_GLESV2) {
result = bsearch(&target, hooks_gles2, HOOKS_GLES2_COUNT,
HOOK_SIZE, hook_cmp);
if (result != NULL)
return result->func;
return NULL;
}
#endif
}

return get_hooked_symbol(sym);
}

int register_hooks(const struct _hook *new_hooks, size_t count)
{
if (hooks_count + count > HOOKS_MAX) {
fprintf(stderr, "too many hooks (%d), increase HOOKS_MAX\n",
hooks_count + count);
return -1;
}

memcpy(&hooks[hooks_count], new_hooks, count * HOOK_SIZE);
hooks_count += count;
qsort(&hooks[0], hooks_count, HOOK_SIZE, hook_cmp);

return 0;
}

void *get_builtin_lib_handle(const char *libname)
{
size_t i;

if (name == NULL)
return 0;
if (libname == NULL)
return NULL;

if (strcmp(libname, "libGLESv1_CM.so") == 0) {
#ifdef APKENV_GLES
if (!global.loader_seen_glesv1)
register_hooks(hooks_gles1, HOOKS_GLES1_COUNT);
#endif
global.loader_seen_glesv1 = 1;
}
else if (strcmp(libname, "libGLESv2.so") == 0) {
#ifdef APKENV_GLES2
if (!global.loader_seen_glesv2)
register_hooks(hooks_gles2, HOOKS_GLES2_COUNT);
#endif
global.loader_seen_glesv2 = 1;
}

for (i = 0; i < sizeof(builtin_libs) / sizeof(builtin_libs[0]); i++)
if (strcmp(name, builtin_libs[i]) == 0)
return i + 1;
if (strcmp(libname, builtin_libs[i]) == 0)
return &builtin_libs[i];

return 0;
return NULL;
}

int is_builtin_lib_handle(void *handle)
{
char *p = handle;
return ((char *)builtin_libs <= p && p < (char *)builtin_libs + sizeof(builtin_libs));
}

int is_lib_optional(const char *name)
Expand All @@ -132,8 +220,21 @@ int is_lib_optional(const char *name)

void hooks_init(void)
{
int i;

for (i = 0; i < HOOKS_MAX; i++)
if (hooks[i].name == NULL)
break;
hooks_count = i;

/* Sort hooks so we can use binary search in get_hooked_symbol() */
qsort(&(hooks[0]), HOOKS_COUNT, HOOK_SIZE, hook_cmp);
qsort(&(hooks[0]), hooks_count, HOOK_SIZE, hook_cmp);
#ifdef APKENV_GLES
qsort(hooks_gles1, HOOKS_GLES1_COUNT, HOOK_SIZE, hook_cmp);
#endif
#ifdef APKENV_GLES2
qsort(hooks_gles2, HOOKS_GLES2_COUNT, HOOK_SIZE, hook_cmp);
#endif

libc_wrappers_init();
}
5 changes: 4 additions & 1 deletion compat/hooks.h
Expand Up @@ -38,7 +38,10 @@ struct _hook {
};

void *get_hooked_symbol(const char *sym);
int is_lib_builtin(const char *name);
void *get_hooked_symbol_dlfcn(void *handle, const char *sym);
void *get_builtin_lib_handle(const char *libname);
int is_builtin_lib_handle(void *handle);
int register_hooks(const struct _hook *hooks, size_t count);
int is_lib_optional(const char *name);
void hooks_init(void);

Expand Down

0 comments on commit 8d624db

Please sign in to comment.