src/video/x11/SDL_x11gl.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. X11_GL_GetVisual
  2. X11_GL_CreateWindow
  3. X11_GL_CreateContext
  4. X11_GL_Shutdown
  5. X11_GL_MakeCurrent
  6. X11_GL_GetAttribute
  7. X11_GL_SwapBuffers
  8. X11_GL_UnloadLibrary
  9. X11_GL_LoadLibrary
  10. X11_GL_GetProcAddress

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 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     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_x11gl.c,v 1.1.2.28 2001/02/10 07:20:15 hercules Exp $";
  26 #endif
  27 
  28 #include <stdlib.h>     /* For getenv() prototype */
  29 #include <string.h>
  30 
  31 #include "SDL_events_c.h"
  32 #include "SDL_error.h"
  33 #include "SDL_x11video.h"
  34 #include "SDL_x11dga_c.h"
  35 #include "SDL_x11gl_c.h"
  36 
  37 #define DEFAULT_OPENGL  "libGL.so.1"
  38 
  39 /* return the preferred visual to use for openGL graphics */
  40 XVisualInfo *X11_GL_GetVisual(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
  41 {
  42 #ifdef HAVE_OPENGL
  43         /* 64 seems nice. */
  44         int attribs[64];
  45         int i;
  46 
  47         /* load the gl driver from a default path */
  48         if ( ! this->gl_config.driver_loaded ) {
  49                 /* no driver has been loaded, use default (ourselves) */
  50                 if ( X11_GL_LoadLibrary(this, NULL) < 0 ) {
  51                         return NULL;
  52                 }
  53         }
  54 
  55         /* See if we already have a window which we must use */
  56         if ( SDL_windowid ) {
  57                 XWindowAttributes a;
  58                 XVisualInfo vi_in;
  59                 int out_count;
  60 
  61                 XGetWindowAttributes(SDL_Display, SDL_Window, &a);
  62                 vi_in.screen = SDL_Screen;
  63                 vi_in.visualid = XVisualIDFromVisual(a.visual);
  64                 glx_visualinfo = XGetVisualInfo(SDL_Display,
  65                              VisualScreenMask|VisualIDMask, &vi_in, &out_count);
  66                 return glx_visualinfo;
  67         }
  68 
  69         /* Setup our GLX attributes according to the gl_config. */
  70         i = 0;
  71         attribs[i++] = GLX_RGBA;
  72         attribs[i++] = GLX_RED_SIZE;
  73         attribs[i++] = this->gl_config.red_size;
  74         attribs[i++] = GLX_GREEN_SIZE;
  75         attribs[i++] = this->gl_config.green_size;
  76         attribs[i++] = GLX_BLUE_SIZE;
  77         attribs[i++] = this->gl_config.blue_size;
  78 
  79         if( this->gl_config.alpha_size ) {
  80                 attribs[i++] = GLX_ALPHA_SIZE;
  81                 attribs[i++] = this->gl_config.alpha_size;
  82         }
  83 
  84         if( this->gl_config.buffer_size ) {
  85                 attribs[i++] = GLX_BUFFER_SIZE;
  86                 attribs[i++] = this->gl_config.buffer_size;
  87         }
  88 
  89         if( this->gl_config.double_buffer ) {
  90                 attribs[i++] = GLX_DOUBLEBUFFER;
  91         }
  92 
  93         attribs[i++] = GLX_DEPTH_SIZE;
  94         attribs[i++] = this->gl_config.depth_size;
  95 
  96         if( this->gl_config.stencil_size ) {
  97                 attribs[i++] = GLX_STENCIL_SIZE;
  98                 attribs[i++] = this->gl_config.stencil_size;
  99         }
 100 
 101         if( this->gl_config.accum_red_size ) {
 102                 attribs[i++] = GLX_ACCUM_RED_SIZE;
 103                 attribs[i++] = this->gl_config.accum_red_size;
 104         }
 105 
 106         if( this->gl_config.accum_green_size ) {
 107                 attribs[i++] = GLX_ACCUM_GREEN_SIZE;
 108                 attribs[i++] = this->gl_config.accum_green_size;
 109         }
 110 
 111         if( this->gl_config.accum_blue_size ) {
 112                 attribs[i++] = GLX_ACCUM_BLUE_SIZE;
 113                 attribs[i++] = this->gl_config.accum_blue_size;
 114         }
 115 
 116         if( this->gl_config.accum_alpha_size ) {
 117                 attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
 118                 attribs[i++] = this->gl_config.accum_alpha_size;
 119         }
 120 
 121 #ifdef GLX_DIRECT_COLOR /* Try for a DirectColor visual for gamma support */
 122         attribs[i++] = GLX_X_VISUAL_TYPE;
 123         attribs[i++] = GLX_DIRECT_COLOR;
 124 #endif
 125         attribs[i++] = None;
 126 
 127         glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display, 
 128                                                   SDL_Screen, attribs);
 129 #ifdef GLX_DIRECT_COLOR
 130         if( !glx_visualinfo ) { /* No DirectColor visual?  Try again.. */
 131                 attribs[i-3] = None;
 132                 glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display, 
 133                                                   SDL_Screen, attribs);
 134         }
 135 #endif
 136         if( !glx_visualinfo ) {
 137                 SDL_SetError( "Couldn't find matching GLX visual");
 138                 return NULL;
 139         }
 140         return glx_visualinfo;
 141 #else
 142         SDL_SetError("X11 driver not configured with OpenGL");
 143         return NULL;
 144 #endif
 145 }
 146 
 147 int X11_GL_CreateWindow(_THIS, int w, int h)
     /* [<][>][^][v][top][bottom][index][help] */
 148 {
 149         int retval;
 150 #ifdef HAVE_OPENGL
 151         XSetWindowAttributes attributes;
 152         unsigned long mask;
 153         unsigned long black;
 154 
 155         black = (glx_visualinfo->visual == DefaultVisual(SDL_Display,
 156                                                         SDL_Screen))
 157                 ? BlackPixel(SDL_Display, SDL_Screen) : 0;
 158         attributes.background_pixel = black;
 159         attributes.border_pixel = black;
 160         attributes.colormap = SDL_XColorMap;
 161         mask = CWBackPixel | CWBorderPixel | CWColormap;
 162 
 163         SDL_Window = XCreateWindow(SDL_Display, WMwindow,
 164                         0, 0, w, h, 0, glx_visualinfo->depth,
 165                         InputOutput, glx_visualinfo->visual,
 166                         mask, &attributes);
 167         if ( !SDL_Window ) {
 168                 SDL_SetError("Could not create window");
 169                 return -1;
 170         }
 171         retval = 0;
 172 #else
 173         SDL_SetError("X11 driver not configured with OpenGL");
 174         retval = -1;
 175 #endif
 176         return(retval);
 177 }
 178 
 179 int X11_GL_CreateContext(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 180 {
 181         int retval;
 182 #ifdef HAVE_OPENGL
 183         /* We do this to create a clean separation between X and GLX errors. */
 184         XSync( SDL_Display, False );
 185         glx_context = this->gl_data->glXCreateContext(GFX_Display, 
 186                                      glx_visualinfo, NULL, True);
 187         XSync( GFX_Display, False );
 188 
 189         if (glx_context == NULL) {
 190                 SDL_SetError("Could not create GL context");
 191                 return -1;
 192         }
 193 
 194         gl_active = 1;
 195 #else
 196         SDL_SetError("X11 driver not configured with OpenGL");
 197 #endif
 198         if ( gl_active ) {
 199                 retval = 0;
 200         } else {
 201                 retval = -1;
 202         }
 203         return(retval);
 204 }
 205 
 206 void X11_GL_Shutdown(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 207 {
 208 #ifdef HAVE_OPENGL
 209         /* Clean up OpenGL */
 210         if( glx_context ) {
 211                 this->gl_data->glXMakeCurrent(GFX_Display, None, NULL);
 212 
 213                 if (glx_context != NULL)
 214                         this->gl_data->glXDestroyContext(GFX_Display, glx_context);
 215 
 216                 if( this->gl_data->glXReleaseBuffersMESA ) {
 217                     this->gl_data->glXReleaseBuffersMESA(GFX_Display,SDL_Window);
 218                 }
 219                 glx_context = NULL;
 220         }
 221         gl_active = 0;
 222 #endif /* HAVE_OPENGL */
 223 }
 224 
 225 #ifdef HAVE_OPENGL
 226 
 227 /* Make the current context active */
 228 int X11_GL_MakeCurrent(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 229 {
 230         int retval;
 231 
 232         retval = 0;
 233         if ( ! this->gl_data->glXMakeCurrent(GFX_Display,
 234                                              SDL_Window, glx_context) ) {
 235                 SDL_SetError("Unable to make GL context current");
 236                 retval = -1;
 237         }
 238         XSync( GFX_Display, False );
 239 
 240         /* More Voodoo X server workarounds... Grr... */
 241         SDL_Lock_EventThread();
 242         X11_CheckDGAMouse(this);
 243         SDL_Unlock_EventThread();
 244 
 245         return(retval);
 246 }
 247 
 248 /* Get attribute data from glX. */
 249 int X11_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
     /* [<][>][^][v][top][bottom][index][help] */
 250 {
 251         int retval;
 252         int glx_attrib = None;
 253 
 254         switch( attrib ) {
 255             case SDL_GL_RED_SIZE:
 256                 glx_attrib = GLX_RED_SIZE;
 257                 break;
 258             case SDL_GL_GREEN_SIZE:
 259                 glx_attrib = GLX_GREEN_SIZE;
 260                 break;
 261             case SDL_GL_BLUE_SIZE:
 262                 glx_attrib = GLX_BLUE_SIZE;
 263                 break;
 264             case SDL_GL_ALPHA_SIZE:
 265                 glx_attrib = GLX_ALPHA_SIZE;
 266                 break;
 267             case SDL_GL_DOUBLEBUFFER:
 268                 glx_attrib = GLX_DOUBLEBUFFER;
 269                 break;
 270             case SDL_GL_BUFFER_SIZE:
 271                 glx_attrib = GLX_BUFFER_SIZE;
 272                 break;
 273             case SDL_GL_DEPTH_SIZE:
 274                 glx_attrib = GLX_DEPTH_SIZE;
 275                 break;
 276             case SDL_GL_STENCIL_SIZE:
 277                 glx_attrib = GLX_STENCIL_SIZE;
 278                 break;
 279             case SDL_GL_ACCUM_RED_SIZE:
 280                 glx_attrib = GLX_ACCUM_RED_SIZE;
 281                 break;
 282             case SDL_GL_ACCUM_GREEN_SIZE:
 283                 glx_attrib = GLX_ACCUM_GREEN_SIZE;
 284                 break;
 285             case SDL_GL_ACCUM_BLUE_SIZE:
 286                 glx_attrib = GLX_ACCUM_BLUE_SIZE;
 287                 break;
 288             case SDL_GL_ACCUM_ALPHA_SIZE:
 289                 glx_attrib = GLX_ACCUM_ALPHA_SIZE;
 290                 break;
 291             default:
 292                 return(-1);
 293         }
 294 
 295         retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value);
 296 
 297         return retval;
 298 }
 299 
 300 void X11_GL_SwapBuffers(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 301 {
 302         this->gl_data->glXSwapBuffers(GFX_Display, SDL_Window);
 303 }
 304 
 305 #endif /* HAVE_OPENGL */
 306 
 307 void X11_GL_UnloadLibrary(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 308 {
 309 #ifdef HAVE_OPENGL
 310         if ( this->gl_config.driver_loaded ) {
 311                 dlclose(this->gl_config.dll_handle);
 312 
 313                 this->gl_data->glXGetProcAddress = NULL;
 314                 this->gl_data->glXChooseVisual = NULL;
 315                 this->gl_data->glXCreateContext = NULL;
 316                 this->gl_data->glXDestroyContext = NULL;
 317                 this->gl_data->glXMakeCurrent = NULL;
 318                 this->gl_data->glXSwapBuffers = NULL;
 319 
 320                 this->gl_config.dll_handle = NULL;
 321                 this->gl_config.driver_loaded = 0;
 322         }
 323 #endif
 324 }
 325 
 326 #ifdef HAVE_OPENGL
 327 
 328 /* Passing a NULL path means load pointers from the application */
 329 int X11_GL_LoadLibrary(_THIS, const char* path) 
     /* [<][>][^][v][top][bottom][index][help] */
 330 {
 331         void* handle;
 332         int dlopen_flags;
 333 
 334         if ( gl_active ) {
 335                 SDL_SetError("OpenGL context already created");
 336                 return -1;
 337         }
 338 
 339 #ifdef RTLD_GLOBAL
 340         dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
 341 #else
 342         dlopen_flags = RTLD_LAZY;
 343 #endif
 344         handle = dlopen(path, dlopen_flags);
 345         /* Catch the case where the application isn't linked with GL */
 346         if ( (dlsym(handle, "glXChooseVisual") == NULL) && (path == NULL) ) {
 347                 dlclose(handle);
 348                 path = getenv("SDL_VIDEO_GL_DRIVER");
 349                 if ( path == NULL ) {
 350                         path = DEFAULT_OPENGL;
 351                 }
 352                 handle = dlopen(path, dlopen_flags);
 353         }
 354         if ( handle == NULL ) {
 355                 SDL_SetError("Could not load OpenGL library");
 356                 return -1;
 357         }
 358 
 359         /* Unload the old driver and reset the pointers */
 360         X11_GL_UnloadLibrary(this);
 361 
 362         /* Load new function pointers */
 363         this->gl_data->glXGetProcAddress = dlsym(handle, "glXGetProcAddressARB");
 364         this->gl_data->glXChooseVisual = dlsym(handle, "glXChooseVisual");
 365         this->gl_data->glXCreateContext = dlsym(handle, "glXCreateContext");
 366         this->gl_data->glXDestroyContext = dlsym(handle, "glXDestroyContext");
 367         this->gl_data->glXMakeCurrent = dlsym(handle, "glXMakeCurrent");
 368         this->gl_data->glXSwapBuffers = dlsym(handle, "glXSwapBuffers");
 369         this->gl_data->glXGetConfig = dlsym(handle, "glXGetConfig");
 370         /* We don't compare below for this in case we're not using Mesa. */
 371         this->gl_data->glXReleaseBuffersMESA = dlsym( handle, "glXReleaseBuffersMESA" );
 372 
 373         if ( (this->gl_data->glXChooseVisual == NULL) || 
 374              (this->gl_data->glXCreateContext == NULL) ||
 375              (this->gl_data->glXDestroyContext == NULL) ||
 376              (this->gl_data->glXMakeCurrent == NULL) ||
 377              (this->gl_data->glXSwapBuffers == NULL) ||
 378              (this->gl_data->glXGetConfig == NULL) ) {
 379                 SDL_SetError("Could not retrieve OpenGL functions");
 380                 return -1;
 381         }
 382 
 383         this->gl_config.dll_handle = handle;
 384         this->gl_config.driver_loaded = 1;
 385         if ( path ) {
 386                 strncpy(this->gl_config.driver_path, path,
 387                         sizeof(this->gl_config.driver_path)-1);
 388         } else {
 389                 strcpy(this->gl_config.driver_path, "");
 390         }
 391         return 0;
 392 }
 393 
 394 void *X11_GL_GetProcAddress(_THIS, const char* proc)
     /* [<][>][^][v][top][bottom][index][help] */
 395 {
 396         void* handle;
 397         
 398         handle = this->gl_config.dll_handle;
 399 #if 0 /* This doesn't work correctly yet */
 400         if ( this->gl_data->glXGetProcAddress ) {
 401         void *func, *func2;
 402                 func = this->gl_data->glXGetProcAddress(proc);
 403         func2 = dlsym(handle, proc);
 404         if ( func != func2 ) {
 405 fprintf(stderr, "glXGetProcAddress returned %p and dlsym returned %p for %s\n", func, func2, proc);
 406         }
 407         return this->gl_data->glXGetProcAddress(proc);
 408         }
 409 #endif
 410         return dlsym(handle, proc);
 411 }
 412 
 413 #endif /* HAVE_OPENGL */

/* [<][>][^][v][top][bottom][index][help] */