SDL_x11gl.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:12k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

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