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

流媒体/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_video.c,v 1.4 2002/04/22 21:38:03 wmay Exp $";
  21. #endif
  22. /* The high-level video driver subsystem */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "SDL.h"
  27. #include "SDL_error.h"
  28. #include "SDL_video.h"
  29. #include "SDL_events.h"
  30. #include "SDL_mutex.h"
  31. #include "SDL_sysvideo.h"
  32. #include "SDL_sysevents.h"
  33. #include "SDL_blit.h"
  34. #include "SDL_pixels_c.h"
  35. #include "SDL_events_c.h"
  36. #include "SDL_cursor_c.h"
  37. /* Available video drivers */
  38. static VideoBootStrap *bootstrap[] = {
  39. #ifdef ENABLE_X11
  40. &X11_bootstrap,
  41. #endif
  42. #ifdef ENABLE_DGA
  43. &DGA_bootstrap,
  44. #endif
  45. #ifdef ENABLE_NANOX
  46. &NX_bootstrap,
  47. #endif
  48. #ifdef ENABLE_FBCON
  49. &FBCON_bootstrap,
  50. #endif
  51. #ifdef ENABLE_DIRECTFB
  52. &DirectFB_bootstrap,
  53. #endif
  54. #ifdef ENABLE_PS2GS
  55. &PS2GS_bootstrap,
  56. #endif
  57. #ifdef ENABLE_GGI
  58. &GGI_bootstrap,
  59. #endif
  60. #ifdef ENABLE_VGL
  61. &VGL_bootstrap,
  62. #endif
  63. #ifdef ENABLE_SVGALIB
  64. &SVGALIB_bootstrap,
  65. #endif
  66. #ifdef ENABLE_AALIB
  67.     &AALIB_bootstrap,
  68. #endif
  69. #ifdef ENABLE_DIRECTX
  70. &DIRECTX_bootstrap,
  71. #endif
  72. #ifdef ENABLE_WINDIB
  73. &WINDIB_bootstrap,
  74. #endif
  75. #ifdef ENABLE_BWINDOW
  76. &BWINDOW_bootstrap,
  77. #endif
  78. #ifdef ENABLE_TOOLBOX
  79. &TOOLBOX_bootstrap,
  80. #endif
  81. #ifdef ENABLE_DRAWSPROCKET
  82. &DSp_bootstrap,
  83. #endif
  84. #ifdef ENABLE_QUARTZ
  85. &QZ_bootstrap,
  86. #endif
  87. #ifdef ENABLE_CYBERGRAPHICS
  88. &CGX_bootstrap,
  89. #endif
  90. #ifdef ENABLE_PHOTON
  91. &ph_bootstrap,
  92. #endif
  93. #ifdef ENABLE_EPOC
  94. &EPOC_bootstrap,
  95. #endif
  96. #ifdef ENABLE_DUMMYVIDEO
  97. &DUMMY_bootstrap,
  98. #endif
  99. #ifdef ENABLE_XBIOS
  100. &XBIOS_bootstrap,
  101. #endif
  102. #ifdef ENABLE_GEM
  103. &GEM_bootstrap,
  104. #endif
  105. NULL
  106. };
  107. SDL_VideoDevice *current_video = NULL;
  108. /* Various local functions */
  109. int SDL_VideoInit(const char *driver_name, Uint32 flags);
  110. void SDL_VideoQuit(void);
  111. void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects);
  112. static SDL_GrabMode SDL_WM_GrabInputOff(void);
  113. #ifdef HAVE_OPENGL
  114. static int lock_count = 0;
  115. #endif
  116. /*
  117.  * Initialize the video and event subsystems -- determine native pixel format
  118.  */
  119. int SDL_VideoInit (const char *driver_name, Uint32 flags)
  120. {
  121. SDL_VideoDevice *video;
  122. int index;
  123. int i;
  124. SDL_PixelFormat vformat;
  125. Uint32 video_flags;
  126. /* Toggle the event thread flags, based on OS requirements */
  127. #if defined(MUST_THREAD_EVENTS)
  128. flags |= SDL_INIT_EVENTTHREAD;
  129. #elif defined(CANT_THREAD_EVENTS)
  130. if ( (flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) {
  131. SDL_SetError("OS doesn't support threaded events");
  132. return(-1);
  133. }
  134. #endif
  135. /* Check to make sure we don't overwrite 'current_video' */
  136. if ( current_video != NULL ) {
  137. SDL_VideoQuit();
  138. }
  139. /* Select the proper video driver */
  140. index = 0;
  141. video = NULL;
  142. if ( driver_name != NULL ) {
  143. #if 0 /* This will be replaced with a better driver selection API */
  144. if ( strrchr(driver_name, ':') != NULL ) {
  145. index = atoi(strrchr(driver_name, ':')+1);
  146. }
  147. #endif
  148. for ( i=0; bootstrap[i]; ++i ) {
  149. if ( strncmp(bootstrap[i]->name, driver_name,
  150.              strlen(bootstrap[i]->name)) == 0 ) {
  151. if ( bootstrap[i]->available() ) {
  152. video = bootstrap[i]->create(index);
  153. break;
  154. }
  155. }
  156. }
  157. } else {
  158. for ( i=0; bootstrap[i]; ++i ) {
  159. if ( bootstrap[i]->available() ) {
  160. video = bootstrap[i]->create(index);
  161. if ( video != NULL ) {
  162. break;
  163. }
  164. }
  165. }
  166. }
  167. if ( video == NULL ) {
  168. SDL_SetError("No available video device");
  169. return(-1);
  170. }
  171. current_video = video;
  172. current_video->name = bootstrap[i]->name;
  173. /* Do some basic variable initialization */
  174. video->screen = NULL;
  175. video->shadow = NULL;
  176. video->visible = NULL;
  177. video->physpal = NULL;
  178. video->gammacols = NULL;
  179. video->gamma = NULL;
  180. video->wm_title = NULL;
  181. video->wm_icon  = NULL;
  182. video->offset_x = 0;
  183. video->offset_y = 0;
  184. memset(&video->info, 0, (sizeof video->info));
  185. /* Set some very sane GL defaults */
  186. video->gl_config.driver_loaded = 0;
  187. video->gl_config.dll_handle = NULL;
  188. video->gl_config.red_size = 5;
  189. #if 1 /* This seems to work on more video cards, as a default */
  190. video->gl_config.green_size = 5;
  191. #else
  192. video->gl_config.green_size = 6;
  193. #endif
  194. video->gl_config.blue_size = 5;
  195. video->gl_config.alpha_size = 0;
  196. video->gl_config.buffer_size = 0;
  197. video->gl_config.depth_size = 16;
  198. video->gl_config.stencil_size = 0;
  199. video->gl_config.double_buffer = 1;
  200. video->gl_config.accum_red_size = 0;
  201. video->gl_config.accum_green_size = 0;
  202. video->gl_config.accum_blue_size = 0;
  203. video->gl_config.accum_alpha_size = 0;
  204. /* Initialize the video subsystem */
  205. memset(&vformat, 0, sizeof(vformat));
  206. if ( video->VideoInit(video, &vformat) < 0 ) {
  207. SDL_VideoQuit();
  208. return(-1);
  209. }
  210. /* Create a zero sized video surface of the appropriate format */
  211. video_flags = SDL_SWSURFACE;
  212. SDL_VideoSurface = SDL_CreateRGBSurface(video_flags, 0, 0,
  213. vformat.BitsPerPixel,
  214. vformat.Rmask, vformat.Gmask, vformat.Bmask, 0);
  215. if ( SDL_VideoSurface == NULL ) {
  216. SDL_VideoQuit();
  217. return(-1);
  218. }
  219. SDL_PublicSurface = NULL; /* Until SDL_SetVideoMode() */
  220. #if 0 /* Don't change the current palette - may be used by other programs.
  221.        * The application can't do anything with the display surface until
  222.        * a video mode has been set anyway. :)
  223.        */
  224. /* If we have a palettized surface, create a default palette */
  225. if ( SDL_VideoSurface->format->palette ) {
  226.         SDL_PixelFormat *vf = SDL_VideoSurface->format;
  227. SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
  228. video->SetColors(video,
  229.  0, vf->palette->ncolors, vf->palette->colors);
  230. }
  231. #endif
  232. video->info.vfmt = SDL_VideoSurface->format;
  233. /* Start the event loop */
  234. if ( SDL_StartEventLoop(flags) < 0 ) {
  235. SDL_VideoQuit();
  236. return(-1);
  237. }
  238. SDL_CursorInit(flags & SDL_INIT_EVENTTHREAD);
  239. /* We're ready to go! */
  240. return(0);
  241. }
  242. char *SDL_VideoDriverName(char *namebuf, int maxlen)
  243. {
  244. if ( current_video != NULL ) {
  245. strncpy(namebuf, current_video->name, maxlen-1);
  246. namebuf[maxlen-1] = '';
  247. return(namebuf);
  248. }
  249. return(NULL);
  250. }
  251. /*
  252.  * Get the current display surface
  253.  */
  254. SDL_Surface *SDL_GetVideoSurface(void)
  255. {
  256. SDL_Surface *visible;
  257. visible = NULL;
  258. if ( current_video ) {
  259. visible = current_video->visible;
  260. }
  261. return(visible);
  262. }
  263. /*
  264.  * Get the current information about the video hardware
  265.  */
  266. const SDL_VideoInfo *SDL_GetVideoInfo(void)
  267. {
  268. const SDL_VideoInfo *info;
  269. info = NULL;
  270. if ( current_video ) {
  271. info = &current_video->info;
  272. }
  273. return(info);
  274. }
  275. /*
  276.  * Return a pointer to an array of available screen dimensions for the
  277.  * given format, sorted largest to smallest.  Returns NULL if there are
  278.  * no dimensions available for a particular format, or (SDL_Rect **)-1
  279.  * if any dimension is okay for the given format.  If 'format' is NULL,
  280.  * the mode list will be for the format given by SDL_GetVideoInfo()->vfmt
  281.  */
  282. SDL_Rect ** SDL_ListModes (SDL_PixelFormat *format, Uint32 flags)
  283. {
  284. SDL_VideoDevice *video = current_video;
  285. SDL_VideoDevice *this  = current_video;
  286. SDL_Rect **modes;
  287. modes = NULL;
  288. if ( SDL_VideoSurface ) {
  289. if ( format == NULL ) {
  290. format = SDL_VideoSurface->format;
  291. }
  292. modes = video->ListModes(this, format, flags);
  293. }
  294. return(modes);
  295. }
  296. /*
  297.  * Check to see if a particular video mode is supported.
  298.  * It returns 0 if the requested mode is not supported under any bit depth,
  299.  * or returns the bits-per-pixel of the closest available mode with the
  300.  * given width and height.  If this bits-per-pixel is different from the
  301.  * one used when setting the video mode, SDL_SetVideoMode() will succeed,
  302.  * but will emulate the requested bits-per-pixel with a shadow surface.
  303.  */
  304. static Uint8 SDL_closest_depths[4][8] = {
  305. /* 8 bit closest depth ordering */
  306. { 0, 8, 16, 15, 32, 24, 0, 0 },
  307. /* 15,16 bit closest depth ordering */
  308. { 0, 16, 15, 32, 24, 8, 0, 0 },
  309. /* 24 bit closest depth ordering */
  310. { 0, 24, 32, 16, 15, 8, 0, 0 },
  311. /* 32 bit closest depth ordering */
  312. { 0, 32, 16, 15, 24, 8, 0, 0 }
  313. };
  314. int SDL_VideoModeOK (int width, int height, int bpp, Uint32 flags) 
  315. {
  316. int table, b, i;
  317. int supported;
  318. SDL_PixelFormat format;
  319. SDL_Rect **sizes;
  320. /* Currently 1 and 4 bpp are not supported */
  321. if ( bpp < 8 || bpp > 32 ) {
  322. return(0);
  323. }
  324. if ( (width == 0) || (height == 0) ) {
  325. return(0);
  326. }
  327. /* Search through the list valid of modes */
  328. memset(&format, 0, sizeof(format));
  329. supported = 0;
  330. table = ((bpp+7)/8)-1;
  331. SDL_closest_depths[table][0] = bpp;
  332. SDL_closest_depths[table][7] = 0;
  333. for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
  334. format.BitsPerPixel = SDL_closest_depths[table][b];
  335. sizes = SDL_ListModes(&format, flags);
  336. if ( sizes == (SDL_Rect **)0 ) {
  337. /* No sizes supported at this bit-depth */
  338. continue;
  339. } else 
  340. #ifdef macintosh /* MPW optimization bug? */
  341. if ( (sizes == (SDL_Rect **)0xFFFFFFFF) ||
  342. #else
  343. if ( (sizes == (SDL_Rect **)-1) ||
  344. #endif
  345.      current_video->handles_any_size ) {
  346. /* Any size supported at this bit-depth */
  347. supported = 1;
  348. continue;
  349. } else
  350. for ( i=0; sizes[i]; ++i ) {
  351. if ((sizes[i]->w == width) && (sizes[i]->h == height)) {
  352. supported = 1;
  353. break;
  354. }
  355. }
  356. }
  357. if ( supported ) {
  358. --b;
  359. return(SDL_closest_depths[table][b]);
  360. } else {
  361. return(0);
  362. }
  363. }
  364. /*
  365.  * Get the closest non-emulated video mode to the one requested
  366.  */
  367. static int SDL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags)
  368. {
  369. int table, b, i;
  370. int supported;
  371. int native_bpp;
  372. SDL_PixelFormat format;
  373. SDL_Rect **sizes;
  374. /* Try the original video mode, get the closest depth */
  375. native_bpp = SDL_VideoModeOK(*w, *h, *BitsPerPixel, flags);
  376. if ( native_bpp == *BitsPerPixel ) {
  377. return(1);
  378. }
  379. if ( native_bpp > 0 ) {
  380. *BitsPerPixel = native_bpp;
  381. return(1);
  382. }
  383. /* No exact size match at any depth, look for closest match */
  384. memset(&format, 0, sizeof(format));
  385. supported = 0;
  386. table = ((*BitsPerPixel+7)/8)-1;
  387. SDL_closest_depths[table][0] = *BitsPerPixel;
  388. SDL_closest_depths[table][7] = SDL_VideoSurface->format->BitsPerPixel;
  389. for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
  390. format.BitsPerPixel = SDL_closest_depths[table][b];
  391. sizes = SDL_ListModes(&format, flags);
  392. if ( sizes == (SDL_Rect **)0 ) {
  393. /* No sizes supported at this bit-depth */
  394. continue;
  395. }
  396. for ( i=0; sizes[i]; ++i ) {
  397. if ((sizes[i]->w < *w) || (sizes[i]->h < *h)) {
  398. if ( i > 0 ) {
  399. --i;
  400. *w = sizes[i]->w;
  401. *h = sizes[i]->h;
  402. *BitsPerPixel = SDL_closest_depths[table][b];
  403. supported = 1;
  404. } else {
  405. /* Largest mode too small... */;
  406. }
  407. break;
  408. }
  409. }
  410. if ( (i > 0) && ! sizes[i] ) {
  411. /* The smallest mode was larger than requested, OK */
  412. --i;
  413. *w = sizes[i]->w;
  414. *h = sizes[i]->h;
  415. *BitsPerPixel = SDL_closest_depths[table][b];
  416. supported = 1;
  417. }
  418. }
  419. if ( ! supported ) {
  420. SDL_SetError("No video mode large enough for %dx%d", *w, *h);
  421. }
  422. return(supported);
  423. }
  424. /* This should probably go somewhere else -- like SDL_surface.c */
  425. static void SDL_ClearSurface(SDL_Surface *surface)
  426. {
  427. Uint32 black;
  428. black = SDL_MapRGB(surface->format, 0, 0, 0);
  429. SDL_FillRect(surface, NULL, black);
  430. if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) {
  431. SDL_Flip(surface);
  432. SDL_FillRect(surface, NULL, black);
  433. }
  434. SDL_Flip(surface);
  435. }
  436. /*
  437.  * Create a shadow surface suitable for fooling the app. :-)
  438.  */
  439. static void SDL_CreateShadowSurface(int depth)
  440. {
  441. Uint32 Rmask, Gmask, Bmask;
  442. /* Allocate the shadow surface */
  443. if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
  444. Rmask = (SDL_VideoSurface->format)->Rmask;
  445. Gmask = (SDL_VideoSurface->format)->Gmask;
  446. Bmask = (SDL_VideoSurface->format)->Bmask;
  447. } else {
  448. Rmask = Gmask = Bmask = 0;
  449. }
  450. SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
  451. SDL_VideoSurface->w, SDL_VideoSurface->h,
  452. depth, Rmask, Gmask, Bmask, 0);
  453. if ( SDL_ShadowSurface == NULL ) {
  454. return;
  455. }
  456. /* 8-bit shadow surfaces report that they have exclusive palette */
  457. if ( SDL_ShadowSurface->format->palette ) {
  458. SDL_ShadowSurface->flags |= SDL_HWPALETTE;
  459. if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
  460. memcpy(SDL_ShadowSurface->format->palette->colors,
  461. SDL_VideoSurface->format->palette->colors,
  462. SDL_VideoSurface->format->palette->ncolors*
  463. sizeof(SDL_Color));
  464. } else {
  465. SDL_DitherColors(
  466. SDL_ShadowSurface->format->palette->colors, depth);
  467. }
  468. }
  469. /* If the video surface is resizable, the shadow should say so */
  470. if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) {
  471. SDL_ShadowSurface->flags |= SDL_RESIZABLE;
  472. }
  473. /* If the video surface has no frame, the shadow should say so */
  474. if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) {
  475. SDL_ShadowSurface->flags |= SDL_NOFRAME;
  476. }
  477. /* If the video surface is fullscreen, the shadow should say so */
  478. if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  479. SDL_ShadowSurface->flags |= SDL_FULLSCREEN;
  480. }
  481. /* If the video surface is flippable, the shadow should say so */
  482. if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  483. SDL_ShadowSurface->flags |= SDL_DOUBLEBUF;
  484. }
  485. return;
  486. }
  487. /*
  488.  * Set the requested video mode, allocating a shadow buffer if necessary.
  489.  */
  490. SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)
  491. {
  492. SDL_VideoDevice *video, *this;
  493. SDL_Surface *prev_mode, *mode;
  494. int video_w;
  495. int video_h;
  496. int video_bpp;
  497. int is_opengl;
  498. SDL_GrabMode saved_grab;
  499. /* Start up the video driver, if necessary..
  500.    WARNING: This is the only function protected this way!
  501.  */
  502. if ( ! current_video ) {
  503. if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
  504. return(NULL);
  505. }
  506. }
  507. this = video = current_video;
  508. /* Default to the current video bpp */
  509. if ( bpp == 0 ) {
  510. flags |= SDL_ANYFORMAT;
  511. bpp = SDL_VideoSurface->format->BitsPerPixel;
  512. }
  513. /* Get a good video mode, the closest one possible */
  514. video_w = width;
  515. video_h = height;
  516. video_bpp = bpp;
  517. if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) {
  518. return(NULL);
  519. }
  520. /* Check the requested flags */
  521. /* There's no palette in > 8 bits-per-pixel mode */
  522. if ( video_bpp > 8 ) {
  523. flags &= ~SDL_HWPALETTE;
  524. }
  525. #if 0
  526. if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  527. /* There's no windowed double-buffering */
  528. flags &= ~SDL_DOUBLEBUF;
  529. }
  530. #endif
  531. if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  532. /* Use hardware surfaces when double-buffering */
  533. flags |= SDL_HWSURFACE;
  534. }
  535. is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL );
  536. if ( is_opengl ) {
  537. /* These flags are for 2D video modes only */
  538. flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF);
  539. }
  540. /* Reset the keyboard here so event callbacks can run */
  541. SDL_ResetKeyboard();
  542. /* Clean up any previous video mode */
  543. if ( SDL_PublicSurface != NULL ) {
  544. SDL_PublicSurface = NULL;
  545. }
  546. if ( SDL_ShadowSurface != NULL ) {
  547. SDL_Surface *ready_to_go;
  548. ready_to_go = SDL_ShadowSurface;
  549. SDL_ShadowSurface = NULL;
  550. SDL_FreeSurface(ready_to_go);
  551. }
  552. if ( video->physpal ) {
  553. free(video->physpal->colors);
  554. free(video->physpal);
  555. video->physpal = NULL;
  556. }
  557. if( video->gammacols) {
  558.         free(video->gammacols);
  559. video->gammacols = NULL;
  560. }
  561. /* Save the previous grab state and turn off grab for mode switch */
  562. saved_grab = SDL_WM_GrabInputOff();
  563. /* Try to set the video mode, along with offset and clipping */
  564. prev_mode = SDL_VideoSurface;
  565. SDL_LockCursor();
  566. SDL_VideoSurface = NULL; /* In case it's freed by driver */
  567. mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
  568. if ( mode ) { /* Prevent resize events from mode change */
  569.     SDL_PrivateResize(mode->w, mode->h);
  570.     /* Sam - If we asked for OpenGL mode, and didn't get it, fail */
  571.     if ( is_opengl && !(mode->flags & SDL_OPENGL) ) {
  572. mode = NULL;
  573.     }
  574.         }
  575. /*
  576.  * rcg11292000
  577.  * If you try to set an SDL_OPENGL surface, and fail to find a
  578.  * matching  visual, then the next call to SDL_SetVideoMode()
  579.  * will segfault, since  we no longer point to a dummy surface,
  580.  * but rather NULL.
  581.  * Sam 11/29/00
  582.  * WARNING, we need to make sure that the previous mode hasn't
  583.  * already been freed by the video driver.  What do we do in
  584.  * that case?  Should we call SDL_VideoInit() again?
  585.  */
  586. SDL_VideoSurface = (mode != NULL) ? mode : prev_mode;
  587. if ( (mode != NULL) && (!is_opengl) ) {
  588. /* Sanity check */
  589. if ( (mode->w < width) || (mode->h < height) ) {
  590. SDL_SetError("Video mode smaller than requested");
  591. return(NULL);
  592. }
  593. /* If we have a palettized surface, create a default palette */
  594. if ( mode->format->palette ) {
  595.          SDL_PixelFormat *vf = mode->format;
  596. SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
  597. video->SetColors(this, 0, vf->palette->ncolors,
  598.                            vf->palette->colors);
  599. }
  600. /* Clear the surface to black */
  601. video->offset_x = 0;
  602. video->offset_y = 0;
  603. mode->offset = 0;
  604. SDL_SetClipRect(mode, NULL);
  605. SDL_ClearSurface(mode);
  606. /* Now adjust the offsets to match the desired mode */
  607. video->offset_x = (mode->w-width)/2;
  608. video->offset_y = (mode->h-height)/2;
  609. mode->offset = video->offset_y*mode->pitch +
  610. video->offset_x*mode->format->BytesPerPixel;
  611. #ifdef DEBUG_VIDEO
  612.   fprintf(stderr,
  613. "Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)n",
  614. width, height, bpp,
  615. mode->w, mode->h, mode->format->BitsPerPixel, mode->offset);
  616. #endif
  617. mode->w = width;
  618. mode->h = height;
  619. SDL_SetClipRect(mode, NULL);
  620. }
  621. SDL_ResetCursor();
  622. SDL_UnlockCursor();
  623. /* If we failed setting a video mode, return NULL... (Uh Oh!) */
  624. if ( mode == NULL ) {
  625. return(NULL);
  626. }
  627. /* If there is no window manager, set the SDL_NOFRAME flag */
  628. if ( ! video->info.wm_available ) {
  629. mode->flags |= SDL_NOFRAME;
  630. }
  631. /* Reset the mouse cursor and grab for new video mode */
  632. SDL_SetCursor(NULL);
  633. if ( video->UpdateMouse ) {
  634. video->UpdateMouse(this);
  635. }
  636. SDL_WM_GrabInput(saved_grab);
  637. SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */
  638. /* If we're running OpenGL, make the context current */
  639. if ( (video->screen->flags & SDL_OPENGL) &&
  640.       video->GL_MakeCurrent ) {
  641. if ( video->GL_MakeCurrent(this) < 0 ) {
  642. return(NULL);
  643. }
  644. }
  645. /* Set up a fake SDL surface for OpenGL "blitting" */
  646. if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) {
  647. /* Load GL functions for performing the texture updates */
  648. #ifdef HAVE_OPENGL
  649. #define SDL_PROC(ret,func,params) 
  650. do { 
  651. video->func = SDL_GL_GetProcAddress(#func); 
  652. if ( ! video->func ) { 
  653. SDL_SetError("Couldn't load GL function: %sn", #func); 
  654. return(NULL); 
  655. } while ( 0 );
  656. #include "SDL_glfuncs.h"
  657. #undef SDL_PROC
  658. /* Create a software surface for blitting */
  659. #ifdef GL_VERSION_1_2
  660. /* If the implementation either supports the packed pixels
  661.    extension, or implements the core OpenGL 1.2 API, it will
  662.    support the GL_UNSIGNED_SHORT_5_6_5 texture format.
  663.  */
  664. if ( (bpp == 16) &&
  665.      (strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") ||
  666.      (atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f))
  667.    ) {
  668. video->is_32bit = 0;
  669. SDL_VideoSurface = SDL_CreateRGBSurface(
  670. flags, 
  671. width, 
  672. height,  
  673. 16,
  674. 31 << 11,
  675. 63 << 5,
  676. 31,
  677. 0
  678. );
  679. }
  680. else
  681. #endif /* OpenGL 1.2 */
  682. {
  683. video->is_32bit = 1;
  684. SDL_VideoSurface = SDL_CreateRGBSurface(
  685. flags, 
  686. width, 
  687. height, 
  688. 32, 
  689. #if SDL_BYTEORDER == SDL_LIL_ENDIAN
  690. 0x000000FF,
  691. 0x0000FF00,
  692. 0x00FF0000,
  693. 0xFF000000
  694. #else
  695. 0xFF000000,
  696. 0x00FF0000,
  697. 0x0000FF00,
  698. 0x000000FF
  699. #endif
  700. );
  701. }
  702. if ( ! SDL_VideoSurface ) {
  703. return(NULL);
  704. }
  705. SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT;
  706. /* Free the original video mode surface (is this safe?) */
  707. SDL_FreeSurface(mode);
  708.                 /* Set the surface completely opaque & white by default */
  709. memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch );
  710. video->glGenTextures( 1, &video->texture );
  711. video->glBindTexture( GL_TEXTURE_2D, video->texture );
  712. video->glTexImage2D(
  713. GL_TEXTURE_2D,
  714. 0,
  715. video->is_32bit ? GL_RGBA : GL_RGB,
  716. 256,
  717. 256,
  718. 0,
  719. video->is_32bit ? GL_RGBA : GL_RGB,
  720. #ifdef GL_VERSION_1_2
  721. video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
  722. #else
  723. GL_UNSIGNED_BYTE,
  724. #endif
  725. NULL);
  726. video->UpdateRects = SDL_GL_UpdateRectsLock;
  727. #else
  728. SDL_SetError("Somebody forgot to #define HAVE_OPENGL");
  729. return(NULL);
  730. #endif
  731. }
  732. /* Create a shadow surface if necessary */
  733. /* There are three conditions under which we create a shadow surface:
  734. 1.  We need a particular bits-per-pixel that we didn't get.
  735. 2.  We need a hardware palette and didn't get one.
  736. 3.  We need a software surface and got a hardware surface.
  737. */
  738. if ( !(SDL_VideoSurface->flags & SDL_OPENGL) &&
  739.      (
  740.      (  !(flags&SDL_ANYFORMAT) &&
  741. (SDL_VideoSurface->format->BitsPerPixel != bpp)) ||
  742.      (   (flags&SDL_HWPALETTE) && 
  743. !(SDL_VideoSurface->flags&SDL_HWPALETTE)) ||
  744. /* If the surface is in hardware, video writes are visible
  745.    as soon as they are performed, so we need to buffer them
  746.  */
  747.      (   ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) &&
  748. (SDL_VideoSurface->flags&SDL_HWSURFACE))
  749.      ) ) {
  750. SDL_CreateShadowSurface(bpp);
  751. if ( SDL_ShadowSurface == NULL ) {
  752. SDL_SetError("Couldn't create shadow surface");
  753. return(NULL);
  754. }
  755. SDL_PublicSurface = SDL_ShadowSurface;
  756. } else {
  757. SDL_PublicSurface = SDL_VideoSurface;
  758. }
  759. video->info.vfmt = SDL_VideoSurface->format;
  760. /* We're done! */
  761. return(SDL_PublicSurface);
  762. }
  763. /* 
  764.  * Convert a surface into the video pixel format.
  765.  */
  766. SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface)
  767. {
  768. Uint32 flags;
  769. if ( ! SDL_PublicSurface ) {
  770. SDL_SetError("No video mode has been set");
  771. return(NULL);
  772. }
  773. /* Set the flags appropriate for copying to display surface */
  774. if (((SDL_PublicSurface->flags&SDL_HWSURFACE) == SDL_HWSURFACE) && current_video->info.blit_hw)
  775. flags = SDL_HWSURFACE;
  776. else 
  777. flags = SDL_SWSURFACE;
  778. #ifdef AUTORLE_DISPLAYFORMAT
  779. flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA));
  780. flags |= SDL_RLEACCELOK;
  781. #else
  782. flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK);
  783. #endif
  784. return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags));
  785. }
  786. /*
  787.  * Convert a surface into a format that's suitable for blitting to
  788.  * the screen, but including an alpha channel.
  789.  */
  790. SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface)
  791. {
  792. SDL_PixelFormat *vf;
  793. SDL_PixelFormat *format;
  794. SDL_Surface *converted;
  795. Uint32 flags;
  796. /* default to ARGB8888 */
  797. Uint32 amask = 0xff000000;
  798. Uint32 rmask = 0x00ff0000;
  799. Uint32 gmask = 0x0000ff00;
  800. Uint32 bmask = 0x000000ff;
  801. if ( ! SDL_PublicSurface ) {
  802. SDL_SetError("No video mode has been set");
  803. return(NULL);
  804. }
  805. vf = SDL_PublicSurface->format;
  806. switch(vf->BytesPerPixel) {
  807.     case 2:
  808. /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
  809.    For anything else (like ARGB4444) it doesn't matter
  810.    since we have no special code for it anyway */
  811. if ( (vf->Rmask == 0x1f) &&
  812.      (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
  813. rmask = 0xff;
  814. bmask = 0xff0000;
  815. }
  816. break;
  817.     case 3:
  818.     case 4:
  819. /* Keep the video format, as long as the high 8 bits are
  820.    unused or alpha */
  821. if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) {
  822. rmask = 0xff;
  823. bmask = 0xff0000;
  824. }
  825. break;
  826.     default:
  827. /* We have no other optimised formats right now. When/if a new
  828.    optimised alpha format is written, add the converter here */
  829. break;
  830. }
  831. format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
  832. flags = SDL_PublicSurface->flags & SDL_HWSURFACE;
  833. flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
  834. converted = SDL_ConvertSurface(surface, format, flags);
  835. SDL_FreeFormat(format);
  836. return(converted);
  837. }
  838. /*
  839.  * Update a specific portion of the physical screen
  840.  */
  841. void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  842. {
  843. if ( screen ) {
  844. SDL_Rect rect;
  845. /* Perform some checking */
  846. if ( w == 0 )
  847. w = screen->w;
  848. if ( h == 0 )
  849. h = screen->h;
  850. if ( (int)(x+w) > screen->w )
  851. return;
  852. if ( (int)(y+h) > screen->h )
  853. return;
  854. /* Fill the rectangle */
  855. rect.x = x;
  856. rect.y = y;
  857. rect.w = w;
  858. rect.h = h;
  859. SDL_UpdateRects(screen, 1, &rect);
  860. }
  861. }
  862. void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects)
  863. {
  864. int i;
  865. SDL_VideoDevice *video = current_video;
  866. SDL_VideoDevice *this = current_video;
  867. if ( screen == SDL_ShadowSurface ) {
  868. /* Blit the shadow surface using saved mapping */
  869.         SDL_Palette *pal = screen->format->palette;
  870. SDL_Color *saved_colors = NULL;
  871.         if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
  872. /* simulated 8bpp, use correct physical palette */
  873. saved_colors = pal->colors;
  874. if ( video->gammacols ) {
  875. /* gamma-corrected palette */
  876. pal->colors = video->gammacols;
  877. } else if ( video->physpal ) {
  878. /* physical palette different from logical */
  879. pal->colors = video->physpal->colors;
  880. }
  881. }
  882. if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
  883. SDL_LockCursor();
  884. SDL_DrawCursor(SDL_ShadowSurface);
  885. for ( i=0; i<numrects; ++i ) {
  886. SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 
  887. SDL_VideoSurface, &rects[i]);
  888. }
  889. SDL_EraseCursor(SDL_ShadowSurface);
  890. SDL_UnlockCursor();
  891. } else {
  892. for ( i=0; i<numrects; ++i ) {
  893. SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 
  894. SDL_VideoSurface, &rects[i]);
  895. }
  896. }
  897. if ( saved_colors )
  898. pal->colors = saved_colors;
  899. /* Fall through to video surface update */
  900. screen = SDL_VideoSurface;
  901. }
  902. if ( screen == SDL_VideoSurface ) {
  903. /* Update the video surface */
  904. if ( screen->offset ) {
  905. for ( i=0; i<numrects; ++i ) {
  906. rects[i].x += video->offset_x;
  907. rects[i].y += video->offset_y;
  908. }
  909. video->UpdateRects(this, numrects, rects);
  910. for ( i=0; i<numrects; ++i ) {
  911. rects[i].x -= video->offset_x;
  912. rects[i].y -= video->offset_y;
  913. }
  914. } else {
  915. video->UpdateRects(this, numrects, rects);
  916. }
  917. }
  918. }
  919. /*
  920.  * Performs hardware double buffering, if possible, or a full update if not.
  921.  */
  922. int SDL_Flip(SDL_Surface *screen)
  923. {
  924. SDL_VideoDevice *video = current_video;
  925. /* Copy the shadow surface to the video surface */
  926. if ( screen == SDL_ShadowSurface ) {
  927. SDL_Rect rect;
  928.         SDL_Palette *pal = screen->format->palette;
  929. SDL_Color *saved_colors = NULL;
  930.         if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
  931. /* simulated 8bpp, use correct physical palette */
  932. saved_colors = pal->colors;
  933. if ( video->gammacols ) {
  934. /* gamma-corrected palette */
  935. pal->colors = video->gammacols;
  936. } else if ( video->physpal ) {
  937. /* physical palette different from logical */
  938. pal->colors = video->physpal->colors;
  939. }
  940. }
  941. rect.x = 0;
  942. rect.y = 0;
  943. rect.w = screen->w;
  944. rect.h = screen->h;
  945. SDL_LowerBlit(SDL_ShadowSurface,&rect, SDL_VideoSurface,&rect);
  946. if ( saved_colors )
  947. pal->colors = saved_colors;
  948. screen = SDL_VideoSurface;
  949. }
  950. if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  951. SDL_VideoDevice *this  = current_video;
  952. return(video->FlipHWSurface(this, SDL_VideoSurface));
  953. } else {
  954. SDL_UpdateRect(screen, 0, 0, 0, 0);
  955. }
  956. return(0);
  957. }
  958. static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors,
  959.        int firstcolor, int ncolors)
  960. {
  961.         SDL_Palette *pal = screen->format->palette;
  962. SDL_Palette *vidpal;
  963. if ( colors != (pal->colors + firstcolor) ) {
  964.         memcpy(pal->colors + firstcolor, colors,
  965.        ncolors * sizeof(*colors));
  966. }
  967. vidpal = SDL_VideoSurface->format->palette;
  968. if ( (screen == SDL_ShadowSurface) && vidpal ) {
  969.         /*
  970.  * This is a shadow surface, and the physical
  971.  * framebuffer is also indexed. Propagate the
  972.  * changes to its logical palette so that
  973.  * updates are always identity blits
  974.  */
  975. memcpy(vidpal->colors + firstcolor, colors,
  976.        ncolors * sizeof(*colors));
  977. }
  978. SDL_FormatChanged(screen);
  979. }
  980. static int SetPalette_physical(SDL_Surface *screen,
  981.                                SDL_Color *colors, int firstcolor, int ncolors)
  982. {
  983. SDL_VideoDevice *video = current_video;
  984. int gotall = 1;
  985. if ( video->physpal ) {
  986. /* We need to copy the new colors, since we haven't
  987.  * already done the copy in the logical set above.
  988.  */
  989. memcpy(video->physpal->colors + firstcolor,
  990.        colors, ncolors * sizeof(*colors));
  991. }
  992. if ( screen == SDL_ShadowSurface ) {
  993. if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) {
  994. /*
  995.  * The real screen is also indexed - set its physical
  996.  * palette. The physical palette does not include the
  997.  * gamma modification, we apply it directly instead,
  998.  * but this only happens if we have hardware palette.
  999.  */
  1000. screen = SDL_VideoSurface;
  1001. } else {
  1002. /*
  1003.  * The video surface is not indexed - invalidate any
  1004.  * active shadow-to-video blit mappings.
  1005.  */
  1006. if ( screen->map->dst == SDL_VideoSurface ) {
  1007. SDL_InvalidateMap(screen->map);
  1008. }
  1009. if ( video->gamma ) {
  1010. if( ! video->gammacols ) {
  1011. SDL_Palette *pp = video->physpal;
  1012. if(!pp)
  1013. pp = screen->format->palette;
  1014. video->gammacols = malloc(pp->ncolors
  1015.   * sizeof(SDL_Color));
  1016. SDL_ApplyGamma(video->gamma,
  1017.        pp->colors,
  1018.        video->gammacols,
  1019.        pp->ncolors);
  1020. } else {
  1021. SDL_ApplyGamma(video->gamma, colors,
  1022.        video->gammacols
  1023.        + firstcolor,
  1024.        ncolors);
  1025. }
  1026. }
  1027. SDL_UpdateRect(screen, 0, 0, 0, 0);
  1028. }
  1029. }
  1030. if ( screen == SDL_VideoSurface ) {
  1031. SDL_Color gcolors[256];
  1032.         if ( video->gamma ) {
  1033.         SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors);
  1034. colors = gcolors;
  1035. }
  1036. gotall = video->SetColors(video, firstcolor, ncolors, colors);
  1037. if ( ! gotall ) {
  1038. /* The video flags shouldn't have SDL_HWPALETTE, and
  1039.    the video driver is responsible for copying back the
  1040.    correct colors into the video surface palette.
  1041. */
  1042. ;
  1043. }
  1044. SDL_CursorPaletteChanged();
  1045. }
  1046. return gotall;
  1047. }
  1048. /*
  1049.  * Set the physical and/or logical colormap of a surface:
  1050.  * Only the screen has a physical colormap. It determines what is actually
  1051.  * sent to the display.
  1052.  * The logical colormap is used to map blits to/from the surface.
  1053.  * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL
  1054.  *
  1055.  * Return nonzero if all colours were set as requested, or 0 otherwise.
  1056.  */
  1057. int SDL_SetPalette(SDL_Surface *screen, int which,
  1058.    SDL_Color *colors, int firstcolor, int ncolors)
  1059. {
  1060.         SDL_Palette *pal;
  1061. int gotall;
  1062. int palsize;
  1063. if ( ! current_video ) {
  1064. return 0;
  1065. }
  1066. if ( screen != SDL_PublicSurface ) {
  1067.         /* only screens have physical palettes */
  1068.         which &= ~SDL_PHYSPAL;
  1069. } else if( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) {
  1070.         /* hardware palettes required for split colormaps */
  1071.         which |= SDL_PHYSPAL | SDL_LOGPAL;
  1072. }
  1073. /* Verify the parameters */
  1074. pal = screen->format->palette;
  1075. if( !pal ) {
  1076.         return 0; /* not a palettized surface */
  1077. }
  1078. gotall = 1;
  1079. palsize = 1 << screen->format->BitsPerPixel;
  1080. if ( ncolors > (palsize - firstcolor) ) {
  1081.         ncolors = (palsize - firstcolor);
  1082. gotall = 0;
  1083. }
  1084. if ( which & SDL_LOGPAL ) {
  1085. /*
  1086.  * Logical palette change: The actual screen isn't affected,
  1087.  * but the internal colormap is altered so that the
  1088.  * interpretation of the pixel values (for blits etc) is
  1089.  * changed.
  1090.  */
  1091.         SetPalette_logical(screen, colors, firstcolor, ncolors);
  1092. }
  1093. if ( which & SDL_PHYSPAL ) {
  1094. SDL_VideoDevice *video = current_video;
  1095.         /*
  1096.  * Physical palette change: This doesn't affect the
  1097.  * program's idea of what the screen looks like, but changes
  1098.  * its actual appearance.
  1099.  */
  1100.         if(!video)
  1101.         return gotall; /* video not yet initialized */
  1102. if(!video->physpal && !(which & SDL_LOGPAL) ) {
  1103. /* Lazy physical palette allocation */
  1104.         int size;
  1105. SDL_Palette *pp = malloc(sizeof(*pp));
  1106. current_video->physpal = pp;
  1107. pp->ncolors = pal->ncolors;
  1108. size = pp->ncolors * sizeof(SDL_Color);
  1109. pp->colors = malloc(size);
  1110. memcpy(pp->colors, pal->colors, size);
  1111. }
  1112. if ( ! SetPalette_physical(screen,
  1113.                            colors, firstcolor, ncolors) ) {
  1114. gotall = 0;
  1115. }
  1116. }
  1117. return gotall;
  1118. }
  1119. int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor,
  1120.   int ncolors)
  1121. {
  1122.         return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL,
  1123.       colors, firstcolor, ncolors);
  1124. }
  1125. /*
  1126.  * Clean up the video subsystem
  1127.  */
  1128. void SDL_VideoQuit (void)
  1129. {
  1130. SDL_Surface *ready_to_go;
  1131. if ( current_video ) {
  1132. SDL_VideoDevice *video = current_video;
  1133. SDL_VideoDevice *this  = current_video;
  1134. /* Halt event processing before doing anything else */
  1135. SDL_StopEventLoop();
  1136. /* Clean up allocated window manager items */
  1137. if ( SDL_PublicSurface ) {
  1138. SDL_PublicSurface = NULL;
  1139. }
  1140. SDL_CursorQuit();
  1141. /* Just in case... */
  1142. SDL_WM_GrabInputOff();
  1143. /* Clean up the system video */
  1144. video->VideoQuit(this);
  1145. /* Free any lingering surfaces */
  1146. ready_to_go = SDL_ShadowSurface;
  1147. SDL_ShadowSurface = NULL;
  1148. SDL_FreeSurface(ready_to_go);
  1149. if ( SDL_VideoSurface != NULL ) {
  1150. ready_to_go = SDL_VideoSurface;
  1151. SDL_VideoSurface = NULL;
  1152. SDL_FreeSurface(ready_to_go);
  1153. }
  1154. SDL_PublicSurface = NULL;
  1155. /* Clean up miscellaneous memory */
  1156. if ( video->physpal ) {
  1157. free(video->physpal->colors);
  1158. free(video->physpal);
  1159. video->physpal = NULL;
  1160. }
  1161. if ( video->gammacols ) {
  1162. free(video->gammacols);
  1163. video->gammacols = NULL;
  1164. }
  1165. if ( video->gamma ) {
  1166. free(video->gamma);
  1167. video->gamma = NULL;
  1168. }
  1169. if ( video->wm_title != NULL ) {
  1170. free(video->wm_title);
  1171. video->wm_title = NULL;
  1172. }
  1173. if ( video->wm_icon != NULL ) {
  1174. free(video->wm_icon);
  1175. video->wm_icon = NULL;
  1176. }
  1177. /* Finish cleaning up video subsystem */
  1178. video->free(this);
  1179. current_video = NULL;
  1180. }
  1181. return;
  1182. }
  1183. /* Load the GL driver library */
  1184. int SDL_GL_LoadLibrary(const char *path)
  1185. {
  1186. SDL_VideoDevice *video = current_video;
  1187. SDL_VideoDevice *this = current_video;
  1188. int retval;
  1189. retval = -1;
  1190. if ( video && video->GL_LoadLibrary ) {
  1191. retval = video->GL_LoadLibrary(this, path);
  1192. } else {
  1193. SDL_SetError("No dynamic GL support in video driver");
  1194. }
  1195. return(retval);
  1196. }
  1197. void *SDL_GL_GetProcAddress(const char* proc)
  1198. {
  1199. SDL_VideoDevice *video = current_video;
  1200. SDL_VideoDevice *this = current_video;
  1201. void *func;
  1202. func = NULL;
  1203. if ( video->GL_GetProcAddress ) {
  1204. if ( video->gl_config.driver_loaded ) {
  1205. func = video->GL_GetProcAddress(this, proc);
  1206. } else {
  1207. SDL_SetError("No GL driver has been loaded");
  1208. }
  1209. } else {
  1210. SDL_SetError("No dynamic GL support in video driver");
  1211. }
  1212. return func;
  1213. }
  1214. /* Set the specified GL attribute for setting up a GL video mode */
  1215. int SDL_GL_SetAttribute( SDL_GLattr attr, int value )
  1216. {
  1217. int retval;
  1218. SDL_VideoDevice *video = current_video;
  1219. retval = 0;
  1220. switch (attr) {
  1221. case SDL_GL_RED_SIZE:
  1222. video->gl_config.red_size = value;
  1223. break;
  1224. case SDL_GL_GREEN_SIZE:
  1225. video->gl_config.green_size = value;
  1226. break;
  1227. case SDL_GL_BLUE_SIZE:
  1228. video->gl_config.blue_size = value;
  1229. break;
  1230. case SDL_GL_ALPHA_SIZE:
  1231. video->gl_config.alpha_size = value;
  1232. break;
  1233. case SDL_GL_DOUBLEBUFFER:
  1234. video->gl_config.double_buffer = value;
  1235. break;
  1236.          case SDL_GL_BUFFER_SIZE:
  1237.          video->gl_config.buffer_size = value;
  1238. break;
  1239. case SDL_GL_DEPTH_SIZE:
  1240. video->gl_config.depth_size = value;
  1241. break;
  1242. case SDL_GL_STENCIL_SIZE:
  1243. video->gl_config.stencil_size = value;
  1244. break;
  1245.         case SDL_GL_ACCUM_RED_SIZE:
  1246. video->gl_config.accum_red_size = value;
  1247. break;
  1248.         case SDL_GL_ACCUM_GREEN_SIZE:
  1249. video->gl_config.accum_green_size = value;
  1250. break;
  1251.         case SDL_GL_ACCUM_BLUE_SIZE:
  1252. video->gl_config.accum_blue_size = value;
  1253. break;
  1254.         case SDL_GL_ACCUM_ALPHA_SIZE:
  1255. video->gl_config.accum_alpha_size = value;
  1256. break;
  1257. default:
  1258. SDL_SetError("Unknown OpenGL attribute");
  1259. retval = -1;
  1260. break;
  1261. }
  1262. return(retval);
  1263. }
  1264. /* Retrieve an attribute value from the windowing system. */
  1265. int SDL_GL_GetAttribute(SDL_GLattr attr, int* value)
  1266. {
  1267. int retval = -1;
  1268. SDL_VideoDevice* video = current_video;
  1269. SDL_VideoDevice* this = current_video;
  1270. if ( video->GL_GetAttribute ) {
  1271. retval = this->GL_GetAttribute(this, attr, value);
  1272. } else {
  1273. *value = 0;
  1274. SDL_SetError("GL_GetAttribute not supported");
  1275. }
  1276. return retval;
  1277. }
  1278. /* Perform a GL buffer swap on the current GL context */
  1279. void SDL_GL_SwapBuffers(void)
  1280. {
  1281. SDL_VideoDevice *video = current_video;
  1282. SDL_VideoDevice *this = current_video;
  1283. if ( video->screen->flags & SDL_OPENGL ) {
  1284. video->GL_SwapBuffers(this);
  1285. } else {
  1286. SDL_SetError("OpenGL video mode has not been set");
  1287. }
  1288. }
  1289. /* Update rects with locking */
  1290. void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects)
  1291. {
  1292. SDL_GL_Lock();
  1293.   SDL_GL_UpdateRects(numrects, rects);
  1294. SDL_GL_Unlock();
  1295. }
  1296. /* Update rects without state setting and changing (the caller is responsible for it) */
  1297. void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects)
  1298. {
  1299. #ifdef HAVE_OPENGL
  1300. SDL_VideoDevice *this = current_video;
  1301. SDL_Rect update, tmp;
  1302. int x, y, i;
  1303. for ( i = 0; i < numrects; i++ )
  1304. {
  1305. tmp.y = rects[i].y;
  1306. tmp.h = rects[i].h;
  1307. for ( y = 0; y <= rects[i].h / 256; y++ )
  1308. {
  1309. tmp.x = rects[i].x;
  1310. tmp.w = rects[i].w;
  1311. for ( x = 0; x <= rects[i].w / 256; x++ )
  1312. {
  1313. update.x = tmp.x;
  1314. update.y = tmp.y;
  1315. update.w = tmp.w;
  1316. update.h = tmp.h;
  1317. if ( update.w > 256 )
  1318. update.w = 256;
  1319. if ( update.h > 256 )
  1320. update.h = 256;
  1321. this->glFlush();
  1322. this->glTexSubImage2D( 
  1323. GL_TEXTURE_2D, 
  1324. 0, 
  1325. 0, 
  1326. 0, 
  1327. update.w, 
  1328. update.h, 
  1329. this->is_32bit? GL_RGBA : GL_RGB,
  1330. #ifdef GL_VERSION_1_2
  1331. this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
  1332. #else
  1333. GL_UNSIGNED_BYTE,
  1334. #endif
  1335. (Uint8 *)this->screen->pixels + 
  1336. this->screen->format->BytesPerPixel * update.x + 
  1337. update.y * this->screen->pitch );
  1338. this->glFlush();
  1339. /*
  1340. * Note the parens around the function name:
  1341. * This is because some OpenGL implementations define glTexCoord etc 
  1342. * as macros, and we don't want them expanded here.
  1343. */
  1344. this->glBegin(GL_TRIANGLE_STRIP);
  1345. (this->glTexCoord2f)( 0.0, 0.0 );
  1346. (this->glVertex2i)( update.x, update.y );
  1347. (this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 );
  1348. (this->glVertex2i)( update.x + update.w, update.y );
  1349. (this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) );
  1350. (this->glVertex2i)( update.x, update.y + update.h );
  1351. (this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) );
  1352. (this->glVertex2i)( update.x + update.w , update.y + update.h );
  1353. this->glEnd();
  1354. tmp.x += 256;
  1355. tmp.w -= 256;
  1356. }
  1357. tmp.y += 256;
  1358. tmp.h -= 256;
  1359. }
  1360. }
  1361. #endif
  1362. }
  1363. /* Lock == save current state */
  1364. void SDL_GL_Lock()
  1365. {
  1366. #ifdef HAVE_OPENGL
  1367. lock_count--;
  1368. if (lock_count==-1)
  1369. {
  1370. SDL_VideoDevice *this = current_video;
  1371. this->glPushAttrib( GL_ALL_ATTRIB_BITS ); /* TODO: narrow range of what is saved */
  1372. #ifdef GL_CLIENT_PIXEL_STORE_BIT
  1373. this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
  1374. #endif
  1375. this->glEnable(GL_TEXTURE_2D);
  1376. this->glEnable(GL_BLEND);
  1377. this->glDisable(GL_FOG);
  1378. this->glDisable(GL_ALPHA_TEST);
  1379. this->glDisable(GL_DEPTH_TEST);
  1380. this->glDisable(GL_SCISSOR_TEST);
  1381. this->glDisable(GL_STENCIL_TEST);
  1382. this->glDisable(GL_CULL_FACE);
  1383. this->glBindTexture( GL_TEXTURE_2D, this->texture );
  1384. this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  1385. this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  1386. this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  1387. this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  1388. this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  1389. this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel );
  1390. this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1391. (this->glColor4f)(1.0, 1.0, 1.0, 1.0); /* Solaris workaround */
  1392. this->glViewport(0, 0, this->screen->w, this->screen->h);
  1393. this->glMatrixMode(GL_PROJECTION);
  1394. this->glPushMatrix();
  1395. this->glLoadIdentity();
  1396. this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0);
  1397. this->glMatrixMode(GL_MODELVIEW);
  1398. this->glPushMatrix();
  1399. this->glLoadIdentity();
  1400. }
  1401. #endif
  1402. }
  1403. /* Unlock == restore saved state */
  1404. void SDL_GL_Unlock()
  1405. {
  1406. #ifdef HAVE_OPENGL
  1407. lock_count++;
  1408. if (lock_count==0)
  1409. {
  1410. SDL_VideoDevice *this = current_video;
  1411. this->glPopMatrix();
  1412. this->glMatrixMode(GL_PROJECTION);
  1413. this->glPopMatrix();
  1414. this->glPopClientAttrib();
  1415. this->glPopAttrib();
  1416. }
  1417. #endif
  1418. }
  1419. /*
  1420.  * Sets/Gets the title and icon text of the display window, if any.
  1421.  */
  1422. void SDL_WM_SetCaption (const char *title, const char *icon)
  1423. {
  1424. SDL_VideoDevice *video = current_video;
  1425. SDL_VideoDevice *this  = current_video;
  1426. if ( video ) {
  1427. if ( title ) {
  1428. if ( video->wm_title ) {
  1429. free(video->wm_title);
  1430. }
  1431. video->wm_title = (char *)malloc(strlen(title)+1);
  1432. if ( video->wm_title != NULL ) {
  1433. strcpy(video->wm_title, title);
  1434. }
  1435. }
  1436. if ( icon ) {
  1437. if ( video->wm_icon ) {
  1438. free(video->wm_icon);
  1439. }
  1440. video->wm_icon = (char *)malloc(strlen(icon)+1);
  1441. if ( video->wm_icon != NULL ) {
  1442. strcpy(video->wm_icon, icon);
  1443. }
  1444. }
  1445. if ( (title || icon) && (video->SetCaption != NULL) ) {
  1446. video->SetCaption(this, video->wm_title,video->wm_icon);
  1447. }
  1448. }
  1449. }
  1450. void SDL_WM_GetCaption (char **title, char **icon)
  1451. {
  1452. SDL_VideoDevice *video = current_video;
  1453. if ( video ) {
  1454. if ( title ) {
  1455. *title = video->wm_title;
  1456. }
  1457. if ( icon ) {
  1458. *icon = video->wm_icon;
  1459. }
  1460. }
  1461. }
  1462. /* Utility function used by SDL_WM_SetIcon() */
  1463. static void CreateMaskFromColorKey(SDL_Surface *icon, Uint8 *mask)
  1464. {
  1465. int x, y;
  1466. Uint32 colorkey;
  1467. #define SET_MASKBIT(icon, x, y, mask) 
  1468. mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
  1469. colorkey = icon->format->colorkey;
  1470. switch (icon->format->BytesPerPixel) {
  1471. case 1: { Uint8 *pixels;
  1472. for ( y=0; y<icon->h; ++y ) {
  1473. pixels = (Uint8 *)icon->pixels + y*icon->pitch;
  1474. for ( x=0; x<icon->w; ++x ) {
  1475. if ( *pixels++ == colorkey ) {
  1476. SET_MASKBIT(icon, x, y, mask);
  1477. }
  1478. }
  1479. }
  1480. }
  1481. break;
  1482. case 2: { Uint16 *pixels;
  1483. for ( y=0; y<icon->h; ++y ) {
  1484. pixels = (Uint16 *)icon->pixels +
  1485.                    y*icon->pitch/2;
  1486. for ( x=0; x<icon->w; ++x ) {
  1487. if ( *pixels++ == colorkey ) {
  1488. SET_MASKBIT(icon, x, y, mask);
  1489. }
  1490. }
  1491. }
  1492. }
  1493. break;
  1494. case 4: { Uint32 *pixels;
  1495. for ( y=0; y<icon->h; ++y ) {
  1496. pixels = (Uint32 *)icon->pixels +
  1497.                    y*icon->pitch/4;
  1498. for ( x=0; x<icon->w; ++x ) {
  1499. if ( *pixels++ == colorkey ) {
  1500. SET_MASKBIT(icon, x, y, mask);
  1501. }
  1502. }
  1503. }
  1504. }
  1505. break;
  1506. }
  1507. }
  1508. /*
  1509.  * Sets the window manager icon for the display window.
  1510.  */
  1511. void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask)
  1512. {
  1513. SDL_VideoDevice *video = current_video;
  1514. SDL_VideoDevice *this  = current_video;
  1515. if ( icon && video->SetIcon ) {
  1516. /* Generate a mask if necessary, and create the icon! */
  1517. if ( mask == NULL ) {
  1518. int mask_len = icon->h*(icon->w+7)/8;
  1519. mask = (Uint8 *)malloc(mask_len);
  1520. if ( mask == NULL ) {
  1521. return;
  1522. }
  1523. memset(mask, ~0, mask_len);
  1524. if ( icon->flags & SDL_SRCCOLORKEY ) {
  1525. CreateMaskFromColorKey(icon, mask);
  1526. }
  1527. video->SetIcon(video, icon, mask);
  1528. free(mask);
  1529. } else {
  1530. video->SetIcon(this, icon, mask);
  1531. }
  1532. }
  1533. }
  1534. /*
  1535.  * Grab or ungrab the keyboard and mouse input.
  1536.  * This function returns the final grab mode after calling the
  1537.  * driver dependent function.
  1538.  */
  1539. static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode)
  1540. {
  1541. SDL_VideoDevice *video = current_video;
  1542. SDL_VideoDevice *this  = current_video;
  1543. /* Only do something if we have support for grabs */
  1544. if ( video->GrabInput == NULL ) {
  1545. return(video->input_grab);
  1546. }
  1547. /* If the final grab mode if off, only then do we actually grab */
  1548. #ifdef DEBUG_GRAB
  1549.   printf("SDL_WM_GrabInputRaw(%d) ... ", mode);
  1550. #endif
  1551. if ( mode == SDL_GRAB_OFF ) {
  1552. if ( video->input_grab != SDL_GRAB_OFF ) {
  1553. mode = video->GrabInput(this, mode);
  1554. }
  1555. } else {
  1556. if ( video->input_grab == SDL_GRAB_OFF ) {
  1557. mode = video->GrabInput(this, mode);
  1558. }
  1559. }
  1560. if ( mode != video->input_grab ) {
  1561. video->input_grab = mode;
  1562. if ( video->CheckMouseMode ) {
  1563. video->CheckMouseMode(this);
  1564. }
  1565. }
  1566. #ifdef DEBUG_GRAB
  1567.   printf("Final mode %dn", video->input_grab);
  1568. #endif
  1569. /* Return the final grab state */
  1570. if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1571. mode -= SDL_GRAB_FULLSCREEN;
  1572. }
  1573. return(mode);
  1574. }
  1575. SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode)
  1576. {
  1577. SDL_VideoDevice *video = current_video;
  1578. /* If the video isn't initialized yet, we can't do anything */
  1579. if ( ! video ) {
  1580. return SDL_GRAB_OFF;
  1581. }
  1582. /* Return the current mode on query */
  1583. if ( mode == SDL_GRAB_QUERY ) {
  1584. mode = video->input_grab;
  1585. if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1586. mode -= SDL_GRAB_FULLSCREEN;
  1587. }
  1588. return(mode);
  1589. }
  1590. #ifdef DEBUG_GRAB
  1591.   printf("SDL_WM_GrabInput(%d) ... ", mode);
  1592. #endif
  1593. /* If the video surface is fullscreen, we always grab */
  1594. if ( mode >= SDL_GRAB_FULLSCREEN ) {
  1595. mode -= SDL_GRAB_FULLSCREEN;
  1596. }
  1597. if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
  1598. mode += SDL_GRAB_FULLSCREEN;
  1599. }
  1600. return(SDL_WM_GrabInputRaw(mode));
  1601. }
  1602. static SDL_GrabMode SDL_WM_GrabInputOff(void)
  1603. {
  1604. SDL_GrabMode mode;
  1605. /* First query the current grab state */
  1606. mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
  1607. /* Now explicitly turn off input grab */
  1608. SDL_WM_GrabInputRaw(SDL_GRAB_OFF);
  1609. /* Return the old state */
  1610. return(mode);
  1611. }
  1612. /*
  1613.  * Iconify the window in window managed environments.
  1614.  * A successful iconification will result in an SDL_APPACTIVE loss event.
  1615.  */
  1616. int SDL_WM_IconifyWindow(void)
  1617. {
  1618. SDL_VideoDevice *video = current_video;
  1619. SDL_VideoDevice *this  = current_video;
  1620. int retval;
  1621. retval = 0;
  1622. if ( video->IconifyWindow ) {
  1623. retval = video->IconifyWindow(this);
  1624. }
  1625. return(retval);
  1626. }
  1627. /*
  1628.  * Toggle fullscreen mode
  1629.  */
  1630. int SDL_WM_ToggleFullScreen(SDL_Surface *surface)
  1631. {
  1632. SDL_VideoDevice *video = current_video;
  1633. SDL_VideoDevice *this  = current_video;
  1634. int toggled;
  1635. toggled = 0;
  1636. if ( SDL_PublicSurface && (surface == SDL_PublicSurface) &&
  1637.      video->ToggleFullScreen ) {
  1638. if ( surface->flags & SDL_FULLSCREEN ) {
  1639. toggled = video->ToggleFullScreen(this, 0);
  1640. if ( toggled ) {
  1641. SDL_VideoSurface->flags &= ~SDL_FULLSCREEN;
  1642. SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
  1643. }
  1644. } else {
  1645. toggled = video->ToggleFullScreen(this, 1);
  1646. if ( toggled ) {
  1647. SDL_VideoSurface->flags |= SDL_FULLSCREEN;
  1648. SDL_PublicSurface->flags |= SDL_FULLSCREEN;
  1649. }
  1650. }
  1651. /* Double-check the grab state inside SDL_WM_GrabInput() */
  1652. if ( toggled ) {
  1653. SDL_WM_GrabInput(video->input_grab);
  1654. }
  1655. }
  1656. return(toggled);
  1657. }
  1658. /*
  1659.  * Get some platform dependent window manager information
  1660.  */
  1661. int SDL_GetWMInfo (SDL_SysWMinfo *info)
  1662. {
  1663. SDL_VideoDevice *video = current_video;
  1664. SDL_VideoDevice *this  = current_video;
  1665. if ( video && video->GetWMInfo ) {
  1666. return(video->GetWMInfo(this, info));
  1667. } else {
  1668. return(0);
  1669. }
  1670. }