#include "bothdefs.h" #if defined(GLQUAKE) && defined(USE_EGL) #include "gl_videgl.h" EGLContext eglctx = EGL_NO_CONTEXT; EGLDisplay egldpy = EGL_NO_DISPLAY; EGLSurface eglsurf = EGL_NO_SURFACE; static dllhandle_t egllibrary; static dllhandle_t eslibrary; static EGLint (*qeglGetError)(void); static EGLDisplay (*qeglGetDisplay)(EGLNativeDisplayType display_id); static EGLBoolean (*qeglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor); static EGLBoolean (*qeglTerminate)(EGLDisplay dpy); static EGLBoolean (*qeglGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); static EGLBoolean (*qeglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); static EGLSurface (*qeglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); static EGLBoolean (*qeglDestroySurface)(EGLDisplay dpy, EGLSurface surface); static EGLBoolean (*qeglQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); static EGLBoolean (*qeglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); static EGLBoolean (*qeglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); static EGLContext (*qeglCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); static EGLBoolean (*qeglDestroyContext)(EGLDisplay dpy, EGLContext ctx); static void *(*qeglGetProcAddress) (char *name); static dllfunction_t qeglfuncs[] = { {(void*)&qeglGetError, "eglGetError"}, {(void*)&qeglGetDisplay, "eglGetDisplay"}, {(void*)&qeglInitialize, "eglInitialize"}, {(void*)&qeglTerminate, "eglTerminate"}, {(void*)&qeglGetConfigs, "eglGetConfigs"}, {(void*)&qeglChooseConfig, "eglChooseConfig"}, {(void*)&qeglCreateWindowSurface, "eglCreateWindowSurface"}, {(void*)&qeglDestroySurface, "eglDestroySurface"}, {(void*)&qeglQuerySurface, "eglQuerySurface"}, {(void*)&qeglSwapBuffers, "eglSwapBuffers"}, {(void*)&qeglMakeCurrent, "eglMakeCurrent"}, {(void*)&qeglCreateContext, "eglCreateContext"}, {(void*)&qeglDestroyContext, "eglDestroyContext"}, {(void*)&qeglGetProcAddress, "eglGetProcAddress"}, {NULL} }; void *EGL_Proc(char *f) { void *proc = NULL; /* char fname[512]; { sprintf(fname, "wrap_%s", f); f = fname; } */ if (qeglGetProcAddress) proc = qeglGetProcAddress(f); if (!proc) proc = Sys_GetAddressForName(eslibrary, f); if (!proc) proc = Sys_GetAddressForName(egllibrary, f); return proc; } void EGL_UnloadLibrary(void) { if (egllibrary) Sys_CloseLibrary(egllibrary); if (egllibrary == eslibrary) eslibrary = NULL; if (eslibrary) Sys_CloseLibrary(eslibrary); eslibrary = egllibrary = NULL; } qboolean EGL_LoadLibrary(char *driver) { /* apps seem to load glesv2 first for dependency issues */ Sys_Printf("Attempting to dlopen libGLESv2... "); eslibrary = Sys_LoadLibrary("libGLESv2", NULL); if (!eslibrary) { Sys_Printf("failed\n"); // return false; } else Sys_Printf("success\n"); if (!eslibrary) { eslibrary = dlopen("libGL", RTLD_NOW|RTLD_GLOBAL); if (eslibrary) Sys_Printf("Loaded libGL\n"); } if (!eslibrary) { eslibrary = dlopen("libGL.so.1.2", RTLD_NOW|RTLD_GLOBAL); if (eslibrary) Sys_Printf("Loaded libGL.so.1.2\n"); } if (!eslibrary) { eslibrary = dlopen("libGL.so.1", RTLD_NOW|RTLD_GLOBAL); if (eslibrary) Sys_Printf("Loaded libGL.so.1\n"); } if (!eslibrary) Sys_Printf("unable to load some libGL\n"); Sys_Printf("Attempting to dlopen libEGL... "); egllibrary = Sys_LoadLibrary("libEGL", qeglfuncs); if (!egllibrary) { Sys_Printf("failed\n"); Con_Printf("libEGL library not loadable\n"); /* TODO: some implementations combine EGL/GLESv2 into single library... */ Sys_CloseLibrary(eslibrary); return false; } Sys_Printf("success\n"); return true; } void EGL_Shutdown(void) { if (eglctx == EGL_NO_CONTEXT) return; qeglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); qeglDestroyContext(egldpy, eglctx); if (eglsurf != EGL_NO_SURFACE) qeglDestroySurface(egldpy, eglsurf); qeglTerminate(egldpy); eglctx = EGL_NO_CONTEXT; egldpy = EGL_NO_DISPLAY; eglsurf = EGL_NO_SURFACE; } void EGL_BeginRendering (void) { } void EGL_EndRendering (void) { qeglSwapBuffers(egldpy, eglsurf); /* TODO: check result? */ } qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, EGLNativeWindowType window, EGLNativeDisplayType dpy) { EGLint numconfig; EGLConfig cfg; EGLint major, minor; EGLint attrib[] = { EGL_BUFFER_SIZE, info->bpp, EGL_SAMPLES, info->multisample, EGL_STENCIL_SIZE, 8, EGL_ALPHA_MASK_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; EGLint contextattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; /* if (!EGL_LoadLibrary("")) { Con_Printf(CON_ERROR "EGL: unable to load library!\n"); return false; } */ egldpy = qeglGetDisplay(dpy); if (egldpy == EGL_NO_DISPLAY) egldpy = qeglGetDisplay(EGL_DEFAULT_DISPLAY); if (egldpy == EGL_NO_DISPLAY) { Con_Printf(CON_ERROR "EGL: can't get display!\n"); return false; } //NOTE: mesa's egl really loves to crash on this call, and I define crash as 'anything that fails to return to caller', which fucks everything up. if (!qeglInitialize(egldpy, &major, &minor)) { Con_Printf(CON_ERROR "EGL: can't initialize display!\n"); return false; } /* if (!qeglGetConfigs(egldpy, NULL, 0, &numconfigs) || !numconfigs) { Con_Printf(CON_ERROR "EGL: can't get configs!\n"); return false; } */ if (!qeglChooseConfig(egldpy, attrib, &cfg, 1, &numconfig)) { Con_Printf(CON_ERROR "EGL: can't choose config!\n"); return false; } eglsurf = qeglCreateWindowSurface(egldpy, cfg, window, NULL); if (eglsurf == EGL_NO_SURFACE) { Con_Printf(CON_ERROR "EGL: no surface!\n"); return false; } eglctx = qeglCreateContext(egldpy, cfg, EGL_NO_SURFACE, contextattr); if (eglctx == EGL_NO_CONTEXT) { Con_Printf(CON_ERROR "EGL: no context!\n"); return false; } if (!qeglMakeCurrent(egldpy, eglsurf, eglsurf, eglctx)) { Con_Printf(CON_ERROR "EGL: can't make current!\n"); return false; } return true; } #endif