PANDORA: Make GLES context compatible with latest driver (FB only, no X11)
[mupen64plus-pandora.git] / source / gles2n64 / src / sdl2_compat.h
CommitLineData
34cf4058 1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include <SDL_surface.h>
23
24typedef struct
25{
26 Uint8 *src;
27 int src_w, src_h;
28 int src_pitch;
29 int src_skip;
30 Uint8 *dst;
31 int dst_w, dst_h;
32 int dst_pitch;
33 int dst_skip;
34 SDL_PixelFormat *src_fmt;
35 SDL_PixelFormat *dst_fmt;
36 Uint8 *table;
37 int flags;
38 Uint32 colorkey;
39 Uint8 r, g, b, a;
40} SDL_BlitInfo;
41
42/* Blit mapping definition */
43typedef struct SDL_BlitMap
44{
45 SDL_Surface *dst;
46 int identity;
47 SDL_blit blit;
48 void *data;
49 SDL_BlitInfo info;
50
51 /* the version count matches the destination; mismatch indicates
52 an invalid mapping */
53 Uint32 dst_palette_version;
54 Uint32 src_palette_version;
55} SDL_BlitMap;
56
57typedef struct SDL_VideoInfo
58{
59 Uint32 hw_available:1;
60 Uint32 wm_available:1;
61 Uint32 UnusedBits1:6;
62 Uint32 UnusedBits2:1;
63 Uint32 blit_hw:1;
64 Uint32 blit_hw_CC:1;
65 Uint32 blit_hw_A:1;
66 Uint32 blit_sw:1;
67 Uint32 blit_sw_CC:1;
68 Uint32 blit_sw_A:1;
69 Uint32 blit_fill:1;
70 Uint32 UnusedBits3:16;
71 Uint32 video_mem;
72
73 SDL_PixelFormat *vfmt;
74
75 int current_w;
76 int current_h;
77} SDL_VideoInfo;
78
79#define SDL_ANYFORMAT 0x00100000
80#define SDL_HWPALETTE 0x00200000
81#define SDL_FULLSCREEN 0x00800000
82#define SDL_RESIZABLE 0x01000000
83#define SDL_NOFRAME 0x02000000
84#define SDL_OPENGL 0x04000000
85#define SDL_HWSURFACE 0x08000001 /**< \note Not used */
86
87#define SDL_BUTTON_WHEELUP 4
88#define SDL_BUTTON_WHEELDOWN 5
89
90int initialized_video = 0;
91
92static SDL_Window *SDL_VideoWindow = NULL;
93static SDL_Surface *SDL_WindowSurface = NULL;
94static SDL_Surface *SDL_VideoSurface = NULL;
95static SDL_Surface *SDL_ShadowSurface = NULL;
96static SDL_Surface *SDL_PublicSurface = NULL;
97static SDL_Rect SDL_VideoViewport;
98static char *wm_title = NULL;
99static Uint32 SDL_VideoFlags = 0;
100static SDL_GLContext *SDL_VideoContext = NULL;
101static SDL_Surface *SDL_VideoIcon;
102
103static void
104SDL_WM_SetCaption(const char *title, const char *icon)
105{
106 if (wm_title) {
107 SDL_free(wm_title);
108 }
109 if (title) {
110 wm_title = SDL_strdup(title);
111 } else {
112 wm_title = NULL;
113 }
114 SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
115}
116
117static int
118GetVideoDisplay()
119{
120 const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
121 if ( !variable ) {
122 variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
123 }
124 if ( variable ) {
125 return SDL_atoi(variable);
126 } else {
127 return 0;
128 }
129}
130
131static const SDL_VideoInfo *
132SDL_GetVideoInfo(void)
133{
134 static SDL_VideoInfo info;
135 SDL_DisplayMode mode;
136
137 /* Memory leak, compatibility code, who cares? */
138 if (!info.vfmt && SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode) == 0) {
139 info.vfmt = SDL_AllocFormat(mode.format);
140 info.current_w = mode.w;
141 info.current_h = mode.h;
142 }
143 return &info;
144}
145
146static SDL_Rect **
147SDL_ListModes(const SDL_PixelFormat * format, Uint32 flags)
148{
149 int i, nmodes;
150 SDL_Rect **modes;
151
152 if (!initialized_video) {
153 return NULL;
154 }
155
156 if (!(flags & SDL_FULLSCREEN)) {
157 return (SDL_Rect **) (-1);
158 }
159
160 if (!format) {
161 format = SDL_GetVideoInfo()->vfmt;
162 }
163
164 /* Memory leak, but this is a compatibility function, who cares? */
165 nmodes = 0;
166 modes = NULL;
167 for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
168 SDL_DisplayMode mode;
169 int bpp;
170
171 SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
172 if (!mode.w || !mode.h) {
173 return (SDL_Rect **) (-1);
174 }
175
176 /* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
177 if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
178 bpp = SDL_BITSPERPIXEL(mode.format);
179 } else {
180 bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
181 }
182
183 if (bpp != format->BitsPerPixel) {
184 continue;
185 }
186 if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
187 && modes[nmodes - 1]->h == mode.h) {
188 continue;
189 }
190
191 modes = (SDL_Rect**)SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
192 if (!modes) {
193 return NULL;
194 }
195 modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
196 if (!modes[nmodes]) {
197 return NULL;
198 }
199 modes[nmodes]->x = 0;
200 modes[nmodes]->y = 0;
201 modes[nmodes]->w = mode.w;
202 modes[nmodes]->h = mode.h;
203 ++nmodes;
204 }
205 if (modes) {
206 modes[nmodes] = NULL;
207 }
208 return modes;
209}
210
211static void
212SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
213{
214 int i;
215
216 if (screen == SDL_ShadowSurface) {
217 for (i = 0; i < numrects; ++i) {
218 SDL_BlitSurface(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
219 &rects[i]);
220 }
221
222 /* Fall through to video surface update */
223 screen = SDL_VideoSurface;
224 }
225 if (screen == SDL_VideoSurface) {
226 if (SDL_VideoViewport.x || SDL_VideoViewport.y) {
227 SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
228 SDL_Rect *stackrect;
229 const SDL_Rect *rect;
230
231 /* Offset all the rectangles before updating */
232 for (i = 0; i < numrects; ++i) {
233 rect = &rects[i];
234 stackrect = &stackrects[i];
235 stackrect->x = SDL_VideoViewport.x + rect->x;
236 stackrect->y = SDL_VideoViewport.y + rect->y;
237 stackrect->w = rect->w;
238 stackrect->h = rect->h;
239 }
240 SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, stackrects, numrects);
241 SDL_stack_free(stackrects);
242 } else {
243 SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, rects, numrects);
244 }
245 }
246}
247
248static void
249SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
250{
251 if (screen) {
252 SDL_Rect rect;
253
254 /* Fill the rectangle */
255 rect.x = (int) x;
256 rect.y = (int) y;
257 rect.w = (int) (w ? w : screen->w);
258 rect.h = (int) (h ? h : screen->h);
259 SDL_UpdateRects(screen, 1, &rect);
260 }
261}
262
263static int
264SDL_Flip(SDL_Surface * screen)
265{
266 SDL_UpdateRect(screen, 0, 0, 0, 0);
267 return 0;
268}
269
270/*
271 * Calculate the pad-aligned scanline width of a surface
272 */
273static int
274SDL_CalculatePitch(SDL_Surface * surface)
275{
276 int pitch;
277
278 /* Surface should be 4-byte aligned for speed */
279 pitch = surface->w * surface->format->BytesPerPixel;
280 switch (surface->format->BitsPerPixel) {
281 case 1:
282 pitch = (pitch + 7) / 8;
283 break;
284 case 4:
285 pitch = (pitch + 1) / 2;
286 break;
287 default:
288 break;
289 }
290 pitch = (pitch + 3) & ~3; /* 4-byte aligning */
291 return (pitch);
292}
293
294static void
295SDL_InvalidateMap(SDL_BlitMap * map)
296{
297 if (!map) {
298 return;
299 }
300 if (map->dst) {
301 /* Release our reference to the surface - see the note below */
302 if (--map->dst->refcount <= 0) {
303 SDL_FreeSurface(map->dst);
304 }
305 }
306 map->dst = NULL;
307 map->src_palette_version = 0;
308 map->dst_palette_version = 0;
309 if (map->info.table) {
310 SDL_free(map->info.table);
311 map->info.table = NULL;
312 }
313}
314
315static void
316SDL_GL_SwapBuffers(void)
317{
318 SDL_GL_SwapWindow(SDL_VideoWindow);
319}
320
321static int
322SDL_WM_ToggleFullScreen(SDL_Surface * surface)
323{
324 int length;
325 void *pixels;
326 Uint8 *src, *dst;
327 int row;
328 int window_w;
329 int window_h;
330
331 if (!SDL_PublicSurface) {
332 SDL_SetError("SDL_SetVideoMode() hasn't been called");
333 return 0;
334 }
335
336 /* Copy the old bits out */
337 length = SDL_PublicSurface->w * SDL_PublicSurface->format->BytesPerPixel;
338 pixels = SDL_malloc(SDL_PublicSurface->h * length);
339 if (pixels && SDL_PublicSurface->pixels) {
340 src = (Uint8*)SDL_PublicSurface->pixels;
341 dst = (Uint8*)pixels;
342 for (row = 0; row < SDL_PublicSurface->h; ++row) {
343 SDL_memcpy(dst, src, length);
344 src += SDL_PublicSurface->pitch;
345 dst += length;
346 }
347 }
348
349 /* Do the physical mode switch */
350 if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
351 if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
352 return 0;
353 }
354 SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
355 } else {
356 if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
357 return 0;
358 }
359 SDL_PublicSurface->flags |= SDL_FULLSCREEN;
360 }
361
362 /* Recreate the screen surface */
363 SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
364 if (!SDL_WindowSurface) {
365 /* We're totally hosed... */
366 return 0;
367 }
368
369 /* Center the public surface in the window surface */
370 SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
371 SDL_VideoViewport.x = (window_w - SDL_VideoSurface->w)/2;
372 SDL_VideoViewport.y = (window_h - SDL_VideoSurface->h)/2;
373 SDL_VideoViewport.w = SDL_VideoSurface->w;
374 SDL_VideoViewport.h = SDL_VideoSurface->h;
375
376 /* Do some shuffling behind the application's back if format changes */
377 if (SDL_VideoSurface->format->format != SDL_WindowSurface->format->format) {
378 if (SDL_ShadowSurface) {
379 if (SDL_ShadowSurface->format->format == SDL_WindowSurface->format->format) {
380 /* Whee! We don't need a shadow surface anymore! */
381 SDL_VideoSurface->flags &= ~SDL_DONTFREE;
382 SDL_FreeSurface(SDL_VideoSurface);
383 SDL_free(SDL_ShadowSurface->pixels);
384 SDL_VideoSurface = SDL_ShadowSurface;
385 SDL_VideoSurface->flags |= SDL_PREALLOC;
386 SDL_ShadowSurface = NULL;
387 } else {
388 /* No problem, just change the video surface format */
389 SDL_FreeFormat(SDL_VideoSurface->format);
390 SDL_VideoSurface->format = SDL_WindowSurface->format;
391 SDL_VideoSurface->format->refcount++;
392 SDL_InvalidateMap(SDL_ShadowSurface->map);
393 }
394 } else {
395 /* We can make the video surface the shadow surface */
396 SDL_ShadowSurface = SDL_VideoSurface;
397 SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
398 SDL_ShadowSurface->pixels = SDL_malloc(SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
399 if (!SDL_ShadowSurface->pixels) {
400 /* Uh oh, we're hosed */
401 SDL_ShadowSurface = NULL;
402 return 0;
403 }
404 SDL_ShadowSurface->flags &= ~SDL_PREALLOC;
405
406 SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
407 SDL_VideoSurface->flags = SDL_ShadowSurface->flags;
408 SDL_VideoSurface->flags |= SDL_PREALLOC;
409 SDL_FreeFormat(SDL_VideoSurface->format);
410 SDL_VideoSurface->format = SDL_WindowSurface->format;
411 SDL_VideoSurface->format->refcount++;
412 SDL_VideoSurface->w = SDL_ShadowSurface->w;
413 SDL_VideoSurface->h = SDL_ShadowSurface->h;
414 }
415 }
416
417 /* Update the video surface */
418 SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
419 SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
420 SDL_VideoViewport.y * SDL_VideoSurface->pitch +
421 SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel);
422 SDL_SetClipRect(SDL_VideoSurface, NULL);
423
424 /* Copy the old bits back */
425 if (pixels) {
426 src = (Uint8*)pixels;
427 dst = (Uint8*)SDL_PublicSurface->pixels;
428 for (row = 0; row < SDL_PublicSurface->h; ++row) {
429 SDL_memcpy(dst, src, length);
430 src += length;
431 dst += SDL_PublicSurface->pitch;
432 }
433 SDL_Flip(SDL_PublicSurface);
434 SDL_free(pixels);
435 }
436
437 /* We're done! */
438 return 1;
439}
440
441static void
442ClearVideoSurface()
443{
444 if (SDL_ShadowSurface) {
445 SDL_FillRect(SDL_ShadowSurface, NULL,
446 SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
447 }
448 SDL_FillRect(SDL_WindowSurface, NULL, 0);
449 SDL_UpdateWindowSurface(SDL_VideoWindow);
450}
451
452static int
453SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags)
454{
455 int w, h;
456
457 /* We can't resize something we don't have... */
458 if (!SDL_VideoSurface) {
459 return -1;
460 }
461
462 /* We probably have to recreate the window in fullscreen mode */
463 if (flags & SDL_FULLSCREEN) {
464 return -1;
465 }
466
467 /* I don't think there's any change we can gracefully make in flags */
468 if (flags != SDL_VideoFlags) {
469 return -1;
470 }
471 if (bpp != SDL_VideoSurface->format->BitsPerPixel) {
472 return -1;
473 }
474
475 /* Resize the window */
476 SDL_GetWindowSize(SDL_VideoWindow, &w, &h);
477 if (w != width || h != height) {
478 SDL_SetWindowSize(SDL_VideoWindow, width, height);
479 }
480
481 /* If we're in OpenGL mode, just resize the stub surface and we're done! */
482 if (flags & SDL_OPENGL) {
483 SDL_VideoSurface->w = width;
484 SDL_VideoSurface->h = height;
485 return 0;
486 }
487
488 SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
489 if (!SDL_WindowSurface) {
490 return -1;
491 }
492 if (SDL_VideoSurface->format != SDL_WindowSurface->format) {
493 return -1;
494 }
495 SDL_VideoSurface->w = width;
496 SDL_VideoSurface->h = height;
497 SDL_VideoSurface->pixels = SDL_WindowSurface->pixels;
498 SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
499 SDL_SetClipRect(SDL_VideoSurface, NULL);
500
501 if (SDL_ShadowSurface) {
502 SDL_ShadowSurface->w = width;
503 SDL_ShadowSurface->h = height;
504 SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
505 SDL_ShadowSurface->pixels =
506 SDL_realloc(SDL_ShadowSurface->pixels,
507 SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
508 SDL_SetClipRect(SDL_ShadowSurface, NULL);
509 SDL_InvalidateMap(SDL_ShadowSurface->map);
510 } else {
511 SDL_PublicSurface = SDL_VideoSurface;
512 }
513
514 ClearVideoSurface();
515
516 return 0;
517}
518
519static int
520SDL_CompatEventFilter(void *userdata, SDL_Event * event)
521{
522 SDL_Event fake;
523
524 switch (event->type) {
525 case SDL_WINDOWEVENT:
526 switch (event->window.event) {
527 case SDL_WINDOWEVENT_CLOSE:
528 fake.type = SDL_QUIT;
529 SDL_PushEvent(&fake);
530 break;
531 }
532 case SDL_TEXTINPUT:
533 {
534 /* FIXME: Generate an old style key repeat event if needed */
535 //printf("TEXTINPUT: '%s'\n", event->text.text);
536 break;
537 }
538 case SDL_MOUSEMOTION:
539 {
540 event->motion.x -= SDL_VideoViewport.x;
541 event->motion.y -= SDL_VideoViewport.y;
542 break;
543 }
544 case SDL_MOUSEBUTTONDOWN:
545 case SDL_MOUSEBUTTONUP:
546 {
547 event->button.x -= SDL_VideoViewport.x;
548 event->button.y -= SDL_VideoViewport.y;
549 break;
550 }
551 case SDL_MOUSEWHEEL:
552 {
553 Uint8 button;
554 int x, y;
555
556 if (event->wheel.y == 0) {
557 break;
558 }
559
560 SDL_GetMouseState(&x, &y);
561
562 if (event->wheel.y > 0) {
563 button = SDL_BUTTON_WHEELUP;
564 } else {
565 button = SDL_BUTTON_WHEELDOWN;
566 }
567
568 fake.button.button = button;
569 fake.button.x = x;
570 fake.button.y = y;
571 fake.button.windowID = event->wheel.windowID;
572
573 fake.type = SDL_MOUSEBUTTONDOWN;
574 fake.button.state = SDL_PRESSED;
575 SDL_PushEvent(&fake);
576
577 fake.type = SDL_MOUSEBUTTONUP;
578 fake.button.state = SDL_RELEASED;
579 SDL_PushEvent(&fake);
580 break;
581 }
582
583 }
584 return 1;
585}
586
587static void
588GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
589{
590 int display = GetVideoDisplay();
591 const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
592 const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
593 if (window) {
594 if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
595 return;
596 }
597 if (SDL_strcmp(window, "center") == 0) {
598 center = window;
599 }
600 }
601 if (center) {
602 *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
603 *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
604 }
605}
606
607static SDL_Surface *
608SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
609{
610 SDL_DisplayMode desktop_mode;
611 int display = GetVideoDisplay();
612 int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
613 int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
614 int window_w;
615 int window_h;
616 Uint32 window_flags;
617 Uint32 surface_flags;
618
619 if (!initialized_video) {
620 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
621 return NULL;
622 }
623 initialized_video = 1;
624 }
625
626 SDL_GetDesktopDisplayMode(display, &desktop_mode);
627
628 if (width == 0) {
629 width = desktop_mode.w;
630 }
631 if (height == 0) {
632 height = desktop_mode.h;
633 }
634 if (bpp == 0) {
635 bpp = SDL_BITSPERPIXEL(desktop_mode.format);
636 }
637
638 /* See if we can simply resize the existing window and surface */
639 if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
640 return SDL_PublicSurface;
641 }
642
643 /* Destroy existing window */
644 SDL_PublicSurface = NULL;
645 if (SDL_ShadowSurface) {
646 SDL_ShadowSurface->flags &= ~SDL_DONTFREE;
647 SDL_FreeSurface(SDL_ShadowSurface);
648 SDL_ShadowSurface = NULL;
649 }
650 if (SDL_VideoSurface) {
651 SDL_VideoSurface->flags &= ~SDL_DONTFREE;
652 SDL_FreeSurface(SDL_VideoSurface);
653 SDL_VideoSurface = NULL;
654 }
655 if (SDL_VideoContext) {
656 /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
657 SDL_GL_DeleteContext(SDL_VideoContext);
658 SDL_VideoContext = NULL;
659 }
660 if (SDL_VideoWindow) {
661 SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
662 SDL_DestroyWindow(SDL_VideoWindow);
663 }
664
665 /* Set up the event filter */
666 if (!SDL_GetEventFilter(NULL, NULL)) {
667 SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
668 }
669
670 /* Create a new window */
671 window_flags = SDL_WINDOW_SHOWN;
672 if (flags & SDL_FULLSCREEN) {
673 window_flags |= SDL_WINDOW_FULLSCREEN;
674 }
675 if (flags & SDL_OPENGL) {
676 window_flags |= SDL_WINDOW_OPENGL;
677 }
678 if (flags & SDL_RESIZABLE) {
679 window_flags |= SDL_WINDOW_RESIZABLE;
680 }
681 if (flags & SDL_NOFRAME) {
682 window_flags |= SDL_WINDOW_BORDERLESS;
683 }
684 GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
685 SDL_VideoWindow =
686 SDL_CreateWindow(wm_title, window_x, window_y, width, height,
687 window_flags);
688 if (!SDL_VideoWindow) {
689 return NULL;
690 }
691 SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
692
693 window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
694 surface_flags = 0;
695 if (window_flags & SDL_WINDOW_FULLSCREEN) {
696 surface_flags |= SDL_FULLSCREEN;
697 }
698 if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
699 surface_flags |= SDL_OPENGL;
700 }
701 if (window_flags & SDL_WINDOW_RESIZABLE) {
702 surface_flags |= SDL_RESIZABLE;
703 }
704 if (window_flags & SDL_WINDOW_BORDERLESS) {
705 surface_flags |= SDL_NOFRAME;
706 }
707
708 SDL_VideoFlags = flags;
709
710 /* If we're in OpenGL mode, just create a stub surface and we're done! */
711 if (flags & SDL_OPENGL) {
712 SDL_VideoContext = (SDL_GLContext *)SDL_GL_CreateContext(SDL_VideoWindow);
713 if (!SDL_VideoContext) {
714 return NULL;
715 }
716 if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
717 return NULL;
718 }
719 SDL_VideoSurface =
720 SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
721 if (!SDL_VideoSurface) {
722 return NULL;
723 }
724 SDL_VideoSurface->flags |= surface_flags;
725 SDL_PublicSurface = SDL_VideoSurface;
726 return SDL_PublicSurface;
727 }
728
729 /* Create the screen surface */
730 SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
731 if (!SDL_WindowSurface) {
732 return NULL;
733 }
734
735 /* Center the public surface in the window surface */
736 SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
737 SDL_VideoViewport.x = (window_w - width)/2;
738 SDL_VideoViewport.y = (window_h - height)/2;
739 SDL_VideoViewport.w = width;
740 SDL_VideoViewport.h = height;
741
742 SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
743 SDL_VideoSurface->flags |= surface_flags;
744 SDL_VideoSurface->flags |= SDL_DONTFREE;
745 SDL_FreeFormat(SDL_VideoSurface->format);
746 SDL_VideoSurface->format = SDL_WindowSurface->format;
747 SDL_VideoSurface->format->refcount++;
748 SDL_VideoSurface->w = width;
749 SDL_VideoSurface->h = height;
750 SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
751 SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
752 SDL_VideoViewport.y * SDL_VideoSurface->pitch +
753 SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel);
754 SDL_SetClipRect(SDL_VideoSurface, NULL);
755
756 /* Create a shadow surface if necessary */
757 if ((bpp != SDL_VideoSurface->format->BitsPerPixel)
758 && !(flags & SDL_ANYFORMAT)) {
759 SDL_ShadowSurface =
760 SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
761 if (!SDL_ShadowSurface) {
762 return NULL;
763 }
764 SDL_ShadowSurface->flags |= surface_flags;
765 SDL_ShadowSurface->flags |= SDL_DONTFREE;
766
767 /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
768 if (SDL_ShadowSurface->format->palette) {
769 SDL_ShadowSurface->flags |= SDL_HWPALETTE;
770 //TODO SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
771 // SDL_ShadowSurface->format->BitsPerPixel);
772 }
773 SDL_FillRect(SDL_ShadowSurface, NULL,
774 SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
775 }
776 SDL_PublicSurface =
777 (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
778
779 ClearVideoSurface();
780
781 /* We're finally done! */
782 return SDL_PublicSurface;
783}