src/video/directfb/SDL_DirectFB_opengl.c
author Ryan C. Gordon
Wed, 01 Aug 2012 20:29:36 -0400
changeset 6382 64d54101773a
parent 6138 4c64952a58fb
child 6885 700f1b25f77f
permissions -rwxr-xr-x
Add support for (GLX|WGL)_EXT_swap_control_tear.

This required a small public API change: SDL_GL_SetSwapInterval() now accepts
negative values, and SDL_GL_GetSwapInterval() doesn't report errors anymore
(if it can't work, it'll return zero as a reasonable default).

If you need to test for errors, such as a lack of swap_control_tear support,
check the results of SDL_GL_SetSwapInterval() when you set your desired
value.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_DIRECTFB
    24 
    25 #include "SDL_DirectFB_video.h"
    26 
    27 #if SDL_DIRECTFB_OPENGL
    28 
    29 #include "SDL_DirectFB_opengl.h"
    30 #include "SDL_DirectFB_window.h"
    31 
    32 #include <directfbgl.h>
    33 #include "SDL_loadso.h"
    34 #endif
    35 
    36 #if SDL_DIRECTFB_OPENGL
    37 
    38 struct SDL_GLDriverData
    39 {
    40     int gl_active;              /* to stop switching drivers while we have a valid context */
    41     int initialized;
    42     DirectFB_GLContext *firstgl;        /* linked list */
    43     
    44     /* OpenGL */
    45     void (*glFinish) (void);
    46     void (*glFlush) (void);
    47 };
    48 
    49 #define OPENGL_REQUIRS_DLOPEN
    50 #if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
    51 #include <dlfcn.h>
    52 #define GL_LoadObject(X)	dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
    53 #define GL_LoadFunction		dlsym
    54 #define GL_UnloadObject		dlclose
    55 #else
    56 #define GL_LoadObject	SDL_LoadObject
    57 #define GL_LoadFunction	SDL_LoadFunction
    58 #define GL_UnloadObject	SDL_UnloadObject
    59 #endif
    60 
    61 static void DirectFB_GL_UnloadLibrary(_THIS);
    62 
    63 int
    64 DirectFB_GL_Initialize(_THIS)
    65 {
    66     if (_this->gl_data) {
    67         return 0;
    68     }
    69 
    70     _this->gl_data =
    71         (struct SDL_GLDriverData *) SDL_calloc(1,
    72                                                sizeof(struct
    73                                                       SDL_GLDriverData));
    74     if (!_this->gl_data) {
    75         SDL_OutOfMemory();
    76         return -1;
    77     }
    78     _this->gl_data->initialized = 0;
    79 
    80     ++_this->gl_data->initialized;
    81     _this->gl_data->firstgl = NULL;
    82 
    83     if (DirectFB_GL_LoadLibrary(_this, NULL) < 0) {
    84         return -1;
    85     }
    86 
    87     /* Initialize extensions */
    88     /* FIXME needed?
    89      * X11_GL_InitExtensions(_this);
    90      */
    91 
    92     return 0;
    93 }
    94 
    95 void
    96 DirectFB_GL_Shutdown(_THIS)
    97 {
    98     if (!_this->gl_data || (--_this->gl_data->initialized > 0)) {
    99         return;
   100     }
   101 
   102     DirectFB_GL_UnloadLibrary(_this);
   103 
   104     SDL_free(_this->gl_data);
   105     _this->gl_data = NULL;
   106 }
   107 
   108 int
   109 DirectFB_GL_LoadLibrary(_THIS, const char *path)
   110 {
   111     //SDL_DFB_DEVICEDATA(_this);
   112 
   113     void *handle = NULL;
   114 
   115     SDL_DFB_DEBUG("Loadlibrary : %s\n", path);
   116 
   117     if (_this->gl_data->gl_active) {
   118         SDL_SetError("OpenGL context already created");
   119         return -1;
   120     }
   121 
   122 
   123     if (path == NULL) {
   124         path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
   125         if (path == NULL) {
   126             path = "libGL.so";
   127         }
   128     }
   129 
   130     handle = GL_LoadObject(path);
   131     if (handle == NULL) {
   132         SDL_DFB_ERR("Library not found: %s\n", path);
   133         /* SDL_LoadObject() will call SDL_SetError() for us. */
   134         return -1;
   135     }
   136 
   137     SDL_DFB_DEBUG("Loaded library: %s\n", path);
   138 
   139     _this->gl_config.dll_handle = handle;
   140     _this->gl_config.driver_loaded = 1;
   141     if (path) {
   142         SDL_strlcpy(_this->gl_config.driver_path, path,
   143                     SDL_arraysize(_this->gl_config.driver_path));
   144     } else {
   145         *_this->gl_config.driver_path = '\0';
   146     }
   147 
   148     _this->gl_data->glFinish = DirectFB_GL_GetProcAddress(_this, "glFinish");
   149     _this->gl_data->glFlush = DirectFB_GL_GetProcAddress(_this, "glFlush");
   150 
   151     return 0;
   152 }
   153 
   154 static void
   155 DirectFB_GL_UnloadLibrary(_THIS)
   156 {
   157  #if 0
   158     int ret;
   159 
   160     if (_this->gl_config.driver_loaded) {
   161 
   162         ret = GL_UnloadObject(_this->gl_config.dll_handle);
   163         if (ret)
   164             SDL_DFB_ERR("Error #%d trying to unload library.\n", ret);
   165         _this->gl_config.dll_handle = NULL;
   166         _this->gl_config.driver_loaded = 0;
   167     }
   168 #endif
   169     /* Free OpenGL memory */
   170     SDL_free(_this->gl_data);
   171     _this->gl_data = NULL;
   172 }
   173 
   174 void *
   175 DirectFB_GL_GetProcAddress(_THIS, const char *proc)
   176 {
   177     void *handle;
   178 
   179     handle = _this->gl_config.dll_handle;
   180     return GL_LoadFunction(handle, proc);
   181 }
   182 
   183 SDL_GLContext
   184 DirectFB_GL_CreateContext(_THIS, SDL_Window * window)
   185 {
   186     //SDL_DFB_DEVICEDATA(_this);
   187     SDL_DFB_WINDOWDATA(window);
   188     DirectFB_GLContext *context;
   189 
   190     SDL_DFB_ALLOC_CLEAR(context, sizeof(DirectFB_GLContext));
   191 
   192     SDL_DFB_CHECKERR(windata->surface->GetGL(windata->surface,
   193                                              &context->context));
   194 
   195     if (!context->context)
   196         return NULL;
   197 
   198     context->is_locked = 0;
   199     context->sdl_window = window;
   200     
   201     context->next = _this->gl_data->firstgl;
   202     _this->gl_data->firstgl = context;
   203 
   204     SDL_DFB_CHECK(context->context->Unlock(context->context));
   205 
   206     if (DirectFB_GL_MakeCurrent(_this, window, context) < 0) {
   207         DirectFB_GL_DeleteContext(_this, context);
   208         return NULL;
   209     }
   210 
   211     return context;
   212 
   213   error:
   214     return NULL;
   215 }
   216 
   217 int
   218 DirectFB_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   219 {
   220     //SDL_DFB_WINDOWDATA(window);
   221     DirectFB_GLContext *ctx = (DirectFB_GLContext *) context;
   222     DirectFB_GLContext *p;
   223 
   224     for (p = _this->gl_data->firstgl; p; p = p->next)
   225     {
   226        if (p->is_locked) {
   227          SDL_DFB_CHECKERR(p->context->Unlock(p->context));
   228          p->is_locked = 0;
   229        }
   230         
   231     }
   232 
   233     if (ctx != NULL) {
   234         SDL_DFB_CHECKERR(ctx->context->Lock(ctx->context));
   235         ctx->is_locked = 1;
   236     }
   237 
   238     return 0;
   239   error:
   240     return -1;
   241 }
   242 
   243 int
   244 DirectFB_GL_SetSwapInterval(_THIS, int interval)
   245 {
   246     SDL_Unsupported();
   247     return -1;
   248 }
   249 
   250 int
   251 DirectFB_GL_GetSwapInterval(_THIS)
   252 {
   253     return 0;
   254 }
   255 
   256 void
   257 DirectFB_GL_SwapWindow(_THIS, SDL_Window * window)
   258 {
   259     //SDL_DFB_DEVICEDATA(_this);
   260     SDL_DFB_WINDOWDATA(window);
   261     DFBRegion region;
   262     DirectFB_GLContext *p;
   263 
   264     region.x1 = 0;
   265     region.y1 = 0;
   266     region.x2 = window->w;
   267     region.y2 = window->h;
   268 
   269 #if 0
   270     if (devdata->glFinish)
   271         devdata->glFinish();
   272     else if (devdata->glFlush)
   273         devdata->glFlush();
   274 #endif
   275 
   276   	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   277         if (p->sdl_window == window && p->is_locked)
   278         {
   279             SDL_DFB_CHECKERR(p->context->Unlock(p->context));
   280             p->is_locked = 0;
   281         }            
   282 
   283     SDL_DFB_CHECKERR(windata->window_surface->Flip(windata->window_surface,NULL,  DSFLIP_PIPELINE |DSFLIP_BLIT | DSFLIP_ONSYNC ));
   284 
   285     //if (windata->gl_context) {
   286         //SDL_DFB_CHECKERR(windata->surface->Flip(windata->surface,NULL, DSFLIP_ONSYNC)); 
   287         //SDL_DFB_CHECKERR(windata->gl_context->context->Lock(windata->gl_context->context));
   288     //}
   289 
   290     return;
   291   error:
   292     return;
   293 }
   294 
   295 void
   296 DirectFB_GL_DeleteContext(_THIS, SDL_GLContext context)
   297 {
   298     DirectFB_GLContext *ctx = (DirectFB_GLContext *) context;
   299     DirectFB_GLContext *p;
   300 
   301     if (ctx->is_locked)
   302         SDL_DFB_CHECK(ctx->context->Unlock(ctx->context));
   303     SDL_DFB_RELEASE(ctx->context);
   304 
   305     for (p = _this->gl_data->firstgl; p && p->next != ctx; p = p->next)
   306         ;
   307     if (p)
   308         p->next = ctx->next;
   309     else
   310         _this->gl_data->firstgl = ctx->next;
   311 
   312     SDL_DFB_FREE(ctx);
   313 }
   314 
   315 void
   316 DirectFB_GL_FreeWindowContexts(_THIS, SDL_Window * window)
   317 {
   318     DirectFB_GLContext *p;
   319     
   320 	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   321 	    if (p->sdl_window == window)
   322 	    {
   323 	    	if (p->is_locked)
   324 	        	SDL_DFB_CHECK(p->context->Unlock(p->context));
   325 	        SDL_DFB_RELEASE(p->context);
   326 	    }
   327 }
   328 
   329 void
   330 DirectFB_GL_ReAllocWindowContexts(_THIS, SDL_Window * window)
   331 {
   332     DirectFB_GLContext *p;
   333 
   334 	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   335 	    if (p->sdl_window == window)
   336 	    {
   337             SDL_DFB_WINDOWDATA(window);
   338 			SDL_DFB_CHECK(windata->surface->GetGL(windata->surface,
   339 	                                         &p->context));
   340     		if (p->is_locked)
   341             	SDL_DFB_CHECK(p->context->Lock(p->context));
   342 	        }
   343 }
   344 
   345 void
   346 DirectFB_GL_DestroyWindowContexts(_THIS, SDL_Window * window)
   347 {
   348     DirectFB_GLContext *p;
   349 
   350 	for (p = _this->gl_data->firstgl; p != NULL; p = p->next)
   351 		if (p->sdl_window == window)
   352 			DirectFB_GL_DeleteContext(_this, p);
   353 }
   354 
   355 #endif
   356 
   357 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */
   358 
   359 /* vi: set ts=4 sw=4 expandtab: */