From 2902232811932201620f0f86a1e9402b75ca5d86 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 10 Jun 2009 13:54:13 +0000 Subject: [PATCH] Added missing files for OpenGL ES support --- src/video/x11/SDL_x11opengles.c | 366 ++++++++++++++++++++++++++++++++ src/video/x11/SDL_x11opengles.h | 95 +++++++++ 2 files changed, 461 insertions(+) create mode 100644 src/video/x11/SDL_x11opengles.c create mode 100644 src/video/x11/SDL_x11opengles.h diff --git a/src/video/x11/SDL_x11opengles.c b/src/video/x11/SDL_x11opengles.c new file mode 100644 index 000000000..6d4a8ba8c --- /dev/null +++ b/src/video/x11/SDL_x11opengles.c @@ -0,0 +1,366 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with _this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Open Pandora SDL driver + Copyright (C) 2009 David Carré + (cpasjuste@gmail.com) +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_OPENGL_ES + +#include "SDL_x11video.h" +#include "SDL_x11opengles.h" + +#define DEFAULT_OPENGL "/usr/lib/libGLES_CM.so" + +#define LOAD_FUNC(NAME) \ + *((void**)&_this->gles_data->NAME) = dlsym(handle, #NAME); \ + if (!_this->gles_data->NAME) \ + { \ + SDL_SetError("Could not retrieve EGL function " #NAME); \ + return -1; \ + } + +/* GLES implementation of SDL OpenGL support */ + +void * +X11_GLES_GetProcAddress(_THIS, const char *proc) +{ + static char procname[1024]; + void *handle; + void *retval; + + handle = _this->gl_config.dll_handle; + if (_this->gles_data->eglGetProcAddress) { + retval = _this->gles_data->eglGetProcAddress(proc); + if (retval) { + return retval; + } + } +#if defined(__OpenBSD__) && !defined(__ELF__) +#undef dlsym(x,y); +#endif + retval = dlsym(handle, proc); + if (!retval && strlen(proc) <= 1022) { + procname[0] = '_'; + strcpy(procname + 1, proc); + retval = dlsym(handle, procname); + } + return retval; +} + +void +X11_GLES_UnloadLibrary(_THIS) +{ + if (_this->gl_config.driver_loaded) { + _this->gles_data->eglTerminate(_this->gles_data->egl_display); + + dlclose(_this->gl_config.dll_handle); + + _this->gles_data->eglGetProcAddress = NULL; + _this->gles_data->eglChooseConfig = NULL; + _this->gles_data->eglCreateContext = NULL; + _this->gles_data->eglCreateWindowSurface = NULL; + _this->gles_data->eglDestroyContext = NULL; + _this->gles_data->eglDestroySurface = NULL; + _this->gles_data->eglMakeCurrent = NULL; + _this->gles_data->eglSwapBuffers = NULL; + _this->gles_data->eglGetDisplay = NULL; + _this->gles_data->eglTerminate = NULL; + + _this->gl_config.dll_handle = NULL; + _this->gl_config.driver_loaded = 0; + } +} + +int +X11_GLES_LoadLibrary(_THIS, const char *path) +{ + void *handle; + int dlopen_flags; + + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + if (_this->gles_data->egl_active) { + SDL_SetError("OpenGL ES context already created"); + return -1; + } +#ifdef RTLD_GLOBAL + dlopen_flags = RTLD_LAZY | RTLD_GLOBAL; +#else + dlopen_flags = RTLD_LAZY; +#endif + handle = dlopen(path, dlopen_flags); + /* Catch the case where the application isn't linked with EGL */ + if ((dlsym(handle, "eglChooseConfig") == NULL) && (path == NULL)) { + + dlclose(handle); + path = getenv("SDL_VIDEO_GL_DRIVER"); + if (path == NULL) { + path = DEFAULT_OPENGL; + } + handle = dlopen(path, dlopen_flags); + } + + if (handle == NULL) { + SDL_SetError("Could not load OpenGL ES/EGL library"); + return -1; + } + + /* Unload the old driver and reset the pointers */ + X11_GLES_UnloadLibrary(_this); + + /* Load new function pointers */ + LOAD_FUNC(eglGetDisplay); + LOAD_FUNC(eglInitialize); + LOAD_FUNC(eglTerminate); + LOAD_FUNC(eglGetProcAddress); + LOAD_FUNC(eglChooseConfig); + LOAD_FUNC(eglGetConfigAttrib); + LOAD_FUNC(eglCreateContext); + LOAD_FUNC(eglDestroyContext); + LOAD_FUNC(eglCreateWindowSurface); + LOAD_FUNC(eglDestroySurface); + LOAD_FUNC(eglMakeCurrent); + LOAD_FUNC(eglSwapBuffers); + + _this->gles_data->egl_display = + _this->gles_data->eglGetDisplay((NativeDisplayType) data->display); + + if (!_this->gles_data->egl_display) { + SDL_SetError("Could not get EGL display"); + return -1; + } + + if (_this->gles_data-> + eglInitialize(_this->gles_data->egl_display, NULL, + NULL) != EGL_TRUE) { + SDL_SetError("Could not initialize EGL"); + return -1; + } + + _this->gl_config.dll_handle = handle; + _this->gl_config.driver_loaded = 1; + + if (path) { + strncpy(_this->gl_config.driver_path, path, + sizeof(_this->gl_config.driver_path) - 1); + } else { + strcpy(_this->gl_config.driver_path, ""); + } + return 0; +} + +XVisualInfo * +X11_GLES_GetVisual(_THIS, Display * display, int screen) +{ + /* 64 seems nice. */ + EGLint attribs[64]; + EGLint found_configs = 0; + VisualID visual_id; + int i; + + /* load the gl driver from a default path */ + if (!_this->gl_config.driver_loaded) { + /* no driver has been loaded, use default (ourselves) */ + if (X11_GLES_LoadLibrary(_this, NULL) < 0) { + return NULL; + } + } + + i = 0; + attribs[i++] = EGL_RED_SIZE; + attribs[i++] = _this->gl_config.red_size; + attribs[i++] = EGL_GREEN_SIZE; + attribs[i++] = _this->gl_config.green_size; + attribs[i++] = EGL_BLUE_SIZE; + attribs[i++] = _this->gl_config.blue_size; + + if (_this->gl_config.alpha_size) { + attribs[i++] = EGL_ALPHA_SIZE; + attribs[i++] = _this->gl_config.alpha_size; + } + + if (_this->gl_config.buffer_size) { + attribs[i++] = EGL_BUFFER_SIZE; + attribs[i++] = _this->gl_config.buffer_size; + } + + attribs[i++] = EGL_DEPTH_SIZE; + attribs[i++] = _this->gl_config.depth_size; + + if (_this->gl_config.stencil_size) { + attribs[i++] = EGL_STENCIL_SIZE; + attribs[i++] = _this->gl_config.stencil_size; + } + + if (_this->gl_config.multisamplebuffers) { + attribs[i++] = EGL_SAMPLE_BUFFERS; + attribs[i++] = _this->gl_config.multisamplebuffers; + } + + if (_this->gl_config.multisamplesamples) { + attribs[i++] = EGL_SAMPLES; + attribs[i++] = _this->gl_config.multisamplesamples; + } + + attribs[i++] = EGL_NONE; + + if (_this->gles_data->eglChooseConfig(_this->gles_data->egl_display, + attribs, + &_this->gles_data->egl_config, 1, + &found_configs) == EGL_FALSE || + found_configs == 0) { + SDL_SetError("Couldn't find matching EGL config"); + return NULL; + } + + if (_this->gles_data->eglGetConfigAttrib(_this->gles_data->egl_display, + _this->gles_data->egl_config, + EGL_NATIVE_VISUAL_ID, + (EGLint *) & visual_id) == + EGL_FALSE || !visual_id) { + /* Use the default visual when all else fails */ + XVisualInfo vi_in; + int out_count; + vi_in.screen = screen; + + _this->gles_data->egl_visualinfo = XGetVisualInfo(display, + VisualScreenMask, + &vi_in, &out_count); + } else { + XVisualInfo vi_in; + int out_count; + + vi_in.screen = screen; + vi_in.visualid = visual_id; + _this->gles_data->egl_visualinfo = XGetVisualInfo(display, + VisualScreenMask | + VisualIDMask, + &vi_in, &out_count); + } + + return _this->gles_data->egl_visualinfo; +} + +SDL_GLContext +X11_GLES_CreateContext(_THIS, SDL_Window * window) +{ + int retval; + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + XSync(display, False); + + + _this->gles_data->egl_context = + _this->gles_data->eglCreateContext(_this->gles_data->egl_display, + _this->gles_data->egl_config, + EGL_NO_CONTEXT, NULL); + XSync(display, False); + + if (_this->gles_data->egl_context == EGL_NO_CONTEXT) { + SDL_SetError("Could not create EGL context"); + return NULL; + } + + _this->gles_data->egl_active = 1; + + if (_this->gles_data->egl_active) + retval = 1; + else + retval = 0; + + return (retval); +} + +int +X11_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) +{ + int retval; + + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + retval = 1; + if (!_this->gles_data->eglMakeCurrent(_this->gles_data->egl_display, + _this->gles_data->egl_surface, + _this->gles_data->egl_surface, + _this->gles_data->egl_context)) { + SDL_SetError("Unable to make EGL context current"); + retval = -1; + } + XSync(display, False); + + return (retval); +} + +static int swapinterval = -1; +int +X11_GLES_SetSwapInterval(_THIS, int interval) +{ + return 0; +} + +int +X11_GLES_GetSwapInterval(_THIS) +{ + return 0; +} + +void +X11_GLES_SwapWindow(_THIS, SDL_Window * window) +{ + _this->gles_data->eglSwapBuffers(_this->gles_data->egl_display, + _this->gles_data->egl_surface); +} + +void +X11_GLES_DeleteContext(_THIS, SDL_GLContext context) +{ + /* Clean up GLES and EGL */ + if (_this->gles_data->egl_context != EGL_NO_CONTEXT || + _this->gles_data->egl_surface != EGL_NO_SURFACE) { + _this->gles_data->eglMakeCurrent(_this->gles_data->egl_display, + EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + if (_this->gles_data->egl_context != EGL_NO_CONTEXT) { + _this->gles_data->eglDestroyContext(_this->gles_data->egl_display, + _this->gles_data-> + egl_context); + _this->gles_data->egl_context = EGL_NO_CONTEXT; + } + + if (_this->gles_data->egl_surface != EGL_NO_SURFACE) { + _this->gles_data->eglDestroySurface(_this->gles_data->egl_display, + _this->gles_data-> + egl_surface); + _this->gles_data->egl_surface = EGL_NO_SURFACE; + } + } + _this->gles_data->egl_active = 0; +} + +#endif /* SDL_VIDEO_OPENGL_ES */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/x11/SDL_x11opengles.h b/src/video/x11/SDL_x11opengles.h new file mode 100644 index 000000000..4667ce948 --- /dev/null +++ b/src/video/x11/SDL_x11opengles.h @@ -0,0 +1,95 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2004 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Open Pandora SDL driver + Copyright (C) 2009 David Carré + (cpasjuste@gmail.com) +*/ + +#include +#include +#include +#if defined(__OpenBSD__) && !defined(__ELF__) +#define dlsym(x,y) dlsym(x, "_" y) +#endif + +#include "../SDL_sysvideo.h" + +typedef struct SDL_PrivateGLESData +{ + int egl_active; /* to stop switching drivers while we have a valid context */ + XVisualInfo *egl_visualinfo; + EGLDisplay egl_display; + EGLContext egl_context; /* Current GLES context */ + EGLSurface egl_surface; + EGLConfig egl_config; + + EGLDisplay(*eglGetDisplay) (NativeDisplayType display); + EGLBoolean(*eglInitialize) (EGLDisplay dpy, EGLint * major, + EGLint * minor); + EGLBoolean(*eglTerminate) (EGLDisplay dpy); + + void *(*eglGetProcAddress) (const GLubyte * procName); + + EGLBoolean(*eglChooseConfig) (EGLDisplay dpy, + const EGLint * attrib_list, + EGLConfig * configs, + EGLint config_size, EGLint * num_config); + + EGLContext(*eglCreateContext) (EGLDisplay dpy, + EGLConfig config, + EGLContext share_list, + const EGLint * attrib_list); + + EGLBoolean(*eglDestroyContext) (EGLDisplay dpy, EGLContext ctx); + + EGLSurface(*eglCreateWindowSurface) (EGLDisplay dpy, + EGLConfig config, + NativeWindowType window, + const EGLint * attrib_list); + EGLBoolean(*eglDestroySurface) (EGLDisplay dpy, EGLSurface surface); + + EGLBoolean(*eglMakeCurrent) (EGLDisplay dpy, EGLSurface draw, + EGLSurface read, EGLContext ctx); + + EGLBoolean(*eglSwapBuffers) (EGLDisplay dpy, EGLSurface draw); + + const char *(*eglQueryString) (EGLDisplay dpy, EGLint name); + + EGLBoolean(*eglGetConfigAttrib) (EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint * value); + +} SDL_PrivateGLESData; + +/* OpenGLES functions */ +extern SDL_GLContext X11_GLES_CreateContext(_THIS, SDL_Window * window); +extern XVisualInfo *X11_GLES_GetVisual(_THIS, Display * display, int screen); +extern int X11_GLES_MakeCurrent(_THIS, SDL_Window * window, + SDL_GLContext context); +extern int X11_GLES_GetAttribute(_THIS, SDL_GLattr attrib, int *value); +extern int X11_GLES_LoadLibrary(_THIS, const char *path); +extern void *X11_GLES_GetProcAddress(_THIS, const char *proc); +extern void X11_GLES_UnloadLibrary(_THIS); + +extern int X11_GLES_SetSwapInterval(_THIS, int interval); +extern int X11_GLES_GetSwapInterval(_THIS); +extern void X11_GLES_SwapWindow(_THIS, SDL_Window * window); +extern void X11_GLES_DeleteContext(_THIS, SDL_GLContext context);