src/video/x11/SDL_x11opengles.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Aug 2009 18:39:57 +0000
changeset 3227 458e53d8662c
parent 3218 81773a1eac83
child 3361 d559edc85610
permissions -rw-r--r--
Clarified API documentation
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with _this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 
    22     Open Pandora SDL driver
    23     Copyright (C) 2009 David Carré
    24     (cpasjuste@gmail.com)
    25 */
    26 #include "SDL_config.h"
    27 
    28 #if SDL_VIDEO_OPENGL_ES
    29 
    30 #include "SDL_x11video.h"
    31 #include "SDL_x11opengles.h"
    32 
    33 #define DEFAULT_OPENGL	"/usr/lib/libGLES_CM.so"
    34 
    35 #define LOAD_FUNC(NAME) \
    36 	*((void**)&_this->gles_data->NAME) = dlsym(handle, #NAME); \
    37 	if (!_this->gles_data->NAME) \
    38 	{ \
    39 		SDL_SetError("Could not retrieve EGL function " #NAME); \
    40 		return -1; \
    41 	}
    42 
    43 /* GLES implementation of SDL OpenGL support */
    44 
    45 void *
    46 X11_GLES_GetProcAddress(_THIS, const char *proc)
    47 {
    48     static char procname[1024];
    49     void *handle;
    50     void *retval;
    51 
    52     handle = _this->gl_config.dll_handle;
    53     if (_this->gles_data->eglGetProcAddress) {
    54         retval = _this->gles_data->eglGetProcAddress(proc);
    55         if (retval) {
    56             return retval;
    57         }
    58     }
    59 #if defined(__OpenBSD__) && !defined(__ELF__)
    60 #undef dlsym(x,y);
    61 #endif
    62     retval = dlsym(handle, proc);
    63     if (!retval && strlen(proc) <= 1022) {
    64         procname[0] = '_';
    65         strcpy(procname + 1, proc);
    66         retval = dlsym(handle, procname);
    67     }
    68     return retval;
    69 }
    70 
    71 void
    72 X11_GLES_UnloadLibrary(_THIS)
    73 {
    74     if (_this->gl_config.driver_loaded) {
    75         _this->gles_data->eglTerminate(_this->gles_data->egl_display);
    76 
    77         dlclose(_this->gl_config.dll_handle);
    78 
    79         _this->gles_data->eglGetProcAddress = NULL;
    80         _this->gles_data->eglChooseConfig = NULL;
    81         _this->gles_data->eglCreateContext = NULL;
    82         _this->gles_data->eglCreateWindowSurface = NULL;
    83         _this->gles_data->eglDestroyContext = NULL;
    84         _this->gles_data->eglDestroySurface = NULL;
    85         _this->gles_data->eglMakeCurrent = NULL;
    86         _this->gles_data->eglSwapBuffers = NULL;
    87         _this->gles_data->eglGetDisplay = NULL;
    88         _this->gles_data->eglTerminate = NULL;
    89 
    90         _this->gl_config.dll_handle = NULL;
    91         _this->gl_config.driver_loaded = 0;
    92     }
    93 }
    94 
    95 int
    96 X11_GLES_LoadLibrary(_THIS, const char *path)
    97 {
    98     void *handle;
    99     int dlopen_flags;
   100 
   101     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   102 
   103     if (_this->gles_data->egl_active) {
   104         SDL_SetError("OpenGL ES context already created");
   105         return -1;
   106     }
   107 #ifdef RTLD_GLOBAL
   108     dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
   109 #else
   110     dlopen_flags = RTLD_LAZY;
   111 #endif
   112     handle = dlopen(path, dlopen_flags);
   113     /* Catch the case where the application isn't linked with EGL */
   114     if ((dlsym(handle, "eglChooseConfig") == NULL) && (path == NULL)) {
   115 
   116         dlclose(handle);
   117         path = getenv("SDL_VIDEO_GL_DRIVER");
   118         if (path == NULL) {
   119             path = DEFAULT_OPENGL;
   120         }
   121         handle = dlopen(path, dlopen_flags);
   122     }
   123 
   124     if (handle == NULL) {
   125         SDL_SetError("Could not load OpenGL ES/EGL library");
   126         return -1;
   127     }
   128 
   129     /* Unload the old driver and reset the pointers */
   130     X11_GLES_UnloadLibrary(_this);
   131 
   132     /* Load new function pointers */
   133     LOAD_FUNC(eglGetDisplay);
   134     LOAD_FUNC(eglInitialize);
   135     LOAD_FUNC(eglTerminate);
   136     LOAD_FUNC(eglGetProcAddress);
   137     LOAD_FUNC(eglChooseConfig);
   138     LOAD_FUNC(eglGetConfigAttrib);
   139     LOAD_FUNC(eglCreateContext);
   140     LOAD_FUNC(eglDestroyContext);
   141     LOAD_FUNC(eglCreateWindowSurface);
   142     LOAD_FUNC(eglDestroySurface);
   143     LOAD_FUNC(eglMakeCurrent);
   144     LOAD_FUNC(eglSwapBuffers);
   145 
   146     _this->gles_data->egl_display =
   147         _this->gles_data->eglGetDisplay((NativeDisplayType) data->display);
   148 
   149     if (!_this->gles_data->egl_display) {
   150         SDL_SetError("Could not get EGL display");
   151         return -1;
   152     }
   153 
   154     if (_this->gles_data->
   155         eglInitialize(_this->gles_data->egl_display, NULL,
   156                       NULL) != EGL_TRUE) {
   157         SDL_SetError("Could not initialize EGL");
   158         return -1;
   159     }
   160 
   161     _this->gl_config.dll_handle = handle;
   162     _this->gl_config.driver_loaded = 1;
   163 
   164     if (path) {
   165         strncpy(_this->gl_config.driver_path, path,
   166                 sizeof(_this->gl_config.driver_path) - 1);
   167     } else {
   168         strcpy(_this->gl_config.driver_path, "");
   169     }
   170     return 0;
   171 }
   172 
   173 XVisualInfo *
   174 X11_GLES_GetVisual(_THIS, Display * display, int screen)
   175 {
   176     /* 64 seems nice. */
   177     EGLint attribs[64];
   178     EGLint found_configs = 0;
   179     VisualID visual_id;
   180     int i;
   181 
   182     /* load the gl driver from a default path */
   183     if (!_this->gl_config.driver_loaded) {
   184         /* no driver has been loaded, use default (ourselves) */
   185         if (X11_GLES_LoadLibrary(_this, NULL) < 0) {
   186             return NULL;
   187         }
   188     }
   189 
   190     i = 0;
   191     attribs[i++] = EGL_RED_SIZE;
   192     attribs[i++] = _this->gl_config.red_size;
   193     attribs[i++] = EGL_GREEN_SIZE;
   194     attribs[i++] = _this->gl_config.green_size;
   195     attribs[i++] = EGL_BLUE_SIZE;
   196     attribs[i++] = _this->gl_config.blue_size;
   197 
   198     if (_this->gl_config.alpha_size) {
   199         attribs[i++] = EGL_ALPHA_SIZE;
   200         attribs[i++] = _this->gl_config.alpha_size;
   201     }
   202 
   203     if (_this->gl_config.buffer_size) {
   204         attribs[i++] = EGL_BUFFER_SIZE;
   205         attribs[i++] = _this->gl_config.buffer_size;
   206     }
   207 
   208     attribs[i++] = EGL_DEPTH_SIZE;
   209     attribs[i++] = _this->gl_config.depth_size;
   210 
   211     if (_this->gl_config.stencil_size) {
   212         attribs[i++] = EGL_STENCIL_SIZE;
   213         attribs[i++] = _this->gl_config.stencil_size;
   214     }
   215 
   216     if (_this->gl_config.multisamplebuffers) {
   217         attribs[i++] = EGL_SAMPLE_BUFFERS;
   218         attribs[i++] = _this->gl_config.multisamplebuffers;
   219     }
   220 
   221     if (_this->gl_config.multisamplesamples) {
   222         attribs[i++] = EGL_SAMPLES;
   223         attribs[i++] = _this->gl_config.multisamplesamples;
   224     }
   225 
   226     attribs[i++] = EGL_NONE;
   227 
   228     if (_this->gles_data->eglChooseConfig(_this->gles_data->egl_display,
   229                                           attribs,
   230                                           &_this->gles_data->egl_config, 1,
   231                                           &found_configs) == EGL_FALSE ||
   232         found_configs == 0) {
   233         SDL_SetError("Couldn't find matching EGL config");
   234         return NULL;
   235     }
   236 
   237     if (_this->gles_data->eglGetConfigAttrib(_this->gles_data->egl_display,
   238                                              _this->gles_data->egl_config,
   239                                              EGL_NATIVE_VISUAL_ID,
   240                                              (EGLint *) & visual_id) ==
   241         EGL_FALSE || !visual_id) {
   242         /* Use the default visual when all else fails */
   243         XVisualInfo vi_in;
   244         int out_count;
   245         vi_in.screen = screen;
   246 
   247         _this->gles_data->egl_visualinfo = XGetVisualInfo(display,
   248                                                           VisualScreenMask,
   249                                                           &vi_in, &out_count);
   250     } else {
   251         XVisualInfo vi_in;
   252         int out_count;
   253 
   254         vi_in.screen = screen;
   255         vi_in.visualid = visual_id;
   256         _this->gles_data->egl_visualinfo = XGetVisualInfo(display,
   257                                                           VisualScreenMask |
   258                                                           VisualIDMask,
   259                                                           &vi_in, &out_count);
   260     }
   261 
   262     return _this->gles_data->egl_visualinfo;
   263 }
   264 
   265 SDL_GLContext
   266 X11_GLES_CreateContext(_THIS, SDL_Window * window)
   267 {
   268     int retval;
   269     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   270     Display *display = data->videodata->display;
   271 
   272     XSync(display, False);
   273 
   274 
   275     _this->gles_data->egl_context =
   276         _this->gles_data->eglCreateContext(_this->gles_data->egl_display,
   277                                            _this->gles_data->egl_config,
   278                                            EGL_NO_CONTEXT, NULL);
   279     XSync(display, False);
   280 
   281     if (_this->gles_data->egl_context == EGL_NO_CONTEXT) {
   282         SDL_SetError("Could not create EGL context");
   283         return NULL;
   284     }
   285 
   286     _this->gles_data->egl_active = 1;
   287 
   288     if (_this->gles_data->egl_active)
   289         retval = 1;
   290     else
   291         retval = 0;
   292 
   293     return (retval);
   294 }
   295 
   296 int
   297 X11_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   298 {
   299     int retval;
   300 
   301 //    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   302 //    Display *display = data->videodata->display;
   303 
   304     retval = 1;
   305     if (!_this->gles_data->eglMakeCurrent(_this->gles_data->egl_display,
   306                                           _this->gles_data->egl_surface,
   307                                           _this->gles_data->egl_surface,
   308                                           _this->gles_data->egl_context)) {
   309         SDL_SetError("Unable to make EGL context current");
   310         retval = -1;
   311     }
   312 //    XSync(display, False);
   313 
   314     return (retval);
   315 }
   316 
   317 static int swapinterval = -1;
   318 int
   319 X11_GLES_SetSwapInterval(_THIS, int interval)
   320 {
   321     return 0;
   322 }
   323 
   324 int
   325 X11_GLES_GetSwapInterval(_THIS)
   326 {
   327     return 0;
   328 }
   329 
   330 void
   331 X11_GLES_SwapWindow(_THIS, SDL_Window * window)
   332 {
   333     _this->gles_data->eglSwapBuffers(_this->gles_data->egl_display,
   334                                      _this->gles_data->egl_surface);
   335 }
   336 
   337 void
   338 X11_GLES_DeleteContext(_THIS, SDL_GLContext context)
   339 {
   340     /* Clean up GLES and EGL */
   341     if (_this->gles_data->egl_context != EGL_NO_CONTEXT ||
   342         _this->gles_data->egl_surface != EGL_NO_SURFACE) {
   343         _this->gles_data->eglMakeCurrent(_this->gles_data->egl_display,
   344                                          EGL_NO_SURFACE, EGL_NO_SURFACE,
   345                                          EGL_NO_CONTEXT);
   346 
   347         if (_this->gles_data->egl_context != EGL_NO_CONTEXT) {
   348             _this->gles_data->eglDestroyContext(_this->gles_data->egl_display,
   349                                                 _this->gles_data->
   350                                                 egl_context);
   351             _this->gles_data->egl_context = EGL_NO_CONTEXT;
   352         }
   353 
   354         if (_this->gles_data->egl_surface != EGL_NO_SURFACE) {
   355             _this->gles_data->eglDestroySurface(_this->gles_data->egl_display,
   356                                                 _this->gles_data->
   357                                                 egl_surface);
   358             _this->gles_data->egl_surface = EGL_NO_SURFACE;
   359         }
   360     }
   361     _this->gles_data->egl_active = 0;
   362 
   363 /* crappy fix */
   364     X11_GLES_UnloadLibrary(_this);
   365 
   366 }
   367 
   368 #endif /* SDL_VIDEO_OPENGL_ES */
   369 
   370 /* vi: set ts=4 sw=4 expandtab: */