1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2010 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 #include "SDL_version.h"
24 
25 /* The high-level video driver subsystem */
26 
27 #include "SDL.h"
28 #if SDL_VERSION_ATLEAST(1,3,0)
29 #include "SDL_video.h"
30 #include "SDL_sysvideo.h"
31 #else
32 #include "SDL_video-1.3.h"
33 #include "SDL_sysvideo-1.3.h"
34 #include "SDL_androidvideo.h"
35 #endif
36 #include "SDL_blit.h"
37 #include "SDL_pixels_c.h"
38 #include "SDL_renderer_gl.h"
39 #include "SDL_renderer_gles.h"
40 #include "SDL_renderer_sw.h"
41 #if SDL_VERSION_ATLEAST(1,3,0)
42 #include "../events/SDL_sysevents.h"
43 #include "../events/SDL_events_c.h"
44 #endif
45 #ifdef ANDROID
46 #include <android/log.h>
47 #endif
48 
49 #if SDL_VIDEO_OPENGL_ES
50 #include "SDL_opengles.h"
51 #endif /* SDL_VIDEO_OPENGL_ES */
52 
53 #if SDL_VIDEO_OPENGL
54 #include "SDL_opengl.h"
55 
56 /* On Windows, windows.h defines CreateWindow */
57 #ifdef CreateWindow
58 #undef CreateWindow
59 #endif
60 #endif /* SDL_VIDEO_OPENGL */
61 
62 /* Available video drivers */
63 static VideoBootStrap *bootstrap[] = {
64 #if SDL_VIDEO_DRIVER_COCOA
65     &COCOA_bootstrap,
66 #endif
67 #if SDL_VIDEO_DRIVER_X11
68     &X11_bootstrap,
69 #endif
70 #if SDL_VIDEO_DRIVER_FBCON
71     &FBCON_bootstrap,
72 #endif
73 #if SDL_VIDEO_DRIVER_DIRECTFB
74     &DirectFB_bootstrap,
75 #endif
76 #if SDL_VIDEO_DRIVER_PS3
77     &PS3_bootstrap,
78 #endif
79 #if SDL_VIDEO_DRIVER_SVGALIB
80     &SVGALIB_bootstrap,
81 #endif
82 #if SDL_VIDEO_DRIVER_GAPI
83     &GAPI_bootstrap,
84 #endif
85 #if SDL_VIDEO_DRIVER_WIN32
86     &WIN32_bootstrap,
87 #endif
88 #if SDL_VIDEO_DRIVER_BWINDOW
89     &BWINDOW_bootstrap,
90 #endif
91 #if SDL_VIDEO_DRIVER_PHOTON
92     &photon_bootstrap,
93 #endif
94 #if SDL_VIDEO_DRIVER_QNXGF
95     &qnxgf_bootstrap,
96 #endif
97 #if SDL_VIDEO_DRIVER_EPOC
98     &EPOC_bootstrap,
99 #endif
100 #if SDL_VIDEO_DRIVER_RISCOS
101     &RISCOS_bootstrap,
102 #endif
103 #if SDL_VIDEO_DRIVER_NDS
104     &NDS_bootstrap,
105 #endif
106 #if SDL_VIDEO_DRIVER_UIKIT
107     &UIKIT_bootstrap,
108 #endif
109 #if SDL_VIDEO_DRIVER_ANDROID
110 	&ANDROID_bootstrap,
111 #endif
112 #if SDL_VIDEO_DRIVER_DUMMY
113     &DUMMY_bootstrap,
114 #endif
115 #if SDL_VIDEO_DRIVER_PANDORA
116     &PND_bootstrap,
117 #endif
118     NULL
119 };
120 
121 static SDL_VideoDevice *_this = NULL;
122 
123 #define CHECK_WINDOW_MAGIC(window, retval) \
124     if (!_this) { \
125         SDL_UninitializedVideo(); \
126         return retval; \
127     } \
128     if (!window || window->magic != &_this->window_magic) { \
129         SDL_SetError("Invalid window"); \
130         return retval; \
131     }
132 
133 #define CHECK_TEXTURE_MAGIC(texture, retval) \
134     if (!_this) { \
135         SDL_UninitializedVideo(); \
136         return retval; \
137     } \
138     if (!texture || texture->magic != &_this->texture_magic) { \
139         SDL_SetError("Invalid texture"); \
140         return retval; \
141     }
142 
143 /* Various local functions */
144 static void SDL_UpdateWindowGrab(SDL_Window * window);
145 
146 static int
cmpmodes(const void * A,const void * B)147 cmpmodes(const void *A, const void *B)
148 {
149     SDL_DisplayMode a = *(const SDL_DisplayMode *) A;
150     SDL_DisplayMode b = *(const SDL_DisplayMode *) B;
151 
152     if (a.w != b.w) {
153         return b.w - a.w;
154     }
155     if (a.h != b.h) {
156         return b.h - a.h;
157     }
158     if (SDL_BITSPERPIXEL(a.format) != SDL_BITSPERPIXEL(b.format)) {
159         return SDL_BITSPERPIXEL(b.format) - SDL_BITSPERPIXEL(a.format);
160     }
161     if (SDL_PIXELLAYOUT(a.format) != SDL_PIXELLAYOUT(b.format)) {
162         return SDL_PIXELLAYOUT(b.format) - SDL_PIXELLAYOUT(a.format);
163     }
164     if (a.refresh_rate != b.refresh_rate) {
165         return b.refresh_rate - a.refresh_rate;
166     }
167     return 0;
168 }
169 
170 static void
SDL_UninitializedVideo()171 SDL_UninitializedVideo()
172 {
173     SDL_SetError("Video subsystem has not been initialized");
174 }
175 
176 int
SDL_GetNumVideoDrivers(void)177 SDL_GetNumVideoDrivers(void)
178 {
179     return SDL_arraysize(bootstrap) - 1;
180 }
181 
182 const char *
SDL_GetVideoDriver(int index)183 SDL_GetVideoDriver(int index)
184 {
185     if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
186         return bootstrap[index]->name;
187     }
188     return NULL;
189 }
190 
191 /*
192  * Initialize the video and event subsystems -- determine native pixel format
193  */
194 #if SDL_VERSION_ATLEAST(1,3,0)
SDL_VideoInit(const char * driver_name,Uint32 flags)195 int SDL_VideoInit
196 #else
197 int SDL_VideoInit_1_3
198 #endif
199 (const char *driver_name, Uint32 flags)
200 {
201     SDL_VideoDevice *video;
202     int index;
203     int i;
204 
205     /* Check to make sure we don't overwrite '_this' */
206     if (_this != NULL) {
207         SDL_VideoQuit();
208     }
209 
210 #if SDL_VERSION_ATLEAST(1,3,0)
211     /* Toggle the event thread flags, based on OS requirements */
212 #if defined(MUST_THREAD_EVENTS)
213     flags |= SDL_INIT_EVENTTHREAD;
214 #elif defined(CANT_THREAD_EVENTS)
215     if ((flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD) {
216         SDL_SetError("OS doesn't support threaded events");
217         return -1;
218     }
219 #endif
220 
221     /* Start the event loop */
222     if (SDL_StartEventLoop(flags) < 0) {
223         return -1;
224     }
225 #endif
226     /* Select the proper video driver */
227     index = 0;
228     video = NULL;
229 #if SDL_VERSION_ATLEAST(1,3,0)
230     if (driver_name == NULL) {
231         driver_name = SDL_getenv("SDL_VIDEODRIVER");
232     }
233     if (driver_name != NULL) {
234         for (i = 0; bootstrap[i]; ++i) {
235             if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
236                 video = bootstrap[i]->create(index);
237                 break;
238             }
239         }
240     } else {
241         for (i = 0; bootstrap[i]; ++i) {
242             if (bootstrap[i]->available()) {
243                 video = bootstrap[i]->create(index);
244                 if (video != NULL) {
245                     break;
246                 }
247             }
248         }
249     }
250     if (video == NULL) {
251         if (driver_name) {
252             SDL_SetError("%s not available", driver_name);
253         } else {
254             SDL_SetError("No available video device");
255         }
256         return -1;
257     }
258 
259     _this = video;
260     _this->name = bootstrap[i]->name;
261 #else
262     video = ANDROID_CreateDevice_1_3(0);
263     _this = video;
264     _this->name = "android";
265 #endif
266     _this->next_object_id = 1;
267 
268 
269     /* Set some very sane GL defaults */
270     _this->gl_config.driver_loaded = 0;
271     _this->gl_config.dll_handle = NULL;
272     _this->gl_config.red_size = 3;
273     _this->gl_config.green_size = 3;
274     _this->gl_config.blue_size = 2;
275     _this->gl_config.alpha_size = 0;
276     _this->gl_config.buffer_size = 0;
277     _this->gl_config.depth_size = 16;
278     _this->gl_config.stencil_size = 0;
279     _this->gl_config.double_buffer = 1;
280     _this->gl_config.accum_red_size = 0;
281     _this->gl_config.accum_green_size = 0;
282     _this->gl_config.accum_blue_size = 0;
283     _this->gl_config.accum_alpha_size = 0;
284     _this->gl_config.stereo = 0;
285     _this->gl_config.multisamplebuffers = 0;
286     _this->gl_config.multisamplesamples = 0;
287     _this->gl_config.retained_backing = 1;
288     _this->gl_config.accelerated = -1;  /* accelerated or not, both are fine */
289     _this->gl_config.major_version = 2;
290     _this->gl_config.minor_version = 1;
291 
292     /* Initialize the video subsystem */
293     if (_this->VideoInit(_this) < 0) {
294         SDL_VideoQuit();
295         return -1;
296     }
297     /* Make sure some displays were added */
298     if (_this->num_displays == 0) {
299         SDL_SetError("The video driver did not add any displays");
300         SDL_VideoQuit();
301         return (-1);
302     }
303     /* The software renderer is always available */
304     for (i = 0; i < _this->num_displays; ++i) {
305         SDL_VideoDisplay *display = &_this->displays[i];
306         if (_this->GL_CreateContext) {
307 #if SDL_VIDEO_RENDER_OGL
308             SDL_AddRenderDriver(display, &GL_RenderDriver);
309 #endif
310 #if SDL_VIDEO_RENDER_OGL_ES
311             SDL_AddRenderDriver(display, &GL_ES_RenderDriver);
312 #endif
313         }
314 #if SDL_VERSION_ATLEAST(1,3,0)
315         if (display->num_render_drivers > 0) {
316             SDL_AddRenderDriver(display, &SW_RenderDriver);
317         }
318 #endif
319     }
320 
321     /* We're ready to go! */
322     return 0;
323 }
324 
325 const char *
SDL_GetCurrentVideoDriver()326 SDL_GetCurrentVideoDriver()
327 {
328     if (!_this) {
329         SDL_UninitializedVideo();
330         return NULL;
331     }
332     return _this->name;
333 }
334 
335 SDL_VideoDevice *
SDL_GetVideoDevice(void)336 SDL_GetVideoDevice(void)
337 {
338     return _this;
339 }
340 
341 int
SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)342 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
343 {
344     SDL_VideoDisplay display;
345 
346     SDL_memset(&display, 0, sizeof(display));
347     if (desktop_mode) {
348         display.desktop_mode = *desktop_mode;
349     }
350     display.current_mode = display.desktop_mode;
351 
352     return SDL_AddVideoDisplay(&display);
353 }
354 
355 int
SDL_AddVideoDisplay(const SDL_VideoDisplay * display)356 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
357 {
358     SDL_VideoDisplay *displays;
359     int index = -1;
360 
361     displays =
362         SDL_realloc(_this->displays,
363                     (_this->num_displays + 1) * sizeof(*displays));
364     if (displays) {
365         index = _this->num_displays++;
366         displays[index] = *display;
367         displays[index].device = _this;
368         _this->displays = displays;
369     } else {
370         SDL_OutOfMemory();
371     }
372     return index;
373 }
374 
375 int
SDL_GetNumVideoDisplays(void)376 SDL_GetNumVideoDisplays(void)
377 {
378     if (!_this) {
379         SDL_UninitializedVideo();
380         return 0;
381     }
382     return _this->num_displays;
383 }
384 
385 int
SDL_GetDisplayBounds(int index,SDL_Rect * rect)386 SDL_GetDisplayBounds(int index, SDL_Rect * rect)
387 {
388     if (!_this) {
389         SDL_UninitializedVideo();
390         return -1;
391     }
392     if (index < 0 || index >= _this->num_displays) {
393         SDL_SetError("index must be in the range 0 - %d",
394                      _this->num_displays - 1);
395         return -1;
396     }
397     if (rect) {
398         SDL_VideoDisplay *display = &_this->displays[index];
399 
400         if (_this->GetDisplayBounds) {
401             if (_this->GetDisplayBounds(_this, display, rect) < 0) {
402                 return -1;
403             }
404         } else {
405             /* Assume that the displays are left to right */
406             if (index == 0) {
407                 rect->x = 0;
408                 rect->y = 0;
409             } else {
410                 SDL_GetDisplayBounds(index-1, rect);
411                 rect->x += rect->w;
412             }
413             rect->w = display->desktop_mode.w;
414             rect->h = display->desktop_mode.h;
415         }
416     }
417     return 0;
418 }
419 
420 int
SDL_SelectVideoDisplay(int index)421 SDL_SelectVideoDisplay(int index)
422 {
423     if (!_this) {
424         SDL_UninitializedVideo();
425         return (-1);
426     }
427     if (index < 0 || index >= _this->num_displays) {
428         SDL_SetError("index must be in the range 0 - %d",
429                      _this->num_displays - 1);
430         return -1;
431     }
432     _this->current_display = index;
433     return 0;
434 }
435 
436 int
SDL_GetCurrentVideoDisplay(void)437 SDL_GetCurrentVideoDisplay(void)
438 {
439     if (!_this) {
440         SDL_UninitializedVideo();
441         return (-1);
442     }
443     return _this->current_display;
444 }
445 
446 SDL_bool
SDL_AddDisplayMode(SDL_VideoDisplay * display,const SDL_DisplayMode * mode)447 SDL_AddDisplayMode(SDL_VideoDisplay * display,  const SDL_DisplayMode * mode)
448 {
449     SDL_DisplayMode *modes;
450     int i, nmodes;
451 
452     /* Make sure we don't already have the mode in the list */
453     modes = display->display_modes;
454     nmodes = display->num_display_modes;
455     for (i = nmodes; i--;) {
456         if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) {
457             return SDL_FALSE;
458         }
459     }
460 
461     /* Go ahead and add the new mode */
462     if (nmodes == display->max_display_modes) {
463         modes =
464             SDL_realloc(modes,
465                         (display->max_display_modes + 32) * sizeof(*modes));
466         if (!modes) {
467             return SDL_FALSE;
468         }
469         display->display_modes = modes;
470         display->max_display_modes += 32;
471     }
472     modes[nmodes] = *mode;
473     display->num_display_modes++;
474 
475     /* Re-sort video modes */
476     SDL_qsort(display->display_modes, display->num_display_modes,
477               sizeof(SDL_DisplayMode), cmpmodes);
478 
479     return SDL_TRUE;
480 }
481 
482 int
SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)483 SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
484 {
485     if (!display->num_display_modes && _this->GetDisplayModes) {
486         _this->GetDisplayModes(_this, display);
487         SDL_qsort(display->display_modes, display->num_display_modes,
488                   sizeof(SDL_DisplayMode), cmpmodes);
489     }
490     return display->num_display_modes;
491 }
492 
493 int
SDL_GetNumDisplayModes()494 SDL_GetNumDisplayModes()
495 {
496     if (_this) {
497         return SDL_GetNumDisplayModesForDisplay(SDL_CurrentDisplay);
498     }
499     return 0;
500 }
501 
502 int
SDL_GetDisplayModeForDisplay(SDL_VideoDisplay * display,int index,SDL_DisplayMode * mode)503 SDL_GetDisplayModeForDisplay(SDL_VideoDisplay * display, int index, SDL_DisplayMode * mode)
504 {
505     if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
506         SDL_SetError("index must be in the range of 0 - %d",
507                      SDL_GetNumDisplayModesForDisplay(display) - 1);
508         return -1;
509     }
510     if (mode) {
511         *mode = display->display_modes[index];
512     }
513     return 0;
514 }
515 
516 int
SDL_GetDisplayMode(int index,SDL_DisplayMode * mode)517 SDL_GetDisplayMode(int index, SDL_DisplayMode * mode)
518 {
519     return SDL_GetDisplayModeForDisplay(SDL_CurrentDisplay, index, mode);
520 }
521 
522 int
SDL_GetDesktopDisplayModeForDisplay(SDL_VideoDisplay * display,SDL_DisplayMode * mode)523 SDL_GetDesktopDisplayModeForDisplay(SDL_VideoDisplay * display, SDL_DisplayMode * mode)
524 {
525     if (mode) {
526         *mode = display->desktop_mode;
527     }
528     return 0;
529 }
530 
531 int
SDL_GetDesktopDisplayMode(SDL_DisplayMode * mode)532 SDL_GetDesktopDisplayMode(SDL_DisplayMode * mode)
533 {
534     if (!_this) {
535         SDL_UninitializedVideo();
536         return -1;
537     }
538     return SDL_GetDesktopDisplayModeForDisplay(SDL_CurrentDisplay, mode);
539 }
540 
541 int
SDL_GetCurrentDisplayModeForDisplay(SDL_VideoDisplay * display,SDL_DisplayMode * mode)542 SDL_GetCurrentDisplayModeForDisplay(SDL_VideoDisplay * display, SDL_DisplayMode * mode)
543 {
544     if (mode) {
545         *mode = display->current_mode;
546     }
547     return 0;
548 }
549 
550 int
SDL_GetCurrentDisplayMode(SDL_DisplayMode * mode)551 SDL_GetCurrentDisplayMode(SDL_DisplayMode * mode)
552 {
553     if (!_this) {
554         SDL_UninitializedVideo();
555         return -1;
556     }
557     return SDL_GetCurrentDisplayModeForDisplay(SDL_CurrentDisplay, mode);
558 }
559 
560 SDL_DisplayMode *
SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,const SDL_DisplayMode * mode,SDL_DisplayMode * closest)561 SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
562                                     const SDL_DisplayMode * mode,
563                                     SDL_DisplayMode * closest)
564 {
565     Uint32 target_format;
566     int target_refresh_rate;
567     int i;
568     SDL_DisplayMode *current, *match;
569 
570     if (!mode || !closest) {
571         SDL_SetError("Missing desired mode or closest mode parameter");
572         return NULL;
573     }
574 
575     /* Default to the desktop format */
576     if (mode->format) {
577         target_format = mode->format;
578     } else {
579         target_format = display->desktop_mode.format;
580     }
581 
582     /* Default to the desktop refresh rate */
583     if (mode->refresh_rate) {
584         target_refresh_rate = mode->refresh_rate;
585     } else {
586         target_refresh_rate = display->desktop_mode.refresh_rate;
587     }
588 
589     match = NULL;
590     for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
591         current = &display->display_modes[i];
592 
593         if (current->w && (current->w < mode->w)) {
594             /* Out of sorted modes large enough here */
595             break;
596         }
597         if (current->h && (current->h < mode->h)) {
598             if (current->w && (current->w == mode->w)) {
599                 /* Out of sorted modes large enough here */
600                 break;
601             }
602             /* Wider, but not tall enough, due to a different
603                aspect ratio. This mode must be skipped, but closer
604                modes may still follow. */
605             continue;
606         }
607         if (!match || current->w < match->w || current->h < match->h) {
608             match = current;
609             continue;
610         }
611         if (current->format != match->format) {
612             /* Sorted highest depth to lowest */
613             if (current->format == target_format ||
614                 (SDL_BITSPERPIXEL(current->format) >=
615                  SDL_BITSPERPIXEL(target_format)
616                  && SDL_PIXELTYPE(current->format) ==
617                  SDL_PIXELTYPE(target_format))) {
618                 match = current;
619             }
620             continue;
621         }
622         if (current->refresh_rate != match->refresh_rate) {
623             /* Sorted highest refresh to lowest */
624             if (current->refresh_rate >= target_refresh_rate) {
625                 match = current;
626             }
627         }
628     }
629     if (match) {
630         if (match->format) {
631             closest->format = match->format;
632         } else {
633             closest->format = mode->format;
634         }
635         if (match->w && match->h) {
636             closest->w = match->w;
637             closest->h = match->h;
638         } else {
639             closest->w = mode->w;
640             closest->h = mode->h;
641         }
642         if (match->refresh_rate) {
643             closest->refresh_rate = match->refresh_rate;
644         } else {
645             closest->refresh_rate = mode->refresh_rate;
646         }
647         closest->driverdata = match->driverdata;
648 
649         /*
650          * Pick some reasonable defaults if the app and driver don't
651          * care
652          */
653         if (!closest->format) {
654             closest->format = SDL_PIXELFORMAT_RGB888;
655         }
656         if (!closest->w) {
657             closest->w = 640;
658         }
659         if (!closest->h) {
660             closest->h = 480;
661         }
662         return closest;
663     }
664     return NULL;
665 }
666 
667 SDL_DisplayMode *
SDL_GetClosestDisplayMode(const SDL_DisplayMode * mode,SDL_DisplayMode * closest)668 SDL_GetClosestDisplayMode(const SDL_DisplayMode * mode,
669                           SDL_DisplayMode * closest)
670 {
671     if (!_this) {
672         SDL_UninitializedVideo();
673         return NULL;
674     }
675     return SDL_GetClosestDisplayModeForDisplay(SDL_CurrentDisplay, mode, closest);
676 }
677 
678 int
SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display,const SDL_DisplayMode * mode)679 SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
680 {
681     SDL_DisplayMode display_mode;
682     SDL_DisplayMode current_mode;
683     int ncolors;
684 
685     if (mode) {
686         display_mode = *mode;
687 
688         /* Default to the current mode */
689         if (!display_mode.format) {
690             display_mode.format = display->current_mode.format;
691         }
692         if (!display_mode.w) {
693             display_mode.w = display->current_mode.w;
694         }
695         if (!display_mode.h) {
696             display_mode.h = display->current_mode.h;
697         }
698         if (!display_mode.refresh_rate) {
699             display_mode.refresh_rate = display->current_mode.refresh_rate;
700         }
701 
702         /* Get a good video mode, the closest one possible */
703         if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
704             SDL_SetError("No video mode large enough for %dx%d",
705                          display_mode.w, display_mode.h);
706             return -1;
707         }
708     } else {
709         display_mode = display->desktop_mode;
710     }
711 
712     /* See if there's anything left to do */
713     SDL_GetCurrentDisplayModeForDisplay(display, &current_mode);
714     if (SDL_memcmp(&display_mode, &current_mode, sizeof(display_mode)) == 0) {
715         return 0;
716     }
717 
718     /* Actually change the display mode */
719     if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
720         return -1;
721     }
722     display->current_mode = display_mode;
723 
724 #if SDL_VERSION_ATLEAST(1,3,0)
725     /* Set up a palette, if necessary */
726     if (SDL_ISPIXELFORMAT_INDEXED(display_mode.format)) {
727         ncolors = (1 << SDL_BITSPERPIXEL(display_mode.format));
728     } else {
729         ncolors = 0;
730     }
731     if ((!ncolors && display->palette) || (ncolors && !display->palette)
732         || (ncolors && ncolors != display->palette->ncolors)) {
733         if (display->palette) {
734             SDL_FreePalette(display->palette);
735             display->palette = NULL;
736         }
737         if (ncolors) {
738             display->palette = SDL_AllocPalette(ncolors);
739             if (!display->palette) {
740                 return -1;
741             }
742             SDL_DitherColors(display->palette->colors,
743                              SDL_BITSPERPIXEL(display_mode.format));
744         }
745     }
746 #endif
747 
748     return 0;
749 }
750 
751 int
SDL_SetWindowDisplayMode(SDL_Window * window,const SDL_DisplayMode * mode)752 SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
753 {
754     CHECK_WINDOW_MAGIC(window, -1);
755 
756     if (mode) {
757         window->fullscreen_mode = *mode;
758     } else {
759         SDL_memset(&(window->fullscreen_mode), 0, sizeof(window->fullscreen_mode));
760     }
761     return 0;
762 }
763 
764 int
SDL_GetWindowDisplayMode(SDL_Window * window,SDL_DisplayMode * mode)765 SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
766 {
767     SDL_DisplayMode fullscreen_mode;
768 
769     CHECK_WINDOW_MAGIC(window, -1);
770 
771     fullscreen_mode = window->fullscreen_mode;
772     if (!fullscreen_mode.w) {
773         fullscreen_mode.w = window->w;
774     }
775     if (!fullscreen_mode.h) {
776         fullscreen_mode.h = window->h;
777     }
778 
779     if (!SDL_GetClosestDisplayModeForDisplay(window->display,
780                                              &fullscreen_mode,
781                                              &fullscreen_mode)) {
782         SDL_SetError("Couldn't find display mode match");
783         return -1;
784     }
785 
786     if (mode) {
787         *mode = fullscreen_mode;
788     }
789     return 0;
790 }
791 
792 #if SDL_VERSION_ATLEAST(1,3,0)
793 
794 static void
SDL_UpdateFullscreenMode(SDL_Window * window,SDL_bool attempt)795 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool attempt)
796 {
797     SDL_VideoDisplay *display = window->display;
798 
799     /* See if we're already processing a window */
800     if (display->updating_fullscreen) {
801         return;
802     }
803 
804     display->updating_fullscreen = SDL_TRUE;
805 
806     /* See if we even want to do anything here */
807     if ((window->flags & SDL_WINDOW_FULLSCREEN) &&
808         (window->flags & SDL_WINDOW_SHOWN)) {
809         if (attempt) {
810             /* We just gained some state, try to gain all states */
811             if (window->flags & SDL_WINDOW_MINIMIZED) {
812                 SDL_RestoreWindow(window);
813             } else {
814                 SDL_RaiseWindow(window);
815             }
816         } else {
817             /* We just lost some state, try to release all states */
818             SDL_MinimizeWindow(window);
819         }
820     }
821 
822     if (FULLSCREEN_VISIBLE(window)) {
823         /* Hide any other fullscreen windows */
824         SDL_Window *other;
825         for (other = display->windows; other; other = other->next) {
826             if (other != window && FULLSCREEN_VISIBLE(other)) {
827                 SDL_MinimizeWindow(other);
828             }
829         }
830     }
831 
832     display->updating_fullscreen = SDL_FALSE;
833 
834     /* See if there are any fullscreen windows */
835     for (window = display->windows; window; window = window->next) {
836         if (FULLSCREEN_VISIBLE(window)) {
837             SDL_DisplayMode fullscreen_mode;
838             if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) {
839                 SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
840                 display->fullscreen_window = window;
841                 return;
842             }
843         }
844     }
845 
846     /* Nope, restore the desktop mode */
847     SDL_SetDisplayModeForDisplay(display, NULL);
848     display->fullscreen_window = NULL;
849 }
850 
851 int
SDL_SetPaletteForDisplay(SDL_VideoDisplay * display,const SDL_Color * colors,int firstcolor,int ncolors)852 SDL_SetPaletteForDisplay(SDL_VideoDisplay * display, const SDL_Color * colors, int firstcolor, int ncolors)
853 {
854     SDL_Palette *palette;
855     int status = 0;
856 
857     palette = display->palette;
858     if (!palette) {
859         SDL_SetError("Display mode does not have a palette");
860         return -1;
861     }
862     status = SDL_SetPaletteColors(palette, colors, firstcolor, ncolors);
863 
864     if (_this->SetDisplayPalette) {
865         if (_this->SetDisplayPalette(_this, display, palette) < 0) {
866             status = -1;
867         }
868     }
869     return status;
870 }
871 
872 int
SDL_SetDisplayPalette(const SDL_Color * colors,int firstcolor,int ncolors)873 SDL_SetDisplayPalette(const SDL_Color * colors, int firstcolor, int ncolors)
874 {
875     if (!_this) {
876         SDL_UninitializedVideo();
877         return -1;
878     }
879     return SDL_SetPaletteForDisplay(SDL_CurrentDisplay, colors, firstcolor, ncolors);
880 }
881 
882 int
SDL_GetPaletteForDisplay(SDL_VideoDisplay * display,SDL_Color * colors,int firstcolor,int ncolors)883 SDL_GetPaletteForDisplay(SDL_VideoDisplay * display, SDL_Color * colors, int firstcolor, int ncolors)
884 {
885     SDL_Palette *palette;
886 
887     palette = display->palette;
888     if (!palette || !palette->ncolors) {
889         SDL_SetError("Display mode does not have a palette");
890         return -1;
891     }
892     if (firstcolor < 0 || (firstcolor + ncolors) > palette->ncolors) {
893         SDL_SetError("Palette indices are out of range");
894         return -1;
895     }
896     SDL_memcpy(colors, &palette->colors[firstcolor],
897                ncolors * sizeof(*colors));
898     return 0;
899 }
900 
901 int
SDL_GetDisplayPalette(SDL_Color * colors,int firstcolor,int ncolors)902 SDL_GetDisplayPalette(SDL_Color * colors, int firstcolor, int ncolors)
903 {
904     if (!_this) {
905         SDL_UninitializedVideo();
906         return -1;
907     }
908     return SDL_GetPaletteForDisplay(SDL_CurrentDisplay, colors, firstcolor, ncolors);
909 }
910 
911 #endif
912 
913 SDL_Window *
SDL_CreateWindow(const char * title,int x,int y,int w,int h,Uint32 flags)914 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
915 {
916     const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN |
917                                   SDL_WINDOW_OPENGL |
918                                   SDL_WINDOW_BORDERLESS |
919                                   SDL_WINDOW_RESIZABLE |
920                                   SDL_WINDOW_INPUT_GRABBED);
921     SDL_VideoDisplay *display;
922     SDL_Window *window;
923 
924 #if SDL_VERSION_ATLEAST(1,3,0)
925     if (!_this) {
926         /* Initialize the video system if needed */
927         if (SDL_VideoInit(NULL, 0) < 0) {
928             return NULL;
929         }
930     }
931     if (flags & SDL_WINDOW_OPENGL) {
932         if (!_this->GL_CreateContext) {
933             SDL_SetError("No OpenGL support in video driver");
934             return NULL;
935         }
936         SDL_GL_LoadLibrary(NULL);
937     }
938 #endif
939 
940     display = SDL_CurrentDisplay;
941     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
942     window->magic = &_this->window_magic;
943     window->id = _this->next_object_id++;
944     window->x = x;
945     window->y = y;
946     window->w = w;
947     window->h = h;
948     window->flags = (flags & allowed_flags);
949     window->display = display;
950     window->next = display->windows;
951     if (display->windows) {
952         display->windows->prev = window;
953     }
954     display->windows = window;
955 
956 #if SDL_VERSION_ATLEAST(1,3,0)
957     if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
958         SDL_DestroyWindow(window);
959         return NULL;
960     }
961 
962     if (title) {
963         SDL_SetWindowTitle(window, title);
964     }
965     if (flags & SDL_WINDOW_MAXIMIZED) {
966         SDL_MaximizeWindow(window);
967     }
968     if (flags & SDL_WINDOW_MINIMIZED) {
969         SDL_MinimizeWindow(window);
970     }
971     if (flags & SDL_WINDOW_SHOWN) {
972         SDL_ShowWindow(window);
973     }
974     SDL_UpdateWindowGrab(window);
975 #endif
976 
977     return window;
978 }
979 
980 #if SDL_VERSION_ATLEAST(1,3,0)
981 
982 SDL_Window *
SDL_CreateWindowFrom(const void * data)983 SDL_CreateWindowFrom(const void *data)
984 {
985     SDL_VideoDisplay *display;
986     SDL_Window *window;
987 
988     if (!_this) {
989         SDL_UninitializedVideo();
990         return NULL;
991     }
992     display = SDL_CurrentDisplay;
993     window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
994     window->magic = &_this->window_magic;
995     window->id = _this->next_object_id++;
996     window->flags = SDL_WINDOW_FOREIGN;
997     window->display = display;
998     window->next = display->windows;
999     if (display->windows) {
1000         display->windows->prev = window;
1001     }
1002     display->windows = window;
1003 
1004     if (!_this->CreateWindowFrom ||
1005         _this->CreateWindowFrom(_this, window, data) < 0) {
1006         SDL_DestroyWindow(window);
1007         return NULL;
1008     }
1009     return window;
1010 }
1011 
1012 int
SDL_RecreateWindow(SDL_Window * window,Uint32 flags)1013 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
1014 {
1015     const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN |
1016                                   SDL_WINDOW_OPENGL |
1017                                   SDL_WINDOW_BORDERLESS |
1018                                   SDL_WINDOW_RESIZABLE |
1019                                   SDL_WINDOW_INPUT_GRABBED |
1020                                   SDL_WINDOW_FOREIGN);
1021     char *title = window->title;
1022 
1023     if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
1024         SDL_SetError("No OpenGL support in video driver");
1025         return -1;
1026     }
1027     if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
1028         if (flags & SDL_WINDOW_OPENGL) {
1029             SDL_GL_LoadLibrary(NULL);
1030         } else {
1031             SDL_GL_UnloadLibrary();
1032         }
1033     }
1034 
1035     if (window->flags & SDL_WINDOW_FOREIGN) {
1036         /* Can't destroy and re-create foreign windows, hrm */
1037         flags |= SDL_WINDOW_FOREIGN;
1038     } else {
1039         flags &= ~SDL_WINDOW_FOREIGN;
1040     }
1041 
1042     if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1043         _this->DestroyWindow(_this, window);
1044     }
1045 
1046     window->title = NULL;
1047     window->flags = (flags & allowed_flags);
1048 
1049     if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1050         if (_this->CreateWindow(_this, window) < 0) {
1051             if (flags & SDL_WINDOW_OPENGL) {
1052                 SDL_GL_UnloadLibrary();
1053             }
1054             return -1;
1055         }
1056     }
1057 
1058     if (title) {
1059         SDL_SetWindowTitle(window, title);
1060         SDL_free(title);
1061     }
1062     if (flags & SDL_WINDOW_MAXIMIZED) {
1063         SDL_MaximizeWindow(window);
1064     }
1065     if (flags & SDL_WINDOW_MINIMIZED) {
1066         SDL_MinimizeWindow(window);
1067     }
1068     if (flags & SDL_WINDOW_SHOWN) {
1069         SDL_ShowWindow(window);
1070     }
1071     SDL_UpdateWindowGrab(window);
1072 
1073     return 0;
1074 }
1075 #endif
1076 
1077 static __inline__ SDL_Renderer *
SDL_GetCurrentRenderer(SDL_bool create)1078 SDL_GetCurrentRenderer(SDL_bool create)
1079 {
1080     if (!_this) {
1081         SDL_UninitializedVideo();
1082         return NULL;
1083     }
1084     if (!SDL_CurrentRenderer) {
1085         if (!create) {
1086             SDL_SetError("Use SDL_CreateRenderer() to create a renderer");
1087             return NULL;
1088         }
1089         if (SDL_CreateRenderer(0, -1, 0) < 0) {
1090             return NULL;
1091         }
1092     }
1093     return SDL_CurrentRenderer;
1094 }
1095 
1096 #if SDL_VERSION_ATLEAST(1,3,0)
1097 Uint32
SDL_GetWindowID(SDL_Window * window)1098 SDL_GetWindowID(SDL_Window * window)
1099 {
1100     CHECK_WINDOW_MAGIC(window, 0);
1101 
1102     return window->id;
1103 }
1104 
1105 SDL_Window *
SDL_GetWindowFromID(Uint32 id)1106 SDL_GetWindowFromID(Uint32 id)
1107 {
1108     SDL_Window *window;
1109     int i;
1110 
1111     if (!_this) {
1112         return NULL;
1113     }
1114     /* FIXME: Should we keep a separate hash table for these? */
1115     for (i = _this->num_displays; i--;) {
1116         SDL_VideoDisplay *display = &_this->displays[i];
1117         for (window = display->windows; window; window = window->next) {
1118             if (window->id == id) {
1119                 return window;
1120             }
1121         }
1122     }
1123     return NULL;
1124 }
1125 
1126 Uint32
SDL_GetWindowFlags(SDL_Window * window)1127 SDL_GetWindowFlags(SDL_Window * window)
1128 {
1129     CHECK_WINDOW_MAGIC(window, 0);
1130 
1131     return window->flags;
1132 }
1133 
1134 void
SDL_SetWindowTitle(SDL_Window * window,const char * title)1135 SDL_SetWindowTitle(SDL_Window * window, const char *title)
1136 {
1137     CHECK_WINDOW_MAGIC(window, );
1138 
1139     if (title == window->title) {
1140         return;
1141     }
1142     if (window->title) {
1143         SDL_free(window->title);
1144     }
1145     if (title) {
1146         window->title = SDL_strdup(title);
1147     } else {
1148         window->title = NULL;
1149     }
1150 
1151     if (_this->SetWindowTitle) {
1152         _this->SetWindowTitle(_this, window);
1153     }
1154 }
1155 
1156 const char *
SDL_GetWindowTitle(SDL_Window * window)1157 SDL_GetWindowTitle(SDL_Window * window)
1158 {
1159     CHECK_WINDOW_MAGIC(window, NULL);
1160 
1161     return window->title;
1162 }
1163 
1164 void
SDL_SetWindowIcon(SDL_Window * window,SDL_Surface * icon)1165 SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
1166 {
1167     CHECK_WINDOW_MAGIC(window, );
1168 
1169     if (_this->SetWindowIcon) {
1170         _this->SetWindowIcon(_this, window, icon);
1171     }
1172 }
1173 
1174 void
SDL_SetWindowData(SDL_Window * window,void * userdata)1175 SDL_SetWindowData(SDL_Window * window, void *userdata)
1176 {
1177     CHECK_WINDOW_MAGIC(window, );
1178 
1179     window->userdata = userdata;
1180 }
1181 
1182 void *
SDL_GetWindowData(SDL_Window * window)1183 SDL_GetWindowData(SDL_Window * window)
1184 {
1185     CHECK_WINDOW_MAGIC(window, NULL);
1186 
1187     return window->userdata;
1188 }
1189 
1190 void
SDL_SetWindowPosition(SDL_Window * window,int x,int y)1191 SDL_SetWindowPosition(SDL_Window * window, int x, int y)
1192 {
1193     CHECK_WINDOW_MAGIC(window, );
1194 
1195     if (x != SDL_WINDOWPOS_UNDEFINED) {
1196         window->x = x;
1197     }
1198     if (y != SDL_WINDOWPOS_UNDEFINED) {
1199         window->y = y;
1200     }
1201     if (_this->SetWindowPosition) {
1202         _this->SetWindowPosition(_this, window);
1203     }
1204     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
1205 }
1206 
1207 void
SDL_GetWindowPosition(SDL_Window * window,int * x,int * y)1208 SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
1209 {
1210     CHECK_WINDOW_MAGIC(window, );
1211 
1212     if (x) {
1213         *x = window->x;
1214     }
1215     if (y) {
1216         *y = window->y;
1217     }
1218 }
1219 
1220 void
SDL_SetWindowSize(SDL_Window * window,int w,int h)1221 SDL_SetWindowSize(SDL_Window * window, int w, int h)
1222 {
1223     CHECK_WINDOW_MAGIC(window, );
1224 
1225     window->w = w;
1226     window->h = h;
1227 
1228     if (_this->SetWindowSize) {
1229         _this->SetWindowSize(_this, window);
1230     }
1231     SDL_OnWindowResized(window);
1232 }
1233 
1234 void
SDL_GetWindowSize(SDL_Window * window,int * w,int * h)1235 SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
1236 {
1237     if (window) {
1238         if (w) {
1239             *w = window->w;
1240         }
1241         if (h) {
1242             *h = window->h;
1243         }
1244     } else {
1245         if (w) {
1246             *w = 0;
1247         }
1248         if (h) {
1249             *h = 0;
1250         }
1251     }
1252 }
1253 
1254 void
SDL_ShowWindow(SDL_Window * window)1255 SDL_ShowWindow(SDL_Window * window)
1256 {
1257     CHECK_WINDOW_MAGIC(window, );
1258 
1259     if (window->flags & SDL_WINDOW_SHOWN) {
1260         return;
1261     }
1262 
1263     if (_this->ShowWindow) {
1264         _this->ShowWindow(_this, window);
1265     }
1266     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
1267 }
1268 
1269 void
SDL_HideWindow(SDL_Window * window)1270 SDL_HideWindow(SDL_Window * window)
1271 {
1272     CHECK_WINDOW_MAGIC(window, );
1273 
1274     if (!(window->flags & SDL_WINDOW_SHOWN)) {
1275         return;
1276     }
1277 
1278     if (_this->HideWindow) {
1279         _this->HideWindow(_this, window);
1280     }
1281     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
1282 }
1283 
1284 void
SDL_RaiseWindow(SDL_Window * window)1285 SDL_RaiseWindow(SDL_Window * window)
1286 {
1287     CHECK_WINDOW_MAGIC(window, );
1288 
1289     if (!(window->flags & SDL_WINDOW_SHOWN)) {
1290         return;
1291     }
1292     if (_this->RaiseWindow) {
1293         _this->RaiseWindow(_this, window);
1294     } else {
1295         /* FIXME: What we really want is a way to request focus */
1296         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
1297     }
1298 }
1299 
1300 void
SDL_MaximizeWindow(SDL_Window * window)1301 SDL_MaximizeWindow(SDL_Window * window)
1302 {
1303     CHECK_WINDOW_MAGIC(window, );
1304 
1305     if (window->flags & SDL_WINDOW_MAXIMIZED) {
1306         return;
1307     }
1308 
1309     if (_this->MaximizeWindow) {
1310         _this->MaximizeWindow(_this, window);
1311     }
1312     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
1313 }
1314 
1315 void
SDL_MinimizeWindow(SDL_Window * window)1316 SDL_MinimizeWindow(SDL_Window * window)
1317 {
1318     CHECK_WINDOW_MAGIC(window, );
1319 
1320     if (window->flags & SDL_WINDOW_MINIMIZED) {
1321         return;
1322     }
1323 
1324     if (_this->MinimizeWindow) {
1325         _this->MinimizeWindow(_this, window);
1326     }
1327     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
1328 }
1329 
1330 void
SDL_RestoreWindow(SDL_Window * window)1331 SDL_RestoreWindow(SDL_Window * window)
1332 {
1333     CHECK_WINDOW_MAGIC(window, );
1334 
1335     if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
1336         return;
1337     }
1338 
1339     if (_this->RestoreWindow) {
1340         _this->RestoreWindow(_this, window);
1341     }
1342     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
1343 }
1344 
1345 int
SDL_SetWindowFullscreen(SDL_Window * window,int fullscreen)1346 SDL_SetWindowFullscreen(SDL_Window * window, int fullscreen)
1347 {
1348     CHECK_WINDOW_MAGIC(window, -1);
1349 
1350     if (fullscreen) {
1351         fullscreen = SDL_WINDOW_FULLSCREEN;
1352     }
1353     if ((window->flags & SDL_WINDOW_FULLSCREEN) == fullscreen) {
1354         return 0;
1355     }
1356     if (fullscreen) {
1357         window->flags |= SDL_WINDOW_FULLSCREEN;
1358 
1359         SDL_UpdateFullscreenMode(window, SDL_TRUE);
1360     } else {
1361         window->flags &= ~SDL_WINDOW_FULLSCREEN;
1362 
1363         SDL_UpdateFullscreenMode(window, SDL_FALSE);
1364     }
1365     return 0;
1366 }
1367 
1368 void
SDL_SetWindowGrab(SDL_Window * window,int mode)1369 SDL_SetWindowGrab(SDL_Window * window, int mode)
1370 {
1371     CHECK_WINDOW_MAGIC(window, );
1372 
1373     if ((!!mode == !!(window->flags & SDL_WINDOW_INPUT_GRABBED))) {
1374         return;
1375     }
1376     if (mode) {
1377         window->flags |= SDL_WINDOW_INPUT_GRABBED;
1378     } else {
1379         window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
1380     }
1381     SDL_UpdateWindowGrab(window);
1382 }
1383 
1384 static void
SDL_UpdateWindowGrab(SDL_Window * window)1385 SDL_UpdateWindowGrab(SDL_Window * window)
1386 {
1387     if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) {
1388         _this->SetWindowGrab(_this, window);
1389     }
1390 }
1391 
1392 int
SDL_GetWindowGrab(SDL_Window * window)1393 SDL_GetWindowGrab(SDL_Window * window)
1394 {
1395     CHECK_WINDOW_MAGIC(window, 0);
1396 
1397     return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
1398 }
1399 
1400 void
SDL_OnWindowShown(SDL_Window * window)1401 SDL_OnWindowShown(SDL_Window * window)
1402 {
1403     SDL_RaiseWindow(window);
1404     SDL_UpdateFullscreenMode(window, SDL_TRUE);
1405 }
1406 
1407 void
SDL_OnWindowHidden(SDL_Window * window)1408 SDL_OnWindowHidden(SDL_Window * window)
1409 {
1410     SDL_UpdateFullscreenMode(window, SDL_FALSE);
1411 }
1412 
1413 void
SDL_OnWindowResized(SDL_Window * window)1414 SDL_OnWindowResized(SDL_Window * window)
1415 {
1416     SDL_Renderer *renderer = window->renderer;
1417 
1418     if (renderer && renderer->DisplayModeChanged) {
1419         renderer->DisplayModeChanged(renderer);
1420     }
1421 }
1422 
1423 void
SDL_OnWindowMinimized(SDL_Window * window)1424 SDL_OnWindowMinimized(SDL_Window * window)
1425 {
1426     SDL_UpdateFullscreenMode(window, SDL_FALSE);
1427 }
1428 
1429 void
SDL_OnWindowRestored(SDL_Window * window)1430 SDL_OnWindowRestored(SDL_Window * window)
1431 {
1432     SDL_RaiseWindow(window);
1433     SDL_UpdateFullscreenMode(window, SDL_TRUE);
1434 }
1435 
1436 void
SDL_OnWindowFocusGained(SDL_Window * window)1437 SDL_OnWindowFocusGained(SDL_Window * window)
1438 {
1439     SDL_VideoDisplay *display = window->display;
1440 
1441     if (display->gamma && _this->SetDisplayGammaRamp) {
1442         _this->SetDisplayGammaRamp(_this, display, display->gamma);
1443     }
1444     if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
1445         && _this->SetWindowGrab) {
1446         _this->SetWindowGrab(_this, window);
1447     }
1448 }
1449 
1450 void
SDL_OnWindowFocusLost(SDL_Window * window)1451 SDL_OnWindowFocusLost(SDL_Window * window)
1452 {
1453     SDL_VideoDisplay *display = window->display;
1454 
1455     /* If we're fullscreen on a single-head system and lose focus, minimize */
1456     if ((window->flags & SDL_WINDOW_FULLSCREEN) &&
1457         _this->num_displays == 1) {
1458         SDL_MinimizeWindow(window);
1459     }
1460 
1461     if (display->gamma && _this->SetDisplayGammaRamp) {
1462         _this->SetDisplayGammaRamp(_this, display, display->saved_gamma);
1463     }
1464     if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
1465         && _this->SetWindowGrab) {
1466         _this->SetWindowGrab(_this, window);
1467     }
1468 }
1469 
1470 SDL_Window *
SDL_GetFocusWindow(void)1471 SDL_GetFocusWindow(void)
1472 {
1473     SDL_VideoDisplay *display;
1474     SDL_Window *window;
1475 
1476     if (!_this) {
1477         return NULL;
1478     }
1479     display = SDL_CurrentDisplay;
1480     for (window = display->windows; window; window = window->next) {
1481         if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
1482             return window;
1483         }
1484     }
1485     return NULL;
1486 }
1487 
1488 #endif
1489 
1490 void
SDL_DestroyWindow(SDL_Window * window)1491 SDL_DestroyWindow(SDL_Window * window)
1492 {
1493     SDL_VideoDisplay *display;
1494 
1495     CHECK_WINDOW_MAGIC(window, );
1496     window->magic = NULL;
1497 
1498     if (window->title) {
1499         SDL_free(window->title);
1500     }
1501     if (window->renderer) {
1502         SDL_DestroyRenderer(window);
1503     }
1504 
1505 #if SDL_VERSION_ATLEAST(1,3,0)
1506     /* Restore video mode, etc. */
1507     SDL_UpdateFullscreenMode(window, SDL_FALSE);
1508 #endif
1509 
1510     if (_this->DestroyWindow) {
1511         _this->DestroyWindow(_this, window);
1512     }
1513 #if SDL_VERSION_ATLEAST(1,3,0)
1514     if (window->flags & SDL_WINDOW_OPENGL) {
1515         SDL_GL_UnloadLibrary();
1516     }
1517 #endif
1518 
1519     /* Unlink the window from the list */
1520     display = window->display;
1521     if (window->next) {
1522         window->next->prev = window->prev;
1523     }
1524     if (window->prev) {
1525         window->prev->next = window->next;
1526     } else {
1527         display->windows = window->next;
1528     }
1529 
1530     SDL_free(window);
1531 }
1532 
1533 void
SDL_AddRenderDriver(SDL_VideoDisplay * display,const SDL_RenderDriver * driver)1534 SDL_AddRenderDriver(SDL_VideoDisplay * display, const SDL_RenderDriver * driver)
1535 {
1536     SDL_RenderDriver *render_drivers;
1537 
1538     render_drivers =
1539         SDL_realloc(display->render_drivers,
1540                     (display->num_render_drivers +
1541                      1) * sizeof(*render_drivers));
1542     if (render_drivers) {
1543         render_drivers[display->num_render_drivers] = *driver;
1544         display->render_drivers = render_drivers;
1545         display->num_render_drivers++;
1546     }
1547 }
1548 
1549 int
SDL_GetNumRenderDrivers(void)1550 SDL_GetNumRenderDrivers(void)
1551 {
1552     if (_this) {
1553         return SDL_CurrentDisplay->num_render_drivers;
1554     }
1555     return 0;
1556 }
1557 
1558 int
SDL_GetRenderDriverInfo(int index,SDL_RendererInfo * info)1559 SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
1560 {
1561     if (!_this) {
1562         SDL_UninitializedVideo();
1563         return -1;
1564     }
1565     if (index < 0 || index >= SDL_GetNumRenderDrivers()) {
1566         SDL_SetError("index must be in the range of 0 - %d",
1567                      SDL_GetNumRenderDrivers() - 1);
1568         return -1;
1569     }
1570     *info = SDL_CurrentDisplay->render_drivers[index].info;
1571     return 0;
1572 }
1573 
1574 int
SDL_CreateRenderer(SDL_Window * window,int index,Uint32 flags)1575 SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
1576 {
1577     CHECK_WINDOW_MAGIC(window, -1);
1578 
1579     /* Free any existing renderer */
1580     SDL_DestroyRenderer(window);
1581 
1582 #if SDL_VERSION_ATLEAST(1,3,0)
1583     if (index < 0) {
1584         char *override = SDL_getenv("SDL_VIDEO_RENDERER");
1585         int n = SDL_GetNumRenderDrivers();
1586 
1587 #if SDL_VIDEO_RENDER_OGL
1588         if (!override && (window->flags & SDL_WINDOW_OPENGL)) {
1589             override = "opengl";
1590         }
1591 #endif /* SDL_VIDEO_RENDER_OGL */
1592 #if SDL_VIDEO_RENDER_OGL_ES
1593         if (!override && (window->flags & SDL_WINDOW_OPENGL)) {
1594             override = "opengl_es";
1595         }
1596 #endif /* SDL_VIDEO_RENDER_OGL_ES */
1597         if (override) {
1598             for (index = 0; index < n; ++index) {
1599                 SDL_RenderDriver *driver =
1600                     &SDL_CurrentDisplay->render_drivers[index];
1601 
1602                 if (SDL_strcasecmp(override, driver->info.name) == 0) {
1603                     /* Create a new renderer instance */
1604                     window->renderer = driver->CreateRenderer(window, flags);
1605                     break;
1606                 }
1607             }
1608         } else {
1609             for (index = 0; index < n; ++index) {
1610                 SDL_RenderDriver *driver =
1611                     &SDL_CurrentDisplay->render_drivers[index];
1612 
1613                 if ((driver->info.flags & flags) == flags) {
1614                     /* Create a new renderer instance */
1615                     window->renderer = driver->CreateRenderer(window, flags);
1616                     if (window->renderer) {
1617                         /* Yay, we got one! */
1618                         break;
1619                     }
1620                 }
1621             }
1622         }
1623         if (index == n) {
1624             SDL_SetError("Couldn't find matching render driver");
1625             return -1;
1626         }
1627     } else {
1628         if (index >= SDL_GetNumRenderDrivers()) {
1629             SDL_SetError("index must be -1 or in the range of 0 - %d",
1630                          SDL_GetNumRenderDrivers() - 1);
1631             return -1;
1632         }
1633         /* Create a new renderer instance */
1634         window->renderer = SDL_CurrentDisplay->render_drivers[index].CreateRenderer(window, flags);
1635     }
1636 #else
1637     window->renderer = GL_ES_RenderDriver.CreateRenderer(window, flags);
1638 #endif
1639 
1640     if (window->renderer == NULL) {
1641         /* Assuming renderer set its error */
1642         return -1;
1643     }
1644 
1645     SDL_SelectRenderer(window);
1646 
1647     return 0;
1648 }
1649 
1650 int
SDL_SelectRenderer(SDL_Window * window)1651 SDL_SelectRenderer(SDL_Window * window)
1652 {
1653     SDL_Renderer *renderer;
1654 
1655     CHECK_WINDOW_MAGIC(window, -1);
1656 
1657     renderer = window->renderer;
1658     if (!renderer) {
1659         SDL_SetError("Use SDL_CreateRenderer() to create a renderer");
1660         return -1;
1661     }
1662     if (renderer->ActivateRenderer) {
1663         if (renderer->ActivateRenderer(renderer) < 0) {
1664             return -1;
1665         }
1666     }
1667     SDL_CurrentDisplay->current_renderer = renderer;
1668     return 0;
1669 }
1670 
1671 int
SDL_GetRendererInfo(SDL_RendererInfo * info)1672 SDL_GetRendererInfo(SDL_RendererInfo * info)
1673 {
1674     SDL_Renderer *renderer = SDL_GetCurrentRenderer(SDL_FALSE);
1675     if (!renderer) {
1676         return -1;
1677     }
1678     *info = renderer->info;
1679     return 0;
1680 }
1681 
1682 SDL_Texture *
SDL_CreateTexture(Uint32 format,int access,int w,int h)1683 SDL_CreateTexture(Uint32 format, int access, int w, int h)
1684 {
1685     SDL_Renderer *renderer;
1686     SDL_Texture *texture;
1687 
1688     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
1689     if (!renderer) {
1690         return 0;
1691     }
1692     if (!renderer->CreateTexture) {
1693         SDL_Unsupported();
1694         return 0;
1695     }
1696     if (w <= 0 || h <= 0) {
1697         SDL_SetError("Texture dimensions can't be 0");
1698         return 0;
1699     }
1700     texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
1701     if (!texture) {
1702         SDL_OutOfMemory();
1703         return 0;
1704     }
1705     texture->magic = &_this->texture_magic;
1706     texture->format = format;
1707     texture->access = access;
1708     texture->w = w;
1709     texture->h = h;
1710     texture->r = 255;
1711     texture->g = 255;
1712     texture->b = 255;
1713     texture->a = 255;
1714     texture->renderer = renderer;
1715     texture->next = renderer->textures;
1716     if (renderer->textures) {
1717         renderer->textures->prev = texture;
1718     }
1719     renderer->textures = texture;
1720 
1721     if (renderer->CreateTexture(renderer, texture) < 0) {
1722         SDL_DestroyTexture(texture);
1723         return 0;
1724     }
1725     return texture;
1726 }
1727 
1728 SDL_Texture *
SDL_CreateTextureFromSurface(Uint32 format,SDL_Surface * surface)1729 SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface)
1730 {
1731     SDL_Texture *texture;
1732     Uint32 requested_format = format;
1733     SDL_PixelFormat *fmt;
1734     SDL_Renderer *renderer;
1735     int bpp;
1736     Uint32 Rmask, Gmask, Bmask, Amask;
1737 
1738     if (!surface) {
1739         SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
1740         return 0;
1741     }
1742     fmt = surface->format;
1743 
1744     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
1745     if (!renderer) {
1746         return 0;
1747     }
1748 
1749     if (format) {
1750         if (!SDL_PixelFormatEnumToMasks
1751             (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
1752             SDL_SetError("Unknown pixel format");
1753             return 0;
1754         }
1755     } else {
1756         if (surface->format->Amask
1757 #if SDL_VERSION_ATLEAST(1,3,0)
1758             || !(surface->map->info.flags &
1759                  (SDL_COPY_COLORKEY | SDL_COPY_MASK | SDL_COPY_BLEND))) {
1760 #else
1761             || !(surface->flags &
1762                  (SDL_SRCCOLORKEY | SDL_SRCALPHA))) {
1763 #endif
1764             Uint32 it;
1765             int pfmt;
1766 
1767             /* Pixel formats, sorted by best first */
1768             static const Uint32 sdl_pformats[] = {
1769                 SDL_PIXELFORMAT_ARGB8888,
1770                 SDL_PIXELFORMAT_RGBA8888,
1771                 SDL_PIXELFORMAT_ABGR8888,
1772                 SDL_PIXELFORMAT_BGRA8888,
1773                 SDL_PIXELFORMAT_RGB888,
1774                 SDL_PIXELFORMAT_BGR888,
1775                 SDL_PIXELFORMAT_RGB24,
1776                 SDL_PIXELFORMAT_BGR24,
1777                 SDL_PIXELFORMAT_RGB565,
1778                 SDL_PIXELFORMAT_BGR565,
1779                 SDL_PIXELFORMAT_ARGB1555,
1780                 SDL_PIXELFORMAT_ABGR1555,
1781                 SDL_PIXELFORMAT_RGBA5551,
1782                 SDL_PIXELFORMAT_RGB555,
1783                 SDL_PIXELFORMAT_BGR555,
1784                 SDL_PIXELFORMAT_ARGB4444,
1785                 SDL_PIXELFORMAT_ABGR4444,
1786                 SDL_PIXELFORMAT_RGBA4444,
1787                 SDL_PIXELFORMAT_RGB444,
1788                 SDL_PIXELFORMAT_ARGB2101010,
1789                 SDL_PIXELFORMAT_INDEX8,
1790                 SDL_PIXELFORMAT_INDEX4LSB,
1791                 SDL_PIXELFORMAT_INDEX4MSB,
1792                 SDL_PIXELFORMAT_RGB332,
1793                 SDL_PIXELFORMAT_INDEX1LSB,
1794                 SDL_PIXELFORMAT_INDEX1MSB,
1795                 SDL_PIXELFORMAT_UNKNOWN
1796             };
1797 
1798             bpp = fmt->BitsPerPixel;
1799             Rmask = fmt->Rmask;
1800             Gmask = fmt->Gmask;
1801             Bmask = fmt->Bmask;
1802             Amask = fmt->Amask;
1803 
1804             format =
1805                 SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
1806             if (!format) {
1807                 SDL_SetError("Unknown pixel format");
1808                 return 0;
1809             }
1810 
1811             /* Search requested format in the supported texture */
1812             /* formats by current renderer                      */
1813             for (it = 0; it < renderer->info.num_texture_formats; it++) {
1814                 if (renderer->info.texture_formats[it] == format) {
1815                     break;
1816                 }
1817             }
1818 
1819             /* If requested format can't be found, search any best */
1820             /* format which renderer provides                      */
1821             if (it == renderer->info.num_texture_formats) {
1822                 pfmt = 0;
1823                 for (;;) {
1824                     if (sdl_pformats[pfmt] == SDL_PIXELFORMAT_UNKNOWN) {
1825                         break;
1826                     }
1827 
1828                     for (it = 0; it < renderer->info.num_texture_formats;
1829                          it++) {
1830                         if (renderer->info.texture_formats[it] ==
1831                             sdl_pformats[pfmt]) {
1832                             break;
1833                         }
1834                     }
1835 
1836                     if (it != renderer->info.num_texture_formats) {
1837                         /* The best format has been found */
1838                         break;
1839                     }
1840                     pfmt++;
1841                 }
1842 
1843                 /* If any format can't be found, then return an error */
1844                 if (it == renderer->info.num_texture_formats) {
1845                     SDL_SetError
1846                         ("Any of the supported pixel formats can't be found");
1847                     return 0;
1848                 }
1849 
1850                 /* Convert found pixel format back to color masks */
1851                 if (SDL_PixelFormatEnumToMasks
1852                     (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
1853                      &Bmask, &Amask) != SDL_TRUE) {
1854                     SDL_SetError("Unknown pixel format");
1855                     return 0;
1856                 }
1857             }
1858         } else {
1859             /* Need a format with alpha */
1860             Uint32 it;
1861             int apfmt;
1862 
1863             /* Pixel formats with alpha, sorted by best first */
1864             static const Uint32 sdl_alpha_pformats[] = {
1865                 SDL_PIXELFORMAT_ARGB8888,
1866                 SDL_PIXELFORMAT_RGBA8888,
1867                 SDL_PIXELFORMAT_ABGR8888,
1868                 SDL_PIXELFORMAT_BGRA8888,
1869                 SDL_PIXELFORMAT_ARGB1555,
1870                 SDL_PIXELFORMAT_ABGR1555,
1871                 SDL_PIXELFORMAT_RGBA5551,
1872                 SDL_PIXELFORMAT_ARGB4444,
1873                 SDL_PIXELFORMAT_ABGR4444,
1874                 SDL_PIXELFORMAT_RGBA4444,
1875                 SDL_PIXELFORMAT_ARGB2101010,
1876                 SDL_PIXELFORMAT_UNKNOWN
1877             };
1878 
1879             if (surface->format->Amask) {
1880                 /* If surface already has alpha, then try an original */
1881                 /* surface format first                               */
1882                 bpp = fmt->BitsPerPixel;
1883                 Rmask = fmt->Rmask;
1884                 Gmask = fmt->Gmask;
1885                 Bmask = fmt->Bmask;
1886                 Amask = fmt->Amask;
1887             } else {
1888                 bpp = 32;
1889                 Rmask = 0x00FF0000;
1890                 Gmask = 0x0000FF00;
1891                 Bmask = 0x000000FF;
1892                 Amask = 0xFF000000;
1893             }
1894 
1895             format =
1896                 SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
1897             if (!format) {
1898                 SDL_SetError("Unknown pixel format");
1899                 return 0;
1900             }
1901 
1902             /* Search this format in the supported texture formats */
1903             /* by current renderer                                 */
1904             for (it = 0; it < renderer->info.num_texture_formats; it++) {
1905                 if (renderer->info.texture_formats[it] == format) {
1906                     break;
1907                 }
1908             }
1909 
1910             /* If this format can't be found, search any best       */
1911             /* compatible format with alpha which renderer provides */
1912             if (it == renderer->info.num_texture_formats) {
1913                 apfmt = 0;
1914                 for (;;) {
1915                     if (sdl_alpha_pformats[apfmt] == SDL_PIXELFORMAT_UNKNOWN) {
1916                         break;
1917                     }
1918 
1919                     for (it = 0; it < renderer->info.num_texture_formats;
1920                          it++) {
1921                         if (renderer->info.texture_formats[it] ==
1922                             sdl_alpha_pformats[apfmt]) {
1923                             break;
1924                         }
1925                     }
1926 
1927                     if (it != renderer->info.num_texture_formats) {
1928                         /* Compatible format has been found */
1929                         break;
1930                     }
1931                     apfmt++;
1932                 }
1933 
1934                 /* If compatible format can't be found, then return an error */
1935                 if (it == renderer->info.num_texture_formats) {
1936                     SDL_SetError("Compatible pixel format can't be found");
1937                     return 0;
1938                 }
1939 
1940                 /* Convert found pixel format back to color masks */
1941                 if (SDL_PixelFormatEnumToMasks
1942                     (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
1943                      &Bmask, &Amask) != SDL_TRUE) {
1944                     SDL_SetError("Unknown pixel format");
1945                     return 0;
1946                 }
1947             }
1948         }
1949 
1950         format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
1951         if (!format) {
1952             SDL_SetError("Unknown pixel format");
1953             return 0;
1954         }
1955     }
1956 
1957     texture =
1958         SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, surface->w,
1959                           surface->h);
1960     if (!texture && !requested_format) {
1961         SDL_DisplayMode desktop_mode;
1962         SDL_GetDesktopDisplayMode(&desktop_mode);
1963         format = desktop_mode.format;
1964         texture =
1965             SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, surface->w,
1966                               surface->h);
1967     }
1968     if (!texture) {
1969         return 0;
1970     }
1971     if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask
1972         && Bmask == fmt->Bmask && Amask == fmt->Amask) {
1973         if (SDL_MUSTLOCK(surface)) {
1974             SDL_LockSurface(surface);
1975             SDL_UpdateTexture(texture, NULL, surface->pixels,
1976                               surface->pitch);
1977             SDL_UnlockSurface(surface);
1978         } else {
1979             SDL_UpdateTexture(texture, NULL, surface->pixels,
1980                               surface->pitch);
1981         }
1982     } else {
1983         SDL_PixelFormat dst_fmt;
1984         SDL_Surface *dst = NULL;
1985 
1986         /* Set up a destination surface for the texture update */
1987         SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask);
1988 #if SDL_VERSION_ATLEAST(1,3,0)
1989         if (SDL_ISPIXELFORMAT_INDEXED(format)) {
1990             dst_fmt.palette =
1991                 SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format)));
1992             if (dst_fmt.palette) {
1993                 /*
1994                  * FIXME: Should we try to copy
1995                  * fmt->palette?
1996                  */
1997                 SDL_DitherColors(dst_fmt.palette->colors,
1998                                  SDL_BITSPERPIXEL(format));
1999             }
2000         }
2001 #endif
2002         dst = SDL_ConvertSurface(surface, &dst_fmt, 0);
2003         if (dst) {
2004             SDL_UpdateTexture(texture, NULL, dst->pixels, dst->pitch);
2005             SDL_FreeSurface(dst);
2006         }
2007 #if SDL_VERSION_ATLEAST(1,3,0)
2008         if (dst_fmt.palette) {
2009             SDL_FreePalette(dst_fmt.palette);
2010         }
2011 #endif
2012         if (!dst) {
2013             SDL_DestroyTexture(texture);
2014             return 0;
2015         }
2016     }
2017 
2018     {
2019         Uint8 r, g, b, a;
2020         int blendMode;
2021         int scaleMode;
2022 
2023 #if SDL_VERSION_ATLEAST(1,3,0)
2024         SDL_GetSurfaceColorMod(surface, &r, &g, &b);
2025         SDL_SetTextureColorMod(texture, r, g, b);
2026 
2027         SDL_GetSurfaceAlphaMod(surface, &a);
2028         SDL_SetTextureAlphaMod(texture, a);
2029 
2030         SDL_GetSurfaceBlendMode(surface, &blendMode);
2031         SDL_SetTextureBlendMode(texture, blendMode);
2032 
2033         SDL_GetSurfaceScaleMode(surface, &scaleMode);
2034         SDL_SetTextureScaleMode(texture, scaleMode);
2035 #else
2036         if(surface->flags & SDL_SRCALPHA) {
2037             SDL_SetTextureAlphaMod(texture, surface->format->alpha);
2038             SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
2039         }
2040 #endif
2041     }
2042 
2043 #if SDL_VERSION_ATLEAST(1,3,0)
2044     if (SDL_ISPIXELFORMAT_INDEXED(format) && fmt->palette) {
2045         SDL_SetTexturePalette(texture, fmt->palette->colors, 0,
2046                               fmt->palette->ncolors);
2047     }
2048 #endif
2049     return texture;
2050 }
2051 
2052 int
2053 SDL_QueryTexture(SDL_Texture * texture, Uint32 * format, int *access,
2054                  int *w, int *h)
2055 {
2056     CHECK_TEXTURE_MAGIC(texture, -1);
2057 
2058     if (format) {
2059         *format = texture->format;
2060     }
2061     if (access) {
2062         *access = texture->access;
2063     }
2064     if (w) {
2065         *w = texture->w;
2066     }
2067     if (h) {
2068         *h = texture->h;
2069     }
2070     return 0;
2071 }
2072 
2073 int
2074 SDL_QueryTexturePixels(SDL_Texture * texture, void **pixels, int *pitch)
2075 {
2076     SDL_Renderer *renderer;
2077 
2078     CHECK_TEXTURE_MAGIC(texture, -1);
2079 
2080     renderer = texture->renderer;
2081     if (!renderer->QueryTexturePixels) {
2082         SDL_Unsupported();
2083         return -1;
2084     }
2085     return renderer->QueryTexturePixels(renderer, texture, pixels, pitch);
2086 }
2087 
2088 int
2089 SDL_SetTexturePalette(SDL_Texture * texture, const SDL_Color * colors,
2090                       int firstcolor, int ncolors)
2091 {
2092     SDL_Renderer *renderer;
2093 
2094     CHECK_TEXTURE_MAGIC(texture, -1);
2095 
2096     renderer = texture->renderer;
2097     if (!renderer->SetTexturePalette) {
2098         SDL_Unsupported();
2099         return -1;
2100     }
2101     return renderer->SetTexturePalette(renderer, texture, colors, firstcolor,
2102                                        ncolors);
2103 }
2104 
2105 int
2106 SDL_GetTexturePalette(SDL_Texture * texture, SDL_Color * colors,
2107                       int firstcolor, int ncolors)
2108 {
2109     SDL_Renderer *renderer;
2110 
2111     CHECK_TEXTURE_MAGIC(texture, -1);
2112 
2113     renderer = texture->renderer;
2114     if (!renderer->GetTexturePalette) {
2115         SDL_Unsupported();
2116         return -1;
2117     }
2118     return renderer->GetTexturePalette(renderer, texture, colors, firstcolor,
2119                                        ncolors);
2120 }
2121 
2122 int
2123 SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
2124 {
2125     SDL_Renderer *renderer;
2126 
2127     CHECK_TEXTURE_MAGIC(texture, -1);
2128 
2129     renderer = texture->renderer;
2130     if (!renderer->SetTextureColorMod) {
2131         SDL_Unsupported();
2132         return -1;
2133     }
2134     if (r < 255 || g < 255 || b < 255) {
2135         texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
2136     } else {
2137         texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
2138     }
2139     texture->r = r;
2140     texture->g = g;
2141     texture->b = b;
2142     return renderer->SetTextureColorMod(renderer, texture);
2143 }
2144 
2145 int
2146 SDL_GetTextureColorMod(SDL_Texture * texture, Uint8 * r, Uint8 * g,
2147                        Uint8 * b)
2148 {
2149     SDL_Renderer *renderer;
2150 
2151     CHECK_TEXTURE_MAGIC(texture, -1);
2152 
2153     renderer = texture->renderer;
2154     if (r) {
2155         *r = texture->r;
2156     }
2157     if (g) {
2158         *g = texture->g;
2159     }
2160     if (b) {
2161         *b = texture->b;
2162     }
2163     return 0;
2164 }
2165 
2166 int
2167 SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha)
2168 {
2169     SDL_Renderer *renderer;
2170 
2171     CHECK_TEXTURE_MAGIC(texture, -1);
2172 
2173     renderer = texture->renderer;
2174     if (!renderer->SetTextureAlphaMod) {
2175         SDL_Unsupported();
2176         return -1;
2177     }
2178     if (alpha < 255) {
2179         texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
2180     } else {
2181         texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
2182     }
2183     texture->a = alpha;
2184     return renderer->SetTextureAlphaMod(renderer, texture);
2185 }
2186 
2187 int
2188 SDL_GetTextureAlphaMod(SDL_Texture * texture, Uint8 * alpha)
2189 {
2190     CHECK_TEXTURE_MAGIC(texture, -1);
2191 
2192     if (alpha) {
2193         *alpha = texture->a;
2194     }
2195     return 0;
2196 }
2197 
2198 int
2199 SDL_SetTextureBlendMode(SDL_Texture * texture, int blendMode)
2200 {
2201     SDL_Renderer *renderer;
2202 
2203     CHECK_TEXTURE_MAGIC(texture, -1);
2204 
2205     renderer = texture->renderer;
2206     if (!renderer->SetTextureBlendMode) {
2207         SDL_Unsupported();
2208         return -1;
2209     }
2210     texture->blendMode = blendMode;
2211     return renderer->SetTextureBlendMode(renderer, texture);
2212 }
2213 
2214 int
2215 SDL_GetTextureBlendMode(SDL_Texture * texture, int *blendMode)
2216 {
2217     CHECK_TEXTURE_MAGIC(texture, -1);
2218 
2219     if (blendMode) {
2220         *blendMode = texture->blendMode;
2221     }
2222     return 0;
2223 }
2224 
2225 int
2226 SDL_SetTextureScaleMode(SDL_Texture * texture, int scaleMode)
2227 {
2228     SDL_Renderer *renderer;
2229 
2230     CHECK_TEXTURE_MAGIC(texture, -1);
2231 
2232     renderer = texture->renderer;
2233     if (!renderer->SetTextureScaleMode) {
2234         SDL_Unsupported();
2235         return -1;
2236     }
2237     texture->scaleMode = scaleMode;
2238     return renderer->SetTextureScaleMode(renderer, texture);
2239 }
2240 
2241 int
2242 SDL_GetTextureScaleMode(SDL_Texture * texture, int *scaleMode)
2243 {
2244     CHECK_TEXTURE_MAGIC(texture, -1);
2245 
2246     if (scaleMode) {
2247         *scaleMode = texture->scaleMode;
2248     }
2249     return 0;
2250 }
2251 
2252 int
2253 SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
2254                   const void *pixels, int pitch)
2255 {
2256     SDL_Renderer *renderer;
2257     SDL_Rect full_rect;
2258 
2259     CHECK_TEXTURE_MAGIC(texture, -1);
2260 
2261     renderer = texture->renderer;
2262     if (!renderer->UpdateTexture) {
2263         SDL_Unsupported();
2264         return -1;
2265     }
2266     if (!rect) {
2267         full_rect.x = 0;
2268         full_rect.y = 0;
2269         full_rect.w = texture->w;
2270         full_rect.h = texture->h;
2271         rect = &full_rect;
2272     }
2273     return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
2274 }
2275 
2276 int
2277 SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect, int markDirty,
2278                 void **pixels, int *pitch)
2279 {
2280     SDL_Renderer *renderer;
2281     SDL_Rect full_rect;
2282 
2283     CHECK_TEXTURE_MAGIC(texture, -1);
2284 
2285     if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
2286         SDL_SetError("SDL_LockTexture(): texture must be streaming");
2287         return -1;
2288     }
2289     renderer = texture->renderer;
2290     if (!renderer->LockTexture) {
2291         SDL_Unsupported();
2292         return -1;
2293     }
2294     if (!rect) {
2295         full_rect.x = 0;
2296         full_rect.y = 0;
2297         full_rect.w = texture->w;
2298         full_rect.h = texture->h;
2299         rect = &full_rect;
2300     }
2301     return renderer->LockTexture(renderer, texture, rect, markDirty, pixels,
2302                                  pitch);
2303 }
2304 
2305 void
2306 SDL_UnlockTexture(SDL_Texture * texture)
2307 {
2308     SDL_Renderer *renderer;
2309 
2310     CHECK_TEXTURE_MAGIC(texture, );
2311 
2312     if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
2313         return;
2314     }
2315     renderer = texture->renderer;
2316     if (!renderer->UnlockTexture) {
2317         return;
2318     }
2319     renderer->UnlockTexture(renderer, texture);
2320 }
2321 
2322 void
2323 SDL_DirtyTexture(SDL_Texture * texture, int numrects,
2324                  const SDL_Rect * rects)
2325 {
2326     SDL_Renderer *renderer;
2327 
2328     CHECK_TEXTURE_MAGIC(texture, );
2329 
2330     if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
2331         return;
2332     }
2333     renderer = texture->renderer;
2334     if (!renderer->DirtyTexture) {
2335         return;
2336     }
2337     renderer->DirtyTexture(renderer, texture, numrects, rects);
2338 }
2339 
2340 int
2341 SDL_SetRenderDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2342 {
2343     SDL_Renderer *renderer;
2344 
2345     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2346     if (!renderer) {
2347         return -1;
2348     }
2349     renderer->r = r;
2350     renderer->g = g;
2351     renderer->b = b;
2352     renderer->a = a;
2353     if (renderer->SetDrawColor) {
2354         return renderer->SetDrawColor(renderer);
2355     } else {
2356         return 0;
2357     }
2358 }
2359 
2360 int
2361 SDL_GetRenderDrawColor(Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
2362 {
2363     SDL_Renderer *renderer;
2364 
2365     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2366     if (!renderer) {
2367         return -1;
2368     }
2369     if (r) {
2370         *r = renderer->r;
2371     }
2372     if (g) {
2373         *g = renderer->g;
2374     }
2375     if (b) {
2376         *b = renderer->b;
2377     }
2378     if (a) {
2379         *a = renderer->a;
2380     }
2381     return 0;
2382 }
2383 
2384 int
2385 SDL_SetRenderDrawBlendMode(int blendMode)
2386 {
2387     SDL_Renderer *renderer;
2388 
2389     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2390     if (!renderer) {
2391         return -1;
2392     }
2393     renderer->blendMode = blendMode;
2394     if (renderer->SetDrawBlendMode) {
2395         return renderer->SetDrawBlendMode(renderer);
2396     } else {
2397         return 0;
2398     }
2399 }
2400 
2401 int
2402 SDL_GetRenderDrawBlendMode(int *blendMode)
2403 {
2404     SDL_Renderer *renderer;
2405 
2406     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2407     if (!renderer) {
2408         return -1;
2409     }
2410     *blendMode = renderer->blendMode;
2411     return 0;
2412 }
2413 
2414 int
2415 SDL_RenderClear()
2416 {
2417     SDL_Renderer *renderer;
2418 
2419     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2420     if (!renderer) {
2421         return -1;
2422     }
2423     if (!renderer->RenderClear) {
2424         int blendMode = renderer->blendMode;
2425         int status;
2426 
2427         if (blendMode >= SDL_BLENDMODE_BLEND) {
2428             SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
2429         }
2430 
2431         status = SDL_RenderFillRect(NULL);
2432 
2433         if (blendMode >= SDL_BLENDMODE_BLEND) {
2434             SDL_SetRenderDrawBlendMode(blendMode);
2435         }
2436         return status;
2437     }
2438     return renderer->RenderClear(renderer);
2439 }
2440 
2441 #if SDL_VIDEO_RENDER_RESIZE
2442 
2443 static inline void
2444 SDL_RESIZE_resizePoints(int realW, int fakeW, int realH, int fakeH,
2445                         const SDL_Point * src, SDL_Point * dest, int count )
2446 {
2447     int i;
2448     for( i = 0; i < count; i++ ) {
2449         dest[i].x = src[i].x * realW / fakeW;
2450         dest[i].y = src[i].y * realH / fakeH;
2451     }
2452 }
2453 
2454 static inline void
2455 SDL_RESIZE_resizeRects(int realW, int fakeW, int realH, int fakeH,
2456                        const SDL_Rect ** src, SDL_Rect * dest, int count )
2457 {
2458     int i;
2459     for( i = 0; i < count; i++ ) {
2460         // Calculate bottom-right corner instead of width/height, and substract upper-left corner,
2461         // otherwise we'll have rounding errors and holes between textures
2462         dest[i].x = src[i]->x * realW / fakeW;
2463         dest[i].y = src[i]->y * realH / fakeH;
2464         dest[i].w = (src[i]->w + src[i]->x) * realW / fakeW - dest[i].x;
2465         dest[i].h = (src[i]->h + src[i]->y) * realH / fakeH - dest[i].y;
2466     }
2467 }
2468 
2469 #endif
2470 
2471 int
2472 SDL_RenderDrawPoint(int x, int y)
2473 {
2474     SDL_Point point;
2475 
2476     point.x = x;
2477     point.y = y;
2478 
2479     return SDL_RenderDrawPoints(&point, 1);
2480 }
2481 
2482 int
2483 SDL_RenderDrawPoints(const SDL_Point * points, int count)
2484 {
2485     SDL_Renderer *renderer;
2486 #if SDL_VIDEO_RENDER_RESIZE
2487     int realW, realH, fakeW, fakeH, ret;
2488 #endif
2489 
2490     if (!points) {
2491         SDL_SetError("SDL_RenderDrawPoints(): Passed NULL points");
2492         return -1;
2493     }
2494 
2495     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2496     if (!renderer) {
2497         return -1;
2498     }
2499     if (!renderer->RenderDrawPoints) {
2500         SDL_Unsupported();
2501         return -1;
2502     }
2503     if (count < 1) {
2504         return 0;
2505     }
2506 
2507 #if SDL_VIDEO_RENDER_RESIZE
2508     realW = renderer->window->display->desktop_mode.w;
2509     realH = renderer->window->display->desktop_mode.h;
2510     fakeW = renderer->window->w;
2511     fakeH = renderer->window->h;
2512     //if( fakeW > realW || fakeH > realH )
2513     {
2514         SDL_Point * resized = SDL_stack_alloc( SDL_Point, count );
2515         if( ! resized ) {
2516             SDL_OutOfMemory();
2517             return -1;
2518         }
2519         SDL_RESIZE_resizePoints( realW, fakeW, realH, fakeH, points, resized, count );
2520         ret = renderer->RenderDrawPoints(renderer, resized, count);
2521         SDL_stack_free(resized);
2522         return ret;
2523     }
2524 #endif
2525 
2526     return renderer->RenderDrawPoints(renderer, points, count);
2527 }
2528 
2529 int
2530 SDL_RenderDrawLine(int x1, int y1, int x2, int y2)
2531 {
2532     SDL_Point points[2];
2533 
2534     points[0].x = x1;
2535     points[0].y = y1;
2536     points[1].x = x2;
2537     points[1].y = y2;
2538     return SDL_RenderDrawLines(points, 2);
2539 }
2540 
2541 int
2542 SDL_RenderDrawLines(const SDL_Point * points, int count)
2543 {
2544     SDL_Renderer *renderer;
2545 #if SDL_VIDEO_RENDER_RESIZE
2546     int realW, realH, fakeW, fakeH, ret;
2547 #endif
2548 
2549     if (!points) {
2550         SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
2551         return -1;
2552     }
2553 
2554     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2555     if (!renderer) {
2556         return -1;
2557     }
2558     if (!renderer->RenderDrawLines) {
2559         SDL_Unsupported();
2560         return -1;
2561     }
2562     if (count < 2) {
2563         return 0;
2564     }
2565 
2566 #if SDL_VIDEO_RENDER_RESIZE
2567     realW = renderer->window->display->desktop_mode.w;
2568     realH = renderer->window->display->desktop_mode.h;
2569     fakeW = renderer->window->w;
2570     fakeH = renderer->window->h;
2571     //if( fakeW > realW || fakeH > realH )
2572     {
2573         SDL_Point * resized = SDL_stack_alloc( SDL_Point, count );
2574         if( ! resized ) {
2575             SDL_OutOfMemory();
2576             return -1;
2577         }
2578         SDL_RESIZE_resizePoints( realW, fakeW, realH, fakeH, points, resized, count );
2579         ret = renderer->RenderDrawLines(renderer, resized, count);
2580         SDL_stack_free(resized);
2581         return ret;
2582     }
2583 #endif
2584 
2585     return renderer->RenderDrawLines(renderer, points, count);
2586 }
2587 
2588 int
2589 SDL_RenderDrawRect(const SDL_Rect * rect)
2590 {
2591     return SDL_RenderDrawRects(&rect, 1);
2592 }
2593 
2594 int
2595 SDL_RenderDrawRects(const SDL_Rect ** rects, int count)
2596 {
2597     SDL_Renderer *renderer;
2598     int i;
2599 #if SDL_VIDEO_RENDER_RESIZE
2600     int realW, realH, fakeW, fakeH, ret;
2601 #endif
2602 
2603     if (!rects) {
2604         SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
2605         return -1;
2606     }
2607 
2608     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2609     if (!renderer) {
2610         return -1;
2611     }
2612     if (!renderer->RenderDrawRects) {
2613         SDL_Unsupported();
2614         return -1;
2615     }
2616     if (count < 1) {
2617         return 0;
2618     }
2619     /* Check for NULL rect, which means fill entire window */
2620     for (i = 0; i < count; ++i) {
2621         if (rects[i] == NULL) {
2622             SDL_Window *window = renderer->window;
2623             SDL_Rect full_rect;
2624             const SDL_Rect *rect;
2625 
2626             full_rect.x = 0;
2627             full_rect.y = 0;
2628             full_rect.w = window->w;
2629             full_rect.h = window->h;
2630             rect = &full_rect;
2631             return renderer->RenderDrawRects(renderer, &rect, 1);
2632         }
2633     }
2634 
2635 #if SDL_VIDEO_RENDER_RESIZE
2636     realW = renderer->window->display->desktop_mode.w;
2637     realH = renderer->window->display->desktop_mode.h;
2638     fakeW = renderer->window->w;
2639     fakeH = renderer->window->h;
2640     //if( fakeW > realW || fakeH > realH )
2641     {
2642         SDL_Rect * resized = SDL_stack_alloc( SDL_Rect, count );
2643         if( ! resized ) {
2644             SDL_OutOfMemory();
2645             return -1;
2646         }
2647 
2648         const SDL_Rect ** resizedPtrs = SDL_stack_alloc( const SDL_Rect *, count );
2649         if( ! resizedPtrs ) {
2650             SDL_OutOfMemory();
2651             return -1;
2652         }
2653 
2654         for( i = 0; i < count; i++ ) {
2655             resizedPtrs[i] = &(resized[i]);
2656         }
2657         SDL_RESIZE_resizeRects( realW, fakeW, realH, fakeH, rects, resized, count );
2658         ret = renderer->RenderDrawRects(renderer, resizedPtrs, count);
2659         SDL_stack_free(resizedPtrs);
2660         SDL_stack_free(resized);
2661         return ret;
2662     }
2663 #endif
2664 
2665     return renderer->RenderDrawRects(renderer, rects, count);
2666 }
2667 
2668 int
2669 SDL_RenderFillRect(const SDL_Rect * rect)
2670 {
2671     return SDL_RenderFillRects(&rect, 1);
2672 }
2673 
2674 int
2675 SDL_RenderFillRects(const SDL_Rect ** rects, int count)
2676 {
2677     SDL_Renderer *renderer;
2678     int i;
2679 #if SDL_VIDEO_RENDER_RESIZE
2680     int realW, realH, fakeW, fakeH, ret;
2681 #endif
2682 
2683     if (!rects) {
2684         SDL_SetError("SDL_RenderFillRects(): Passed NULL rects");
2685         return -1;
2686     }
2687 
2688     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2689     if (!renderer) {
2690         return -1;
2691     }
2692     if (!renderer->RenderFillRects) {
2693         SDL_Unsupported();
2694         return -1;
2695     }
2696     if (count < 1) {
2697         return 0;
2698     }
2699     /* Check for NULL rect, which means fill entire window */
2700     for (i = 0; i < count; ++i) {
2701         if (rects[i] == NULL) {
2702             SDL_Window *window = renderer->window;
2703             SDL_Rect full_rect;
2704             const SDL_Rect *rect;
2705 
2706             full_rect.x = 0;
2707             full_rect.y = 0;
2708             full_rect.w = window->w;
2709             full_rect.h = window->h;
2710             rect = &full_rect;
2711             return renderer->RenderFillRects(renderer, &rect, 1);
2712         }
2713     }
2714 
2715 #if SDL_VIDEO_RENDER_RESIZE
2716     realW = renderer->window->display->desktop_mode.w;
2717     realH = renderer->window->display->desktop_mode.h;
2718     fakeW = renderer->window->w;
2719     fakeH = renderer->window->h;
2720     //if( fakeW > realW || fakeH > realH )
2721     {
2722         SDL_Rect * resized = SDL_stack_alloc( SDL_Rect, count );
2723         if( ! resized ) {
2724             SDL_OutOfMemory();
2725             return -1;
2726         }
2727 
2728         const SDL_Rect ** resizedPtrs = SDL_stack_alloc( const SDL_Rect *, count );
2729         if( ! resizedPtrs ) {
2730             SDL_OutOfMemory();
2731             return -1;
2732         }
2733 
2734         for( i = 0; i < count; i++ ) {
2735             resizedPtrs[i] = &(resized[i]);
2736         }
2737         SDL_RESIZE_resizeRects( realW, fakeW, realH, fakeH, rects, resized, count );
2738         ret = renderer->RenderFillRects(renderer, resizedPtrs, count);
2739         SDL_stack_free(resizedPtrs);
2740         SDL_stack_free(resized);
2741         return ret;
2742     }
2743 #endif
2744 
2745     return renderer->RenderFillRects(renderer, rects, count);
2746 }
2747 
2748 int
2749 SDL_RenderCopy(SDL_Texture * texture, const SDL_Rect * srcrect,
2750                const SDL_Rect * dstrect)
2751 {
2752     SDL_Renderer *renderer;
2753     SDL_Window *window;
2754     SDL_Rect real_srcrect;
2755     SDL_Rect real_dstrect;
2756 #if SDL_VIDEO_RENDER_RESIZE
2757     int realW;
2758     int realH;
2759     int fakeW;
2760     int fakeH;
2761 #endif
2762 
2763     CHECK_TEXTURE_MAGIC(texture, -1);
2764 
2765     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2766     if (!renderer) {
2767         return -1;
2768     }
2769     if (texture->renderer != renderer) {
2770         SDL_SetError("Texture was not created with this renderer");
2771         return -1;
2772     }
2773     if (!renderer->RenderCopy) {
2774         SDL_Unsupported();
2775         return -1;
2776     }
2777     window = renderer->window;
2778 
2779     real_srcrect.x = 0;
2780     real_srcrect.y = 0;
2781     real_srcrect.w = texture->w;
2782     real_srcrect.h = texture->h;
2783     if (srcrect) {
2784         if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
2785             return 0;
2786         }
2787     }
2788 
2789     real_dstrect.x = 0;
2790     real_dstrect.y = 0;
2791     real_dstrect.w = window->w;
2792     real_dstrect.h = window->h;
2793     if (dstrect) {
2794         if (!SDL_IntersectRect(dstrect, &real_dstrect, &real_dstrect)) {
2795             return 0;
2796         }
2797         /* Clip srcrect by the same amount as dstrect was clipped */
2798         if (dstrect->w != real_dstrect.w) {
2799             int deltax = (real_dstrect.x - dstrect->x);
2800             int deltaw = (real_dstrect.w - dstrect->w);
2801             real_srcrect.x += (deltax * real_srcrect.w) / dstrect->w;
2802             real_srcrect.w += (deltaw * real_srcrect.w) / dstrect->w;
2803         }
2804         if (dstrect->h != real_dstrect.h) {
2805             int deltay = (real_dstrect.y - dstrect->y);
2806             int deltah = (real_dstrect.h - dstrect->h);
2807             real_srcrect.y += (deltay * real_srcrect.h) / dstrect->h;
2808             real_srcrect.h += (deltah * real_srcrect.h) / dstrect->h;
2809         }
2810     }
2811 
2812 #if SDL_VIDEO_RENDER_RESIZE
2813     realW = window->display->desktop_mode.w;
2814     realH = window->display->desktop_mode.h;
2815     fakeW = window->w;
2816     fakeH = window->h;
2817     //if( fakeW > realW || fakeH > realH )
2818     {
2819         // Calculate bottom-right corner instead of width/height, and substract upper-left corner,
2820         // otherwise we'll have rounding errors and holes between textures
2821         real_dstrect.w = (real_dstrect.w + real_dstrect.x) * realW / fakeW;
2822         real_dstrect.h = (real_dstrect.h + real_dstrect.y) * realH / fakeH;
2823         real_dstrect.x = real_dstrect.x * realW / fakeW;
2824         real_dstrect.y = real_dstrect.y * realH / fakeH;
2825         real_dstrect.w -= real_dstrect.x;
2826         real_dstrect.h -= real_dstrect.y;
2827         //__android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_RenderCopy dest %d:%d+%d+%d desktop_mode %d:%d", (int)real_dstrect.x, (int)real_dstrect.y, (int)real_dstrect.w, (int)real_dstrect.h, (int)realW, (int)realH);
2828     }
2829 #endif
2830 
2831     return renderer->RenderCopy(renderer, texture, &real_srcrect,
2832                                 &real_dstrect);
2833 }
2834 
2835 int
2836 SDL_RenderReadPixels(const SDL_Rect * rect, Uint32 format,
2837                      void * pixels, int pitch)
2838 {
2839     SDL_Renderer *renderer;
2840     SDL_Window *window;
2841     SDL_Rect real_rect;
2842 
2843     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2844     if (!renderer) {
2845         return -1;
2846     }
2847     if (!renderer->RenderReadPixels) {
2848         SDL_Unsupported();
2849         return -1;
2850     }
2851     window = renderer->window;
2852 
2853     if (!format) {
2854         format = window->display->current_mode.format;
2855     }
2856 
2857     real_rect.x = 0;
2858     real_rect.y = 0;
2859     real_rect.w = window->w;
2860     real_rect.h = window->h;
2861     if (rect) {
2862         if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
2863             return 0;
2864         }
2865         if (real_rect.y > rect->y) {
2866             pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
2867         }
2868         if (real_rect.x > rect->x) {
2869             Uint32 format = SDL_CurrentDisplay->current_mode.format;
2870             int bpp = SDL_BYTESPERPIXEL(format);
2871             pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
2872         }
2873     }
2874 
2875     return renderer->RenderReadPixels(renderer, &real_rect,
2876                                       format, pixels, pitch);
2877 }
2878 
2879 int
2880 SDL_RenderWritePixels(const SDL_Rect * rect, Uint32 format,
2881                       const void * pixels, int pitch)
2882 {
2883     SDL_Renderer *renderer;
2884     SDL_Window *window;
2885     SDL_Rect real_rect;
2886 
2887     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2888     if (!renderer) {
2889         return -1;
2890     }
2891     if (!renderer->RenderWritePixels) {
2892         SDL_Unsupported();
2893         return -1;
2894     }
2895     window = renderer->window;
2896 
2897     if (!format) {
2898         format = window->display->current_mode.format;
2899     }
2900 
2901     real_rect.x = 0;
2902     real_rect.y = 0;
2903     real_rect.w = window->w;
2904     real_rect.h = window->h;
2905     if (rect) {
2906         if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
2907             return 0;
2908         }
2909         if (real_rect.y > rect->y) {
2910             pixels = (const Uint8 *)pixels + pitch * (real_rect.y - rect->y);
2911         }
2912         if (real_rect.x > rect->x) {
2913             Uint32 format = SDL_CurrentDisplay->current_mode.format;
2914             int bpp = SDL_BYTESPERPIXEL(format);
2915             pixels = (const Uint8 *)pixels + bpp * (real_rect.x - rect->x);
2916         }
2917     }
2918 
2919     return renderer->RenderWritePixels(renderer, &real_rect,
2920                                        format, pixels, pitch);
2921 }
2922 
2923 void
2924 SDL_RenderPresent(void)
2925 {
2926     SDL_Renderer *renderer;
2927 
2928     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
2929     if (!renderer || !renderer->RenderPresent) {
2930         return;
2931     }
2932     renderer->RenderPresent(renderer);
2933 }
2934 
2935 void
2936 SDL_DestroyTexture(SDL_Texture * texture)
2937 {
2938     SDL_Renderer *renderer;
2939 
2940     CHECK_TEXTURE_MAGIC(texture, );
2941     texture->magic = NULL;
2942 
2943     renderer = texture->renderer;
2944     if (texture->next) {
2945         texture->next->prev = texture->prev;
2946     }
2947     if (texture->prev) {
2948         texture->prev->next = texture->next;
2949     } else {
2950         renderer->textures = texture->next;
2951     }
2952 
2953     renderer->DestroyTexture(renderer, texture);
2954     SDL_free(texture);
2955 }
2956 
2957 void
2958 SDL_DestroyRenderer(SDL_Window * window)
2959 {
2960     SDL_Renderer *renderer;
2961 
2962     CHECK_WINDOW_MAGIC(window, );
2963 
2964     renderer = window->renderer;
2965     if (!renderer) {
2966         return;
2967     }
2968 
2969     /* Free existing textures for this renderer */
2970     while (renderer->textures) {
2971         SDL_DestroyTexture(renderer->textures);
2972     }
2973 
2974     /* Free the renderer instance */
2975     renderer->DestroyRenderer(renderer);
2976 
2977     /* Clear references */
2978     window->renderer = NULL;
2979     if (SDL_CurrentDisplay->current_renderer == renderer) {
2980         SDL_CurrentDisplay->current_renderer = NULL;
2981     }
2982 }
2983 
2984 SDL_bool
2985 SDL_IsScreenSaverEnabled()
2986 {
2987     if (!_this) {
2988         return SDL_TRUE;
2989     }
2990     return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
2991 }
2992 
2993 void
2994 SDL_EnableScreenSaver()
2995 {
2996     if (!_this) {
2997         return;
2998     }
2999     if (!_this->suspend_screensaver) {
3000         return;
3001     }
3002     _this->suspend_screensaver = SDL_FALSE;
3003     if (_this->SuspendScreenSaver) {
3004         _this->SuspendScreenSaver(_this);
3005     }
3006 }
3007 
3008 void
3009 SDL_DisableScreenSaver()
3010 {
3011     if (!_this) {
3012         return;
3013     }
3014     if (_this->suspend_screensaver) {
3015         return;
3016     }
3017     _this->suspend_screensaver = SDL_TRUE;
3018     if (_this->SuspendScreenSaver) {
3019         _this->SuspendScreenSaver(_this);
3020     }
3021 }
3022 
3023 #if SDL_VERSION_ATLEAST(1,3,0)
3024 
3025 void
3026 SDL_VideoQuit(void)
3027 {
3028     int i, j;
3029 
3030     if (!_this) {
3031         return;
3032     }
3033     /* Halt event processing before doing anything else */
3034     SDL_StopEventLoop();
3035     SDL_EnableScreenSaver();
3036 
3037     /* Clean up the system video */
3038     for (i = _this->num_displays; i--;) {
3039         SDL_VideoDisplay *display = &_this->displays[i];
3040         while (display->windows) {
3041             SDL_DestroyWindow(display->windows);
3042         }
3043         if (display->render_drivers) {
3044             SDL_free(display->render_drivers);
3045             display->render_drivers = NULL;
3046         }
3047         display->num_render_drivers = 0;
3048     }
3049     _this->VideoQuit(_this);
3050 
3051     for (i = _this->num_displays; i--;) {
3052         SDL_VideoDisplay *display = &_this->displays[i];
3053         for (j = display->num_display_modes; j--;) {
3054             if (display->display_modes[j].driverdata) {
3055                 SDL_free(display->display_modes[j].driverdata);
3056                 display->display_modes[j].driverdata = NULL;
3057             }
3058         }
3059         if (display->display_modes) {
3060             SDL_free(display->display_modes);
3061             display->display_modes = NULL;
3062         }
3063         if (display->desktop_mode.driverdata) {
3064             SDL_free(display->desktop_mode.driverdata);
3065             display->desktop_mode.driverdata = NULL;
3066         }
3067         if (display->palette) {
3068             SDL_FreePalette(display->palette);
3069             display->palette = NULL;
3070         }
3071         if (display->gamma) {
3072             SDL_free(display->gamma);
3073             display->gamma = NULL;
3074         }
3075         if (display->driverdata) {
3076             SDL_free(display->driverdata);
3077             display->driverdata = NULL;
3078         }
3079     }
3080     if (_this->displays) {
3081         SDL_free(_this->displays);
3082         _this->displays = NULL;
3083     }
3084     if (_this->clipboard_text) {
3085         SDL_free(_this->clipboard_text);
3086         _this->clipboard_text = NULL;
3087     }
3088     _this->free(_this);
3089     _this = NULL;
3090 }
3091 
3092 int
3093 SDL_GL_LoadLibrary(const char *path)
3094 {
3095     int retval;
3096 
3097     if (!_this) {
3098         SDL_UninitializedVideo();
3099         return -1;
3100     }
3101     if (_this->gl_config.driver_loaded) {
3102         if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
3103             SDL_SetError("OpenGL library already loaded");
3104             return -1;
3105         }
3106         retval = 0;
3107     } else {
3108         if (!_this->GL_LoadLibrary) {
3109             SDL_SetError("No dynamic GL support in video driver");
3110             return -1;
3111         }
3112         retval = _this->GL_LoadLibrary(_this, path);
3113     }
3114     if (retval == 0) {
3115         ++_this->gl_config.driver_loaded;
3116     }
3117     return (retval);
3118 }
3119 
3120 void *
3121 SDL_GL_GetProcAddress(const char *proc)
3122 {
3123     void *func;
3124 
3125     if (!_this) {
3126         SDL_UninitializedVideo();
3127         return NULL;
3128     }
3129     func = NULL;
3130     if (_this->GL_GetProcAddress) {
3131         if (_this->gl_config.driver_loaded) {
3132             func = _this->GL_GetProcAddress(_this, proc);
3133         } else {
3134             SDL_SetError("No GL driver has been loaded");
3135         }
3136     } else {
3137         SDL_SetError("No dynamic GL support in video driver");
3138     }
3139     return func;
3140 }
3141 
3142 void
3143 SDL_GL_UnloadLibrary(void)
3144 {
3145     if (!_this) {
3146         SDL_UninitializedVideo();
3147         return;
3148     }
3149     if (_this->gl_config.driver_loaded > 0) {
3150         if (--_this->gl_config.driver_loaded > 0) {
3151             return;
3152         }
3153         if (_this->GL_UnloadLibrary) {
3154             _this->GL_UnloadLibrary(_this);
3155         }
3156     }
3157 }
3158 
3159 #endif
3160 
3161 SDL_bool
3162 SDL_GL_ExtensionSupported(const char *extension)
3163 {
3164 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES
3165     const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
3166     const char *extensions;
3167     const char *start;
3168     const char *where, *terminator;
3169 
3170     /* Extension names should not have spaces. */
3171     where = SDL_strchr(extension, ' ');
3172     if (where || *extension == '\0') {
3173         return SDL_FALSE;
3174     }
3175     /* See if there's an environment variable override */
3176     start = SDL_getenv(extension);
3177     if (start && *start == '0') {
3178         return SDL_FALSE;
3179     }
3180     /* Lookup the available extensions */
3181     glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
3182     if (glGetStringFunc) {
3183         extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
3184     } else {
3185         extensions = NULL;
3186     }
3187     if (!extensions) {
3188         return SDL_FALSE;
3189     }
3190     /*
3191      * It takes a bit of care to be fool-proof about parsing the OpenGL
3192      * extensions string. Don't be fooled by sub-strings, etc.
3193      */
3194 
3195     start = extensions;
3196 
3197     for (;;) {
3198         where = SDL_strstr(start, extension);
3199         if (!where)
3200             break;
3201 
3202         terminator = where + SDL_strlen(extension);
3203         if (where == start || *(where - 1) == ' ')
3204             if (*terminator == ' ' || *terminator == '\0')
3205                 return SDL_TRUE;
3206 
3207         start = terminator;
3208     }
3209     return SDL_FALSE;
3210 #else
3211     return SDL_FALSE;
3212 #endif
3213 }
3214 
3215 #if SDL_VERSION_ATLEAST(1,3,0)
3216 
3217 int
3218 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
3219 {
3220 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES
3221     int retval;
3222 
3223     if (!_this) {
3224         SDL_UninitializedVideo();
3225         return -1;
3226     }
3227     retval = 0;
3228     switch (attr) {
3229     case SDL_GL_RED_SIZE:
3230         _this->gl_config.red_size = value;
3231         break;
3232     case SDL_GL_GREEN_SIZE:
3233         _this->gl_config.green_size = value;
3234         break;
3235     case SDL_GL_BLUE_SIZE:
3236         _this->gl_config.blue_size = value;
3237         break;
3238     case SDL_GL_ALPHA_SIZE:
3239         _this->gl_config.alpha_size = value;
3240         break;
3241     case SDL_GL_DOUBLEBUFFER:
3242         _this->gl_config.double_buffer = value;
3243         break;
3244     case SDL_GL_BUFFER_SIZE:
3245         _this->gl_config.buffer_size = value;
3246         break;
3247     case SDL_GL_DEPTH_SIZE:
3248         _this->gl_config.depth_size = value;
3249         break;
3250     case SDL_GL_STENCIL_SIZE:
3251         _this->gl_config.stencil_size = value;
3252         break;
3253     case SDL_GL_ACCUM_RED_SIZE:
3254         _this->gl_config.accum_red_size = value;
3255         break;
3256     case SDL_GL_ACCUM_GREEN_SIZE:
3257         _this->gl_config.accum_green_size = value;
3258         break;
3259     case SDL_GL_ACCUM_BLUE_SIZE:
3260         _this->gl_config.accum_blue_size = value;
3261         break;
3262     case SDL_GL_ACCUM_ALPHA_SIZE:
3263         _this->gl_config.accum_alpha_size = value;
3264         break;
3265     case SDL_GL_STEREO:
3266         _this->gl_config.stereo = value;
3267         break;
3268     case SDL_GL_MULTISAMPLEBUFFERS:
3269         _this->gl_config.multisamplebuffers = value;
3270         break;
3271     case SDL_GL_MULTISAMPLESAMPLES:
3272         _this->gl_config.multisamplesamples = value;
3273         break;
3274     case SDL_GL_ACCELERATED_VISUAL:
3275         _this->gl_config.accelerated = value;
3276         break;
3277     case SDL_GL_RETAINED_BACKING:
3278         _this->gl_config.retained_backing = value;
3279         break;
3280     case SDL_GL_CONTEXT_MAJOR_VERSION:
3281         _this->gl_config.major_version = value;
3282         break;
3283     case SDL_GL_CONTEXT_MINOR_VERSION:
3284         _this->gl_config.minor_version = value;
3285         break;
3286     default:
3287         SDL_SetError("Unknown OpenGL attribute");
3288         retval = -1;
3289         break;
3290     }
3291     return retval;
3292 #else
3293     SDL_Unsupported();
3294     return -1;
3295 #endif /* SDL_VIDEO_OPENGL */
3296 }
3297 
3298 int
3299 SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
3300 {
3301 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES
3302     void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
3303     GLenum(APIENTRY * glGetErrorFunc) (void);
3304     GLenum attrib = 0;
3305     GLenum error = 0;
3306 
3307     glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
3308     if (!glGetIntegervFunc) {
3309         return -1;
3310     }
3311 
3312     glGetErrorFunc = SDL_GL_GetProcAddress("glGetError");
3313     if (!glGetErrorFunc) {
3314         return -1;
3315     }
3316 
3317     /* Clear value in any case */
3318     *value = 0;
3319 
3320     switch (attr) {
3321     case SDL_GL_RETAINED_BACKING:
3322         *value = _this->gl_config.retained_backing;
3323         return 0;
3324     case SDL_GL_RED_SIZE:
3325         attrib = GL_RED_BITS;
3326         break;
3327     case SDL_GL_BLUE_SIZE:
3328         attrib = GL_BLUE_BITS;
3329         break;
3330     case SDL_GL_GREEN_SIZE:
3331         attrib = GL_GREEN_BITS;
3332         break;
3333     case SDL_GL_ALPHA_SIZE:
3334         attrib = GL_ALPHA_BITS;
3335         break;
3336     case SDL_GL_DOUBLEBUFFER:
3337 #ifndef SDL_VIDEO_OPENGL_ES
3338         attrib = GL_DOUBLEBUFFER;
3339         break;
3340 #else
3341         /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER      */
3342         /* parameter which switches double buffer to single buffer. OpenGL ES */
3343         /* SDL driver must set proper value after initialization              */
3344         *value = _this->gl_config.double_buffer;
3345         return 0;
3346 #endif
3347     case SDL_GL_DEPTH_SIZE:
3348         attrib = GL_DEPTH_BITS;
3349         break;
3350     case SDL_GL_STENCIL_SIZE:
3351         attrib = GL_STENCIL_BITS;
3352         break;
3353 #ifndef SDL_VIDEO_OPENGL_ES
3354     case SDL_GL_ACCUM_RED_SIZE:
3355         attrib = GL_ACCUM_RED_BITS;
3356         break;
3357     case SDL_GL_ACCUM_GREEN_SIZE:
3358         attrib = GL_ACCUM_GREEN_BITS;
3359         break;
3360     case SDL_GL_ACCUM_BLUE_SIZE:
3361         attrib = GL_ACCUM_BLUE_BITS;
3362         break;
3363     case SDL_GL_ACCUM_ALPHA_SIZE:
3364         attrib = GL_ACCUM_ALPHA_BITS;
3365         break;
3366     case SDL_GL_STEREO:
3367         attrib = GL_STEREO;
3368         break;
3369 #else
3370     case SDL_GL_ACCUM_RED_SIZE:
3371     case SDL_GL_ACCUM_GREEN_SIZE:
3372     case SDL_GL_ACCUM_BLUE_SIZE:
3373     case SDL_GL_ACCUM_ALPHA_SIZE:
3374     case SDL_GL_STEREO:
3375         /* none of these are supported in OpenGL ES */
3376         *value = 0;
3377         return 0;
3378 #endif
3379     case SDL_GL_MULTISAMPLEBUFFERS:
3380 #ifndef SDL_VIDEO_OPENGL_ES
3381         attrib = GL_SAMPLE_BUFFERS_ARB;
3382 #else
3383         attrib = GL_SAMPLE_BUFFERS;
3384 #endif
3385         break;
3386     case SDL_GL_MULTISAMPLESAMPLES:
3387 #ifndef SDL_VIDEO_OPENGL_ES
3388         attrib = GL_SAMPLES_ARB;
3389 #else
3390         attrib = GL_SAMPLES;
3391 #endif
3392         break;
3393     case SDL_GL_BUFFER_SIZE:
3394         {
3395             GLint bits = 0;
3396             GLint component;
3397 
3398             /*
3399              * there doesn't seem to be a single flag in OpenGL
3400              * for this!
3401              */
3402             glGetIntegervFunc(GL_RED_BITS, &component);
3403             bits += component;
3404             glGetIntegervFunc(GL_GREEN_BITS, &component);
3405             bits += component;
3406             glGetIntegervFunc(GL_BLUE_BITS, &component);
3407             bits += component;
3408             glGetIntegervFunc(GL_ALPHA_BITS, &component);
3409             bits += component;
3410 
3411             *value = bits;
3412             return 0;
3413         }
3414     case SDL_GL_ACCELERATED_VISUAL:
3415         {
3416             /* FIXME: How do we get this information? */
3417             *value = (_this->gl_config.accelerated != 0);
3418             return 0;
3419         }
3420     default:
3421         SDL_SetError("Unknown OpenGL attribute");
3422         return -1;
3423     }
3424 
3425     glGetIntegervFunc(attrib, (GLint *) value);
3426     error = glGetErrorFunc();
3427     if (error != GL_NO_ERROR) {
3428         switch (error) {
3429         case GL_INVALID_ENUM:
3430             {
3431                 SDL_SetError("OpenGL error: GL_INVALID_ENUM");
3432             }
3433             break;
3434         case GL_INVALID_VALUE:
3435             {
3436                 SDL_SetError("OpenGL error: GL_INVALID_VALUE");
3437             }
3438             break;
3439         default:
3440             {
3441                 SDL_SetError("OpenGL error: %08X", error);
3442             }
3443             break;
3444         }
3445         return -1;
3446     }
3447     return 0;
3448 #else
3449     SDL_Unsupported();
3450     return -1;
3451 #endif /* SDL_VIDEO_OPENGL */
3452 }
3453 
3454 #endif /* SDL 1.3.0 */
3455 
3456 SDL_GLContext
3457 SDL_GL_CreateContext(SDL_Window * window)
3458 {
3459     CHECK_WINDOW_MAGIC(window, NULL);
3460 
3461     if (!(window->flags & SDL_WINDOW_OPENGL)) {
3462         SDL_SetError("The specified window isn't an OpenGL window");
3463         return NULL;
3464     }
3465     return _this->GL_CreateContext(_this, window);
3466 }
3467 
3468 int
3469 SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext context)
3470 {
3471     CHECK_WINDOW_MAGIC(window, -1);
3472 
3473     if (!(window->flags & SDL_WINDOW_OPENGL)) {
3474         SDL_SetError("The specified window isn't an OpenGL window");
3475         return -1;
3476     }
3477     if (!context) {
3478         window = NULL;
3479     }
3480     return _this->GL_MakeCurrent(_this, window, context);
3481 }
3482 
3483 int
3484 SDL_GL_SetSwapInterval(int interval)
3485 {
3486     if (!_this) {
3487         SDL_UninitializedVideo();
3488         return -1;
3489     }
3490     if (_this->GL_SetSwapInterval) {
3491         return _this->GL_SetSwapInterval(_this, interval);
3492     } else {
3493         SDL_SetError("Setting the swap interval is not supported");
3494         return -1;
3495     }
3496 }
3497 
3498 int
3499 SDL_GL_GetSwapInterval(void)
3500 {
3501     if (!_this) {
3502         SDL_UninitializedVideo();
3503         return -1;
3504     }
3505     if (_this->GL_GetSwapInterval) {
3506         return _this->GL_GetSwapInterval(_this);
3507     } else {
3508         SDL_SetError("Getting the swap interval is not supported");
3509         return -1;
3510     }
3511 }
3512 
3513 void
3514 SDL_GL_SwapWindow(SDL_Window * window)
3515 {
3516     CHECK_WINDOW_MAGIC(window, );
3517 
3518     if (!(window->flags & SDL_WINDOW_OPENGL)) {
3519         SDL_SetError("The specified window isn't an OpenGL window");
3520         return;
3521     }
3522     _this->GL_SwapWindow(_this, window);
3523 }
3524 
3525 void
3526 SDL_GL_DeleteContext(SDL_GLContext context)
3527 {
3528     if (!_this || !_this->gl_data || !context) {
3529         return;
3530     }
3531     _this->GL_MakeCurrent(_this, NULL, NULL);
3532     _this->GL_DeleteContext(_this, context);
3533 }
3534 
3535 #if 0                           // FIXME
3536 /*
3537  * Utility function used by SDL_WM_SetIcon(); flags & 1 for color key, flags
3538  * & 2 for alpha channel.
3539  */
3540 static void
3541 CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
3542 {
3543     int x, y;
3544     Uint32 colorkey;
3545 #define SET_MASKBIT(icon, x, y, mask) \
3546 	mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
3547 
3548     colorkey = icon->format->colorkey;
3549     switch (icon->format->BytesPerPixel) {
3550     case 1:
3551         {
3552             Uint8 *pixels;
3553             for (y = 0; y < icon->h; ++y) {
3554                 pixels = (Uint8 *) icon->pixels + y * icon->pitch;
3555                 for (x = 0; x < icon->w; ++x) {
3556                     if (*pixels++ == colorkey) {
3557                         SET_MASKBIT(icon, x, y, mask);
3558                     }
3559                 }
3560             }
3561         }
3562         break;
3563 
3564     case 2:
3565         {
3566             Uint16 *pixels;
3567             for (y = 0; y < icon->h; ++y) {
3568                 pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
3569                 for (x = 0; x < icon->w; ++x) {
3570                     if ((flags & 1) && *pixels == colorkey) {
3571                         SET_MASKBIT(icon, x, y, mask);
3572                     } else if ((flags & 2)
3573                                && (*pixels & icon->format->Amask) == 0) {
3574                         SET_MASKBIT(icon, x, y, mask);
3575                     }
3576                     pixels++;
3577                 }
3578             }
3579         }
3580         break;
3581 
3582     case 4:
3583         {
3584             Uint32 *pixels;
3585             for (y = 0; y < icon->h; ++y) {
3586                 pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
3587                 for (x = 0; x < icon->w; ++x) {
3588                     if ((flags & 1) && *pixels == colorkey) {
3589                         SET_MASKBIT(icon, x, y, mask);
3590                     } else if ((flags & 2)
3591                                && (*pixels & icon->format->Amask) == 0) {
3592                         SET_MASKBIT(icon, x, y, mask);
3593                     }
3594                     pixels++;
3595                 }
3596             }
3597         }
3598         break;
3599     }
3600 }
3601 
3602 /*
3603  * Sets the window manager icon for the display window.
3604  */
3605 void
3606 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
3607 {
3608     if (icon && _this->SetIcon) {
3609         /* Generate a mask if necessary, and create the icon! */
3610         if (mask == NULL) {
3611             int mask_len = icon->h * (icon->w + 7) / 8;
3612             int flags = 0;
3613             mask = (Uint8 *) SDL_malloc(mask_len);
3614             if (mask == NULL) {
3615                 return;
3616             }
3617             SDL_memset(mask, ~0, mask_len);
3618             if (icon->flags & SDL_SRCCOLORKEY)
3619                 flags |= 1;
3620             if (icon->flags & SDL_SRCALPHA)
3621                 flags |= 2;
3622             if (flags) {
3623                 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
3624             }
3625             _this->SetIcon(_this, icon, mask);
3626             SDL_free(mask);
3627         } else {
3628             _this->SetIcon(_this, icon, mask);
3629         }
3630     }
3631 }
3632 #endif
3633 
3634 #if SDL_VERSION_ATLEAST(1,3,0)
3635 SDL_bool
3636 SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
3637 {
3638     CHECK_WINDOW_MAGIC(window, SDL_FALSE);
3639 
3640     if (!_this->GetWindowWMInfo) {
3641         return SDL_FALSE;
3642     }
3643     return (_this->GetWindowWMInfo(_this, window, info));
3644 }
3645 
3646 void
3647 SDL_StartTextInput(void)
3648 {
3649     if (_this && _this->StartTextInput) {
3650         _this->StartTextInput(_this);
3651     }
3652     SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
3653     SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
3654 }
3655 
3656 void
3657 SDL_StopTextInput(void)
3658 {
3659     if (_this && _this->StopTextInput) {
3660         _this->StopTextInput(_this);
3661     }
3662     SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
3663     SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
3664 }
3665 
3666 void
3667 SDL_SetTextInputRect(SDL_Rect *rect)
3668 {
3669     if (_this && _this->SetTextInputRect) {
3670         _this->SetTextInputRect(_this, rect);
3671     }
3672 }
3673 #endif
3674 
3675 /* vi: set ts=4 sw=4 expandtab: */
3676