2 Simple DirectMedia Layer
3 Copyright (C) 1997-2012 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_config.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 "../events/SDL_events_c.h"
34 #include "SDL_opengl.h"
35 #endif /* SDL_VIDEO_OPENGL */
37 #if SDL_VIDEO_OPENGL_ES
38 #include "SDL_opengles.h"
39 #endif /* SDL_VIDEO_OPENGL_ES */
41 #if SDL_VIDEO_OPENGL_ES2
42 #include "SDL_opengles2.h"
43 #endif /* SDL_VIDEO_OPENGL_ES2 */
45 #include "SDL_syswm.h"
47 /* On Windows, windows.h defines CreateWindow */
52 /* Available video drivers */
53 static VideoBootStrap *bootstrap[] = {
54 #if SDL_VIDEO_DRIVER_COCOA
57 #if SDL_VIDEO_DRIVER_X11
60 #if SDL_VIDEO_DRIVER_DIRECTFB
63 #if SDL_VIDEO_DRIVER_WINDOWS
66 #if SDL_VIDEO_DRIVER_BWINDOW
69 #if SDL_VIDEO_DRIVER_PANDORA
72 #if SDL_VIDEO_DRIVER_NDS
75 #if SDL_VIDEO_DRIVER_UIKIT
78 #if SDL_VIDEO_DRIVER_ANDROID
81 #if SDL_VIDEO_DRIVER_DUMMY
87 static SDL_VideoDevice *_this = NULL;
89 #define CHECK_WINDOW_MAGIC(window, retval) \
91 SDL_UninitializedVideo(); \
94 if (!window || window->magic != &_this->window_magic) { \
95 SDL_SetError("Invalid window"); \
99 #define CHECK_DISPLAY_INDEX(displayIndex, retval) \
101 SDL_UninitializedVideo(); \
104 if (displayIndex < 0 || displayIndex >= _this->num_displays) { \
105 SDL_SetError("displayIndex must be in the range 0 - %d", \
106 _this->num_displays - 1); \
110 /* Support for framebuffer emulation using an accelerated renderer */
112 #define SDL_WINDOWTEXTUREDATA "_SDL_WindowTextureData"
115 SDL_Renderer *renderer;
116 SDL_Texture *texture;
120 } SDL_WindowTextureData;
123 ShouldUseTextureFramebuffer()
127 /* If there's no native framebuffer support then there's no option */
128 if (!_this->CreateWindowFramebuffer) {
132 /* If the user has specified a software renderer we can't use a
133 texture framebuffer, or renderer creation will go recursive.
135 hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
136 if (hint && SDL_strcasecmp(hint, "software") == 0) {
140 /* See if the user or application wants a specific behavior */
141 hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
150 /* Each platform has different performance characteristics */
151 #if defined(__WIN32__)
152 /* GDI BitBlt() is way faster than Direct3D dynamic textures right now.
156 #elif defined(__MACOSX__)
157 /* Mac OS X uses OpenGL as the native fast path */
160 #elif defined(__LINUX__)
161 /* Properly configured OpenGL drivers are faster than MIT-SHM */
163 /* Ugh, find a way to cache this value! */
166 SDL_GLContext context;
167 SDL_bool hasAcceleratedOpenGL = SDL_FALSE;
169 window = SDL_CreateWindow("OpenGL test", -32, -32, 32, 32, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
171 context = SDL_GL_CreateContext(window);
173 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
174 const char *vendor = NULL;
176 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
177 if (glGetStringFunc) {
178 vendor = (const char *) glGetStringFunc(GL_VENDOR);
180 /* Add more vendors here at will... */
182 (SDL_strstr(vendor, "ATI Technologies") ||
183 SDL_strstr(vendor, "NVIDIA"))) {
184 hasAcceleratedOpenGL = SDL_TRUE;
186 SDL_GL_DeleteContext(context);
188 SDL_DestroyWindow(window);
190 return hasAcceleratedOpenGL;
192 #elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
193 /* Let's be optimistic about this! */
200 /* Play it safe, assume that if there is a framebuffer driver that it's
201 optimized for the current platform.
208 SDL_CreateWindowTexture(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
210 SDL_WindowTextureData *data;
211 SDL_RendererInfo info;
214 data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
216 SDL_Renderer *renderer = NULL;
217 SDL_RendererInfo info;
219 const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
221 /* Check to see if there's a specific driver requested */
222 if (hint && *hint != '0' && *hint != '1' &&
223 SDL_strcasecmp(hint, "software") != 0) {
224 for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
225 SDL_GetRenderDriverInfo(i, &info);
226 if (SDL_strcasecmp(info.name, hint) == 0) {
227 renderer = SDL_CreateRenderer(window, i, 0);
234 for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
235 SDL_GetRenderDriverInfo(i, &info);
236 if (SDL_strcmp(info.name, "software") != 0) {
237 renderer = SDL_CreateRenderer(window, i, 0);
245 SDL_SetError("No hardware accelerated renderers available");
249 /* Create the data after we successfully create the renderer (bug #1116) */
250 data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
252 SDL_DestroyRenderer(renderer);
256 SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
258 data->renderer = renderer;
261 /* Free any old texture and pixel data */
263 SDL_DestroyTexture(data->texture);
264 data->texture = NULL;
267 SDL_free(data->pixels);
271 if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
275 /* Find the first format without an alpha channel */
276 *format = info.texture_formats[0];
277 for (i = 0; i < info.num_texture_formats; ++i) {
278 if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
279 !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
280 *format = info.texture_formats[i];
285 data->texture = SDL_CreateTexture(data->renderer, *format,
286 SDL_TEXTUREACCESS_STREAMING,
287 window->w, window->h);
288 if (!data->texture) {
292 /* Create framebuffer data */
293 data->bytes_per_pixel = SDL_BYTESPERPIXEL(*format);
294 data->pitch = (((window->w * data->bytes_per_pixel) + 3) & ~3);
295 data->pixels = SDL_malloc(window->h * data->pitch);
301 *pixels = data->pixels;
302 *pitch = data->pitch;
304 /* Make sure we're not double-scaling the viewport */
305 SDL_RenderSetViewport(data->renderer, NULL);
311 SDL_UpdateWindowTexture(_THIS, SDL_Window * window, SDL_Rect * rects, int numrects)
313 SDL_WindowTextureData *data;
317 data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
318 if (!data || !data->texture) {
319 SDL_SetError("No window texture data");
323 /* Update a single rect that contains subrects for best DMA performance */
324 if (SDL_GetSpanEnclosingRect(window->w, window->h, numrects, rects, &rect)) {
325 src = (void *)((Uint8 *)data->pixels +
326 rect.y * data->pitch +
327 rect.x * data->bytes_per_pixel);
328 if (SDL_UpdateTexture(data->texture, &rect, src, data->pitch) < 0) {
332 if (SDL_RenderCopy(data->renderer, data->texture, NULL, NULL) < 0) {
336 SDL_RenderPresent(data->renderer);
342 SDL_DestroyWindowTexture(_THIS, SDL_Window * window)
344 SDL_WindowTextureData *data;
346 data = SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, NULL);
351 SDL_DestroyTexture(data->texture);
353 if (data->renderer) {
354 SDL_DestroyRenderer(data->renderer);
357 SDL_free(data->pixels);
364 cmpmodes(const void *A, const void *B)
366 SDL_DisplayMode a = *(const SDL_DisplayMode *) A;
367 SDL_DisplayMode b = *(const SDL_DisplayMode *) B;
375 if (SDL_BITSPERPIXEL(a.format) != SDL_BITSPERPIXEL(b.format)) {
376 return SDL_BITSPERPIXEL(b.format) - SDL_BITSPERPIXEL(a.format);
378 if (SDL_PIXELLAYOUT(a.format) != SDL_PIXELLAYOUT(b.format)) {
379 return SDL_PIXELLAYOUT(b.format) - SDL_PIXELLAYOUT(a.format);
381 if (a.refresh_rate != b.refresh_rate) {
382 return b.refresh_rate - a.refresh_rate;
388 SDL_UninitializedVideo()
390 SDL_SetError("Video subsystem has not been initialized");
394 SDL_GetNumVideoDrivers(void)
396 return SDL_arraysize(bootstrap) - 1;
400 SDL_GetVideoDriver(int index)
402 if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
403 return bootstrap[index]->name;
409 * Initialize the video and event subsystems -- determine native pixel format
412 SDL_VideoInit(const char *driver_name)
414 SDL_VideoDevice *video;
418 /* Check to make sure we don't overwrite '_this' */
423 /* Start the event loop */
424 if (SDL_StartEventLoop() < 0 ||
425 SDL_KeyboardInit() < 0 ||
426 SDL_MouseInit() < 0 ||
427 SDL_TouchInit() < 0 ||
428 SDL_QuitInit() < 0) {
432 /* Select the proper video driver */
435 if (driver_name == NULL) {
436 driver_name = SDL_getenv("SDL_VIDEODRIVER");
438 if (driver_name != NULL) {
439 for (i = 0; bootstrap[i]; ++i) {
440 if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
441 video = bootstrap[i]->create(index);
446 for (i = 0; bootstrap[i]; ++i) {
447 if (bootstrap[i]->available()) {
448 video = bootstrap[i]->create(index);
457 SDL_SetError("%s not available", driver_name);
459 SDL_SetError("No available video device");
464 _this->name = bootstrap[i]->name;
465 _this->next_object_id = 1;
468 /* Set some very sane GL defaults */
469 _this->gl_config.driver_loaded = 0;
470 _this->gl_config.dll_handle = NULL;
471 _this->gl_config.red_size = 3;
472 _this->gl_config.green_size = 3;
473 _this->gl_config.blue_size = 2;
474 _this->gl_config.alpha_size = 0;
475 _this->gl_config.buffer_size = 0;
476 _this->gl_config.depth_size = 16;
477 _this->gl_config.stencil_size = 0;
478 _this->gl_config.double_buffer = 1;
479 _this->gl_config.accum_red_size = 0;
480 _this->gl_config.accum_green_size = 0;
481 _this->gl_config.accum_blue_size = 0;
482 _this->gl_config.accum_alpha_size = 0;
483 _this->gl_config.stereo = 0;
484 _this->gl_config.multisamplebuffers = 0;
485 _this->gl_config.multisamplesamples = 0;
486 _this->gl_config.retained_backing = 1;
487 _this->gl_config.accelerated = -1; /* accelerated or not, both are fine */
489 _this->gl_config.major_version = 2;
490 _this->gl_config.minor_version = 1;
491 #elif SDL_VIDEO_OPENGL_ES
492 _this->gl_config.major_version = 1;
493 _this->gl_config.minor_version = 1;
494 #elif SDL_VIDEO_OPENGL_ES2
495 _this->gl_config.major_version = 2;
496 _this->gl_config.minor_version = 0;
499 /* Initialize the video subsystem */
500 if (_this->VideoInit(_this) < 0) {
505 /* Make sure some displays were added */
506 if (_this->num_displays == 0) {
507 SDL_SetError("The video driver did not add any displays");
512 /* Add the renderer framebuffer emulation if desired */
513 if (ShouldUseTextureFramebuffer()) {
514 _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
515 _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
516 _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
519 /* We're ready to go! */
524 SDL_GetCurrentVideoDriver()
527 SDL_UninitializedVideo();
534 SDL_GetVideoDevice(void)
540 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
542 SDL_VideoDisplay display;
546 display.desktop_mode = *desktop_mode;
548 display.current_mode = display.desktop_mode;
550 return SDL_AddVideoDisplay(&display);
554 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
556 SDL_VideoDisplay *displays;
560 SDL_realloc(_this->displays,
561 (_this->num_displays + 1) * sizeof(*displays));
563 index = _this->num_displays++;
564 displays[index] = *display;
565 displays[index].device = _this;
566 _this->displays = displays;
574 SDL_GetNumVideoDisplays(void)
577 SDL_UninitializedVideo();
580 return _this->num_displays;
584 SDL_GetIndexOfDisplay(SDL_VideoDisplay *display)
588 for (displayIndex = 0; displayIndex < _this->num_displays; ++displayIndex) {
589 if (display == &_this->displays[displayIndex]) {
594 /* Couldn't find the display, just use index 0 */
599 SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
601 CHECK_DISPLAY_INDEX(displayIndex, -1);
604 SDL_VideoDisplay *display = &_this->displays[displayIndex];
606 if (_this->GetDisplayBounds) {
607 if (_this->GetDisplayBounds(_this, display, rect) == 0) {
612 /* Assume that the displays are left to right */
613 if (displayIndex == 0) {
617 SDL_GetDisplayBounds(displayIndex-1, rect);
620 rect->w = display->desktop_mode.w;
621 rect->h = display->desktop_mode.h;
627 SDL_AddDisplayMode(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
629 SDL_DisplayMode *modes;
632 /* Make sure we don't already have the mode in the list */
633 modes = display->display_modes;
634 nmodes = display->num_display_modes;
635 for (i = nmodes; i--;) {
636 if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) {
641 /* Go ahead and add the new mode */
642 if (nmodes == display->max_display_modes) {
645 (display->max_display_modes + 32) * sizeof(*modes));
649 display->display_modes = modes;
650 display->max_display_modes += 32;
652 modes[nmodes] = *mode;
653 display->num_display_modes++;
655 /* Re-sort video modes */
656 SDL_qsort(display->display_modes, display->num_display_modes,
657 sizeof(SDL_DisplayMode), cmpmodes);
663 SDL_GetNumDisplayModesForDisplay(SDL_VideoDisplay * display)
665 if (!display->num_display_modes && _this->GetDisplayModes) {
666 _this->GetDisplayModes(_this, display);
667 SDL_qsort(display->display_modes, display->num_display_modes,
668 sizeof(SDL_DisplayMode), cmpmodes);
670 return display->num_display_modes;
674 SDL_GetNumDisplayModes(int displayIndex)
676 CHECK_DISPLAY_INDEX(displayIndex, -1);
678 return SDL_GetNumDisplayModesForDisplay(&_this->displays[displayIndex]);
682 SDL_GetDisplayMode(int displayIndex, int index, SDL_DisplayMode * mode)
684 SDL_VideoDisplay *display;
686 CHECK_DISPLAY_INDEX(displayIndex, -1);
688 display = &_this->displays[displayIndex];
689 if (index < 0 || index >= SDL_GetNumDisplayModesForDisplay(display)) {
690 SDL_SetError("index must be in the range of 0 - %d",
691 SDL_GetNumDisplayModesForDisplay(display) - 1);
695 *mode = display->display_modes[index];
701 SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode)
703 SDL_VideoDisplay *display;
705 CHECK_DISPLAY_INDEX(displayIndex, -1);
707 display = &_this->displays[displayIndex];
709 *mode = display->desktop_mode;
715 SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode)
717 SDL_VideoDisplay *display;
719 CHECK_DISPLAY_INDEX(displayIndex, -1);
721 display = &_this->displays[displayIndex];
723 *mode = display->current_mode;
728 static SDL_DisplayMode *
729 SDL_GetClosestDisplayModeForDisplay(SDL_VideoDisplay * display,
730 const SDL_DisplayMode * mode,
731 SDL_DisplayMode * closest)
733 Uint32 target_format;
734 int target_refresh_rate;
736 SDL_DisplayMode *current, *match;
738 if (!mode || !closest) {
739 SDL_SetError("Missing desired mode or closest mode parameter");
743 /* Default to the desktop format */
745 target_format = mode->format;
747 target_format = display->desktop_mode.format;
750 /* Default to the desktop refresh rate */
751 if (mode->refresh_rate) {
752 target_refresh_rate = mode->refresh_rate;
754 target_refresh_rate = display->desktop_mode.refresh_rate;
758 for (i = 0; i < SDL_GetNumDisplayModesForDisplay(display); ++i) {
759 current = &display->display_modes[i];
761 if (current->w && (current->w < mode->w)) {
762 /* Out of sorted modes large enough here */
765 if (current->h && (current->h < mode->h)) {
766 if (current->w && (current->w == mode->w)) {
767 /* Out of sorted modes large enough here */
770 /* Wider, but not tall enough, due to a different
771 aspect ratio. This mode must be skipped, but closer
772 modes may still follow. */
775 if (!match || current->w < match->w || current->h < match->h) {
779 if (current->format != match->format) {
780 /* Sorted highest depth to lowest */
781 if (current->format == target_format ||
782 (SDL_BITSPERPIXEL(current->format) >=
783 SDL_BITSPERPIXEL(target_format)
784 && SDL_PIXELTYPE(current->format) ==
785 SDL_PIXELTYPE(target_format))) {
790 if (current->refresh_rate != match->refresh_rate) {
791 /* Sorted highest refresh to lowest */
792 if (current->refresh_rate >= target_refresh_rate) {
799 closest->format = match->format;
801 closest->format = mode->format;
803 if (match->w && match->h) {
804 closest->w = match->w;
805 closest->h = match->h;
807 closest->w = mode->w;
808 closest->h = mode->h;
810 if (match->refresh_rate) {
811 closest->refresh_rate = match->refresh_rate;
813 closest->refresh_rate = mode->refresh_rate;
815 closest->driverdata = match->driverdata;
818 * Pick some reasonable defaults if the app and driver don't
821 if (!closest->format) {
822 closest->format = SDL_PIXELFORMAT_RGB888;
836 SDL_GetClosestDisplayMode(int displayIndex,
837 const SDL_DisplayMode * mode,
838 SDL_DisplayMode * closest)
840 SDL_VideoDisplay *display;
842 CHECK_DISPLAY_INDEX(displayIndex, NULL);
844 display = &_this->displays[displayIndex];
845 return SDL_GetClosestDisplayModeForDisplay(display, mode, closest);
849 SDL_SetDisplayModeForDisplay(SDL_VideoDisplay * display, const SDL_DisplayMode * mode)
851 SDL_DisplayMode display_mode;
852 SDL_DisplayMode current_mode;
855 display_mode = *mode;
857 /* Default to the current mode */
858 if (!display_mode.format) {
859 display_mode.format = display->current_mode.format;
861 if (!display_mode.w) {
862 display_mode.w = display->current_mode.w;
864 if (!display_mode.h) {
865 display_mode.h = display->current_mode.h;
867 if (!display_mode.refresh_rate) {
868 display_mode.refresh_rate = display->current_mode.refresh_rate;
871 /* Get a good video mode, the closest one possible */
872 if (!SDL_GetClosestDisplayModeForDisplay(display, &display_mode, &display_mode)) {
873 SDL_SetError("No video mode large enough for %dx%d",
874 display_mode.w, display_mode.h);
878 display_mode = display->desktop_mode;
881 /* See if there's anything left to do */
882 current_mode = display->current_mode;
883 if (SDL_memcmp(&display_mode, ¤t_mode, sizeof(display_mode)) == 0) {
887 /* Actually change the display mode */
888 if (!_this->SetDisplayMode) {
889 SDL_SetError("Video driver doesn't support changing display mode");
892 if (_this->SetDisplayMode(_this, display, &display_mode) < 0) {
895 display->current_mode = display_mode;
900 SDL_GetWindowDisplay(SDL_Window * window)
905 int closest_dist = 0x7FFFFFFF;
910 CHECK_WINDOW_MAGIC(window, -1);
912 if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
913 SDL_WINDOWPOS_ISCENTERED(window->x)) {
914 displayIndex = (window->x & 0xFFFF);
915 if (displayIndex >= _this->num_displays) {
920 if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
921 SDL_WINDOWPOS_ISCENTERED(window->y)) {
922 displayIndex = (window->y & 0xFFFF);
923 if (displayIndex >= _this->num_displays) {
929 /* Find the display containing the window */
930 center.x = window->x + window->w / 2;
931 center.y = window->y + window->h / 2;
932 for (i = 0; i < _this->num_displays; ++i) {
933 SDL_VideoDisplay *display = &_this->displays[i];
935 SDL_GetDisplayBounds(i, &rect);
936 if (display->fullscreen_window == window || SDL_EnclosePoints(¢er, 1, &rect, NULL)) {
940 delta.x = center.x - (rect.x + rect.w / 2);
941 delta.y = center.y - (rect.y + rect.h / 2);
942 dist = (delta.x*delta.x + delta.y*delta.y);
943 if (dist < closest_dist) {
949 SDL_SetError("Couldn't find any displays");
955 SDL_GetDisplayForWindow(SDL_Window *window)
957 int displayIndex = SDL_GetWindowDisplay(window);
958 if (displayIndex >= 0) {
959 return &_this->displays[displayIndex];
966 SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
968 CHECK_WINDOW_MAGIC(window, -1);
971 window->fullscreen_mode = *mode;
973 SDL_zero(window->fullscreen_mode);
979 SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
981 SDL_DisplayMode fullscreen_mode;
983 CHECK_WINDOW_MAGIC(window, -1);
985 fullscreen_mode = window->fullscreen_mode;
986 if (!fullscreen_mode.w) {
987 fullscreen_mode.w = window->w;
989 if (!fullscreen_mode.h) {
990 fullscreen_mode.h = window->h;
993 if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
996 SDL_SetError("Couldn't find display mode match");
1001 *mode = fullscreen_mode;
1007 SDL_GetWindowPixelFormat(SDL_Window * window)
1009 SDL_VideoDisplay *display;
1011 CHECK_WINDOW_MAGIC(window, SDL_PIXELFORMAT_UNKNOWN);
1013 display = SDL_GetDisplayForWindow(window);
1014 return display->current_mode.format;
1018 SDL_RestoreMousePosition(SDL_Window *window)
1022 if (window == SDL_GetMouseFocus()) {
1023 SDL_GetMouseState(&x, &y);
1024 SDL_WarpMouseInWindow(window, x, y);
1029 SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
1031 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1035 /* Hide any other fullscreen windows */
1036 if (display->fullscreen_window &&
1037 display->fullscreen_window != window) {
1038 SDL_MinimizeWindow(display->fullscreen_window);
1042 /* See if anything needs to be done now */
1043 if ((display->fullscreen_window == window) == fullscreen) {
1047 /* See if there are any fullscreen windows */
1048 for (other = _this->windows; other; other = other->next) {
1049 SDL_bool setDisplayMode = SDL_FALSE;
1051 if (other == window) {
1052 setDisplayMode = fullscreen;
1053 } else if (FULLSCREEN_VISIBLE(other) &&
1054 SDL_GetDisplayForWindow(other) == display) {
1055 setDisplayMode = SDL_TRUE;
1058 if (setDisplayMode) {
1059 SDL_DisplayMode fullscreen_mode;
1061 if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
1062 SDL_bool resized = SDL_TRUE;
1064 if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
1065 resized = SDL_FALSE;
1068 SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
1069 if (_this->SetWindowFullscreen) {
1070 _this->SetWindowFullscreen(_this, other, display, SDL_TRUE);
1072 display->fullscreen_window = other;
1074 /* Generate a mode change event here */
1076 SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
1077 fullscreen_mode.w, fullscreen_mode.h);
1079 SDL_OnWindowResized(other);
1082 SDL_RestoreMousePosition(other);
1088 /* Nope, restore the desktop mode */
1089 SDL_SetDisplayModeForDisplay(display, NULL);
1091 if (_this->SetWindowFullscreen) {
1092 _this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
1094 display->fullscreen_window = NULL;
1096 /* Generate a mode change event here */
1097 SDL_OnWindowResized(window);
1099 /* Restore the cursor position */
1100 SDL_RestoreMousePosition(window);
1103 #define CREATE_FLAGS \
1104 (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE)
1107 SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
1109 window->windowed.x = window->x;
1110 window->windowed.y = window->y;
1111 window->windowed.w = window->w;
1112 window->windowed.h = window->h;
1114 if (flags & SDL_WINDOW_MAXIMIZED) {
1115 SDL_MaximizeWindow(window);
1117 if (flags & SDL_WINDOW_MINIMIZED) {
1118 SDL_MinimizeWindow(window);
1120 if (flags & SDL_WINDOW_FULLSCREEN) {
1121 SDL_SetWindowFullscreen(window, SDL_TRUE);
1123 if (flags & SDL_WINDOW_INPUT_GRABBED) {
1124 SDL_SetWindowGrab(window, SDL_TRUE);
1126 if (!(flags & SDL_WINDOW_HIDDEN)) {
1127 SDL_ShowWindow(window);
1132 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
1137 /* Initialize the video system if needed */
1138 if (SDL_VideoInit(NULL) < 0) {
1143 /* Some platforms have OpenGL enabled by default */
1144 #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__
1145 flags |= SDL_WINDOW_OPENGL;
1147 if (flags & SDL_WINDOW_OPENGL) {
1148 if (!_this->GL_CreateContext) {
1149 SDL_SetError("No OpenGL support in video driver");
1152 SDL_GL_LoadLibrary(NULL);
1154 window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
1155 window->magic = &_this->window_magic;
1156 window->id = _this->next_object_id++;
1161 if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
1162 SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
1163 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1167 displayIndex = SDL_GetIndexOfDisplay(display);
1168 SDL_GetDisplayBounds(displayIndex, &bounds);
1169 if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
1170 window->x = bounds.x + (bounds.w - w) / 2;
1172 if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
1173 window->y = bounds.y + (bounds.h - h) / 2;
1176 window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
1177 window->brightness = 1.0f;
1178 window->next = _this->windows;
1179 if (_this->windows) {
1180 _this->windows->prev = window;
1182 _this->windows = window;
1184 if (_this->CreateWindow && _this->CreateWindow(_this, window) < 0) {
1185 SDL_DestroyWindow(window);
1190 SDL_SetWindowTitle(window, title);
1192 SDL_FinishWindowCreation(window, flags);
1194 /* If the window was created fullscreen, make sure the mode code matches */
1195 SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
1201 SDL_CreateWindowFrom(const void *data)
1206 SDL_UninitializedVideo();
1209 window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
1210 window->magic = &_this->window_magic;
1211 window->id = _this->next_object_id++;
1212 window->flags = SDL_WINDOW_FOREIGN;
1213 window->brightness = 1.0f;
1214 window->next = _this->windows;
1215 if (_this->windows) {
1216 _this->windows->prev = window;
1218 _this->windows = window;
1220 if (!_this->CreateWindowFrom ||
1221 _this->CreateWindowFrom(_this, window, data) < 0) {
1222 SDL_DestroyWindow(window);
1229 SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
1231 char *title = window->title;
1233 if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
1234 SDL_SetError("No OpenGL support in video driver");
1238 if (window->flags & SDL_WINDOW_FOREIGN) {
1239 /* Can't destroy and re-create foreign windows, hrm */
1240 flags |= SDL_WINDOW_FOREIGN;
1242 flags &= ~SDL_WINDOW_FOREIGN;
1245 /* Restore video mode, etc. */
1246 SDL_HideWindow(window);
1248 /* Tear down the old native window */
1249 if (window->surface) {
1250 window->surface->flags &= ~SDL_DONTFREE;
1251 SDL_FreeSurface(window->surface);
1253 if (_this->DestroyWindowFramebuffer) {
1254 _this->DestroyWindowFramebuffer(_this, window);
1256 if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1257 _this->DestroyWindow(_this, window);
1260 if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
1261 if (flags & SDL_WINDOW_OPENGL) {
1262 SDL_GL_LoadLibrary(NULL);
1264 SDL_GL_UnloadLibrary();
1268 window->title = NULL;
1269 window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
1271 if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) {
1272 if (_this->CreateWindow(_this, window) < 0) {
1273 if (flags & SDL_WINDOW_OPENGL) {
1274 SDL_GL_UnloadLibrary();
1281 SDL_SetWindowTitle(window, title);
1284 SDL_FinishWindowCreation(window, flags);
1290 SDL_GetWindowID(SDL_Window * window)
1292 CHECK_WINDOW_MAGIC(window, 0);
1298 SDL_GetWindowFromID(Uint32 id)
1305 for (window = _this->windows; window; window = window->next) {
1306 if (window->id == id) {
1314 SDL_GetWindowFlags(SDL_Window * window)
1316 CHECK_WINDOW_MAGIC(window, 0);
1318 return window->flags;
1322 SDL_SetWindowTitle(SDL_Window * window, const char *title)
1324 CHECK_WINDOW_MAGIC(window, );
1326 if (title == window->title) {
1329 if (window->title) {
1330 SDL_free(window->title);
1332 if (title && *title) {
1333 window->title = SDL_strdup(title);
1335 window->title = NULL;
1338 if (_this->SetWindowTitle) {
1339 _this->SetWindowTitle(_this, window);
1344 SDL_GetWindowTitle(SDL_Window * window)
1346 CHECK_WINDOW_MAGIC(window, "");
1348 return window->title ? window->title : "";
1352 SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon)
1354 CHECK_WINDOW_MAGIC(window, );
1360 if (_this->SetWindowIcon) {
1361 _this->SetWindowIcon(_this, window, icon);
1366 SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata)
1368 SDL_WindowUserData *prev, *data;
1370 CHECK_WINDOW_MAGIC(window, NULL);
1372 /* See if the named data already exists */
1374 for (data = window->data; data; prev = data, data = data->next) {
1375 if (SDL_strcmp(data->name, name) == 0) {
1376 void *last_value = data->data;
1379 /* Set the new value */
1380 data->data = userdata;
1382 /* Delete this value */
1384 prev->next = data->next;
1386 window->data = data->next;
1388 SDL_free(data->name);
1395 /* Add new data to the window */
1397 data = (SDL_WindowUserData *)SDL_malloc(sizeof(*data));
1398 data->name = SDL_strdup(name);
1399 data->data = userdata;
1400 data->next = window->data;
1401 window->data = data;
1407 SDL_GetWindowData(SDL_Window * window, const char *name)
1409 SDL_WindowUserData *data;
1411 CHECK_WINDOW_MAGIC(window, NULL);
1413 for (data = window->data; data; data = data->next) {
1414 if (SDL_strcmp(data->name, name) == 0) {
1422 SDL_SetWindowPosition(SDL_Window * window, int x, int y)
1424 CHECK_WINDOW_MAGIC(window, );
1426 if (!SDL_WINDOWPOS_ISUNDEFINED(x)) {
1429 if (!SDL_WINDOWPOS_ISUNDEFINED(y)) {
1432 if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
1433 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1437 displayIndex = SDL_GetIndexOfDisplay(display);
1438 SDL_GetDisplayBounds(displayIndex, &bounds);
1439 if (SDL_WINDOWPOS_ISCENTERED(x)) {
1440 window->x = bounds.x + (bounds.w - window->w) / 2;
1442 if (SDL_WINDOWPOS_ISCENTERED(y)) {
1443 window->y = bounds.y + (bounds.h - window->h) / 2;
1446 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1447 if (_this->SetWindowPosition) {
1448 _this->SetWindowPosition(_this, window);
1450 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
1455 SDL_GetWindowPosition(SDL_Window * window, int *x, int *y)
1457 /* Clear the values */
1465 CHECK_WINDOW_MAGIC(window, );
1467 /* Fullscreen windows are always at their display's origin */
1468 if (window->flags & SDL_WINDOW_FULLSCREEN) {
1480 SDL_SetWindowSize(SDL_Window * window, int w, int h)
1482 CHECK_WINDOW_MAGIC(window, );
1484 /* FIXME: Should this change fullscreen modes? */
1485 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1488 if (_this->SetWindowSize) {
1489 _this->SetWindowSize(_this, window);
1491 if (window->w == w && window->h == h) {
1492 /* We didn't get a SDL_WINDOWEVENT_RESIZED event (by design) */
1493 SDL_OnWindowResized(window);
1499 SDL_GetWindowSize(SDL_Window * window, int *w, int *h)
1513 CHECK_WINDOW_MAGIC(window, );
1515 if (_this && window && window->magic == &_this->window_magic) {
1533 SDL_ShowWindow(SDL_Window * window)
1535 CHECK_WINDOW_MAGIC(window, );
1537 if (window->flags & SDL_WINDOW_SHOWN) {
1541 if (_this->ShowWindow) {
1542 _this->ShowWindow(_this, window);
1544 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
1548 SDL_HideWindow(SDL_Window * window)
1550 CHECK_WINDOW_MAGIC(window, );
1552 if (!(window->flags & SDL_WINDOW_SHOWN)) {
1556 SDL_UpdateFullscreenMode(window, SDL_FALSE);
1558 if (_this->HideWindow) {
1559 _this->HideWindow(_this, window);
1561 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
1565 SDL_RaiseWindow(SDL_Window * window)
1567 CHECK_WINDOW_MAGIC(window, );
1569 if (!(window->flags & SDL_WINDOW_SHOWN)) {
1572 if (_this->RaiseWindow) {
1573 _this->RaiseWindow(_this, window);
1578 SDL_MaximizeWindow(SDL_Window * window)
1580 CHECK_WINDOW_MAGIC(window, );
1582 if (window->flags & SDL_WINDOW_MAXIMIZED) {
1586 if (_this->MaximizeWindow) {
1587 _this->MaximizeWindow(_this, window);
1592 SDL_MinimizeWindow(SDL_Window * window)
1594 CHECK_WINDOW_MAGIC(window, );
1596 if (window->flags & SDL_WINDOW_MINIMIZED) {
1600 SDL_UpdateFullscreenMode(window, SDL_FALSE);
1602 if (_this->MinimizeWindow) {
1603 _this->MinimizeWindow(_this, window);
1608 SDL_RestoreWindow(SDL_Window * window)
1610 CHECK_WINDOW_MAGIC(window, );
1612 if (!(window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
1616 if (_this->RestoreWindow) {
1617 _this->RestoreWindow(_this, window);
1622 SDL_SetWindowFullscreen(SDL_Window * window, SDL_bool fullscreen)
1624 CHECK_WINDOW_MAGIC(window, -1);
1626 if (!!fullscreen == !!(window->flags & SDL_WINDOW_FULLSCREEN)) {
1630 window->flags |= SDL_WINDOW_FULLSCREEN;
1632 window->flags &= ~SDL_WINDOW_FULLSCREEN;
1634 SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
1639 static SDL_Surface *
1640 SDL_CreateWindowFramebuffer(SDL_Window * window)
1646 Uint32 Rmask, Gmask, Bmask, Amask;
1648 if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
1652 if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
1656 if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
1660 return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
1664 SDL_GetWindowSurface(SDL_Window * window)
1666 CHECK_WINDOW_MAGIC(window, NULL);
1668 if (!window->surface_valid) {
1669 if (window->surface) {
1670 window->surface->flags &= ~SDL_DONTFREE;
1671 SDL_FreeSurface(window->surface);
1673 window->surface = SDL_CreateWindowFramebuffer(window);
1674 if (window->surface) {
1675 window->surface_valid = SDL_TRUE;
1676 window->surface->flags |= SDL_DONTFREE;
1679 return window->surface;
1683 SDL_UpdateWindowSurface(SDL_Window * window)
1687 CHECK_WINDOW_MAGIC(window, -1);
1691 full_rect.w = window->w;
1692 full_rect.h = window->h;
1693 return SDL_UpdateWindowSurfaceRects(window, &full_rect, 1);
1697 SDL_UpdateWindowSurfaceRects(SDL_Window * window, SDL_Rect * rects,
1700 CHECK_WINDOW_MAGIC(window, -1);
1702 if (!window->surface_valid) {
1703 SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
1707 return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
1711 SDL_SetWindowBrightness(SDL_Window * window, float brightness)
1716 CHECK_WINDOW_MAGIC(window, -1);
1718 SDL_CalculateGammaRamp(brightness, ramp);
1719 status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
1721 window->brightness = brightness;
1727 SDL_GetWindowBrightness(SDL_Window * window)
1729 CHECK_WINDOW_MAGIC(window, 1.0f);
1731 return window->brightness;
1735 SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
1736 const Uint16 * green,
1737 const Uint16 * blue)
1739 CHECK_WINDOW_MAGIC(window, -1);
1741 if (!_this->SetWindowGammaRamp) {
1746 if (!window->gamma) {
1747 if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
1753 SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
1756 SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
1759 SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
1761 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
1762 return _this->SetWindowGammaRamp(_this, window, window->gamma);
1769 SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
1773 CHECK_WINDOW_MAGIC(window, -1);
1775 if (!window->gamma) {
1778 window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
1779 if (!window->gamma) {
1783 window->saved_gamma = window->gamma + 3*256;
1785 if (_this->GetWindowGammaRamp) {
1786 if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
1790 /* Create an identity gamma ramp */
1791 for (i = 0; i < 256; ++i) {
1792 Uint16 value = (Uint16)((i << 8) | i);
1794 window->gamma[0*256+i] = value;
1795 window->gamma[1*256+i] = value;
1796 window->gamma[2*256+i] = value;
1799 SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
1803 SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
1806 SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
1809 SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
1815 SDL_UpdateWindowGrab(SDL_Window * window)
1817 if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) {
1818 _this->SetWindowGrab(_this, window);
1823 SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
1825 CHECK_WINDOW_MAGIC(window, );
1827 if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
1831 window->flags |= SDL_WINDOW_INPUT_GRABBED;
1833 window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
1835 SDL_UpdateWindowGrab(window);
1839 SDL_GetWindowGrab(SDL_Window * window)
1841 CHECK_WINDOW_MAGIC(window, SDL_FALSE);
1843 return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
1847 SDL_OnWindowShown(SDL_Window * window)
1849 SDL_OnWindowRestored(window);
1853 SDL_OnWindowHidden(SDL_Window * window)
1855 SDL_UpdateFullscreenMode(window, SDL_FALSE);
1859 SDL_OnWindowResized(SDL_Window * window)
1861 window->surface_valid = SDL_FALSE;
1862 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
1866 SDL_OnWindowMinimized(SDL_Window * window)
1868 SDL_UpdateFullscreenMode(window, SDL_FALSE);
1872 SDL_OnWindowRestored(SDL_Window * window)
1874 SDL_RaiseWindow(window);
1876 if (FULLSCREEN_VISIBLE(window)) {
1877 SDL_UpdateFullscreenMode(window, SDL_TRUE);
1882 SDL_OnWindowFocusGained(SDL_Window * window)
1884 if (window->gamma && _this->SetWindowGammaRamp) {
1885 _this->SetWindowGammaRamp(_this, window, window->gamma);
1888 if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN)) &&
1889 _this->SetWindowGrab) {
1890 _this->SetWindowGrab(_this, window);
1895 SDL_OnWindowFocusLost(SDL_Window * window)
1897 if (window->gamma && _this->SetWindowGammaRamp) {
1898 _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
1901 if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN)) &&
1902 _this->SetWindowGrab) {
1903 _this->SetWindowGrab(_this, window);
1906 /* If we're fullscreen on a single-head system and lose focus, minimize */
1907 if ((window->flags & SDL_WINDOW_FULLSCREEN) && _this->num_displays == 1) {
1908 SDL_MinimizeWindow(window);
1913 SDL_GetFocusWindow(void)
1920 for (window = _this->windows; window; window = window->next) {
1921 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
1929 SDL_DestroyWindow(SDL_Window * window)
1931 SDL_VideoDisplay *display;
1933 CHECK_WINDOW_MAGIC(window, );
1935 /* Restore video mode, etc. */
1936 SDL_HideWindow(window);
1938 /* Make sure this window no longer has focus */
1939 if (SDL_GetKeyboardFocus() == window) {
1940 SDL_SetKeyboardFocus(NULL);
1942 if (SDL_GetMouseFocus() == window) {
1943 SDL_SetMouseFocus(NULL);
1946 /* make no context current if this is the current context window. */
1947 if (window->flags & SDL_WINDOW_OPENGL) {
1948 if (_this->current_glwin == window) {
1949 SDL_GL_MakeCurrent(NULL, NULL);
1953 if (window->surface) {
1954 window->surface->flags &= ~SDL_DONTFREE;
1955 SDL_FreeSurface(window->surface);
1957 if (_this->DestroyWindowFramebuffer) {
1958 _this->DestroyWindowFramebuffer(_this, window);
1960 if (_this->DestroyWindow) {
1961 _this->DestroyWindow(_this, window);
1963 if (window->flags & SDL_WINDOW_OPENGL) {
1964 SDL_GL_UnloadLibrary();
1967 display = SDL_GetDisplayForWindow(window);
1968 if (display->fullscreen_window == window) {
1969 display->fullscreen_window = NULL;
1972 /* Now invalidate magic */
1973 window->magic = NULL;
1975 /* Free memory associated with the window */
1976 if (window->title) {
1977 SDL_free(window->title);
1979 if (window->gamma) {
1980 SDL_free(window->gamma);
1982 while (window->data) {
1983 SDL_WindowUserData *data = window->data;
1985 window->data = data->next;
1986 SDL_free(data->name);
1990 /* Unlink the window from the list */
1992 window->next->prev = window->prev;
1995 window->prev->next = window->next;
1997 _this->windows = window->next;
2004 SDL_IsScreenSaverEnabled()
2009 return _this->suspend_screensaver ? SDL_FALSE : SDL_TRUE;
2013 SDL_EnableScreenSaver()
2018 if (!_this->suspend_screensaver) {
2021 _this->suspend_screensaver = SDL_FALSE;
2022 if (_this->SuspendScreenSaver) {
2023 _this->SuspendScreenSaver(_this);
2028 SDL_DisableScreenSaver()
2033 if (_this->suspend_screensaver) {
2036 _this->suspend_screensaver = SDL_TRUE;
2037 if (_this->SuspendScreenSaver) {
2038 _this->SuspendScreenSaver(_this);
2051 /* Halt event processing before doing anything else */
2055 SDL_StopEventLoop();
2057 SDL_EnableScreenSaver();
2059 /* Clean up the system video */
2060 while (_this->windows) {
2061 SDL_DestroyWindow(_this->windows);
2063 _this->VideoQuit(_this);
2065 for (i = _this->num_displays; i--;) {
2066 SDL_VideoDisplay *display = &_this->displays[i];
2067 for (j = display->num_display_modes; j--;) {
2068 if (display->display_modes[j].driverdata) {
2069 SDL_free(display->display_modes[j].driverdata);
2070 display->display_modes[j].driverdata = NULL;
2073 if (display->display_modes) {
2074 SDL_free(display->display_modes);
2075 display->display_modes = NULL;
2077 if (display->desktop_mode.driverdata) {
2078 SDL_free(display->desktop_mode.driverdata);
2079 display->desktop_mode.driverdata = NULL;
2081 if (display->driverdata) {
2082 SDL_free(display->driverdata);
2083 display->driverdata = NULL;
2086 if (_this->displays) {
2087 SDL_free(_this->displays);
2088 _this->displays = NULL;
2090 if (_this->clipboard_text) {
2091 SDL_free(_this->clipboard_text);
2092 _this->clipboard_text = NULL;
2099 SDL_GL_LoadLibrary(const char *path)
2104 SDL_UninitializedVideo();
2107 if (_this->gl_config.driver_loaded) {
2108 if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) {
2109 SDL_SetError("OpenGL library already loaded");
2114 if (!_this->GL_LoadLibrary) {
2115 SDL_SetError("No dynamic GL support in video driver");
2118 retval = _this->GL_LoadLibrary(_this, path);
2121 ++_this->gl_config.driver_loaded;
2127 SDL_GL_GetProcAddress(const char *proc)
2132 SDL_UninitializedVideo();
2136 if (_this->GL_GetProcAddress) {
2137 if (_this->gl_config.driver_loaded) {
2138 func = _this->GL_GetProcAddress(_this, proc);
2140 SDL_SetError("No GL driver has been loaded");
2143 SDL_SetError("No dynamic GL support in video driver");
2149 SDL_GL_UnloadLibrary(void)
2152 SDL_UninitializedVideo();
2155 if (_this->gl_config.driver_loaded > 0) {
2156 if (--_this->gl_config.driver_loaded > 0) {
2159 if (_this->GL_UnloadLibrary) {
2160 _this->GL_UnloadLibrary(_this);
2166 SDL_GL_ExtensionSupported(const char *extension)
2168 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2169 const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
2170 const char *extensions;
2172 const char *where, *terminator;
2174 /* Extension names should not have spaces. */
2175 where = SDL_strchr(extension, ' ');
2176 if (where || *extension == '\0') {
2179 /* See if there's an environment variable override */
2180 start = SDL_getenv(extension);
2181 if (start && *start == '0') {
2184 /* Lookup the available extensions */
2185 glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
2186 if (glGetStringFunc) {
2187 extensions = (const char *) glGetStringFunc(GL_EXTENSIONS);
2195 * It takes a bit of care to be fool-proof about parsing the OpenGL
2196 * extensions string. Don't be fooled by sub-strings, etc.
2202 where = SDL_strstr(start, extension);
2206 terminator = where + SDL_strlen(extension);
2207 if (where == start || *(where - 1) == ' ')
2208 if (*terminator == ' ' || *terminator == '\0')
2220 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
2222 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2226 SDL_UninitializedVideo();
2231 case SDL_GL_RED_SIZE:
2232 _this->gl_config.red_size = value;
2234 case SDL_GL_GREEN_SIZE:
2235 _this->gl_config.green_size = value;
2237 case SDL_GL_BLUE_SIZE:
2238 _this->gl_config.blue_size = value;
2240 case SDL_GL_ALPHA_SIZE:
2241 _this->gl_config.alpha_size = value;
2243 case SDL_GL_DOUBLEBUFFER:
2244 _this->gl_config.double_buffer = value;
2246 case SDL_GL_BUFFER_SIZE:
2247 _this->gl_config.buffer_size = value;
2249 case SDL_GL_DEPTH_SIZE:
2250 _this->gl_config.depth_size = value;
2252 case SDL_GL_STENCIL_SIZE:
2253 _this->gl_config.stencil_size = value;
2255 case SDL_GL_ACCUM_RED_SIZE:
2256 _this->gl_config.accum_red_size = value;
2258 case SDL_GL_ACCUM_GREEN_SIZE:
2259 _this->gl_config.accum_green_size = value;
2261 case SDL_GL_ACCUM_BLUE_SIZE:
2262 _this->gl_config.accum_blue_size = value;
2264 case SDL_GL_ACCUM_ALPHA_SIZE:
2265 _this->gl_config.accum_alpha_size = value;
2268 _this->gl_config.stereo = value;
2270 case SDL_GL_MULTISAMPLEBUFFERS:
2271 _this->gl_config.multisamplebuffers = value;
2273 case SDL_GL_MULTISAMPLESAMPLES:
2274 _this->gl_config.multisamplesamples = value;
2276 case SDL_GL_ACCELERATED_VISUAL:
2277 _this->gl_config.accelerated = value;
2279 case SDL_GL_RETAINED_BACKING:
2280 _this->gl_config.retained_backing = value;
2282 case SDL_GL_CONTEXT_MAJOR_VERSION:
2283 _this->gl_config.major_version = value;
2285 case SDL_GL_CONTEXT_MINOR_VERSION:
2286 _this->gl_config.minor_version = value;
2289 SDL_SetError("Unknown OpenGL attribute");
2297 #endif /* SDL_VIDEO_OPENGL */
2301 SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
2303 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2304 void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
2305 GLenum(APIENTRY * glGetErrorFunc) (void);
2309 glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
2310 if (!glGetIntegervFunc) {
2314 glGetErrorFunc = SDL_GL_GetProcAddress("glGetError");
2315 if (!glGetErrorFunc) {
2319 /* Clear value in any case */
2323 case SDL_GL_RED_SIZE:
2324 attrib = GL_RED_BITS;
2326 case SDL_GL_BLUE_SIZE:
2327 attrib = GL_BLUE_BITS;
2329 case SDL_GL_GREEN_SIZE:
2330 attrib = GL_GREEN_BITS;
2332 case SDL_GL_ALPHA_SIZE:
2333 attrib = GL_ALPHA_BITS;
2335 case SDL_GL_DOUBLEBUFFER:
2336 #if SDL_VIDEO_OPENGL
2337 attrib = GL_DOUBLEBUFFER;
2340 /* OpenGL ES 1.0 and above specifications have EGL_SINGLE_BUFFER */
2341 /* parameter which switches double buffer to single buffer. OpenGL ES */
2342 /* SDL driver must set proper value after initialization */
2343 *value = _this->gl_config.double_buffer;
2346 case SDL_GL_DEPTH_SIZE:
2347 attrib = GL_DEPTH_BITS;
2349 case SDL_GL_STENCIL_SIZE:
2350 attrib = GL_STENCIL_BITS;
2352 #if SDL_VIDEO_OPENGL
2353 case SDL_GL_ACCUM_RED_SIZE:
2354 attrib = GL_ACCUM_RED_BITS;
2356 case SDL_GL_ACCUM_GREEN_SIZE:
2357 attrib = GL_ACCUM_GREEN_BITS;
2359 case SDL_GL_ACCUM_BLUE_SIZE:
2360 attrib = GL_ACCUM_BLUE_BITS;
2362 case SDL_GL_ACCUM_ALPHA_SIZE:
2363 attrib = GL_ACCUM_ALPHA_BITS;
2369 case SDL_GL_ACCUM_RED_SIZE:
2370 case SDL_GL_ACCUM_GREEN_SIZE:
2371 case SDL_GL_ACCUM_BLUE_SIZE:
2372 case SDL_GL_ACCUM_ALPHA_SIZE:
2374 /* none of these are supported in OpenGL ES */
2378 case SDL_GL_MULTISAMPLEBUFFERS:
2379 #if SDL_VIDEO_OPENGL
2380 attrib = GL_SAMPLE_BUFFERS_ARB;
2382 attrib = GL_SAMPLE_BUFFERS;
2385 case SDL_GL_MULTISAMPLESAMPLES:
2386 #if SDL_VIDEO_OPENGL
2387 attrib = GL_SAMPLES_ARB;
2389 attrib = GL_SAMPLES;
2392 case SDL_GL_BUFFER_SIZE:
2398 * there doesn't seem to be a single flag in OpenGL
2401 glGetIntegervFunc(GL_RED_BITS, &component);
2403 glGetIntegervFunc(GL_GREEN_BITS, &component);
2405 glGetIntegervFunc(GL_BLUE_BITS, &component);
2407 glGetIntegervFunc(GL_ALPHA_BITS, &component);
2413 case SDL_GL_ACCELERATED_VISUAL:
2415 /* FIXME: How do we get this information? */
2416 *value = (_this->gl_config.accelerated != 0);
2419 case SDL_GL_RETAINED_BACKING:
2421 *value = _this->gl_config.retained_backing;
2424 case SDL_GL_CONTEXT_MAJOR_VERSION:
2426 *value = _this->gl_config.major_version;
2429 case SDL_GL_CONTEXT_MINOR_VERSION:
2431 *value = _this->gl_config.minor_version;
2435 SDL_SetError("Unknown OpenGL attribute");
2439 glGetIntegervFunc(attrib, (GLint *) value);
2440 error = glGetErrorFunc();
2441 if (error != GL_NO_ERROR) {
2443 case GL_INVALID_ENUM:
2445 SDL_SetError("OpenGL error: GL_INVALID_ENUM");
2448 case GL_INVALID_VALUE:
2450 SDL_SetError("OpenGL error: GL_INVALID_VALUE");
2455 SDL_SetError("OpenGL error: %08X", error);
2465 #endif /* SDL_VIDEO_OPENGL */
2469 SDL_GL_CreateContext(SDL_Window * window)
2471 SDL_GLContext ctx = NULL;
2472 CHECK_WINDOW_MAGIC(window, NULL);
2474 if (!(window->flags & SDL_WINDOW_OPENGL)) {
2475 SDL_SetError("The specified window isn't an OpenGL window");
2479 ctx = _this->GL_CreateContext(_this, window);
2481 /* Creating a context is assumed to make it current in the SDL driver. */
2482 _this->current_glwin = window;
2483 _this->current_glctx = ctx;
2489 SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
2493 CHECK_WINDOW_MAGIC(window, -1);
2495 if (!(window->flags & SDL_WINDOW_OPENGL)) {
2496 SDL_SetError("The specified window isn't an OpenGL window");
2503 if ((window == _this->current_glwin) && (ctx == _this->current_glctx)) {
2504 retval = 0; /* we're already current. */
2506 retval = _this->GL_MakeCurrent(_this, window, ctx);
2508 _this->current_glwin = window;
2509 _this->current_glctx = ctx;
2517 SDL_GL_SetSwapInterval(int interval)
2520 SDL_UninitializedVideo();
2522 } else if (_this->current_glctx == NULL) {
2523 SDL_SetError("No OpenGL context has been made current");
2525 } else if (_this->GL_SetSwapInterval) {
2526 return _this->GL_SetSwapInterval(_this, interval);
2528 SDL_SetError("Setting the swap interval is not supported");
2534 SDL_GL_GetSwapInterval(void)
2537 SDL_UninitializedVideo();
2539 } else if (_this->current_glctx == NULL) {
2540 SDL_SetError("No OpenGL context has been made current");
2542 } else if (_this->GL_GetSwapInterval) {
2543 return _this->GL_GetSwapInterval(_this);
2545 SDL_SetError("Getting the swap interval is not supported");
2551 SDL_GL_SwapWindow(SDL_Window * window)
2553 CHECK_WINDOW_MAGIC(window, );
2555 if (!(window->flags & SDL_WINDOW_OPENGL)) {
2556 SDL_SetError("The specified window isn't an OpenGL window");
2559 _this->GL_SwapWindow(_this, window);
2563 SDL_GL_DeleteContext(SDL_GLContext context)
2565 if (!_this || !_this->gl_data || !context) {
2568 _this->GL_MakeCurrent(_this, NULL, NULL);
2569 _this->GL_DeleteContext(_this, context);
2574 * Utility function used by SDL_WM_SetIcon(); flags & 1 for color key, flags
2575 * & 2 for alpha channel.
2578 CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
2582 #define SET_MASKBIT(icon, x, y, mask) \
2583 mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
2585 colorkey = icon->format->colorkey;
2586 switch (icon->format->BytesPerPixel) {
2590 for (y = 0; y < icon->h; ++y) {
2591 pixels = (Uint8 *) icon->pixels + y * icon->pitch;
2592 for (x = 0; x < icon->w; ++x) {
2593 if (*pixels++ == colorkey) {
2594 SET_MASKBIT(icon, x, y, mask);
2604 for (y = 0; y < icon->h; ++y) {
2605 pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
2606 for (x = 0; x < icon->w; ++x) {
2607 if ((flags & 1) && *pixels == colorkey) {
2608 SET_MASKBIT(icon, x, y, mask);
2609 } else if ((flags & 2)
2610 && (*pixels & icon->format->Amask) == 0) {
2611 SET_MASKBIT(icon, x, y, mask);
2622 for (y = 0; y < icon->h; ++y) {
2623 pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
2624 for (x = 0; x < icon->w; ++x) {
2625 if ((flags & 1) && *pixels == colorkey) {
2626 SET_MASKBIT(icon, x, y, mask);
2627 } else if ((flags & 2)
2628 && (*pixels & icon->format->Amask) == 0) {
2629 SET_MASKBIT(icon, x, y, mask);
2640 * Sets the window manager icon for the display window.
2643 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
2645 if (icon && _this->SetIcon) {
2646 /* Generate a mask if necessary, and create the icon! */
2648 int mask_len = icon->h * (icon->w + 7) / 8;
2650 mask = (Uint8 *) SDL_malloc(mask_len);
2654 SDL_memset(mask, ~0, mask_len);
2655 if (icon->flags & SDL_SRCCOLORKEY)
2657 if (icon->flags & SDL_SRCALPHA)
2660 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
2662 _this->SetIcon(_this, icon, mask);
2665 _this->SetIcon(_this, icon, mask);
2672 SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
2674 CHECK_WINDOW_MAGIC(window, SDL_FALSE);
2679 info->subsystem = SDL_SYSWM_UNKNOWN;
2681 if (!_this->GetWindowWMInfo) {
2684 return (_this->GetWindowWMInfo(_this, window, info));
2688 SDL_StartTextInput(void)
2690 if (_this && _this->StartTextInput) {
2691 _this->StartTextInput(_this);
2693 SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
2694 SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
2698 SDL_StopTextInput(void)
2700 if (_this && _this->StopTextInput) {
2701 _this->StopTextInput(_this);
2703 SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
2704 SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
2708 SDL_SetTextInputRect(SDL_Rect *rect)
2710 if (_this && _this->SetTextInputRect) {
2711 _this->SetTextInputRect(_this, rect);
2715 /* vi: set ts=4 sw=4 expandtab: */