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, ¤t_mode);
714 if (SDL_memcmp(&display_mode, ¤t_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