Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / api / vidext_sdl2_compat.h
CommitLineData
451ab91e 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_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_KEYDOWN:
533 case SDL_KEYUP:
534 {
535 Uint32 unicode = 0;
536 if (event->key.type == SDL_KEYDOWN && event->key.keysym.sym < 256) {
537 unicode = event->key.keysym.sym;
538 if (unicode >= 'a' && unicode <= 'z') {
539 int shifted = !!(event->key.keysym.mod & KMOD_SHIFT);
540 int capslock = !!(event->key.keysym.mod & KMOD_CAPS);
541 if ((shifted ^ capslock) != 0) {
542 unicode = SDL_toupper(unicode);
543 }
544 }
545 }
546 if (unicode) {
547 event->key.keysym.unicode = unicode;
548 }
549 break;
550 }
551 case SDL_TEXTINPUT:
552 {
553 /* FIXME: Generate an old style key repeat event if needed */
554 //printf("TEXTINPUT: '%s'\n", event->text.text);
555 break;
556 }
557 case SDL_MOUSEMOTION:
558 {
559 event->motion.x -= SDL_VideoViewport.x;
560 event->motion.y -= SDL_VideoViewport.y;
561 break;
562 }
563 case SDL_MOUSEBUTTONDOWN:
564 case SDL_MOUSEBUTTONUP:
565 {
566 event->button.x -= SDL_VideoViewport.x;
567 event->button.y -= SDL_VideoViewport.y;
568 break;
569 }
570 case SDL_MOUSEWHEEL:
571 {
572 Uint8 button;
573 int x, y;
574
575 if (event->wheel.y == 0) {
576 break;
577 }
578
579 SDL_GetMouseState(&x, &y);
580
581 if (event->wheel.y > 0) {
582 button = SDL_BUTTON_WHEELUP;
583 } else {
584 button = SDL_BUTTON_WHEELDOWN;
585 }
586
587 fake.button.button = button;
588 fake.button.x = x;
589 fake.button.y = y;
590 fake.button.windowID = event->wheel.windowID;
591
592 fake.type = SDL_MOUSEBUTTONDOWN;
593 fake.button.state = SDL_PRESSED;
594 SDL_PushEvent(&fake);
595
596 fake.type = SDL_MOUSEBUTTONUP;
597 fake.button.state = SDL_RELEASED;
598 SDL_PushEvent(&fake);
599 break;
600 }
601
602 }
603 return 1;
604}
605
606static void
607GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
608{
609 int display = GetVideoDisplay();
610 const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
611 const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
612 if (window) {
613 if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
614 return;
615 }
616 if (SDL_strcmp(window, "center") == 0) {
617 center = window;
618 }
619 }
620 if (center) {
621 *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
622 *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
623 }
624}
625
626static SDL_Surface *
627SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
628{
629 SDL_DisplayMode desktop_mode;
630 int display = GetVideoDisplay();
631 int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
632 int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
633 int window_w;
634 int window_h;
635 Uint32 window_flags;
636 Uint32 surface_flags;
637
638 if (!initialized_video) {
639 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
640 return NULL;
641 }
642 initialized_video = 1;
643 }
644
645 SDL_GetDesktopDisplayMode(display, &desktop_mode);
646
647 if (width == 0) {
648 width = desktop_mode.w;
649 }
650 if (height == 0) {
651 height = desktop_mode.h;
652 }
653 if (bpp == 0) {
654 bpp = SDL_BITSPERPIXEL(desktop_mode.format);
655 }
656
657 /* See if we can simply resize the existing window and surface */
658 if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
659 return SDL_PublicSurface;
660 }
661
662 /* Destroy existing window */
663 SDL_PublicSurface = NULL;
664 if (SDL_ShadowSurface) {
665 SDL_ShadowSurface->flags &= ~SDL_DONTFREE;
666 SDL_FreeSurface(SDL_ShadowSurface);
667 SDL_ShadowSurface = NULL;
668 }
669 if (SDL_VideoSurface) {
670 SDL_VideoSurface->flags &= ~SDL_DONTFREE;
671 SDL_FreeSurface(SDL_VideoSurface);
672 SDL_VideoSurface = NULL;
673 }
674 if (SDL_VideoContext) {
675 /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
676 SDL_GL_DeleteContext(SDL_VideoContext);
677 SDL_VideoContext = NULL;
678 }
679 if (SDL_VideoWindow) {
680 SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
681 SDL_DestroyWindow(SDL_VideoWindow);
682 }
683
684 /* Set up the event filter */
685 if (!SDL_GetEventFilter(NULL, NULL)) {
686 SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
687 }
688
689 /* Create a new window */
690 window_flags = SDL_WINDOW_SHOWN;
691 if (flags & SDL_FULLSCREEN) {
692 window_flags |= SDL_WINDOW_FULLSCREEN;
693 }
694 if (flags & SDL_OPENGL) {
695 window_flags |= SDL_WINDOW_OPENGL;
696 }
697 if (flags & SDL_RESIZABLE) {
698 window_flags |= SDL_WINDOW_RESIZABLE;
699 }
700 if (flags & SDL_NOFRAME) {
701 window_flags |= SDL_WINDOW_BORDERLESS;
702 }
703 GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
704 SDL_VideoWindow =
705 SDL_CreateWindow(wm_title, window_x, window_y, width, height,
706 window_flags);
707 if (!SDL_VideoWindow) {
708 return NULL;
709 }
710 SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
711
712 window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
713 surface_flags = 0;
714 if (window_flags & SDL_WINDOW_FULLSCREEN) {
715 surface_flags |= SDL_FULLSCREEN;
716 }
717 if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
718 surface_flags |= SDL_OPENGL;
719 }
720 if (window_flags & SDL_WINDOW_RESIZABLE) {
721 surface_flags |= SDL_RESIZABLE;
722 }
723 if (window_flags & SDL_WINDOW_BORDERLESS) {
724 surface_flags |= SDL_NOFRAME;
725 }
726
727 SDL_VideoFlags = flags;
728
729 /* If we're in OpenGL mode, just create a stub surface and we're done! */
730 if (flags & SDL_OPENGL) {
731 SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow);
732 if (!SDL_VideoContext) {
733 return NULL;
734 }
735 if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
736 return NULL;
737 }
738 SDL_VideoSurface =
739 SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
740 if (!SDL_VideoSurface) {
741 return NULL;
742 }
743 SDL_VideoSurface->flags |= surface_flags;
744 SDL_PublicSurface = SDL_VideoSurface;
745 return SDL_PublicSurface;
746 }
747
748 /* Create the screen surface */
749 SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
750 if (!SDL_WindowSurface) {
751 return NULL;
752 }
753
754 /* Center the public surface in the window surface */
755 SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
756 SDL_VideoViewport.x = (window_w - width)/2;
757 SDL_VideoViewport.y = (window_h - height)/2;
758 SDL_VideoViewport.w = width;
759 SDL_VideoViewport.h = height;
760
761 SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
762 SDL_VideoSurface->flags |= surface_flags;
763 SDL_VideoSurface->flags |= SDL_DONTFREE;
764 SDL_FreeFormat(SDL_VideoSurface->format);
765 SDL_VideoSurface->format = SDL_WindowSurface->format;
766 SDL_VideoSurface->format->refcount++;
767 SDL_VideoSurface->w = width;
768 SDL_VideoSurface->h = height;
769 SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
770 SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
771 SDL_VideoViewport.y * SDL_VideoSurface->pitch +
772 SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel);
773 SDL_SetClipRect(SDL_VideoSurface, NULL);
774
775 /* Create a shadow surface if necessary */
776 if ((bpp != SDL_VideoSurface->format->BitsPerPixel)
777 && !(flags & SDL_ANYFORMAT)) {
778 SDL_ShadowSurface =
779 SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
780 if (!SDL_ShadowSurface) {
781 return NULL;
782 }
783 SDL_ShadowSurface->flags |= surface_flags;
784 SDL_ShadowSurface->flags |= SDL_DONTFREE;
785
786 /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
787 if (SDL_ShadowSurface->format->palette) {
788 SDL_ShadowSurface->flags |= SDL_HWPALETTE;
789 //TODO SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
790 // SDL_ShadowSurface->format->BitsPerPixel);
791 }
792 SDL_FillRect(SDL_ShadowSurface, NULL,
793 SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
794 }
795 SDL_PublicSurface =
796 (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
797
798 ClearVideoSurface();
799
800 /* We're finally done! */
801 return SDL_PublicSurface;
802}