21 #include "../SDL_internal.h"
31 #include "../events/SDL_events_c.h"
32 #include "../timer/SDL_timer_c.h"
40 #if SDL_VIDEO_OPENGL_ES
45 #if SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL
50 #ifndef GL_CONTEXT_RELEASE_BEHAVIOR_KHR
51 #define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
56 #include <emscripten.h>
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_KMSDRM
103 #if SDL_VIDEO_DRIVER_RPI
106 #if SDL_VIDEO_DRIVER_NACL
109 #if SDL_VIDEO_DRIVER_EMSCRIPTEN
112 #if SDL_VIDEO_DRIVER_QNX
115 #if SDL_VIDEO_DRIVER_DUMMY
123 #define CHECK_WINDOW_MAGIC(window, retval) \
125 SDL_UninitializedVideo(); \
128 SDL_assert(window && window->magic == &_this->window_magic); \
129 if (!window || window->magic != &_this->window_magic) { \
130 SDL_SetError("Invalid window"); \
134 #define CHECK_DISPLAY_INDEX(displayIndex, retval) \
136 SDL_UninitializedVideo(); \
139 SDL_assert(_this->displays != NULL); \
140 SDL_assert(displayIndex >= 0 && displayIndex < _this->num_displays); \
141 if (displayIndex < 0 || displayIndex >= _this->num_displays) { \
142 SDL_SetError("displayIndex must be in the range 0 - %d", \
143 _this->num_displays - 1); \
147 #define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN)
158 #define SDL_WINDOWTEXTUREDATA "_SDL_WindowTextureData"
202 #if defined(__WIN32__)
207 #elif defined(__MACOSX__)
211 #elif defined(__LINUX__)
225 const char *vendor =
NULL;
228 if (glGetStringFunc) {
229 vendor = (
const char *) glGetStringFunc(
GL_VENDOR);
241 return hasAcceleratedOpenGL;
243 #elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
270 if (hint && *hint !=
'0' && *hint !=
'1' &&
297 return SDL_SetError(
"No hardware accelerated renderers available");
341 window->
w, window->
h);
352 const size_t allocsize = window->
h * data->
pitch;
360 *pitch = data->
pitch;
425 }
else if (a->
w != b->
w) {
427 }
else if (a->
h != b->
h) {
442 return SDL_SetError(
"Video subsystem has not been initialized");
475 #if !SDL_TIMERS_DISABLED
490 if (driver_name ==
NULL) {
493 if (driver_name !=
NULL) {
494 for (i = 0; bootstrap[
i]; ++
i) {
497 video = bootstrap[
i]->
create(index);
503 for (i = 0; bootstrap[
i]; ++
i) {
505 video = bootstrap[
i]->
create(index);
540 return SDL_SetError(
"The video driver did not add any displays");
616 displays[
index] = *display;
649 for (displayIndex = 0; displayIndex < _this->
num_displays; ++displayIndex) {
650 if (display == &_this->
displays[displayIndex]) {
690 if (displayIndex == 0) {
729 display = &_this->
displays[displayIndex];
732 if (_this->
GetDisplayDPI(_this, display, ddpi, hdpi, vdpi) == 0) {
749 display = &_this->
displays[displayIndex];
762 for (i = 0; i < nmodes; ++
i) {
763 if (
cmpmodes(mode, &modes[i]) == 0) {
779 modes[nmodes] = *
mode;
815 display = &_this->
displays[displayIndex];
817 return SDL_SetError(
"index must be in the range of 0 - %d",
833 display = &_this->
displays[displayIndex];
847 display = &_this->
displays[displayIndex];
860 int target_refresh_rate;
864 if (!mode || !closest) {
865 SDL_SetError(
"Missing desired mode or closest mode parameter");
871 target_format = mode->
format;
887 if (current->
w && (current->
w < mode->
w)) {
891 if (current->
h && (current->
h < mode->
h)) {
892 if (current->
w && (current->
w == mode->
w)) {
901 if (!match || current->
w < match->
w || current->
h < match->
h) {
907 if (current->
format == target_format ||
929 if (match->
w && match->
h) {
930 closest->
w = match->
w;
931 closest->
h = match->
h;
933 closest->
w = mode->
w;
934 closest->
h = mode->
h;
970 display = &_this->
displays[displayIndex];
981 display_mode = *
mode;
984 if (!display_mode.
format) {
987 if (!display_mode.
w) {
990 if (!display_mode.
h) {
999 return SDL_SetError(
"No video mode large enough for %dx%d",
1000 display_mode.
w, display_mode.
h);
1008 if (
SDL_memcmp(&display_mode, ¤t_mode,
sizeof(display_mode)) == 0) {
1014 return SDL_SetError(
"SDL video driver doesn't support changing display mode");
1028 return &_this->
displays[displayIndex];
1037 int closest_dist = 0x7FFFFFFF;
1046 displayIndex = (window->
x & 0xFFFF);
1050 return displayIndex;
1054 displayIndex = (window->
y & 0xFFFF);
1058 return displayIndex;
1069 center.
x = window->
x + window->
w / 2;
1070 center.
y = window->
y + window->
h / 2;
1077 delta.
x = center.
x - (rect.
x + rect.
w / 2);
1078 delta.
y = center.
y - (rect.
y + rect.
h / 2);
1079 dist = (delta.
x*delta.
x + delta.
y*delta.
y);
1080 if (dist < closest_dist) {
1082 closest_dist = dist;
1095 if (displayIndex >= 0) {
1096 return &_this->
displays[displayIndex];
1135 if (!fullscreen_mode.
w) {
1138 if (!fullscreen_mode.
h) {
1149 &fullscreen_mode)) {
1150 return SDL_SetError(
"Couldn't find display mode match");
1154 *mode = fullscreen_mode;
1208 if (!Cocoa_SetWindowFullscreenSpace(window,
SDL_FALSE)) {
1219 if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
1220 if (Cocoa_IsWindowInFullscreenSpace(window) != fullscreen) {
1227 #elif __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
1271 for (other = _this->
windows; other; other = other->
next) {
1274 if (other == window) {
1275 setDisplayMode = fullscreen;
1281 if (setDisplayMode) {
1289 if (other->
w == fullscreen_mode.
w && other->
h == fullscreen_mode.
h) {
1318 fullscreen_mode.
w, fullscreen_mode.
h);
1350 #define CREATE_FLAGS \
1351 (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED)
1379 for (window = _this->
windows; window; window = window->
next) {
1433 if ((w > 16384) || (h > 16384)) {
1439 #if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
1446 SDL_SetError(
"OpenGL support is either not configured in SDL "
1447 "or not available in current SDL video driver "
1448 "(%s) or platform", _this->
name);
1456 if (flags & SDL_WINDOW_VULKAN) {
1458 SDL_SetError(
"Vulkan support is either not configured in SDL "
1459 "or not available in current SDL video driver "
1460 "(%s) or platform", _this->
name);
1463 if (flags & SDL_WINDOW_OPENGL) {
1464 SDL_SetError(
"Vulkan and OpenGL not supported on same window");
1477 flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
1501 window->
x = bounds.
x + (bounds.
w -
w) / 2;
1504 window->
y = bounds.
y + (bounds.
h -
h) / 2;
1520 window->
x = bounds.
x;
1521 window->
y = bounds.
y;
1522 window->
w = bounds.
w;
1523 window->
h = bounds.
h;
1546 #if !defined(__WIN32__)
1552 #if __WINRT__ && (NTDDI_VERSION < NTDDI_WIN10)
1561 flags = window->
flags;
1622 return SDL_SetError(
"OpenGL support is either not configured in SDL "
1623 "or not available in current SDL video driver "
1624 "(%s) or platform", _this->
name);
1650 if ((window->
flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
1651 if (flags & SDL_WINDOW_OPENGL) {
1662 SDL_SetError(
"Can't change SDL_WINDOW_VULKAN window flag");
1666 if ((window->
flags & SDL_WINDOW_VULKAN) && (flags & SDL_WINDOW_OPENGL)) {
1667 SDL_SetError(
"Vulkan and OpenGL not supported on same window");
1677 if (loaded_opengl) {
1679 window->
flags &= ~SDL_WINDOW_OPENGL;
1685 if (flags & SDL_WINDOW_FOREIGN) {
1728 for (window = _this->
windows; window; window = window->
next) {
1729 if (window->
id ==
id) {
1741 return window->
flags;
1749 if (title == window->
title) {
1782 if (!window->
icon) {
1799 if (name ==
NULL || name[0] ==
'\0') {
1806 for (data = window->
data; data; prev = data, data = data->
next) {
1808 void *last_value = data->
data;
1812 data->
data = userdata;
1831 data->
data = userdata;
1846 if (name ==
NULL || name[0] ==
'\0') {
1851 for (data = window->
data; data; data = data->
next) {
1865 int displayIndex = (x & 0xFFFF);
1875 x = bounds.
x + (bounds.
w - window->
w) / 2;
1878 y = bounds.
y + (bounds.
h - window->
h) / 2;
1923 if (displayIndex >= 0) {
1951 const int want = (bordered !=
SDL_FALSE);
1969 const int want = (resizable !=
SDL_FALSE);
2023 if (window->
w == w && window->
h == h) {
2047 if (!top) { top = &dummy; }
2048 if (!left) { left = &dummy; }
2049 if (!right) { right = &dummy; }
2050 if (!bottom) { bottom = &dummy; }
2053 *top = *left = *bottom = *right = 0;
2077 if ((window->
max_w && min_w >= window->
max_w) ||
2079 SDL_SetError(
"SDL_SetWindowMinimumSize(): Tried to set minimum size larger than maximum size");
2083 window->
min_w = min_w;
2084 window->
min_h = min_h;
2100 *min_w = window->
min_w;
2103 *min_h = window->
min_h;
2120 if (max_w <= window->min_w || max_h <= window->min_h) {
2121 SDL_SetError(
"SDL_SetWindowMaximumSize(): Tried to set maximum size smaller than minimum size");
2125 window->
max_w = max_w;
2126 window->
max_h = max_h;
2142 *max_w = window->
max_w;
2145 *max_h = window->
max_h;
2264 window->
flags |= oldflags;
2275 Uint32 Rmask, Gmask, Bmask, Amask;
2320 full_rect.
w = window->
w;
2321 full_rect.
h = window->
h;
2332 return SDL_SetError(
"Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
2372 if (opacity < 0.0
f) {
2374 }
else if (opacity > 1.0
f) {
2392 *out_opacity = window->
opacity;
2435 if (!window->
gamma) {
2465 if (!window->
gamma) {
2469 if (!window->
gamma) {
2480 for (i = 0; i < 256; ++
i) {
2517 if (grabbed_window && (grabbed_window != window)) {
2525 }
else if (grabbed_window == window) {
2645 if (Cocoa_IsWindowInFullscreenSpace(window)) {
2678 for (window = _this->
windows; window; window = window->
next) {
2742 while (window->
data) {
2867 return SDL_SetError(
"No dynamic GL support in current SDL video driver (%s)", _this->
name);
2898 SDL_SetError(
"No dynamic GL support in current SDL video driver (%s)", _this->
name);
2920 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2924 return (verstr && (
SDL_atoi(verstr) >= 3));
2931 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
2933 const char *extensions;
2935 const char *where, *terminator;
2939 if (where || *extension ==
'\0') {
2944 if (start && *start ==
'0') {
2951 if (!glGetStringFunc) {
2963 if ((!glGetStringiFunc) || (!glGetIntegervFunc)) {
2967 #ifndef GL_NUM_EXTENSIONS
2968 #define GL_NUM_EXTENSIONS 0x821D
2971 for (i = 0; i < num_exts; i++) {
2972 const char *thisext = (
const char *) glGetStringiFunc(
GL_EXTENSIONS, i);
3000 if (where == extensions || *(where - 1) ==
' ')
3001 if (*terminator ==
' ' || *terminator ==
'\0')
3023 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
3073 #if SDL_VIDEO_OPENGL
3077 #elif SDL_VIDEO_OPENGL_ES2
3081 #elif SDL_VIDEO_OPENGL_ES
3100 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
3178 retval =
SDL_SetError(
"Unknown OpenGL context flag %d", value);
3188 retval =
SDL_SetError(
"Unknown OpenGL context profile %d", value);
3221 #if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
3232 #if SDL_VIDEO_OPENGL
3236 GLenum attachmentattrib = 0;
3252 #if SDL_VIDEO_OPENGL
3258 #if SDL_VIDEO_OPENGL
3264 #if SDL_VIDEO_OPENGL
3270 #if SDL_VIDEO_OPENGL
3276 #if SDL_VIDEO_OPENGL
3287 #if SDL_VIDEO_OPENGL
3294 #if SDL_VIDEO_OPENGL
3300 #if SDL_VIDEO_OPENGL
3333 #if SDL_VIDEO_OPENGL
3341 int rsize = 0, gsize = 0, bsize = 0, asize = 0;
3357 *value = rsize + gsize + bsize + asize;
3421 #if SDL_VIDEO_OPENGL
3423 if (!glGetStringFunc) {
3428 glGetFramebufferAttachmentParameterivFunc =
SDL_GL_GetProcAddress(
"glGetFramebufferAttachmentParameteriv");
3430 if (glGetFramebufferAttachmentParameterivFunc) {
3431 glGetFramebufferAttachmentParameterivFunc(
GL_FRAMEBUFFER, attachment, attachmentattrib, (
GLint *) value);
3440 if (glGetIntegervFunc) {
3441 glGetIntegervFunc(attrib, (
GLint *) value);
3448 if (!glGetErrorFunc) {
3452 error = glGetErrorFunc();
3474 SDL_SetError(
"The specified window isn't an OpenGL window");
3507 return SDL_SetError(
"The specified window isn't an OpenGL window");
3558 return SDL_SetError(
"No OpenGL context has been made current");
3562 return SDL_SetError(
"Setting the swap interval is not supported");
3586 SDL_SetError(
"The specified window isn't an OpenGL window");
3591 SDL_SetError(
"The specified window has not been made current");
3601 if (!_this || !context) {
3622 #define SET_MASKBIT(icon, x, y, mask) \
3623 mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
3625 colorkey = icon->
format->colorkey;
3630 for (y = 0; y < icon->
h; ++
y) {
3632 for (x = 0; x < icon->
w; ++
x) {
3633 if (*pixels++ == colorkey) {
3634 SET_MASKBIT(icon, x, y, mask);
3644 for (y = 0; y < icon->
h; ++
y) {
3646 for (x = 0; x < icon->
w; ++
x) {
3647 if ((flags & 1) && *pixels == colorkey) {
3648 SET_MASKBIT(icon, x, y, mask);
3649 }
else if ((flags & 2)
3651 SET_MASKBIT(icon, x, y, mask);
3662 for (y = 0; y < icon->
h; ++
y) {
3664 for (x = 0; x < icon->
w; ++
x) {
3665 if ((flags & 1) && *pixels == colorkey) {
3666 SET_MASKBIT(icon, x, y, mask);
3667 }
else if ((flags & 2)
3669 SET_MASKBIT(icon, x, y, mask);
3685 if (icon && _this->SetIcon) {
3688 int mask_len = icon->
h * (icon->
w + 7) / 8;
3695 if (icon->
flags & SDL_SRCCOLORKEY)
3697 if (icon->
flags & SDL_SRCALPHA)
3700 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
3702 _this->SetIcon(_this, icon, mask);
3705 _this->SetIcon(_this, icon, mask);
3803 #if SDL_VIDEO_DRIVER_ANDROID
3806 #if SDL_VIDEO_DRIVER_WINDOWS
3809 #if SDL_VIDEO_DRIVER_WINRT
3812 #if SDL_VIDEO_DRIVER_COCOA
3815 #if SDL_VIDEO_DRIVER_UIKIT
3818 #if SDL_VIDEO_DRIVER_X11
3823 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11
3848 int show_cursor_prev;
3852 if (!messageboxdata) {
3867 buttonid = &dummybutton;
3875 #if SDL_VIDEO_DRIVER_ANDROID
3877 Android_ShowMessageBox(messageboxdata, buttonid) == 0) {
3881 #if SDL_VIDEO_DRIVER_WINDOWS
3884 WIN_ShowMessageBox(messageboxdata, buttonid) == 0) {
3888 #if SDL_VIDEO_DRIVER_WINRT
3891 WINRT_ShowMessageBox(messageboxdata, buttonid) == 0) {
3895 #if SDL_VIDEO_DRIVER_COCOA
3898 Cocoa_ShowMessageBox(messageboxdata, buttonid) == 0) {
3902 #if SDL_VIDEO_DRIVER_UIKIT
3905 UIKit_ShowMessageBox(messageboxdata, buttonid) == 0) {
3909 #if SDL_VIDEO_DRIVER_X11
3912 X11_ShowMessageBox(messageboxdata, buttonid) == 0) {
3920 if (current_window) {
3922 if (mouse_captured) {
3936 #ifdef __EMSCRIPTEN__
3942 alert(UTF8ToString($0) +
"\n\n" + UTF8ToString($1));
3992 float den2 = hinches * hinches + vinches * vinches;
3997 return (
float)(
SDL_sqrt((
double)hpix * (
double)hpix + (
double)vpix * (
double)vpix) /
4018 for (window = _this->
windows; window !=
NULL; window = window->
next) {
4042 for (window = _this->
windows; window !=
NULL; window = window->
next) {
4049 #define NOT_A_VULKAN_WINDOW "The specified window isn't a Vulkan window"
4060 return SDL_SetError(
"Vulkan loader library already loaded");
4065 return SDL_SetError(
"Vulkan support is either not configured in SDL "
4066 "or not available in current SDL video driver "
4067 "(%s) or platform", _this->
name);
4127 VkInstance instance,