src/video/directfb/SDL_DirectFB_opengl.c
author Sam Lantinga
Mon, 16 Aug 2010 09:04:55 -0700
changeset 4636 b196d2758026
parent 3697 f7b03b6838cb
child 5199 164f20ba08eb
permissions -rw-r--r--
Couriersud to Sam

Hi Sam,

20100815_1.diff contains updates for the directfb driver:

- more documentation, mainly on software OpenGL in README.directfb
- Revised error handling leading to leaner code
- Improved/fixed OpenGL handling of multiple contexts.
- Made the built-in simple window manager handle OpenGL windows.
- Rewrote pixelformat mapping - this was quite ugly before.

Well, all software GL, but working :-)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 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 #include "SDL_config.h"
    23 
    24 #include "SDL_DirectFB_video.h"
    25 
    26 #if SDL_DIRECTFB_OPENGL
    27 
    28 struct SDL_GLDriverData
    29 {
    30     int gl_active;              /* to stop switching drivers while we have a valid context */
    31     int initialized;
    32     DirectFB_GLContext *firstgl;        /* linked list */
    33     
    34     /* OpenGL */
    35     void (*glFinish) (void);
    36     void (*glFlush) (void);
    37 };
    38 
    39 #define OPENGL_REQUIRS_DLOPEN
    40 #if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
    41 #include <dlfcn.h>
    42 #define GL_LoadObject(X)	dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
    43 #define GL_LoadFunction		dlsym
    44 #define GL_UnloadObject		dlclose
    45 #else
    46 #define GL_LoadObject	SDL_LoadObject
    47 #define GL_LoadFunction	SDL_LoadFunction
    48 #define GL_UnloadObject	SDL_UnloadObject
    49 #endif
    50 
    51 static void DirectFB_GL_UnloadLibrary(_THIS);
    52 
    53 int
    54 DirectFB_GL_Initialize(_THIS)
    55 {
    56     if (_this->gl_data) {
    57         return 0;
    58     }
    59 
    60     _this->gl_data =
    61         (struct SDL_GLDriverData *) SDL_calloc(1,
    62                                                sizeof(struct
    63                                                       SDL_GLDriverData));
    64     if (!_this->gl_data) {
    65         SDL_OutOfMemory();
    66         return -1;
    67     }
    68     _this->gl_data->initialized = 0;
    69 
    70     ++_this->gl_data->initialized;
    71     _this->gl_data->firstgl = NULL;
    72 
    73     if (DirectFB_GL_LoadLibrary(_this, NULL) < 0) {
    74         return -1;
    75     }
    76 
    77     /* Initialize extensions */
    78     /* FIXME needed?
    79      * X11_GL_InitExtensions(_this);
    80      */
    81 
    82     return 0;
    83 }
    84 
    85 void
    86 DirectFB_GL_Shutdown(_THIS)
    87 {
    88     if (!_this->gl_data || (--_this->gl_data->initialized > 0)) {
    89         return;
    90     }
    91 
    92     DirectFB_GL_UnloadLibrary(_this);
    93 
    94     SDL_free(_this->gl_data);
    95     _this->gl_data = NULL;
    96 }
    97 
    98 int
    99 DirectFB_GL_LoadLibrary(_THIS, const char *path)
   100 {
   101     //SDL_DFB_DEVICEDATA(_this);
   102 
   103     void *handle = NULL;
   104 
   105     SDL_DFB_DEBUG("Loadlibrary : %s\n", path);
   106 
   107     if (_this->gl_data->gl_active) {
   108         SDL_SetError("OpenGL context already created");
   109         return -1;
   110     }
   111 
   112 
   113     if (path == NULL) {
   114         path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
   115         if (path == NULL) {
   116             path = "libGL.so";
   117         }
   118     }
   119 
   120     handle = GL_LoadObject(path);
   121     if (handle == NULL) {
   122         SDL_DFB_ERR("Library not found: %s\n", path);
   123         /* SDL_LoadObject() will call SDL_SetError() for us. */
   124         return -1;
   125     }
   126 
   127     SDL_DFB_DEBUG("Loaded library: %s\n", path);
   128 
   129     _this->gl_config.dll_handle = handle;
   130     _this->gl_config.driver_loaded = 1;
   131     if (path) {
   132         SDL_strlcpy(_this->gl_config.driver_path, path,
   133                     SDL_arraysize(_this->gl_config.driver_path));
   134     } else {
   135         *_this->gl_config.driver_path = '\0';
   136     }
   137 
   138     _this->gl_data->glFinish = DirectFB_GL_GetProcAddress(_this, "glFinish");
   139     _this->gl_data->glFlush = DirectFB_GL_GetProcAddress(_this, "glFlush");
   140 
   141     return 0;
   142 }
   143 
   144 static void
   145 DirectFB_GL_UnloadLibrary(_THIS)
   146 {
   147  #if 0
   148     int ret;
   149 
   150     if (_this->gl_config.driver_loaded) {
   151 
   152         ret = GL_UnloadObject(_this->gl_config.dll_handle);
   153         if (ret)
   154             SDL_DFB_ERR("Error #%d trying to unload library.\n", ret);
   155         _this->gl_config.dll_handle = NULL;
   156         _this->gl_config.driver_loaded = 0;
   157     }
   158 #endif
   159     /* Free OpenGL memory */
   160     SDL_free(_this->gl_data);
   161     _this->gl_data = NULL;
   162 }
   163 
   164 void *
   165 DirectFB_GL_GetProcAddress(_THIS, const char *proc)
   166 {
   167     void *handle;
   168 
   169     handle = _this->gl_config.dll_handle;
   170     return GL_LoadFunction(handle, proc);
   171 }
   172 
   173 SDL_GLContext
   174 DirectFB_GL_CreateContext(_THIS, SDL_Window * window)
   175 {
   176     //SDL_DFB_DEVICEDATA(_this);
   177     SDL_DFB_WINDOWDATA(window);
   178     DirectFB_GLContext *context;
   179 
   180     SDL_DFB_CALLOC(context, 1, sizeof(DirectFB_GLContext));
   181 
   182     SDL_DFB_CHECKERR(windata->surface->GetGL(windata->surface,
   183                                              &context->context));
   184 
   185     if (!context->context)
   186         return NULL;
   187 
   188     context->is_locked = 0;
   189     context->sdl_window = window;
   190     
   191     context->next = _this->gl_data->firstgl;
   192     _this->gl_data->firstgl = context;
   193 
   194     SDL_DFB_CHECK(context->context->Unlock(context->context));
   195 
   196     if (DirectFB_GL_MakeCurrent(_this, window, context) < 0) {
   197         DirectFB_GL_DeleteContext(_this, context);
   198         return NULL;
   199     }
   200 
   201     return context;
   202 
   203   error:
   204     return NULL;
   205 }
   206 
   207 int
   208 DirectFB_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   209 {
   210     //SDL_DFB_WINDOWDATA(window);
   211     DirectFB_GLContext *ctx = (DirectFB_GLContext *) context;
   212     DirectFB_GLContext *p;
   213 
   214     for (p = _this->gl_data->firstgl; p; p = p->next)
   215     {
   216        if (p->is_locked) {
   217          SDL_DFB_CHECKERR(p->context->Unlock(p->context));
   218          p->is_locked = 0;
   219        }
   220         
   221     }
   222 
   223     if (ctx != NULL) {
   224         SDL_DFB_CHECKERR(ctx->context->Lock(ctx->context));
   225         ctx->is_locked = 1;
   226     }
   227 
   228     return 0;
   229   error:
   230     return -1;
   231 }
   232 
   233 int
   234 DirectFB_GL_SetSwapInterval(_THIS, int interval)
   235 {
   236     SDL_Unsupported();
   237     return -1;
   238 }
   239 
   240 int
   241 DirectFB_GL_GetSwapInterval(_THIS)
   242 {
   243     SDL_Unsupported();
   244     return -1;
   245 }
   246 
   247 void
   248 DirectFB_GL_SwapWindow(_THIS, SDL_Window * window)
   249 {
   250     //SDL_DFB_DEVICEDATA(_this);
   251     SDL_DFB_WINDOWDATA(window);
   252     DFBRegion region;
   253     DirectFB_GLContext *p;
   254 
   255     region.x1 = 0;
   256     region.y1 = 0;
   257     region.x2 = window->w;
   258     region.y2 = window->h;
   259 
   260 #if 0
   261     if (devdata->glFinish)
   262         devdata->glFinish();
   263     else if (devdata->glFlush)
   264         devdata->glFlush();
   265 #endif
   266 
   267   	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   268         if (p->sdl_window == window && p->is_locked)
   269         {
   270             SDL_DFB_CHECKERR(p->context->Unlock(p->context));
   271             p->is_locked = 0;
   272         }            
   273 
   274     SDL_DFB_CHECKERR(windata->window_surface->Flip(windata->window_surface,NULL,  DSFLIP_PIPELINE |DSFLIP_BLIT | DSFLIP_ONSYNC ));
   275 
   276     //if (windata->gl_context) {
   277         //SDL_DFB_CHECKERR(windata->surface->Flip(windata->surface,NULL, DSFLIP_ONSYNC)); 
   278         //SDL_DFB_CHECKERR(windata->gl_context->context->Lock(windata->gl_context->context));
   279     //}
   280 
   281     return;
   282   error:
   283     return;
   284 }
   285 
   286 void
   287 DirectFB_GL_DeleteContext(_THIS, SDL_GLContext context)
   288 {
   289     DirectFB_GLContext *ctx = (DirectFB_GLContext *) context;
   290     DirectFB_GLContext *p;
   291 
   292     if (ctx->is_locked)
   293         SDL_DFB_CHECK(ctx->context->Unlock(ctx->context));
   294     SDL_DFB_RELEASE(ctx->context);
   295 
   296     for (p = _this->gl_data->firstgl; p && p->next != ctx; p = p->next)
   297         ;
   298     if (p)
   299         p->next = ctx->next;
   300     else
   301         _this->gl_data->firstgl = ctx->next;
   302 
   303     SDL_DFB_FREE(ctx);
   304 }
   305 
   306 void
   307 DirectFB_GL_FreeWindowContexts(_THIS, SDL_Window * window)
   308 {
   309     DirectFB_GLContext *p;
   310     
   311 	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   312 	    if (p->sdl_window == window)
   313 	    {
   314 	    	if (p->is_locked)
   315 	        	SDL_DFB_CHECK(p->context->Unlock(p->context));
   316 	        SDL_DFB_RELEASE(p->context);
   317 	    }
   318 }
   319 
   320 void
   321 DirectFB_GL_ReAllocWindowContexts(_THIS, SDL_Window * window)
   322 {
   323     DirectFB_GLContext *p;
   324 
   325 	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   326 	    if (p->sdl_window == window)
   327 	    {
   328             SDL_DFB_WINDOWDATA(window);
   329 			SDL_DFB_CHECK(windata->surface->GetGL(windata->surface,
   330 	                                         &p->context));
   331     		if (p->is_locked)
   332             	SDL_DFB_CHECK(p->context->Lock(p->context));
   333 	        }
   334 }
   335 
   336 void
   337 DirectFB_GL_DestroyWindowContexts(_THIS, SDL_Window * window)
   338 {
   339     DirectFB_GLContext *p;
   340 
   341 	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   342 		if (p->sdl_window == window)
   343 			DirectFB_GL_DeleteContext(_this, p);
   344 }
   345 
   346 #endif
   347 
   348 /* vi: set ts=4 sw=4 expandtab: */