Make it clear that you can't mix 2D rendering and the window surface API Also added functions to query and destroy the window surface so you can switch between modes if you want. See https://github.com/pygame-community/pygame-ce/issues/2190 for more details.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
diff --git a/WhatsNew.txt b/WhatsNew.txt
index e93ddca..a5636ed 100644
--- a/WhatsNew.txt
+++ b/WhatsNew.txt
@@ -6,6 +6,7 @@ This is a list of major changes in SDL's version history.
---------------------------------------------------------------------------
General:
+* Added SDL_HasWindowSurface() and SDL_DestroyWindowSurface() to switch between the window surface and rendering APIs
* Added a display event SDL_DISPLAYEVENT_MOVED which is sent when the primary monitor changes or displays change position relative to each other
* Added the hint SDL_HINT_ENABLE_SCREEN_KEYBOARD to control whether the on-screen keyboard should be shown when text input is active
diff --git a/include/SDL_video.h b/include/SDL_video.h
index 599b563..99637f7 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -1276,6 +1276,17 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window,
Uint32 flags);
/**
+ * Return whether the window has a surface associated with it.
+ *
+ * \returns SDL_TRUE if there is a surface associated with the window, or SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.28.0.
+ *
+ * \sa SDL_GetWindowSurface
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasWindowSurface(SDL_Window *window);
+
+/**
* Get the SDL surface associated with the window.
*
* A new surface will be created with the optimal format for the window, if
@@ -1295,6 +1306,8 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window,
*
* \since This function is available since SDL 2.0.0.
*
+ * \sa SDL_DestroyWindowSurface
+ * \sa SDL_HasWindowSurface
* \sa SDL_UpdateWindowSurface
* \sa SDL_UpdateWindowSurfaceRects
*/
@@ -1344,6 +1357,20 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window,
int numrects);
/**
+ * Destroy the surface associated with the window.
+ *
+ * \param window the window to update
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.28.0.
+ *
+ * \sa SDL_GetWindowSurface
+ * \sa SDL_HasWindowSurface
+ */
+extern DECLSPEC int SDLCALL SDL_DestroyWindowSurface(SDL_Window *window);
+
+/**
* Set a window's input grab mode.
*
* When input is grabbed, the mouse is confined to the window. This function
diff --git a/src/dynapi/SDL2.exports b/src/dynapi/SDL2.exports
index 0a50983..696e2be 100644
--- a/src/dynapi/SDL2.exports
+++ b/src/dynapi/SDL2.exports
@@ -868,3 +868,5 @@
++'_SDL_ResetHints'.'SDL2.dll'.'SDL_ResetHints'
++'_SDL_strcasestr'.'SDL2.dll'.'SDL_strcasestr'
# ++'_SDL_GDKSuspendComplete'.'SDL2.dll'.'SDL_GDKSuspendComplete'
+++'_SDL_HasWindowSurface'.'SDL2.dll'.'SDL_HasWindowSurface'
+++'_SDL_DestroyWindowSurface'.'SDL2.dll'.'SDL_DestroyWindowSurface'
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 0ee320b..0b59a21 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -894,3 +894,5 @@
#define SDL_ResetHints SDL_ResetHints_REAL
#define SDL_strcasestr SDL_strcasestr_REAL
#define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL
+#define SDL_HasWindowSurface SDL_HasWindowSurface_REAL
+#define SDL_DestroyWindowSurface SDL_DestroyWindowSurface_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index ebc9fc3..8e1d36d 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -979,3 +979,5 @@ SDL_DYNAPI_PROC(char*,SDL_strcasestr,(const char *a, const char *b),(a,b),return
#if defined(__GDK__)
SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),)
#endif
+SDL_DYNAPI_PROC(SDL_bool,SDL_HasWindowSurface,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_DestroyWindowSurface,(SDL_Window *a),(a),return)
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 5831b10..21d6324 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -950,6 +950,11 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, int index, Uint32 flags)
goto error;
}
+ if (SDL_HasWindowSurface(window)) {
+ SDL_SetError("Surface already associated with window");
+ goto error;
+ }
+
if (SDL_GetRenderer(window)) {
SDL_SetError("Renderer already associated with window");
goto error;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 73a4d2c..00de546 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -1884,12 +1884,7 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
}
/* Tear down the old native window */
- if (window->surface) {
- window->surface->flags &= ~SDL_DONTFREE;
- SDL_FreeSurface(window->surface);
- window->surface = NULL;
- window->surface_valid = SDL_FALSE;
- }
+ SDL_DestroyWindowSurface(window);
if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
if (_this->DestroyWindowFramebuffer) {
@@ -2670,16 +2665,19 @@ static SDL_Surface *SDL_CreateWindowFramebuffer(SDL_Window *window)
return SDL_CreateRGBSurfaceFrom(pixels, window->w, window->h, bpp, pitch, Rmask, Gmask, Bmask, Amask);
}
+SDL_bool SDL_HasWindowSurface(SDL_Window *window)
+{
+ CHECK_WINDOW_MAGIC(window, SDL_FALSE);
+
+ return window->surface ? SDL_TRUE : SDL_FALSE;
+}
+
SDL_Surface *SDL_GetWindowSurface(SDL_Window *window)
{
CHECK_WINDOW_MAGIC(window, NULL);
if (!window->surface_valid) {
- if (window->surface) {
- window->surface->flags &= ~SDL_DONTFREE;
- SDL_FreeSurface(window->surface);
- window->surface = NULL;
- }
+ SDL_DestroyWindowSurface(window);
window->surface = SDL_CreateWindowFramebuffer(window);
if (window->surface) {
window->surface_valid = SDL_TRUE;
@@ -2761,6 +2759,19 @@ int SDL_SetWindowOpacity(SDL_Window * window, float opacity)
return retval;
}
+int SDL_DestroyWindowSurface(SDL_Window *window)
+{
+ CHECK_WINDOW_MAGIC(window, -1);
+
+ if (window->surface) {
+ window->surface->flags &= ~SDL_DONTFREE;
+ SDL_DestroySurface(window->surface);
+ window->surface = NULL;
+ window->surface_valid = SDL_FALSE;
+ }
+ return 0;
+}
+
int SDL_GetWindowOpacity(SDL_Window *window, float *out_opacity)
{
CHECK_WINDOW_MAGIC(window, -1);
@@ -3206,12 +3217,7 @@ void SDL_DestroyWindow(SDL_Window *window)
}
}
- if (window->surface) {
- window->surface->flags &= ~SDL_DONTFREE;
- SDL_FreeSurface(window->surface);
- window->surface = NULL;
- window->surface_valid = SDL_FALSE;
- }
+ SDL_DestroyWindowSurface(window);
if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
if (_this->DestroyWindowFramebuffer) {
_this->DestroyWindowFramebuffer(_this, window);