2013-03-12 22:49:04 +00:00
|
|
|
#include "bothdefs.h"
|
|
|
|
#if defined(GLQUAKE) && defined(USE_EGL)
|
2011-03-24 14:35:24 +00:00
|
|
|
#include "gl_videgl.h"
|
2011-02-06 20:56:39 +00:00
|
|
|
|
|
|
|
EGLContext eglctx = EGL_NO_CONTEXT;
|
|
|
|
EGLDisplay egldpy = EGL_NO_DISPLAY;
|
|
|
|
EGLSurface eglsurf = EGL_NO_SURFACE;
|
|
|
|
|
2011-05-30 21:48:32 +00:00
|
|
|
static dllhandle_t egllibrary;
|
|
|
|
static dllhandle_t eslibrary;
|
2011-02-06 20:56:39 +00:00
|
|
|
|
|
|
|
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"},
|
2011-05-30 21:48:32 +00:00
|
|
|
|
|
|
|
{(void*)&qeglGetDisplay, "eglGetDisplay"},
|
2011-02-06 20:56:39 +00:00
|
|
|
{(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}
|
|
|
|
};
|
2011-05-30 21:48:32 +00:00
|
|
|
|
2011-02-06 20:56:39 +00:00
|
|
|
|
|
|
|
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)
|
2011-05-30 21:48:32 +00:00
|
|
|
proc = Sys_GetAddressForName(eslibrary, f);
|
2011-02-06 20:56:39 +00:00
|
|
|
if (!proc)
|
2011-05-30 21:48:32 +00:00
|
|
|
proc = Sys_GetAddressForName(egllibrary, f);
|
2011-02-06 20:56:39 +00:00
|
|
|
|
|
|
|
return proc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EGL_UnloadLibrary(void)
|
|
|
|
{
|
|
|
|
if (egllibrary)
|
2011-05-30 21:48:32 +00:00
|
|
|
Sys_CloseLibrary(egllibrary);
|
2011-02-06 20:56:39 +00:00
|
|
|
if (egllibrary == eslibrary)
|
|
|
|
eslibrary = NULL;
|
|
|
|
if (eslibrary)
|
2011-05-30 21:48:32 +00:00
|
|
|
Sys_CloseLibrary(eslibrary);
|
2011-02-06 20:56:39 +00:00
|
|
|
eslibrary = egllibrary = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean EGL_LoadLibrary(char *driver)
|
|
|
|
{
|
2011-05-30 21:48:32 +00:00
|
|
|
/* apps seem to load glesv2 first for dependency issues */
|
2013-03-12 22:49:04 +00:00
|
|
|
Sys_Printf("Attempting to dlopen libGLESv2... ");
|
2011-05-30 21:48:32 +00:00
|
|
|
eslibrary = Sys_LoadLibrary("libGLESv2", NULL);
|
2011-02-06 20:56:39 +00:00
|
|
|
if (!eslibrary)
|
2013-03-12 22:49:04 +00:00
|
|
|
{
|
|
|
|
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");
|
2011-05-30 21:48:32 +00:00
|
|
|
|
2013-03-12 22:49:04 +00:00
|
|
|
Sys_Printf("Attempting to dlopen libEGL... ");
|
2011-05-30 21:48:32 +00:00
|
|
|
egllibrary = Sys_LoadLibrary("libEGL", qeglfuncs);
|
|
|
|
if (!egllibrary)
|
|
|
|
{
|
2013-03-12 22:49:04 +00:00
|
|
|
Sys_Printf("failed\n");
|
|
|
|
Con_Printf("libEGL library not loadable\n");
|
2011-05-30 21:48:32 +00:00
|
|
|
/* TODO: some implementations combine EGL/GLESv2 into single library... */
|
|
|
|
Sys_CloseLibrary(eslibrary);
|
2011-02-06 20:56:39 +00:00
|
|
|
return false;
|
2011-05-30 21:48:32 +00:00
|
|
|
}
|
2013-03-12 22:49:04 +00:00
|
|
|
Sys_Printf("success\n");
|
2011-02-06 20:56:39 +00:00
|
|
|
|
|
|
|
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? */
|
|
|
|
}
|
|
|
|
|
2013-03-12 22:49:04 +00:00
|
|
|
qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, EGLNativeWindowType window, EGLNativeDisplayType dpy)
|
2011-02-06 20:56:39 +00:00
|
|
|
{
|
|
|
|
EGLint numconfig;
|
|
|
|
EGLConfig cfg;
|
2013-03-12 22:49:04 +00:00
|
|
|
EGLint major, minor;
|
2011-02-06 20:56:39 +00:00
|
|
|
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
|
|
|
|
};
|
|
|
|
|
2013-03-12 22:49:04 +00:00
|
|
|
/* if (!EGL_LoadLibrary(""))
|
2011-02-06 20:56:39 +00:00
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: unable to load library!\n");
|
|
|
|
return false;
|
|
|
|
}
|
2013-03-12 22:49:04 +00:00
|
|
|
*/
|
|
|
|
egldpy = qeglGetDisplay(dpy);
|
2013-03-12 23:00:29 +00:00
|
|
|
if (egldpy == EGL_NO_DISPLAY)
|
|
|
|
egldpy = qeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
2011-02-06 20:56:39 +00:00
|
|
|
if (egldpy == EGL_NO_DISPLAY)
|
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: can't get display!\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-03-12 22:49:04 +00:00
|
|
|
//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))
|
2011-02-06 20:56:39 +00:00
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: can't initialize display!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (!qeglGetConfigs(egldpy, NULL, 0, &numconfigs) || !numconfigs)
|
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: can't get configs!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!qeglChooseConfig(egldpy, attrib, &cfg, 1, &numconfig))
|
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: can't choose config!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
eglsurf = qeglCreateWindowSurface(egldpy, cfg, window, NULL);
|
|
|
|
if (eglsurf == EGL_NO_SURFACE)
|
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: no surface!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
eglctx = qeglCreateContext(egldpy, cfg, EGL_NO_SURFACE, contextattr);
|
|
|
|
if (eglctx == EGL_NO_CONTEXT)
|
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: no context!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!qeglMakeCurrent(egldpy, eglsurf, eglsurf, eglctx))
|
|
|
|
{
|
|
|
|
Con_Printf(CON_ERROR "EGL: can't make current!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2013-03-12 22:49:04 +00:00
|
|
|
#endif
|
|
|
|
|