src/video/x11/SDL_x11opengles.c
changeset 3190 c68d2ca5970f
child 3218 81773a1eac83
equal deleted inserted replaced
3189:ba1e64340565 3190:c68d2ca5970f
       
     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 
       
   364 #endif /* SDL_VIDEO_OPENGL_ES */
       
   365 
       
   366 /* vi: set ts=4 sw=4 expandtab: */