2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "../SDL_internal.h"
23 /* The high-level video driver subsystem */
26 #include "SDL_video.h"
27 #include "SDL_sysvideo.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_rect_c.h"
31 #include "SDL_egl_c.h"
32 #include "../events/SDL_events_c.h"
33 #include "../timer/SDL_timer_c.h"
35 #include "SDL_syswm.h"
38 #include "SDL_opengl.h"
39 #endif /* SDL_VIDEO_OPENGL */
41 #if SDL_VIDEO_OPENGL_ES
42 #include "SDL_opengles.h"
43 #endif /* SDL_VIDEO_OPENGL_ES */
45 /* GL and GLES2 headers conflict on Linux 32 bits */
46 #if SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL
47 #include "SDL_opengles2.h"
48 #endif /* SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL */
50 #ifndef GL_CONTEXT_RELEASE_BEHAVIOR_KHR
51 #define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
54 /* On Windows, windows.h defines CreateWindow */
59 /* Available video drivers */
60 static VideoBootStrap *bootstrap[] = {
61 #if SDL_VIDEO_DRIVER_COCOA
64 #if SDL_VIDEO_DRIVER_X11
67 #if SDL_VIDEO_DRIVER_MIR
70 #if SDL_VIDEO_DRIVER_WAYLAND
73 #if SDL_VIDEO_DRIVER_VIVANTE
76 #if SDL_VIDEO_DRIVER_DIRECTFB
79 #if SDL_VIDEO_DRIVER_WINDOWS
82 #if SDL_VIDEO_DRIVER_WINRT
85 #if SDL_VIDEO_DRIVER_HAIKU
88 #if SDL_VIDEO_DRIVER_PANDORA
91 #if SDL_VIDEO_DRIVER_UIKIT
94 #if SDL_VIDEO_DRIVER_ANDROID
97 #if SDL_VIDEO_DRIVER_PSP
100 #if SDL_VIDEO_DRIVER_RPI
103 #if SDL_VIDEO_DRIVER_NACL
106 #if SDL_VIDEO_DRIVER_EMSCRIPTEN
107 &Emscripten_bootstrap,
109 #if SDL_VIDEO_DRIVER_DUMMY
112 #if SDL_VIDEO_DRIVER_TIZEN
118 static SDL_VideoDevice *_this = NULL;
120 #define CHECK_WINDOW_MAGIC(window, retval) \
122 SDL_UninitializedVideo(); \
125 if (!window || window->magic != &_this->window_magic) { \
126 SDL_SetError("Invalid window"); \
130 #define CHECK_DISPLAY_INDEX(displayIndex, retval) \
132 SDL_UninitializedVideo(); \
135 SDL_assert(_this->displays != NULL); \
136 if (displayIndex < 0 || displayIndex >= _this->num_displays) { \
137 SDL_SetError("displayIndex must be in the range 0 - %d", \
138 _this->num_displays - 1); \
142 #define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN)
145 /* Support for Mac OS X fullscreen spaces */
146 extern SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window * window);
147 extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state);
151 /* Support for framebuffer emulation using an accelerated renderer */
153 #define SDL_WINDOWTEXTUREDATA "_SDL_WindowTextureData"
156 SDL_Renderer *renderer;
157 SDL_Texture *texture;
161 } SDL_WindowTextureData;
164 ShouldUseTextureFramebuffer()
168 /* If there's no native framebuffer support then there's no option */
169 if (!_this->CreateWindowFramebuffer) {
173 /* If the user has specified a software renderer we can't use a
174 texture framebuffer, or renderer creation will go recursive.
176 hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
177 if (hint && SDL_strcasecmp(hint, "software") == 0) {
181 /* See if the user or application wants a specific behavior */
182 hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
191 /* Each platform has different performance characteristics */
192 #if defined(__WIN32__)
193 /* GDI BitBlt() is way faster than Direct3D dynamic textures right now.
197 #elif defined(__MACOSX__)
198 /* Mac OS X uses OpenGL as the native fast path */
201 #elif defined(__LINUX__)
202 /* Properly configured OpenGL drivers are faster than MIT-SHM */
204 /* Ugh, find a way to cache this value! */
207 SDL_GLContext context;
208 SDL_bool hasAcceleratedOpenGL = SDL_FALSE;
210 window = SDL_CreateWindow("OpenGL test", -32, -32, 32, 32, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
212 context = SDL_GL_CreateContext(window);
214 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
215 const char *vendor = NULL;
217 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
218 if (glGetStringFunc) {
219 vendor = (const char *) glGetStringFunc(GL_VENDOR);
221 /* Add more vendors here at will... */
223 (SDL_strstr(vendor, "ATI Technologies") ||
224 SDL_strstr(vendor, "NVIDIA"))) {
225 hasAcceleratedOpenGL = SDL_TRUE;
227 SDL_GL_DeleteContext(context);
229 SDL_DestroyWindow(window);
231 return hasAcceleratedOpenGL;
233 #elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
234 /* Let's be optimistic about this! */
241 /* Play it safe, assume that if there is a framebuffer driver that it's
242 optimized for the current platform.
249 SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
251 SDL_WindowTextureData *data;
253 data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
255 SDL_Renderer *renderer = NULL;
257 const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
259 /* Check to see if there's a specific driver requested */
260 if (hint && *hint != '0' && *hint != '1' &&
261 SDL_strcasecmp(hint, "software") != 0) {
262 for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
263 SDL_RendererInfo info;
264 SDL_GetRenderDriverInfo(i, &info);
265 if (SDL_strcasecmp(info.name, hint) == 0) {
266 renderer = SDL_CreateRenderer(window, i, 0);
273 for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
274 SDL_RendererInfo info;
275 SDL_GetRenderDriverInfo(i, &info);
276 if (SDL_strcmp(info.name, "software") != 0) {
277 renderer = SDL_CreateRenderer(window, i, 0);
285 return SDL_SetError("No hardware accelerated renderers available");
288 /* Create the data after we successfully create the renderer (bug #1116) */
289 data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
291 SDL_DestroyRenderer(renderer);
292 return SDL_OutOfMemory();
294 SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
296 data->renderer = renderer;
299 /* Free any old texture and pixel data */
301 SDL_DestroyTexture(data->texture);
302 data->texture = NULL;
304 SDL_free(data->pixels);
308 SDL_RendererInfo info;
311 if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
315 /* Find the first format without an alpha channel */
316 *format = info.texture_formats[0];
318 for (i = 0; i < info.num_texture_formats; ++i) {
319 if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
320 !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
321 *format = info.texture_formats[i];
327 data->texture = SDL_CreateTexture(data->renderer, *format,
328 SDL_TEXTUREACCESS_STREAMING,
329 window->w, window->h);
330 if (!data->texture) {
334 /* Create framebuffer data */
335 data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
336 data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
337 data->pixels = SDL_malloc(window->h * data->pitch);
339 return SDL_OutOfMemory();
342 *pixels = data->pixels;
343 *pitch = data->pitch;
345 /* Make sure we're not double-scaling the viewport */
346 SDL_RenderSetViewport(data->renderer, NULL);
352 SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, const SDL_Rect * rects, int numrects)
354 SDL_WindowTextureData *data;
358 data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
359 if (!data || !data->texture) {
360 return SDL_SetError("No window texture data");
363 /* Update a single rect that contains subrects for best DMA performance */
364 if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) {
365 src = (void *)((Uint8 *)data->pixels +
366 rect.y * data->pitch +
367 rect.x * data->bytes_per_pixel);
368 if (SDL_UpdateTexture(data->texture, &rect, src, data->pitch) < 0) {
372 if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) {
376 SDL_RenderPresent(data->renderer);
382 SDL_DestroyWindowTexture(SDL_VideoDevice *unused, SDL_Window * window)
384 SDL_WindowTextureData *data;
386 data = SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, NULL);
391 SDL_DestroyTexture(data->texture);
393 if (data->renderer) {
394 SDL_DestroyRenderer(data->renderer);
396 SDL_free(data->pixels);
402 cmpmodes(const void *A, const void *B)
404 const SDL_DisplayMode *a = (const SDL_DisplayMode *) A;
405 const SDL_DisplayMode *b = (const SDL_DisplayMode *) B;
408 } else if (a->w != b->w) {
410 } else if (a->h != b->h) {
412 } else if (SDL_BITSPERPIXEL(a->format) != SDL_BITSPERPIXEL(b->format)) {
413 return SDL_BITSPERPIXEL(b->format) - SDL_BITSPERPIXEL(a->format);
414 } else if (SDL_PIXELLAYOUT(a->format) != SDL_PIXELLAYOUT(b->format)) {
415 return SDL_PIXELLAYOUT(b->format) - SDL_PIXELLAYOUT(a->format);
416 } else if (a->refresh_rate != b->refresh_rate) {
417 return b->refresh_rate - a->refresh_rate;
423 SDL_UninitializedVideo()
425 return SDL_SetError("Video subsystem has not been initialized");
429 SDL_GetNumVideoDrivers(void)
431 return SDL_arraysize(bootstrap) - 1;
435 SDL_GetVideoDriver(int index)
437 if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
438 return bootstrap[index]->name;
444 * Initialize the video and event subsystems -- determine native pixel format
447 SDL_VideoInit(const char *driver_name)
449 SDL_VideoDevice *video;
453 SDL_bool allow_screensaver;
455 /* Check to make sure we don't overwrite '_this' */
460 #if !SDL_TIMERS_DISABLED
464 /* Start the event loop */
465 if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0 ||
466 SDL_KeyboardInit() < 0 ||
467 SDL_MouseInit() < 0 ||
468 SDL_TouchInit() < 0) {
472 /* Select the proper video driver */
475 if (driver_name == NULL) {
476 driver_name = SDL_getenv("SDL_VIDEODRIVER");
480 if (driver_name == NULL) {
481 driver_name = "tizen";
484 if (driver_name != NULL) {
485 for (i = 0; bootstrap[i]; ++i) {
486 if (SDL_strncasecmp(bootstrap[i]->name, driver_name, SDL_strlen(driver_name)) == 0) {
487 if (bootstrap[i]->available()) {
488 video = bootstrap[i]->create(index);
494 for (i = 0; bootstrap[i]; ++i) {
495 if (bootstrap[i]->available()) {
496 video = bootstrap[i]->create(index);
505 return SDL_SetError("%s not available", driver_name);
507 return SDL_SetError("No available video device");
510 _this->name = bootstrap[i]->name;
511 _this->next_object_id = 1;
514 /* Set some very sane GL defaults */
515 _this->gl_config.driver_loaded = 0;
516 _this->gl_config.dll_handle = NULL;
517 SDL_GL_ResetAttributes();
519 _this->current_glwin_tls = SDL_TLSCreate();
520 _this->current_glctx_tls = SDL_TLSCreate();
522 /* Set vk_config to default values */
523 _this->vk_config.driver_loaded = 0;
525 /* Initialize the video subsystem */
526 if (_this->VideoInit(_this) < 0) {
531 /* Make sure some displays were added */
532 if (_this->num_displays == 0) {
534 return SDL_SetError("The video driver did not add any displays");
537 /* Add the renderer framebuffer emulation if desired */
538 if (ShouldUseTextureFramebuffer()) {
539 _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
540 _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
541 _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
544 /* Disable the screen saver by default. This is a change from <= 2.0.1,
545 but most things using SDL are games or media players; you wouldn't
546 want a screensaver to trigger if you're playing exclusively with a
547 joystick, or passively watching a movie. Things that use SDL but
548 function more like a normal desktop app should explicitly reenable the
550 hint = SDL_GetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER);
552 allow_screensaver = SDL_atoi(hint) ? SDL_TRUE : SDL_FALSE;
554 allow_screensaver = SDL_FALSE;
556 if (!allow_screensaver) {
557 SDL_DisableScreenSaver();
560 /* If we don't use a screen keyboard, turn on text input by default,
561 otherwise programs that expect to get text events without enabling
562 UNICODE input won't get any events.
564 Actually, come to think of it, you needed to call SDL_EnableUNICODE(1)
565 in SDL 1.2 before you got text input events. Hmm...
567 if (!SDL_HasScreenKeyboardSupport()) {
568 SDL_StartTextInput();
571 /* We're ready to go! */
576 SDL_GetCurrentVideoDriver()
579 SDL_UninitializedVideo();
586 SDL_GetVideoDevice(void)
592 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
594 SDL_VideoDisplay display;
598 display.desktop_mode = *desktop_mode;
600 display.current_mode = display.desktop_mode;
602 return SDL_AddVideoDisplay(&display);
606 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
608 SDL_VideoDisplay *displays;
612 SDL_realloc(_this->displays,
613 (_this->num_displays + 1) * sizeof(*displays));
615 index = _this->num_displays++;
616 displays[index] = *display;
617 displays[index].device = _this;
618 _this->displays = displays;
621 displays[index].name = SDL_strdup(display->name);
625 SDL_itoa(index, name, 10);
626 displays[index].name = SDL_strdup(name);
635 SDL_GetNumVideoDisplays(void)
638 SDL_UninitializedVideo();
641 return _this->num_displays;
645 SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
649 for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
650 if (display == &_this->displays[displayIndex]) {
655 /* Couldn't find the display, just use index 0 */
660 SDL_GetDisplayDriverData(int displayIndex)
662 CHECK_DISPLAY_INDEX(displayIndex, NULL);
664 return _this->displays[displayIndex].driverdata;
668 SDL_GetDisplayName(int displayIndex)
670 CHECK_DISPLAY_INDEX(displayIndex, NULL);
672 return _this->displays[displayIndex].name;
676 SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
678 CHECK_DISPLAY_INDEX(displayIndex, -1);
681 SDL_VideoDisplay *display = &_this->displays[displayIndex];
683 if (_this->GetDisplayBounds) {
684 if (_this->GetDisplayBounds(_this, display, rect) == 0) {
689 /* Assume that the displays are left to right */
690 if (displayIndex == 0) {
694 SDL_GetDisplayBounds(displayIndex-1, rect);
697 rect->w = display->current_mode.w;
698 rect->h = display->current_mode.h;
704 SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi)
706 SDL_VideoDisplay *display;
708 CHECK_DISPLAY_INDEX(displayIndex, -1);
710 display = &_this->displays[displayIndex];
712 if (_this->GetDisplayDPI) {
713 if (_this->GetDisplayDPI(_this, display, ddpi, hdpi, vdpi) == 0) {
722 SDL_AddDisplayMode(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
724 SDL_DisplayMode *modes;
727 /* Make sure we don't already have the mode in the list */
728 modes = display->display_modes;
729 nmodes = display->num_display_modes;
730 for (i = 0; i < nmodes; ++i) {
731 if (cmpmodes(mode, &modes[i]) == 0) {
736 /* Go ahead and add the new mode */
737 if (nmodes == display->max_display_modes) {
740 (display->max_display_modes + 32) * sizeof(*modes));
744 display->display_modes = modes;
745 display->max_display_modes += 32;
747 modes[nmodes] = *mode;
748 display->num_display_modes++;
750 /* Re-sort video modes */
751 SDL_qsort(display->display_modes, display->num_display_modes,
752 sizeof(SDL_DisplayMode), cmpmodes);
758 SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
760 if (!display->num_display_modes && _this->GetDisplayModes) {
761 _this->GetDisplayModes(_this, display);
762 SDL_qsort(display->display_modes, display->num_display_modes,
763 sizeof(SDL_DisplayMode), cmpmodes);
765 return display->num_display_modes;
769 SDL_GetNumDisplayModes(int displayIndex)
771 CHECK_DISPLAY_INDEX(displayIndex, -1);
773 return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
777 SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
779 SDL_VideoDisplay *display;
781 CHECK_DISPLAY_INDEX(displayIndex, -1);
783 display = &_this->displays[displayIndex];
784 if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
785 return SDL_SetError("index must be in the range of 0 - %d",
786 SDL_GetNumDisplayModesForDisplay(display) - 1);
789 *mode = display->display_modes[index];
795 SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
797 SDL_VideoDisplay *display;
799 CHECK_DISPLAY_INDEX(displayIndex, -1);
801 display = &_this->displays[displayIndex];
803 *mode = display->desktop_mode;
809 SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
811 SDL_VideoDisplay *display;
813 CHECK_DISPLAY_INDEX(displayIndex, -1);
815 display = &_this->displays[displayIndex];
817 *mode = display->current_mode;
822 static SDL_DisplayMode *
823 SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
824 const SDL_DisplayMode * mode,
825 SDL_DisplayMode * closest)
827 Uint32 target_format;
828 int target_refresh_rate;
830 SDL_DisplayMode *current, *match;
832 if (!mode || !closest) {
833 SDL_SetError("Missing desired mode or closest mode parameter");
837 /* Default to the desktop format */
839 target_format = mode->format;
841 target_format = display->desktop_mode.format;
844 /* Default to the desktop refresh rate */
845 if (mode->refresh_rate) {
846 target_refresh_rate = mode->refresh_rate;
848 target_refresh_rate = display->desktop_mode.refresh_rate;
852 for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
853 current = &display->display_modes[i];
855 if (current->w && (current->w < mode->w)) {
856 /* Out of sorted modes large enough here */
859 if (current->h && (current->h < mode->h)) {
860 if (current->w && (current->w == mode->w)) {
861 /* Out of sorted modes large enough here */
864 /* Wider, but not tall enough, due to a different
865 aspect ratio. This mode must be skipped, but closer
866 modes may still follow. */
869 if (!match || current->w < match->w || current->h < match->h) {
873 if (current->format != match->format) {
874 /* Sorted highest depth to lowest */
875 if (current->format == target_format ||
876 (SDL_BITSPERPIXEL(current->format) >=
877 SDL_BITSPERPIXEL(target_format)
878 && SDL_PIXELTYPE(current->format) ==
879 SDL_PIXELTYPE(target_format))) {
884 if (current->refresh_rate != match->refresh_rate) {
885 /* Sorted highest refresh to lowest */
886 if (current->refresh_rate >= target_refresh_rate) {
893 closest->format = match->format;
895 closest->format = mode->format;
897 if (match->w && match->h) {
898 closest->w = match->w;
899 closest->h = match->h;
901 closest->w = mode->w;
902 closest->h = mode->h;
904 if (match->refresh_rate) {
905 closest->refresh_rate = match->refresh_rate;
907 closest->refresh_rate = mode->refresh_rate;
909 closest->driverdata = match->driverdata;
912 * Pick some reasonable defaults if the app and driver don't
915 if (!closest->format) {
916 closest->format = SDL_PIXELFORMAT_RGB888;
930 SDL_GetClosestDisplayMode(int displayIndex,
931 const SDL_DisplayMode * mode,
932 SDL_DisplayMode * closest)
934 SDL_VideoDisplay *display;
936 CHECK_DISPLAY_INDEX(displayIndex, NULL);
938 display = &_this->displays[displayIndex];
939 return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
943 SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
945 SDL_DisplayMode display_mode;
946 SDL_DisplayMode current_mode;
949 display_mode = *mode;
951 /* Default to the current mode */
952 if (!display_mode.format) {
953 display_mode.format = display->current_mode.format;
955 if (!display_mode.w) {
956 display_mode.w = display->current_mode.w;
958 if (!display_mode.h) {
959 display_mode.h = display->current_mode.h;
961 if (!display_mode.refresh_rate) {
962 display_mode.refresh_rate = display->current_mode.refresh_rate;
965 /* Get a good video mode, the closest one possible */
966 if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
967 return SDL_SetError("No video mode large enough for %dx%d",
968 display_mode.w, display_mode.h);
971 display_mode = display->desktop_mode;
974 /* See if there's anything left to do */
975 current_mode = display->current_mode;
976 if (SDL_memcmp(&display_mode, ¤t_mode, sizeof(display_mode)) == 0) {
980 /* Actually change the display mode */
981 if (!_this->SetDisplayMode) {
982 return SDL_SetError("Video driver doesn't support changing display mode");
984 if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
987 display->current_mode = display_mode;
992 SDL_GetWindowDisplayIndex(SDL_Window * window)
997 int closest_dist = 0x7FFFFFFF;
1002 CHECK_WINDOW_MAGIC(window, -1);
1004 if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
1005 SDL_WINDOWPOS_ISCENTERED(window->x)) {
1006 displayIndex = (window->x & 0xFFFF);
1007 if (displayIndex >= _this->num_displays) {
1010 return displayIndex;
1012 if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
1013 SDL_WINDOWPOS_ISCENTERED(window->y)) {
1014 displayIndex = (window->y & 0xFFFF);
1015 if (displayIndex >= _this->num_displays) {
1018 return displayIndex;
1021 /* Find the display containing the window */
1022 for (i = 0; i < _this->num_displays; ++i) {
1023 SDL_VideoDisplay *display = &_this->displays[i];
1025 if (display->fullscreen_window == window) {
1029 center.x = window->x + window->w / 2;
1030 center.y = window->y + window->h / 2;
1031 for (i = 0; i < _this->num_displays; ++i) {
1032 SDL_GetDisplayBounds(i, &rect);
1033 if (SDL_EnclosePoints(¢er, 1, &rect, NULL)) {
1037 delta.x = center.x - (rect.x + rect.w / 2);
1038 delta.y = center.y - (rect.y + rect.h / 2);
1039 dist = (delta.x*delta.x + delta.y*delta.y);
1040 if (dist < closest_dist) {
1042 closest_dist = dist;
1046 SDL_SetError("Couldn't find any displays");
1052 SDL_GetDisplayForWindow(SDL_Window *window)
1054 int displayIndex = SDL_GetWindowDisplayIndex(window);
1055 if (displayIndex >= 0) {
1056 return &_this->displays[displayIndex];
1063 SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
1065 CHECK_WINDOW_MAGIC(window, -1);
1068 window->fullscreen_mode = *mode;
1070 SDL_zero(window->fullscreen_mode);
1073 if (FULLSCREEN_VISIBLE(window) && (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
1074 SDL_DisplayMode fullscreen_mode;
1075 if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) {
1076 SDL_SetDisplayModeForDisplay(SDL_GetDisplayForWindow(window), &fullscreen_mode);
1083 SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
1085 SDL_DisplayMode fullscreen_mode;
1086 SDL_VideoDisplay *display;
1088 CHECK_WINDOW_MAGIC(window, -1);
1091 return SDL_InvalidParamError("mode");
1094 fullscreen_mode = window->fullscreen_mode;
1095 if (!fullscreen_mode.w) {
1096 fullscreen_mode.w = window->windowed.w;
1098 if (!fullscreen_mode.h) {
1099 fullscreen_mode.h = window->windowed.h;
1102 display = SDL_GetDisplayForWindow(window);
1104 /* if in desktop size mode, just return the size of the desktop */
1105 if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
1106 fullscreen_mode = display->desktop_mode;
1107 } else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
1109 &fullscreen_mode)) {
1110 return SDL_SetError("Couldn't find display mode match");
1114 *mode = fullscreen_mode;
1120 SDL_GetWindowPixelFormat(SDL_Window * window)
1122 SDL_VideoDisplay *display;
1124 CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
1126 display = SDL_GetDisplayForWindow(window);
1127 return display->current_mode.format;
1131 SDL_RestoreMousePosition(SDL_Window *window)
1135 if (window == SDL_GetMouseFocus()) {
1136 SDL_GetMouseState(&x, &y);
1137 SDL_WarpMouseInWindow(window, x, y);
1142 extern Uint32 WINRT_DetectWindowFlags(SDL_Window * window);
1146 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
1148 SDL_VideoDisplay *display;
1151 CHECK_WINDOW_MAGIC(window,-1);
1153 /* if we are in the process of hiding don't go back to fullscreen */
1154 if ( window->is_hiding && fullscreen )
1158 /* if the window is going away and no resolution change is necessary,
1159 do nothing, or else we may trigger an ugly double-transition
1161 if (window->is_destroying && (window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP)
1164 /* If we're switching between a fullscreen Space and "normal" fullscreen, we need to get back to normal first. */
1165 if (fullscreen && ((window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP) && ((window->flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN)) {
1166 if (!Cocoa_SetWindowFullscreenSpace(window, SDL_FALSE)) {
1169 } else if (fullscreen && ((window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN) && ((window->flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP)) {
1170 display = SDL_GetDisplayForWindow(window);
1171 SDL_SetDisplayModeForDisplay(display, NULL);
1172 if (_this->SetWindowFullscreen) {
1173 _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
1177 if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
1178 if (Cocoa_IsWindowInFullscreenSpace(window) != fullscreen) {
1181 window->last_fullscreen_flags = window->flags;
1184 #elif __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
1185 /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
1186 or not. The user can choose this, via OS-provided UI, but this can't
1187 be set programmatically.
1189 Just look at what SDL's WinRT video backend code detected with regards
1190 to fullscreen (being active, or not), and figure out a return/error code
1193 if (fullscreen == !(WINRT_DetectWindowFlags(window) & FULLSCREEN_MASK)) {
1195 1. fullscreen was requested, and we're already windowed
1196 2. windowed-mode was requested, and we're already fullscreen
1198 WinRT 8.x can't resolve either programmatically, so we're
1203 /* Whatever was requested, fullscreen or windowed mode, is already
1210 display = SDL_GetDisplayForWindow(window);
1213 /* Hide any other fullscreen windows */
1214 if (display->fullscreen_window &&
1215 display->fullscreen_window != window) {
1216 SDL_MinimizeWindow(display->fullscreen_window);
1220 /* See if anything needs to be done now */
1221 if ((display->fullscreen_window == window) == fullscreen) {
1222 if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) {
1227 /* See if there are any fullscreen windows */
1228 for (other = _this->windows; other; other = other->next) {
1229 SDL_bool setDisplayMode = SDL_FALSE;
1231 if (other == window) {
1232 setDisplayMode = fullscreen;
1233 } else if (FULLSCREEN_VISIBLE(other) &&
1234 SDL_GetDisplayForWindow(other) == display) {
1235 setDisplayMode = SDL_TRUE;
1238 if (setDisplayMode) {
1239 SDL_DisplayMode fullscreen_mode;
1241 SDL_zero(fullscreen_mode);
1243 if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
1244 SDL_bool resized = SDL_TRUE;
1246 if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
1247 resized = SDL_FALSE;
1250 /* only do the mode change if we want exclusive fullscreen */
1251 if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
1252 if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
1256 if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
1261 if (_this->SetWindowFullscreen) {
1262 _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
1264 display->fullscreen_window = other;
1266 /* Generate a mode change event here */
1268 SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
1269 fullscreen_mode.w, fullscreen_mode.h);
1271 SDL_OnWindowResized(other);
1274 SDL_RestoreMousePosition(other);
1276 window->last_fullscreen_flags = window->flags;
1282 /* Nope, restore the desktop mode */
1283 SDL_SetDisplayModeForDisplay(display, NULL);
1285 if (_this->SetWindowFullscreen) {
1286 _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
1288 display->fullscreen_window = NULL;
1290 /* Generate a mode change event here */
1291 SDL_OnWindowResized(window);
1293 /* Restore the cursor position */
1294 SDL_RestoreMousePosition(window);
1296 window->last_fullscreen_flags = window->flags;
1300 #define CREATE_FLAGS \
1301 (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_VULKAN | 0x00008000)
1304 SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
1306 window->windowed.x = window->x;
1307 window->windowed.y = window->y;
1308 window->windowed.w = window->w;
1309 window->windowed.h = window->h;
1311 if (flags & SDL_WINDOW_MAXIMIZED) {
1312 SDL_MaximizeWindow(window);
1314 if (flags & SDL_WINDOW_MINIMIZED) {
1315 SDL_MinimizeWindow(window);
1317 if (flags & SDL_WINDOW_FULLSCREEN) {
1318 SDL_SetWindowFullscreen(window, flags);
1320 if (flags & SDL_WINDOW_INPUT_GRABBED) {
1321 SDL_SetWindowGrab(window, SDL_TRUE);
1323 if (!(flags & SDL_WINDOW_HIDDEN)) {
1324 SDL_ShowWindow(window);
1329 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
1335 /* Initialize the video system if needed */
1336 if (SDL_VideoInit(NULL) < 0) {
1341 /* Some platforms can't create zero-sized windows */
1349 /* Some platforms blow up if the windows are too large. Raise it later? */
1350 if ((w > 16384) || (h > 16384)) {
1351 SDL_SetError("Window is too large.");
1355 /* Some platforms have OpenGL enabled by default */
1356 #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
1357 flags |= SDL_WINDOW_OPENGL;
1359 if (flags & SDL_WINDOW_OPENGL) {
1360 if (!_this->GL_CreateContext) {
1361 SDL_SetError("No OpenGL support in video driver");
1364 if (SDL_GL_LoadLibrary(NULL) < 0) {
1369 #if (SDL_VIDEO_VULKAN)
1370 if (flags & SDL_WINDOW_VULKAN) {
1371 if (!_this->vulkan_GetInstanceExtensions) {
1372 SDL_SetError("No Vulkan support in video driver");
1376 if (_this->vulkan_LoadLibrary(_this, NULL) < 0) {
1381 if ((flags & SDL_WINDOW_OPENGL) && (flags & SDL_WINDOW_VULKAN)) {
1382 SDL_SetError("Don't use both OPENGL and VULKAN");
1387 /* Unless the user has specified the high-DPI disabling hint, respect the
1388 * SDL_WINDOW_ALLOW_HIGHDPI flag.
1390 if (flags & SDL_WINDOW_ALLOW_HIGHDPI) {
1391 hint = SDL_GetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED);
1392 if (hint && SDL_atoi(hint) > 0) {
1393 flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
1397 window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
1402 window->magic = &_this->window_magic;
1403 window->id = _this->next_object_id++;
1408 if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
1409 SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
1410 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1414 displayIndex = SDL_GetIndexOfDisplay(display);
1415 SDL_GetDisplayBounds(displayIndex, &bounds);
1416 if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
1417 window->x = bounds.x + (bounds.w - w) / 2;
1419 if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
1420 window->y = bounds.y + (bounds.h - h) / 2;
1424 window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
1425 window->last_fullscreen_flags = window->flags;
1426 window->brightness = 1.0f;
1427 window->next = _this->windows;
1428 window->is_destroying = SDL_FALSE;
1430 if (_this->windows) {
1431 _this->windows->prev = window;
1433 _this->windows = window;
1435 if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
1436 SDL_DestroyWindow(window);
1440 #if __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
1441 /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
1442 or not. The user can choose this, via OS-provided UI, but this can't
1443 be set programmatically.
1445 Just look at what SDL's WinRT video backend code detected with regards
1446 to fullscreen (being active, or not), and figure out a return/error code
1449 flags = window->flags;
1453 SDL_SetWindowTitle(window, title);
1455 SDL_FinishWindowCreation(window, flags);
1457 /* If the window was created fullscreen, make sure the mode code matches */
1458 SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
1464 SDL_CreateWindowFrom(const void *data)
1469 SDL_UninitializedVideo();
1472 if (!_this->CreateWindowFrom) {
1476 window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
1481 window->magic = &_this->window_magic;
1482 window->id = _this->next_object_id++;
1483 window->flags = SDL_WINDOW_FOREIGN;
1484 window->last_fullscreen_flags = window->flags;
1485 window->is_destroying = SDL_FALSE;
1486 window->brightness = 1.0f;
1487 window->next = _this->windows;
1488 if (_this->windows) {
1489 _this->windows->prev = window;
1491 _this->windows = window;
1493 if (_this->CreateWindowFrom(_this, window, data) < 0) {
1494 SDL_DestroyWindow(window);
1501 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
1503 SDL_bool loaded_opengl = SDL_FALSE;
1505 if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
1506 return SDL_SetError("No OpenGL support in video driver");
1509 if (window->flags & SDL_WINDOW_FOREIGN) {
1510 /* Can't destroy and re-create foreign windows, hrm */
1511 flags |= SDL_WINDOW_FOREIGN;
1513 flags &= ~SDL_WINDOW_FOREIGN;
1516 /* Restore video mode, etc. */
1517 SDL_HideWindow(window);
1519 /* Tear down the old native window */
1520 if (window->surface) {
1521 window->surface->flags &= ~SDL_DONTFREE;
1522 SDL_FreeSurface(window->surface);
1523 window->surface = NULL;
1525 if (_this->DestroyWindowFramebuffer) {
1526 _this->DestroyWindowFramebuffer(_this, window);
1528 if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1529 _this->DestroyWindow(_this, window);
1532 if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
1533 if (flags & SDL_WINDOW_OPENGL) {
1534 if (SDL_GL_LoadLibrary(NULL) < 0) {
1537 loaded_opengl = SDL_TRUE;
1539 SDL_GL_UnloadLibrary();
1543 window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
1544 window->last_fullscreen_flags = window->flags;
1545 window->is_destroying = SDL_FALSE;
1547 if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1548 if (_this->CreateWindow(_this, window) < 0) {
1549 if (loaded_opengl) {
1550 SDL_GL_UnloadLibrary();
1551 window->flags &= ~SDL_WINDOW_OPENGL;
1557 if (flags & SDL_WINDOW_FOREIGN) {
1558 window->flags |= SDL_WINDOW_FOREIGN;
1561 if (_this->SetWindowTitle && window->title) {
1562 _this->SetWindowTitle(_this, window);
1565 if (_this->SetWindowIcon && window->icon) {
1566 _this->SetWindowIcon(_this, window, window->icon);
1569 if (window->hit_test) {
1570 _this->SetWindowHitTest(window, SDL_TRUE);
1573 SDL_FinishWindowCreation(window, flags);
1579 SDL_GetWindowID(SDL_Window * window)
1581 CHECK_WINDOW_MAGIC(window, 0);
1587 SDL_GetWindowFromID(Uint32 id)
1594 for (window = _this->windows; window; window = window->next) {
1595 if (window->id == id) {
1603 SDL_GetWindowFlags(SDL_Window * window)
1605 CHECK_WINDOW_MAGIC(window, 0);
1607 return window->flags;
1611 SDL_SetWindowTitle(SDL_Window * window, const char *title)
1613 CHECK_WINDOW_MAGIC(window,);
1615 if (title == window->title) {
1618 SDL_free(window->title);
1620 window->title = SDL_strdup(title ? title : "");
1622 if (_this->SetWindowTitle) {
1623 _this->SetWindowTitle(_this, window);
1628 SDL_GetWindowTitle(SDL_Window * window)
1630 CHECK_WINDOW_MAGIC(window, "");
1632 return window->title ? window->title : "";
1636 SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
1638 CHECK_WINDOW_MAGIC(window,);
1644 SDL_FreeSurface(window->icon);
1646 /* Convert the icon into ARGB8888 */
1647 window->icon = SDL_ConvertSurfaceFormat(icon, SDL_PIXELFORMAT_ARGB8888, 0);
1648 if (!window->icon) {
1652 if (_this->SetWindowIcon) {
1653 _this->SetWindowIcon(_this, window, window->icon);
1658 SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
1660 SDL_WindowUserData *prev, *data;
1662 CHECK_WINDOW_MAGIC(window, NULL);
1664 /* Input validation */
1665 if (name == NULL || name[0] == '\0') {
1666 SDL_InvalidParamError("name");
1670 /* See if the named data already exists */
1672 for (data = window->data; data; prev = data, data = data->next) {
1673 if (data->name && SDL_strcmp(data->name, name) == 0) {
1674 void *last_value = data->data;
1677 /* Set the new value */
1678 data->data = userdata;
1680 /* Delete this value */
1682 prev->next = data->next;
1684 window->data = data->next;
1686 SDL_free(data->name);
1693 /* Add new data to the window */
1695 data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
1696 data->name = SDL_strdup(name);
1697 data->data = userdata;
1698 data->next = window->data;
1699 window->data = data;
1705 SDL_GetWindowData(SDL_Window * window, const char *name)
1707 SDL_WindowUserData *data;
1709 CHECK_WINDOW_MAGIC(window, NULL);
1711 /* Input validation */
1712 if (name == NULL || name[0] == '\0') {
1713 SDL_InvalidParamError("name");
1717 for (data = window->data; data; data = data->next) {
1718 if (data->name && SDL_strcmp(data->name, name) == 0) {
1726 SDL_SetWindowPosition(SDL_Window * window, int x, int y)
1728 CHECK_WINDOW_MAGIC(window,);
1730 if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
1731 int displayIndex = (x & 0xFFFF);
1733 if (displayIndex > _this->num_displays) {
1739 SDL_GetDisplayBounds(displayIndex, &bounds);
1740 if (SDL_WINDOWPOS_ISCENTERED(x)) {
1741 x = bounds.x + (bounds.w - window->w) / 2;
1743 if (SDL_WINDOWPOS_ISCENTERED(y)) {
1744 y = bounds.y + (bounds.h - window->h) / 2;
1748 if ((window->flags & SDL_WINDOW_FULLSCREEN)) {
1749 if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
1750 window->windowed.x = x;
1752 if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
1753 window->windowed.y = y;
1756 if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
1759 if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
1763 if (_this->SetWindowPosition) {
1764 _this->SetWindowPosition(_this, window);
1766 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
1771 SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
1773 CHECK_WINDOW_MAGIC(window,);
1775 /* Fullscreen windows are always at their display's origin */
1776 if (window->flags & SDL_WINDOW_FULLSCREEN) {
1786 /* Find the window's monitor and update to the
1788 displayIndex = SDL_GetWindowDisplayIndex(window);
1789 if (displayIndex >= 0) {
1794 SDL_GetDisplayBounds(displayIndex, &bounds);
1813 SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
1815 CHECK_WINDOW_MAGIC(window,);
1816 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1817 const int want = (bordered != SDL_FALSE); /* normalize the flag. */
1818 const int have = ((window->flags & SDL_WINDOW_BORDERLESS) == 0);
1819 if ((want != have) && (_this->SetWindowBordered)) {
1821 window->flags &= ~SDL_WINDOW_BORDERLESS;
1823 window->flags |= SDL_WINDOW_BORDERLESS;
1825 _this->SetWindowBordered(_this, window, (SDL_bool) want);
1831 SDL_SetWindowSize(SDL_Window * window, int w, int h)
1833 CHECK_WINDOW_MAGIC(window,);
1835 SDL_InvalidParamError("w");
1839 SDL_InvalidParamError("h");
1843 /* Make sure we don't exceed any window size limits */
1844 if (window->min_w && w < window->min_w)
1848 if (window->max_w && w > window->max_w)
1852 if (window->min_h && h < window->min_h)
1856 if (window->max_h && h > window->max_h)
1861 window->windowed.w = w;
1862 window->windowed.h = h;
1864 if (window->flags & SDL_WINDOW_FULLSCREEN) {
1865 if (FULLSCREEN_VISIBLE(window) && (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
1866 window->last_fullscreen_flags = 0;
1867 SDL_UpdateFullscreenMode(window, SDL_TRUE);
1872 if (_this->SetWindowSize) {
1873 _this->SetWindowSize(_this, window);
1875 if (window->w == w && window->h == h) {
1876 /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
1877 SDL_OnWindowResized(window);
1883 SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
1885 CHECK_WINDOW_MAGIC(window,);
1887 if (_this->GetWindowSize) {
1888 _this->GetWindowSize(_this, window, w, h);
1909 SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
1911 CHECK_WINDOW_MAGIC(window,);
1913 SDL_InvalidParamError("min_w");
1917 SDL_InvalidParamError("min_h");
1921 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1922 window->min_w = min_w;
1923 window->min_h = min_h;
1924 if (_this->SetWindowMinimumSize) {
1925 _this->SetWindowMinimumSize(_this, window);
1927 /* Ensure that window is not smaller than minimal size */
1928 SDL_SetWindowSize(window, SDL_max(window->w, window->min_w), SDL_max(window->h, window->min_h));
1933 SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
1935 CHECK_WINDOW_MAGIC(window,);
1937 *min_w = window->min_w;
1940 *min_h = window->min_h;
1945 SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h)
1947 CHECK_WINDOW_MAGIC(window,);
1949 SDL_InvalidParamError("max_w");
1953 SDL_InvalidParamError("max_h");
1957 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1958 window->max_w = max_w;
1959 window->max_h = max_h;
1960 if (_this->SetWindowMaximumSize) {
1961 _this->SetWindowMaximumSize(_this, window);
1963 /* Ensure that window is not larger than maximal size */
1964 SDL_SetWindowSize(window, SDL_min(window->w, window->max_w), SDL_min(window->h, window->max_h));
1969 SDL_GetWindowMaximumSize(SDL_Window * window, int *max_w, int *max_h)
1971 CHECK_WINDOW_MAGIC(window,);
1973 *max_w = window->max_w;
1976 *max_h = window->max_h;
1981 SDL_ShowWindow(SDL_Window * window)
1983 CHECK_WINDOW_MAGIC(window,);
1985 if (window->flags & SDL_WINDOW_SHOWN) {
1989 if (_this->ShowWindow) {
1990 _this->ShowWindow(_this, window);
1992 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
1996 SDL_HideWindow(SDL_Window * window)
1998 CHECK_WINDOW_MAGIC(window,);
2000 if (!(window->flags & SDL_WINDOW_SHOWN)) {
2004 window->is_hiding = SDL_TRUE;
2005 SDL_UpdateFullscreenMode(window, SDL_FALSE);
2007 if (_this->HideWindow) {
2008 _this->HideWindow(_this, window);
2010 window->is_hiding = SDL_FALSE;
2011 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
2015 SDL_RaiseWindow(SDL_Window * window)
2017 CHECK_WINDOW_MAGIC(window,);
2019 if (!(window->flags & SDL_WINDOW_SHOWN)) {
2022 if (_this->RaiseWindow) {
2023 _this->RaiseWindow(_this, window);
2028 SDL_MaximizeWindow(SDL_Window * window)
2030 CHECK_WINDOW_MAGIC(window,);
2032 if (window->flags & SDL_WINDOW_MAXIMIZED) {
2036 /* !!! FIXME: should this check if the window is resizable? */
2038 if (_this->MaximizeWindow) {
2039 _this->MaximizeWindow(_this, window);
2044 SDL_MinimizeWindow(SDL_Window * window)
2046 CHECK_WINDOW_MAGIC(window,);
2048 if (window->flags & SDL_WINDOW_MINIMIZED) {
2052 SDL_UpdateFullscreenMode(window, SDL_FALSE);
2054 if (_this->MinimizeWindow) {
2055 _this->MinimizeWindow(_this, window);
2060 SDL_RestoreWindow(SDL_Window * window)
2062 CHECK_WINDOW_MAGIC(window,);
2064 if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
2068 if (_this->RestoreWindow) {
2069 _this->RestoreWindow(_this, window);
2074 SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
2077 CHECK_WINDOW_MAGIC(window, -1);
2079 flags &= FULLSCREEN_MASK;
2081 if (flags == (window->flags & FULLSCREEN_MASK)) {
2085 /* clear the previous flags and OR in the new ones */
2086 oldflags = window->flags & FULLSCREEN_MASK;
2087 window->flags &= ~FULLSCREEN_MASK;
2088 window->flags |= flags;
2090 if (SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window)) == 0) {
2094 window->flags &= ~FULLSCREEN_MASK;
2095 window->flags |= oldflags;
2099 static SDL_Surface *
2100 SDL_CreateWindowFramebuffer(SDL_Window * window)
2106 Uint32 Rmask, Gmask, Bmask, Amask;
2108 if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
2112 if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
2116 if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
2120 return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
2124 SDL_GetWindowSurface(SDL_Window * window)
2126 CHECK_WINDOW_MAGIC(window, NULL);
2128 if (!window->surface_valid) {
2129 if (window->surface) {
2130 window->surface->flags &= ~SDL_DONTFREE;
2131 SDL_FreeSurface(window->surface);
2133 window->surface = SDL_CreateWindowFramebuffer(window);
2134 if (window->surface) {
2135 window->surface_valid = SDL_TRUE;
2136 window->surface->flags |= SDL_DONTFREE;
2139 return window->surface;
2143 SDL_UpdateWindowSurface(SDL_Window * window)
2147 CHECK_WINDOW_MAGIC(window, -1);
2151 full_rect.w = window->w;
2152 full_rect.h = window->h;
2153 return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
2157 SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
2160 CHECK_WINDOW_MAGIC(window, -1);
2162 if (!window->surface_valid) {
2163 return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
2166 return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
2170 SDL_SetWindowBrightness(SDL_Window * window, float brightness)
2175 CHECK_WINDOW_MAGIC(window, -1);
2177 SDL_CalculateGammaRamp(brightness, ramp);
2178 status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
2180 window->brightness = brightness;
2186 SDL_GetWindowBrightness(SDL_Window * window)
2188 CHECK_WINDOW_MAGIC(window, 1.0f);
2190 return window->brightness;
2194 SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
2195 const Uint16 * green,
2196 const Uint16 * blue)
2198 CHECK_WINDOW_MAGIC(window, -1);
2200 if (!_this->SetWindowGammaRamp) {
2201 return SDL_Unsupported();
2204 if (!window->gamma) {
2205 if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
2208 SDL_assert(window->gamma != NULL);
2212 SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
2215 SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
2218 SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
2220 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
2221 return _this->SetWindowGammaRamp(_this, window, window->gamma);
2228 SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
2232 CHECK_WINDOW_MAGIC(window, -1);
2234 if (!window->gamma) {
2237 window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
2238 if (!window->gamma) {
2239 return SDL_OutOfMemory();
2241 window->saved_gamma = window->gamma + 3*256;
2243 if (_this->GetWindowGammaRamp) {
2244 if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
2248 /* Create an identity gamma ramp */
2249 for (i = 0; i < 256; ++i) {
2250 Uint16 value = (Uint16)((i << 8) | i);
2252 window->gamma[0*256+i] = value;
2253 window->gamma[1*256+i] = value;
2254 window->gamma[2*256+i] = value;
2257 SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
2261 SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
2264 SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
2267 SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
2273 SDL_UpdateWindowGrab(SDL_Window * window)
2275 SDL_Window *grabbed_window;
2277 if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
2278 (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
2281 grabbed = SDL_FALSE;
2284 grabbed_window = _this->grabbed_window;
2286 if (grabbed_window && (grabbed_window != window)) {
2287 /* stealing a grab from another window! */
2288 grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
2289 if (_this->SetWindowGrab) {
2290 _this->SetWindowGrab(_this, grabbed_window, SDL_FALSE);
2293 _this->grabbed_window = window;
2294 } else if (grabbed_window == window) {
2295 _this->grabbed_window = NULL; /* ungrabbing. */
2298 if (_this->SetWindowGrab) {
2299 _this->SetWindowGrab(_this, window, grabbed);
2304 SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
2306 CHECK_WINDOW_MAGIC(window,);
2308 if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
2312 window->flags |= SDL_WINDOW_INPUT_GRABBED;
2314 window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
2316 SDL_UpdateWindowGrab(window);
2320 SDL_GetWindowGrab(SDL_Window * window)
2322 CHECK_WINDOW_MAGIC(window, SDL_FALSE);
2323 SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
2324 return window == _this->grabbed_window;
2328 SDL_GetGrabbedWindow(void)
2330 SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
2331 return _this->grabbed_window;
2335 SDL_OnWindowShown(SDL_Window * window)
2337 SDL_OnWindowRestored(window);
2341 SDL_OnWindowHidden(SDL_Window * window)
2343 SDL_UpdateFullscreenMode(window, SDL_FALSE);
2347 SDL_OnWindowResized(SDL_Window * window)
2349 window->surface_valid = SDL_FALSE;
2350 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
2354 SDL_OnWindowMinimized(SDL_Window * window)
2356 SDL_UpdateFullscreenMode(window, SDL_FALSE);
2360 SDL_OnWindowRestored(SDL_Window * window)
2363 * FIXME: Is this fine to just remove this, or should it be preserved just
2364 * for the fullscreen case? In principle it seems like just hiding/showing
2365 * windows shouldn't affect the stacking order; maybe the right fix is to
2366 * re-decouple OnWindowShown and OnWindowRestored.
2368 /*SDL_RaiseWindow(window);*/
2370 if (FULLSCREEN_VISIBLE(window)) {
2371 SDL_UpdateFullscreenMode(window, SDL_TRUE);
2376 SDL_OnWindowEnter(SDL_Window * window)
2378 if (_this->OnWindowEnter) {
2379 _this->OnWindowEnter(_this, window);
2384 SDL_OnWindowLeave(SDL_Window * window)
2389 SDL_OnWindowFocusGained(SDL_Window * window)
2391 SDL_Mouse *mouse = SDL_GetMouse();
2393 if (window->gamma && _this->SetWindowGammaRamp) {
2394 _this->SetWindowGammaRamp(_this, window, window->gamma);
2397 if (mouse && mouse->relative_mode) {
2398 SDL_SetMouseFocus(window);
2399 SDL_WarpMouseInWindow(window, window->w/2, window->h/2);
2402 SDL_UpdateWindowGrab(window);
2406 ShouldMinimizeOnFocusLoss(SDL_Window * window)
2410 if (!(window->flags & SDL_WINDOW_FULLSCREEN) || window->is_destroying) {
2415 if (Cocoa_IsWindowInFullscreenSpace(window)) {
2420 hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
2433 SDL_OnWindowFocusLost(SDL_Window * window)
2435 if (window->gamma && _this->SetWindowGammaRamp) {
2436 _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
2439 SDL_UpdateWindowGrab(window);
2441 if (ShouldMinimizeOnFocusLoss(window)) {
2442 SDL_MinimizeWindow(window);
2446 /* !!! FIXME: is this different than SDL_GetKeyboardFocus()?
2447 !!! FIXME: Also, SDL_GetKeyboardFocus() is O(1), this isn't. */
2449 SDL_GetFocusWindow(void)
2456 for (window = _this->windows; window; window = window->next) {
2457 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
2465 SDL_DestroyWindow(SDL_Window * window)
2467 SDL_VideoDisplay *display;
2469 CHECK_WINDOW_MAGIC(window,);
2471 window->is_destroying = SDL_TRUE;
2473 /* Restore video mode, etc. */
2474 SDL_HideWindow(window);
2476 /* Make sure this window no longer has focus */
2477 if (SDL_GetKeyboardFocus() == window) {
2478 SDL_SetKeyboardFocus(NULL);
2480 if (SDL_GetMouseFocus() == window) {
2481 SDL_SetMouseFocus(NULL);
2484 /* make no context current if this is the current context window. */
2485 if (window->flags & SDL_WINDOW_OPENGL) {
2486 if (_this->current_glwin == window) {
2487 SDL_GL_MakeCurrent(window, NULL);
2491 if (window->surface) {
2492 window->surface->flags &= ~SDL_DONTFREE;
2493 SDL_FreeSurface(window->surface);
2495 if (_this->DestroyWindowFramebuffer) {
2496 _this->DestroyWindowFramebuffer(_this, window);
2498 if (_this->DestroyWindow) {
2499 _this->DestroyWindow(_this, window);
2501 if (window->flags & SDL_WINDOW_OPENGL) {
2502 SDL_GL_UnloadLibrary();
2505 display = SDL_GetDisplayForWindow(window);
2506 if (display->fullscreen_window == window) {
2507 display->fullscreen_window = NULL;
2510 /* Now invalidate magic */
2511 window->magic = NULL;
2513 /* Free memory associated with the window */
2514 SDL_free(window->title);
2515 SDL_FreeSurface(window->icon);
2516 SDL_free(window->gamma);
2517 while (window->data) {
2518 SDL_WindowUserData *data = window->data;
2520 window->data = data->next;
2521 SDL_free(data->name);
2525 /* Unlink the window from the list */
2527 window->next->prev = window->prev;
2530 window->prev->next = window->next;
2532 _this->windows = window->next;
2539 SDL_IsScreenSaverEnabled()
2544 return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
2548 SDL_EnableScreenSaver()
2553 if (!_this->suspend_screensaver) {
2556 _this->suspend_screensaver = SDL_FALSE;
2557 if (_this->SuspendScreenSaver) {
2558 _this->SuspendScreenSaver(_this);
2563 SDL_DisableScreenSaver()
2568 if (_this->suspend_screensaver) {
2571 _this->suspend_screensaver = SDL_TRUE;
2572 if (_this->SuspendScreenSaver) {
2573 _this->SuspendScreenSaver(_this);
2586 /* Halt event processing before doing anything else */
2590 SDL_QuitSubSystem(SDL_INIT_EVENTS);
2592 SDL_EnableScreenSaver();
2594 /* Clean up the system video */
2595 while (_this->windows) {
2596 SDL_DestroyWindow(_this->windows);
2598 _this->VideoQuit(_this);
2600 for (i = 0; i < _this->num_displays; ++i) {
2601 SDL_VideoDisplay *display = &_this->displays[i];
2602 for (j = display->num_display_modes; j--;) {
2603 SDL_free(display->display_modes[j].driverdata);
2604 display->display_modes[j].driverdata = NULL;
2606 SDL_free(display->display_modes);
2607 display->display_modes = NULL;
2608 SDL_free(display->desktop_mode.driverdata);
2609 display->desktop_mode.driverdata = NULL;
2610 SDL_free(display->driverdata);
2611 display->driverdata = NULL;
2613 if (_this->displays) {
2614 for (i = 0; i < _this->num_displays; ++i) {
2615 SDL_free(_this->displays[i].name);
2617 SDL_free(_this->displays);
2618 _this->displays = NULL;
2619 _this->num_displays = 0;
2621 SDL_free(_this->clipboard_text);
2622 _this->clipboard_text = NULL;
2628 SDL_GL_LoadLibrary(const char *path)
2633 return SDL_UninitializedVideo();
2635 if (_this->gl_config.driver_loaded) {
2636 if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
2637 return SDL_SetError("OpenGL library already loaded");
2641 if (!_this->GL_LoadLibrary) {
2642 return SDL_SetError("No dynamic GL support in video driver");
2644 retval = _this->GL_LoadLibrary(_this, path);
2647 ++_this->gl_config.driver_loaded;
2649 if (_this->GL_UnloadLibrary) {
2650 _this->GL_UnloadLibrary(_this);
2657 SDL_GL_GetProcAddress(const char *proc)
2662 SDL_UninitializedVideo();
2666 if (_this->GL_GetProcAddress) {
2667 if (_this->gl_config.driver_loaded) {
2668 func = _this->GL_GetProcAddress(_this, proc);
2670 SDL_SetError("No GL driver has been loaded");
2673 SDL_SetError("No dynamic GL support in video driver");
2679 SDL_GL_UnloadLibrary(void)
2682 SDL_UninitializedVideo();
2685 if (_this->gl_config.driver_loaded > 0) {
2686 if (--_this->gl_config.driver_loaded > 0) {
2689 if (_this->GL_UnloadLibrary) {
2690 _this->GL_UnloadLibrary(_this);
2695 static SDL_INLINE SDL_bool
2696 isAtLeastGL3(const char *verstr)
2698 return (verstr && (SDL_atoi(verstr) >= 3));
2702 SDL_GL_ExtensionSupported(const char *extension)
2704 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2705 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
2706 const char *extensions;
2708 const char *where, *terminator;
2710 /* Extension names should not have spaces. */
2711 where = SDL_strchr(extension, ' ');
2712 if (where || *extension == '\0') {
2715 /* See if there's an environment variable override */
2716 start = SDL_getenv(extension);
2717 if (start && *start == '0') {
2721 /* Lookup the available extensions */
2723 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
2724 if (!glGetStringFunc) {
2728 if (isAtLeastGL3((const char *) glGetStringFunc(GL_VERSION))) {
2729 const GLubyte *(APIENTRY * glGetStringiFunc) (GLenum, GLuint);
2730 void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
2734 glGetStringiFunc = SDL_GL_GetProcAddress("glGetStringi");
2735 glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
2736 if ((!glGetStringiFunc) || (!glGetIntegervFunc)) {
2740 #ifndef GL_NUM_EXTENSIONS
2741 #define GL_NUM_EXTENSIONS 0x821D
2743 glGetIntegervFunc(GL_NUM_EXTENSIONS, &num_exts);
2744 for (i = 0; i < num_exts; i++) {
2745 const char *thisext = (const char *) glGetStringiFunc(GL_EXTENSIONS, i);
2746 if (SDL_strcmp(thisext, extension) == 0) {
2754 /* Try the old way with glGetString(GL_EXTENSIONS) ... */
2756 extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
2761 * It takes a bit of care to be fool-proof about parsing the OpenGL
2762 * extensions string. Don't be fooled by sub-strings, etc.
2768 where = SDL_strstr(start, extension);
2772 terminator = where + SDL_strlen(extension);
2773 if (where == start || *(where - 1) == ' ')
2774 if (*terminator == ' ' || *terminator == '\0')
2780 /* check EGL extensions (copied from SDL_EGL_HasExtension())*/
2785 const char *ext_word;
2787 ext_len = SDL_strlen(extension);
2788 exts = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS);
2793 for (i = 0; exts[i] != 0; i++) {
2794 if (exts[i] == ' ') {
2795 if (ext_len == len && !SDL_strncmp(ext_word, extension, len)) {
2800 ext_word = &exts[i + 1];
2815 SDL_GL_ResetAttributes()
2821 _this->gl_config.red_size = 3;
2822 _this->gl_config.green_size = 3;
2823 _this->gl_config.blue_size = 2;
2824 _this->gl_config.alpha_size = 0;
2825 _this->gl_config.buffer_size = 0;
2826 _this->gl_config.depth_size = 16;
2827 _this->gl_config.stencil_size = 0;
2828 _this->gl_config.double_buffer = 1;
2829 _this->gl_config.accum_red_size = 0;
2830 _this->gl_config.accum_green_size = 0;
2831 _this->gl_config.accum_blue_size = 0;
2832 _this->gl_config.accum_alpha_size = 0;
2833 _this->gl_config.stereo = 0;
2834 _this->gl_config.multisamplebuffers = 0;
2835 _this->gl_config.multisamplesamples = 0;
2836 _this->gl_config.retained_backing = 1;
2837 _this->gl_config.accelerated = -1; /* accelerated or not, both are fine */
2838 _this->gl_config.profile_mask = 0;
2839 #if SDL_VIDEO_OPENGL
2840 _this->gl_config.major_version = 2;
2841 _this->gl_config.minor_version = 1;
2842 #elif SDL_VIDEO_OPENGL_ES2
2843 _this->gl_config.major_version = 2;
2844 _this->gl_config.minor_version = 0;
2845 _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
2846 #elif SDL_VIDEO_OPENGL_ES
2847 _this->gl_config.major_version = 1;
2848 _this->gl_config.minor_version = 1;
2849 _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
2851 _this->gl_config.flags = 0;
2852 _this->gl_config.framebuffer_srgb_capable = 0;
2853 _this->gl_config.release_behavior = SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH;
2855 _this->gl_config.share_with_current_context = 0;
2857 _this->gl_config.context_priority_level = SDL_GL_CONTEXT_PRIORITY_NONE;
2862 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
2864 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2868 return SDL_UninitializedVideo();
2872 case SDL_GL_RED_SIZE:
2873 _this->gl_config.red_size = value;
2875 case SDL_GL_GREEN_SIZE:
2876 _this->gl_config.green_size = value;
2878 case SDL_GL_BLUE_SIZE:
2879 _this->gl_config.blue_size = value;
2881 case SDL_GL_ALPHA_SIZE:
2882 _this->gl_config.alpha_size = value;
2884 case SDL_GL_DOUBLEBUFFER:
2885 _this->gl_config.double_buffer = value;
2887 case SDL_GL_BUFFER_SIZE:
2888 _this->gl_config.buffer_size = value;
2890 case SDL_GL_DEPTH_SIZE:
2891 _this->gl_config.depth_size = value;
2893 case SDL_GL_STENCIL_SIZE:
2894 _this->gl_config.stencil_size = value;
2896 case SDL_GL_ACCUM_RED_SIZE:
2897 _this->gl_config.accum_red_size = value;
2899 case SDL_GL_ACCUM_GREEN_SIZE:
2900 _this->gl_config.accum_green_size = value;
2902 case SDL_GL_ACCUM_BLUE_SIZE:
2903 _this->gl_config.accum_blue_size = value;
2905 case SDL_GL_ACCUM_ALPHA_SIZE:
2906 _this->gl_config.accum_alpha_size = value;
2909 _this->gl_config.stereo = value;
2911 case SDL_GL_MULTISAMPLEBUFFERS:
2912 _this->gl_config.multisamplebuffers = value;
2914 case SDL_GL_MULTISAMPLESAMPLES:
2915 _this->gl_config.multisamplesamples = value;
2917 case SDL_GL_ACCELERATED_VISUAL:
2918 _this->gl_config.accelerated = value;
2920 case SDL_GL_RETAINED_BACKING:
2921 _this->gl_config.retained_backing = value;
2923 case SDL_GL_CONTEXT_MAJOR_VERSION:
2924 _this->gl_config.major_version = value;
2926 case SDL_GL_CONTEXT_MINOR_VERSION:
2927 _this->gl_config.minor_version = value;
2929 case SDL_GL_CONTEXT_EGL:
2930 /* FIXME: SDL_GL_CONTEXT_EGL to be deprecated in SDL 2.1 */
2932 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
2934 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
2937 case SDL_GL_CONTEXT_FLAGS:
2938 if (value & ~(SDL_GL_CONTEXT_DEBUG_FLAG |
2939 SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG |
2940 SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG |
2941 SDL_GL_CONTEXT_RESET_ISOLATION_FLAG)) {
2942 retval = SDL_SetError("Unknown OpenGL context flag %d", value);
2945 _this->gl_config.flags = value;
2947 case SDL_GL_CONTEXT_PROFILE_MASK:
2949 value != SDL_GL_CONTEXT_PROFILE_CORE &&
2950 value != SDL_GL_CONTEXT_PROFILE_COMPATIBILITY &&
2951 value != SDL_GL_CONTEXT_PROFILE_ES) {
2952 retval = SDL_SetError("Unknown OpenGL context profile %d", value);
2955 _this->gl_config.profile_mask = value;
2957 case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
2958 _this->gl_config.share_with_current_context = value;
2960 case SDL_GL_FRAMEBUFFER_SRGB_CAPABLE:
2961 _this->gl_config.framebuffer_srgb_capable = value;
2963 case SDL_GL_CONTEXT_RELEASE_BEHAVIOR:
2964 _this->gl_config.release_behavior = value;
2967 case SDL_GL_CONTEXT_PRIORITY:
2968 _this->gl_config.context_priority_level = value;
2972 retval = SDL_SetError("Unknown OpenGL attribute");
2977 return SDL_Unsupported();
2978 #endif /* SDL_VIDEO_OPENGL */
2982 SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
2984 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2985 GLenum (APIENTRY *glGetErrorFunc) (void);
2990 * Some queries in Core Profile desktop OpenGL 3+ contexts require
2991 * glGetFramebufferAttachmentParameteriv instead of glGetIntegerv. Note that
2992 * the enums we use for the former function don't exist in OpenGL ES 2, and
2993 * the function itself doesn't exist prior to OpenGL 3 and OpenGL ES 2.
2995 #if SDL_VIDEO_OPENGL
2996 const GLubyte *(APIENTRY *glGetStringFunc) (GLenum name);
2997 void (APIENTRY *glGetFramebufferAttachmentParameterivFunc) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
2998 GLenum attachment = GL_BACK_LEFT;
2999 GLenum attachmentattrib = 0;
3002 /* Clear value in any case */
3006 case SDL_GL_RED_SIZE:
3007 #if SDL_VIDEO_OPENGL
3008 attachmentattrib = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
3010 attrib = GL_RED_BITS;
3012 case SDL_GL_BLUE_SIZE:
3013 #if SDL_VIDEO_OPENGL
3014 attachmentattrib = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
3016 attrib = GL_BLUE_BITS;
3018 case SDL_GL_GREEN_SIZE:
3019 #if SDL_VIDEO_OPENGL
3020 attachmentattrib = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
3022 attrib = GL_GREEN_BITS;
3024 case SDL_GL_ALPHA_SIZE:
3025 #if SDL_VIDEO_OPENGL
3026 attachmentattrib = GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
3028 attrib = GL_ALPHA_BITS;
3030 case SDL_GL_DOUBLEBUFFER:
3031 #if SDL_VIDEO_OPENGL
3032 attrib = GL_DOUBLEBUFFER;
3035 /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER */
3036 /* parameter which switches double buffer to single buffer. OpenGL ES */
3037 /* SDL driver must set proper value after initialization */
3038 *value = _this->gl_config.double_buffer;
3041 case SDL_GL_DEPTH_SIZE:
3042 #if SDL_VIDEO_OPENGL
3043 attachment = GL_DEPTH;
3044 attachmentattrib = GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
3046 attrib = GL_DEPTH_BITS;
3048 case SDL_GL_STENCIL_SIZE:
3049 #if SDL_VIDEO_OPENGL
3050 attachment = GL_STENCIL;
3051 attachmentattrib = GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
3053 attrib = GL_STENCIL_BITS;
3055 #if SDL_VIDEO_OPENGL
3056 case SDL_GL_ACCUM_RED_SIZE:
3057 attrib = GL_ACCUM_RED_BITS;
3059 case SDL_GL_ACCUM_GREEN_SIZE:
3060 attrib = GL_ACCUM_GREEN_BITS;
3062 case SDL_GL_ACCUM_BLUE_SIZE:
3063 attrib = GL_ACCUM_BLUE_BITS;
3065 case SDL_GL_ACCUM_ALPHA_SIZE:
3066 attrib = GL_ACCUM_ALPHA_BITS;
3072 case SDL_GL_ACCUM_RED_SIZE:
3073 case SDL_GL_ACCUM_GREEN_SIZE:
3074 case SDL_GL_ACCUM_BLUE_SIZE:
3075 case SDL_GL_ACCUM_ALPHA_SIZE:
3077 /* none of these are supported in OpenGL ES */
3081 case SDL_GL_MULTISAMPLEBUFFERS:
3082 attrib = GL_SAMPLE_BUFFERS;
3084 case SDL_GL_MULTISAMPLESAMPLES:
3085 attrib = GL_SAMPLES;
3087 case SDL_GL_CONTEXT_RELEASE_BEHAVIOR:
3088 #if SDL_VIDEO_OPENGL
3089 attrib = GL_CONTEXT_RELEASE_BEHAVIOR;
3091 attrib = GL_CONTEXT_RELEASE_BEHAVIOR_KHR;
3094 case SDL_GL_BUFFER_SIZE:
3096 int rsize = 0, gsize = 0, bsize = 0, asize = 0;
3098 /* There doesn't seem to be a single flag in OpenGL for this! */
3099 if (SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &rsize) < 0) {
3102 if (SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &gsize) < 0) {
3105 if (SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &bsize) < 0) {
3108 if (SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &asize) < 0) {
3112 *value = rsize + gsize + bsize + asize;
3115 case SDL_GL_ACCELERATED_VISUAL:
3117 /* FIXME: How do we get this information? */
3118 *value = (_this->gl_config.accelerated != 0);
3121 case SDL_GL_RETAINED_BACKING:
3123 *value = _this->gl_config.retained_backing;
3126 case SDL_GL_CONTEXT_MAJOR_VERSION:
3128 *value = _this->gl_config.major_version;
3131 case SDL_GL_CONTEXT_MINOR_VERSION:
3133 *value = _this->gl_config.minor_version;
3136 case SDL_GL_CONTEXT_EGL:
3137 /* FIXME: SDL_GL_CONTEXT_EGL to be deprecated in SDL 2.1 */
3139 if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
3147 case SDL_GL_CONTEXT_FLAGS:
3149 *value = _this->gl_config.flags;
3152 case SDL_GL_CONTEXT_PROFILE_MASK:
3154 *value = _this->gl_config.profile_mask;
3157 case SDL_GL_SHARE_WITH_CURRENT_CONTEXT:
3159 *value = _this->gl_config.share_with_current_context;
3162 case SDL_GL_FRAMEBUFFER_SRGB_CAPABLE:
3164 *value = _this->gl_config.framebuffer_srgb_capable;
3168 case SDL_GL_CONTEXT_PRIORITY:
3170 *value = _this->gl_config.context_priority_level;
3175 return SDL_SetError("Unknown OpenGL attribute");
3178 #if SDL_VIDEO_OPENGL
3179 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
3180 if (!glGetStringFunc) {
3181 return SDL_SetError("Failed getting OpenGL glGetString entry point");
3184 if (attachmentattrib && isAtLeastGL3((const char *) glGetStringFunc(GL_VERSION))) {
3185 glGetFramebufferAttachmentParameterivFunc = SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameteriv");
3187 if (glGetFramebufferAttachmentParameterivFunc) {
3188 glGetFramebufferAttachmentParameterivFunc(GL_FRAMEBUFFER, attachment, attachmentattrib, (GLint *) value);
3190 return SDL_SetError("Failed getting OpenGL glGetFramebufferAttachmentParameteriv entry point");
3195 void (APIENTRY *glGetIntegervFunc) (GLenum pname, GLint * params);
3196 glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
3197 if (glGetIntegervFunc) {
3198 glGetIntegervFunc(attrib, (GLint *) value);
3200 return SDL_SetError("Failed getting OpenGL glGetIntegerv entry point");
3204 glGetErrorFunc = SDL_GL_GetProcAddress("glGetError");
3205 if (!glGetErrorFunc) {
3206 return SDL_SetError("Failed getting OpenGL glGetError entry point");
3209 error = glGetErrorFunc();
3210 if (error != GL_NO_ERROR) {
3211 if (error == GL_INVALID_ENUM) {
3212 return SDL_SetError("OpenGL error: GL_INVALID_ENUM");
3213 } else if (error == GL_INVALID_VALUE) {
3214 return SDL_SetError("OpenGL error: GL_INVALID_VALUE");
3216 return SDL_SetError("OpenGL error: %08X", error);
3220 return SDL_Unsupported();
3221 #endif /* SDL_VIDEO_OPENGL */
3225 SDL_GL_CreateContext(SDL_Window * window)
3227 SDL_GLContext ctx = NULL;
3228 CHECK_WINDOW_MAGIC(window, NULL);
3230 if (!(window->flags & SDL_WINDOW_OPENGL)) {
3231 SDL_SetError("The specified window isn't an OpenGL window");
3235 ctx = _this->GL_CreateContext(_this, window);
3237 /* Creating a context is assumed to make it current in the SDL driver. */
3239 _this->current_glwin = window;
3240 _this->current_glctx = ctx;
3241 SDL_TLSSet(_this->current_glwin_tls, window, NULL);
3242 SDL_TLSSet(_this->current_glctx_tls, ctx, NULL);
3248 SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
3252 if (window == SDL_GL_GetCurrentWindow() &&
3253 ctx == SDL_GL_GetCurrentContext()) {
3254 /* We're already current. */
3259 if ((SDL_GL_ExtensionSupported("EGL_KHR_surfaceless_context")) && (!window)) {
3260 /* current window checking */
3261 SDL_Window* cur_win = SDL_GL_GetCurrentWindow();
3262 if (!ctx) cur_win = NULL;
3263 CHECK_WINDOW_MAGIC(cur_win, -1);
3265 if (!(cur_win->flags & SDL_WINDOW_OPENGL)) {
3266 return SDL_SetError("The specified window isn't an OpenGL window");
3268 retval = _this->GL_MakeCurrent(_this, NULL, ctx);
3270 _this->current_glwin = cur_win;
3271 _this->current_glctx = ctx;
3272 SDL_TLSSet(_this->current_glwin_tls, cur_win, NULL);
3273 SDL_TLSSet(_this->current_glctx_tls, ctx, NULL);
3282 CHECK_WINDOW_MAGIC(window, -1);
3284 if (!(window->flags & SDL_WINDOW_OPENGL)) {
3285 return SDL_SetError("The specified window isn't an OpenGL window");
3289 retval = _this->GL_MakeCurrent(_this, window, ctx);
3291 _this->current_glwin = window;
3292 _this->current_glctx = ctx;
3293 SDL_TLSSet(_this->current_glwin_tls, window, NULL);
3294 SDL_TLSSet(_this->current_glctx_tls, ctx, NULL);
3300 SDL_GL_GetCurrentWindow(void)
3303 SDL_UninitializedVideo();
3306 return (SDL_Window *)SDL_TLSGet(_this->current_glwin_tls);
3310 SDL_GL_GetCurrentContext(void)
3313 SDL_UninitializedVideo();
3316 return (SDL_GLContext)SDL_TLSGet(_this->current_glctx_tls);
3319 void SDL_GL_GetDrawableSize(SDL_Window * window, int *w, int *h)
3321 CHECK_WINDOW_MAGIC(window,);
3323 if (_this->GL_GetDrawableSize) {
3324 _this->GL_GetDrawableSize(_this, window, w, h);
3326 SDL_GetWindowSize(window, w, h);
3331 SDL_GL_SetSwapInterval(int interval)
3334 return SDL_UninitializedVideo();
3335 } else if (SDL_GL_GetCurrentContext() == NULL) {
3336 return SDL_SetError("No OpenGL context has been made current");
3337 } else if (_this->GL_SetSwapInterval) {
3338 return _this->GL_SetSwapInterval(_this, interval);
3340 return SDL_SetError("Setting the swap interval is not supported");
3345 SDL_GL_GetSwapInterval(void)
3349 } else if (SDL_GL_GetCurrentContext() == NULL) {
3351 } else if (_this->GL_GetSwapInterval) {
3352 return _this->GL_GetSwapInterval(_this);
3359 SDL_GL_SwapWindow(SDL_Window * window)
3361 CHECK_WINDOW_MAGIC(window,);
3363 if (!(window->flags & SDL_WINDOW_OPENGL)) {
3364 SDL_SetError("The specified window isn't an OpenGL window");
3368 if (SDL_GL_GetCurrentWindow() != window) {
3369 SDL_SetError("The specified window has not been made current");
3373 _this->GL_SwapWindow(_this, window);
3377 SDL_GL_DeleteContext(SDL_GLContext context)
3379 if (!_this || !context) {
3383 if (SDL_GL_GetCurrentContext() == context) {
3384 SDL_GL_MakeCurrent(NULL, NULL);
3387 _this->GL_DeleteContext(_this, context);
3392 * Utility function used by SDL_WM_SetIcon(); flags & 1 for color key, flags
3393 * & 2 for alpha channel.
3396 CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
3400 #define SET_MASKBIT(icon, x, y, mask) \
3401 mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
3403 colorkey = icon->format->colorkey;
3404 switch (icon->format->BytesPerPixel) {
3408 for (y = 0; y < icon->h; ++y) {
3409 pixels = (Uint8 *) icon->pixels + y * icon->pitch;
3410 for (x = 0; x < icon->w; ++x) {
3411 if (*pixels++ == colorkey) {
3412 SET_MASKBIT(icon, x, y, mask);
3422 for (y = 0; y < icon->h; ++y) {
3423 pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
3424 for (x = 0; x < icon->w; ++x) {
3425 if ((flags & 1) && *pixels == colorkey) {
3426 SET_MASKBIT(icon, x, y, mask);
3427 } else if ((flags & 2)
3428 && (*pixels & icon->format->Amask) == 0) {
3429 SET_MASKBIT(icon, x, y, mask);
3440 for (y = 0; y < icon->h; ++y) {
3441 pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
3442 for (x = 0; x < icon->w; ++x) {
3443 if ((flags & 1) && *pixels == colorkey) {
3444 SET_MASKBIT(icon, x, y, mask);
3445 } else if ((flags & 2)
3446 && (*pixels & icon->format->Amask) == 0) {
3447 SET_MASKBIT(icon, x, y, mask);
3458 * Sets the window manager icon for the display window.
3461 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
3463 if (icon && _this->SetIcon) {
3464 /* Generate a mask if necessary, and create the icon! */
3466 int mask_len = icon->h * (icon->w + 7) / 8;
3468 mask = (Uint8 *) SDL_malloc(mask_len);
3472 SDL_memset(mask, ~0, mask_len);
3473 if (icon->flags & SDL_SRCCOLORKEY)
3475 if (icon->flags & SDL_SRCALPHA)
3478 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
3480 _this->SetIcon(_this, icon, mask);
3483 _this->SetIcon(_this, icon, mask);
3490 SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
3492 CHECK_WINDOW_MAGIC(window, SDL_FALSE);
3495 SDL_InvalidParamError("info");
3498 info->subsystem = SDL_SYSWM_UNKNOWN;
3500 if (!_this->GetWindowWMInfo) {
3504 return (_this->GetWindowWMInfo(_this, window, info));
3508 SDL_StartTextInput(void)
3512 /* First, enable text events */
3513 SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
3514 SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
3516 /* Then show the on-screen keyboard, if any */
3517 window = SDL_GetFocusWindow();
3518 if (window && _this && _this->ShowScreenKeyboard) {
3519 _this->ShowScreenKeyboard(_this, window);
3522 /* Finally start the text input system */
3523 if (_this && _this->StartTextInput) {
3524 _this->StartTextInput(_this);
3529 SDL_IsTextInputActive(void)
3531 return (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE);
3535 SDL_StopTextInput(void)
3539 /* Stop the text input system */
3540 if (_this && _this->StopTextInput) {
3541 _this->StopTextInput(_this);
3544 /* Hide the on-screen keyboard, if any */
3545 window = SDL_GetFocusWindow();
3546 if (window && _this && _this->HideScreenKeyboard) {
3547 _this->HideScreenKeyboard(_this, window);
3550 /* Finally disable text events */
3551 SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
3552 SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
3556 SDL_SetTextInputRect(SDL_Rect *rect)
3558 if (_this && _this->SetTextInputRect) {
3559 _this->SetTextInputRect(_this, rect);
3564 SDL_HasScreenKeyboardSupport(void)
3566 if (_this && _this->HasScreenKeyboardSupport) {
3567 return _this->HasScreenKeyboardSupport(_this);
3573 SDL_IsScreenKeyboardShown(SDL_Window *window)
3575 if (window && _this && _this->IsScreenKeyboardShown) {
3576 return _this->IsScreenKeyboardShown(_this, window);
3581 #if SDL_VIDEO_DRIVER_ANDROID
3582 #include "android/SDL_androidmessagebox.h"
3584 #if SDL_VIDEO_DRIVER_WINDOWS
3585 #include "windows/SDL_windowsmessagebox.h"
3587 #if SDL_VIDEO_DRIVER_WINRT
3588 #include "winrt/SDL_winrtmessagebox.h"
3590 #if SDL_VIDEO_DRIVER_COCOA
3591 #include "cocoa/SDL_cocoamessagebox.h"
3593 #if SDL_VIDEO_DRIVER_UIKIT
3594 #include "uikit/SDL_uikitmessagebox.h"
3596 #if SDL_VIDEO_DRIVER_X11
3597 #include "x11/SDL_x11messagebox.h"
3600 // This function will be unused if none of the above video drivers are present.
3601 SDL_UNUSED static SDL_bool SDL_MessageboxValidForDriver(const SDL_MessageBoxData *messageboxdata, SDL_SYSWM_TYPE drivertype)
3604 SDL_Window *window = messageboxdata->window;
3610 SDL_VERSION(&info.version);
3611 if (!SDL_GetWindowWMInfo(window, &info)) {
3614 return (info.subsystem == drivertype);
3619 SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
3623 SDL_bool relative_mode;
3624 int show_cursor_prev;
3625 SDL_bool mouse_captured;
3626 SDL_Window *current_window;
3628 if (!messageboxdata) {
3629 return SDL_InvalidParamError("messageboxdata");
3632 current_window = SDL_GetKeyboardFocus();
3633 mouse_captured = current_window && ((SDL_GetWindowFlags(current_window) & SDL_WINDOW_MOUSE_CAPTURE) != 0);
3634 relative_mode = SDL_GetRelativeMouseMode();
3635 SDL_CaptureMouse(SDL_FALSE);
3636 SDL_SetRelativeMouseMode(SDL_FALSE);
3637 show_cursor_prev = SDL_ShowCursor(1);
3638 SDL_ResetKeyboard();
3641 buttonid = &dummybutton;
3644 if (_this && _this->ShowMessageBox) {
3645 retval = _this->ShowMessageBox(_this, messageboxdata, buttonid);
3648 /* It's completely fine to call this function before video is initialized */
3649 #if SDL_VIDEO_DRIVER_ANDROID
3651 Android_ShowMessageBox(messageboxdata, buttonid) == 0) {
3655 #if SDL_VIDEO_DRIVER_WINDOWS
3657 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WINDOWS) &&
3658 WIN_ShowMessageBox(messageboxdata, buttonid) == 0) {
3662 #if SDL_VIDEO_DRIVER_WINRT
3664 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WINRT) &&
3665 WINRT_ShowMessageBox(messageboxdata, buttonid) == 0) {
3669 #if SDL_VIDEO_DRIVER_COCOA
3671 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_COCOA) &&
3672 Cocoa_ShowMessageBox(messageboxdata, buttonid) == 0) {
3676 #if SDL_VIDEO_DRIVER_UIKIT
3678 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_UIKIT) &&
3679 UIKit_ShowMessageBox(messageboxdata, buttonid) == 0) {
3683 #if SDL_VIDEO_DRIVER_X11
3685 SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_X11) &&
3686 X11_ShowMessageBox(messageboxdata, buttonid) == 0) {
3691 SDL_SetError("No message system available");
3694 if (current_window) {
3695 SDL_RaiseWindow(current_window);
3696 if (mouse_captured) {
3697 SDL_CaptureMouse(SDL_TRUE);
3701 SDL_ShowCursor(show_cursor_prev);
3702 SDL_SetRelativeMouseMode(relative_mode);
3708 SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window)
3710 SDL_MessageBoxData data;
3711 SDL_MessageBoxButtonData button;
3716 data.message = message;
3717 data.numbuttons = 1;
3718 data.buttons = &button;
3719 data.window = window;
3722 button.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
3723 button.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
3726 return SDL_ShowMessageBox(&data, NULL);
3730 SDL_ShouldAllowTopmost(void)
3732 const char *hint = SDL_GetHint(SDL_HINT_ALLOW_TOPMOST);
3744 SDL_SetWindowHitTest(SDL_Window * window, SDL_HitTest callback, void *userdata)
3746 CHECK_WINDOW_MAGIC(window, -1);
3748 if (!_this->SetWindowHitTest) {
3749 return SDL_Unsupported();
3750 } else if (_this->SetWindowHitTest(window, callback != NULL) == -1) {
3754 window->hit_test = callback;
3755 window->hit_test_data = userdata;
3760 float SDL_ComputeDiagonalDPI(int hpix, int vpix, float hinches, float vinches)
3762 float den2 = hinches * hinches + vinches * vinches;
3763 if ( den2 <= 0.0f ) {
3767 return (float)(SDL_sqrt((double)hpix * (double)hpix + (double)vpix * (double)vpix) /
3768 SDL_sqrt((double)den2));
3772 SDL_Vulkan_GetInstanceExtensions(SDL_Window* window, unsigned int* count, char** names)
3775 SDL_SetError("count ptr is null");
3779 if (!(window->flags & SDL_WINDOW_VULKAN)) {
3780 SDL_SetError("Not setup with SDL_WINDOW_VULKAN flags");
3784 const char *driver = SDL_GetCurrentVideoDriver();
3786 SDL_SetError("Current video driveer is NULL");
3790 return _this->vulkan_GetInstanceExtensions(_this, driver, count, names);
3794 SDL_Vulkan_CreateSurface(SDL_Window* window, SDL_vulkanInstance instance, SDL_vulkanSurface* surface)
3797 SDL_SetError("'window' is null");
3801 if (instance == 0) {
3802 SDL_SetError("'instance' is null");
3806 return _this->vulkan_CreateSurface(_this, window, instance, surface);
3809 /* vi: set ts=4 sw=4 expandtab: */