Browse Source

Render: Allow empty cliprect.

This fixes an issue where an empty cliprect is treated the same as a NULL
cliprect, causing the render backends to disable clipping.

Also adds a new API, SDL_RenderIsClipEnabled(render) that allows you to
differentiate between:
 - SDL_RenderSetClipRect(render, NULL)
 - SDL_Rect r = {0,0,0,0}; SDL_RenderSetClipRect(render, &r);

Fixes https://bugzilla.libsdl.org/show_bug.cgi?id=2504
J?rgen P. Tjern? 11 years ago
parent
commit
defd90b6f6

+ 10 - 0
include/SDL_render.h

@@ -551,6 +551,16 @@ extern DECLSPEC int SDLCALL SDL_RenderSetClipRect(SDL_Renderer * renderer,
 extern DECLSPEC void SDLCALL SDL_RenderGetClipRect(SDL_Renderer * renderer,
 extern DECLSPEC void SDLCALL SDL_RenderGetClipRect(SDL_Renderer * renderer,
                                                    SDL_Rect * rect);
                                                    SDL_Rect * rect);
 
 
+/**
+ *  \brief Get wether clipping is enabled on the given renderer
+ *
+ *  \param renderer The renderer from which clip state should be queried.
+ *
+ *  \sa SDL_RenderGetClipRect()
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderIsClipEnabled(SDL_Renderer * renderer);
+
+
 /**
 /**
  *  \brief Set the drawing scale for rendering on the current target.
  *  \brief Set the drawing scale for rendering on the current target.
  *
  *

+ 1 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -575,3 +575,4 @@
 #define SDL_GetDefaultAssertionHandler SDL_GetDefaultAssertionHandler_REAL
 #define SDL_GetDefaultAssertionHandler SDL_GetDefaultAssertionHandler_REAL
 #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL
 #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL
 #define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL
 #define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL
+#define SDL_RenderIsClipEnabled SDL_RenderIsClipEnabled_REAL

+ 1 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -606,3 +606,4 @@ SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),retu
 #ifdef __WIN32__
 #ifdef __WIN32__
 SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),return)
 #endif
 #endif
+SDL_DYNAPI_PROC(SDL_bool,SDL_RenderIsClipEnabled,(SDL_Renderer *a),(a),return)

+ 11 - 0
src/render/SDL_render.c

@@ -1071,6 +1071,7 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
         /* Make a backup of the viewport */
         /* Make a backup of the viewport */
         renderer->viewport_backup = renderer->viewport;
         renderer->viewport_backup = renderer->viewport;
         renderer->clip_rect_backup = renderer->clip_rect;
         renderer->clip_rect_backup = renderer->clip_rect;
+        renderer->clipping_enabled_backup = renderer->clipping_enabled;
         renderer->scale_backup = renderer->scale;
         renderer->scale_backup = renderer->scale;
         renderer->logical_w_backup = renderer->logical_w;
         renderer->logical_w_backup = renderer->logical_w;
         renderer->logical_h_backup = renderer->logical_h;
         renderer->logical_h_backup = renderer->logical_h;
@@ -1093,6 +1094,7 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
     } else {
     } else {
         renderer->viewport = renderer->viewport_backup;
         renderer->viewport = renderer->viewport_backup;
         renderer->clip_rect = renderer->clip_rect_backup;
         renderer->clip_rect = renderer->clip_rect_backup;
+        renderer->clipping_enabled = renderer->clipping_enabled_backup;
         renderer->scale = renderer->scale_backup;
         renderer->scale = renderer->scale_backup;
         renderer->logical_w = renderer->logical_w_backup;
         renderer->logical_w = renderer->logical_w_backup;
         renderer->logical_h = renderer->logical_h_backup;
         renderer->logical_h = renderer->logical_h_backup;
@@ -1233,11 +1235,13 @@ SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
     CHECK_RENDERER_MAGIC(renderer, -1)
     CHECK_RENDERER_MAGIC(renderer, -1)
 
 
     if (rect) {
     if (rect) {
+        renderer->clipping_enabled = SDL_TRUE;
         renderer->clip_rect.x = (int)SDL_floor(rect->x * renderer->scale.x);
         renderer->clip_rect.x = (int)SDL_floor(rect->x * renderer->scale.x);
         renderer->clip_rect.y = (int)SDL_floor(rect->y * renderer->scale.y);
         renderer->clip_rect.y = (int)SDL_floor(rect->y * renderer->scale.y);
         renderer->clip_rect.w = (int)SDL_ceil(rect->w * renderer->scale.x);
         renderer->clip_rect.w = (int)SDL_ceil(rect->w * renderer->scale.x);
         renderer->clip_rect.h = (int)SDL_ceil(rect->h * renderer->scale.y);
         renderer->clip_rect.h = (int)SDL_ceil(rect->h * renderer->scale.y);
     } else {
     } else {
+        renderer->clipping_enabled = SDL_FALSE;
         SDL_zero(renderer->clip_rect);
         SDL_zero(renderer->clip_rect);
     }
     }
     return renderer->UpdateClipRect(renderer);
     return renderer->UpdateClipRect(renderer);
@@ -1256,6 +1260,13 @@ SDL_RenderGetClipRect(SDL_Renderer * renderer, SDL_Rect * rect)
     }
     }
 }
 }
 
 
+SDL_bool
+SDL_RenderIsClipEnabled(SDL_Renderer * renderer)
+{
+    CHECK_RENDERER_MAGIC(renderer, SDL_FALSE)
+    return renderer->clipping_enabled;
+}
+
 int
 int
 SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY)
 SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY)
 {
 {

+ 4 - 0
src/render/SDL_sysrender.h

@@ -143,6 +143,10 @@ struct SDL_Renderer
     SDL_Rect clip_rect;
     SDL_Rect clip_rect;
     SDL_Rect clip_rect_backup;
     SDL_Rect clip_rect_backup;
 
 
+    /* Wether or not the clipping rectangle is used. */
+    SDL_bool clipping_enabled;
+    SDL_bool clipping_enabled_backup;
+
     /* The render output coordinate scale */
     /* The render output coordinate scale */
     SDL_FPoint scale;
     SDL_FPoint scale;
     SDL_FPoint scale_backup;
     SDL_FPoint scale_backup;

+ 5 - 4
src/render/direct3d/SDL_render_d3d.c

@@ -1145,12 +1145,13 @@ D3D_UpdateViewport(SDL_Renderer * renderer)
 static int
 static int
 D3D_UpdateClipRect(SDL_Renderer * renderer)
 D3D_UpdateClipRect(SDL_Renderer * renderer)
 {
 {
-    const SDL_Rect *rect = &renderer->clip_rect;
     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
-    RECT r;
-    HRESULT result;
 
 
-    if (!SDL_RectEmpty(rect)) {
+    if (renderer->clipping_enabled) {
+        const SDL_Rect *rect = &renderer->clip_rect;
+        RECT r;
+        HRESULT result;
+
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
         r.left = rect->x;
         r.left = rect->x;
         r.top = rect->y;
         r.top = rect->y;

+ 3 - 4
src/render/direct3d11/SDL_render_d3d11.c

@@ -2232,13 +2232,12 @@ static int
 D3D11_UpdateClipRect(SDL_Renderer * renderer)
 D3D11_UpdateClipRect(SDL_Renderer * renderer)
 {
 {
     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
-    const SDL_Rect *rect = &renderer->clip_rect;
 
 
-    if (SDL_RectEmpty(rect)) {
+    if (!renderer->clipping_enabled) {
         ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 0, NULL);
         ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 0, NULL);
     } else {
     } else {
         D3D11_RECT scissorRect;
         D3D11_RECT scissorRect;
-        if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &scissorRect) != 0) {
+        if (D3D11_GetViewportAlignedD3DRect(renderer, &renderer->clip_rect, &scissorRect) != 0) {
             /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
             /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
             return -1;
             return -1;
         }
         }
@@ -2366,7 +2365,7 @@ D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
         rendererData->currentRenderTargetView = renderTargetView;
         rendererData->currentRenderTargetView = renderTargetView;
     }
     }
 
 
-    if (SDL_RectEmpty(&renderer->clip_rect)) {
+    if (!renderer->clipping_enabled) {
         rasterizerState = rendererData->mainRasterizer;
         rasterizerState = rendererData->mainRasterizer;
     } else {
     } else {
         rasterizerState = rendererData->clippedRasterizer;
         rasterizerState = rendererData->clippedRasterizer;

+ 2 - 2
src/render/opengl/SDL_render_gl.c

@@ -976,10 +976,10 @@ GL_UpdateViewport(SDL_Renderer * renderer)
 static int
 static int
 GL_UpdateClipRect(SDL_Renderer * renderer)
 GL_UpdateClipRect(SDL_Renderer * renderer)
 {
 {
-    const SDL_Rect *rect = &renderer->clip_rect;
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
 
 
-    if (!SDL_RectEmpty(rect)) {
+    if (renderer->clipping_enabled) {
+        const SDL_Rect *rect = &renderer->clip_rect;
         data->glEnable(GL_SCISSOR_TEST);
         data->glEnable(GL_SCISSOR_TEST);
         data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
         data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
     } else {
     } else {

+ 2 - 2
src/render/opengles/SDL_render_gles.c

@@ -684,14 +684,14 @@ static int
 GLES_UpdateClipRect(SDL_Renderer * renderer)
 GLES_UpdateClipRect(SDL_Renderer * renderer)
 {
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-    const SDL_Rect *rect = &renderer->clip_rect;
 
 
     if (SDL_CurrentContext != data->context) {
     if (SDL_CurrentContext != data->context) {
         /* We'll update the clip rect after we rebind the context */
         /* We'll update the clip rect after we rebind the context */
         return 0;
         return 0;
     }
     }
 
 
-    if (!SDL_RectEmpty(rect)) {
+    if (renderer->clipping_enabled) {
+        const SDL_Rect *rect = &renderer->clip_rect;
         data->glEnable(GL_SCISSOR_TEST);
         data->glEnable(GL_SCISSOR_TEST);
         data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
         data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
     } else {
     } else {

+ 2 - 2
src/render/opengles2/SDL_render_gles2.c

@@ -362,14 +362,14 @@ static int
 GLES2_UpdateClipRect(SDL_Renderer * renderer)
 GLES2_UpdateClipRect(SDL_Renderer * renderer)
 {
 {
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
-    const SDL_Rect *rect = &renderer->clip_rect;
 
 
     if (SDL_CurrentContext != data->context) {
     if (SDL_CurrentContext != data->context) {
         /* We'll update the clip rect after we rebind the context */
         /* We'll update the clip rect after we rebind the context */
         return 0;
         return 0;
     }
     }
 
 
-    if (!SDL_RectEmpty(rect)) {
+    if (renderer->clipping_enabled) {
+        const SDL_Rect *rect = &renderer->clip_rect;
         data->glEnable(GL_SCISSOR_TEST);
         data->glEnable(GL_SCISSOR_TEST);
         data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
         data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
     } else {
     } else {

+ 2 - 4
src/render/software/SDL_render_sw.c

@@ -347,11 +347,9 @@ SW_UpdateClipRect(SDL_Renderer * renderer)
 {
 {
     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
     SDL_Surface *surface = data->surface;
     SDL_Surface *surface = data->surface;
-    const SDL_Rect *rect = &renderer->clip_rect;
-
     if (surface) {
     if (surface) {
-        if (!SDL_RectEmpty(rect)) {
-            SDL_SetClipRect(surface, rect);
+        if (renderer->clipping_enabled) {
+            SDL_SetClipRect(surface, &renderer->clip_rect);
         } else {
         } else {
             SDL_SetClipRect(surface, NULL);
             SDL_SetClipRect(surface, NULL);
         }
         }