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