From defd90b6f62235f1fa8d30a73f7a7c427ba216d5 Mon Sep 17 00:00:00 2001 From: "J?rgen P. Tjern?" Date: Sat, 19 Apr 2014 13:15:41 -0700 Subject: [PATCH] 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 --- include/SDL_render.h | 10 ++++++++++ src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/render/SDL_render.c | 11 +++++++++++ src/render/SDL_sysrender.h | 4 ++++ src/render/direct3d/SDL_render_d3d.c | 9 +++++---- src/render/direct3d11/SDL_render_d3d11.c | 7 +++---- src/render/opengl/SDL_render_gl.c | 4 ++-- src/render/opengles/SDL_render_gles.c | 4 ++-- src/render/opengles2/SDL_render_gles2.c | 4 ++-- src/render/software/SDL_render_sw.c | 6 ++---- 11 files changed, 43 insertions(+), 18 deletions(-) diff --git a/include/SDL_render.h b/include/SDL_render.h index 77f706a9b2375..192e502ebf8c6 100644 --- a/include/SDL_render.h +++ b/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, 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. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 5ae7927f2d8cd..f03f4b23df98a 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -575,3 +575,4 @@ #define SDL_GetDefaultAssertionHandler SDL_GetDefaultAssertionHandler_REAL #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL #define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL +#define SDL_RenderIsClipEnabled SDL_RenderIsClipEnabled_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index ed0ea86e8c057..9c652052b542f 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -606,3 +606,4 @@ SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),retu #ifdef __WIN32__ SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),return) #endif +SDL_DYNAPI_PROC(SDL_bool,SDL_RenderIsClipEnabled,(SDL_Renderer *a),(a),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 2a5ea41576eb7..3aea6bcbd4831 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1071,6 +1071,7 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) /* Make a backup of the viewport */ renderer->viewport_backup = renderer->viewport; renderer->clip_rect_backup = renderer->clip_rect; + renderer->clipping_enabled_backup = renderer->clipping_enabled; renderer->scale_backup = renderer->scale; renderer->logical_w_backup = renderer->logical_w; renderer->logical_h_backup = renderer->logical_h; @@ -1093,6 +1094,7 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) } else { renderer->viewport = renderer->viewport_backup; renderer->clip_rect = renderer->clip_rect_backup; + renderer->clipping_enabled = renderer->clipping_enabled_backup; renderer->scale = renderer->scale_backup; renderer->logical_w = renderer->logical_w_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) if (rect) { + renderer->clipping_enabled = SDL_TRUE; 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.w = (int)SDL_ceil(rect->w * renderer->scale.x); renderer->clip_rect.h = (int)SDL_ceil(rect->h * renderer->scale.y); } else { + renderer->clipping_enabled = SDL_FALSE; SDL_zero(renderer->clip_rect); } 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 SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY) { diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 5098d34faff0c..aba4bbb457a22 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -143,6 +143,10 @@ struct SDL_Renderer SDL_Rect clip_rect; 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 */ SDL_FPoint scale; SDL_FPoint scale_backup; diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 24482818ded4c..d462ca86e008c 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1145,12 +1145,13 @@ D3D_UpdateViewport(SDL_Renderer * renderer) static int D3D_UpdateClipRect(SDL_Renderer * renderer) { - const SDL_Rect *rect = &renderer->clip_rect; 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); r.left = rect->x; r.top = rect->y; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 806846c784341..27ca61f66a63b 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -2232,13 +2232,12 @@ static int D3D11_UpdateClipRect(SDL_Renderer * renderer) { 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); } else { 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 */ return -1; } @@ -2366,7 +2365,7 @@ D3D11_RenderStartDrawOp(SDL_Renderer * renderer) rendererData->currentRenderTargetView = renderTargetView; } - if (SDL_RectEmpty(&renderer->clip_rect)) { + if (!renderer->clipping_enabled) { rasterizerState = rendererData->mainRasterizer; } else { rasterizerState = rendererData->clippedRasterizer; diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 6962267327465..20a7f66a4debf 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -976,10 +976,10 @@ GL_UpdateViewport(SDL_Renderer * renderer) static int GL_UpdateClipRect(SDL_Renderer * renderer) { - const SDL_Rect *rect = &renderer->clip_rect; 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->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h); } else { diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index 43a07a4b146d0..dcfd41b6eee77 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -684,14 +684,14 @@ static int GLES_UpdateClipRect(SDL_Renderer * renderer) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; - const SDL_Rect *rect = &renderer->clip_rect; if (SDL_CurrentContext != data->context) { /* We'll update the clip rect after we rebind the context */ return 0; } - if (!SDL_RectEmpty(rect)) { + if (renderer->clipping_enabled) { + const SDL_Rect *rect = &renderer->clip_rect; data->glEnable(GL_SCISSOR_TEST); data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h); } else { diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 44484783f7d39..2671973f1f810 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -362,14 +362,14 @@ static int GLES2_UpdateClipRect(SDL_Renderer * renderer) { GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; - const SDL_Rect *rect = &renderer->clip_rect; if (SDL_CurrentContext != data->context) { /* We'll update the clip rect after we rebind the context */ return 0; } - if (!SDL_RectEmpty(rect)) { + if (renderer->clipping_enabled) { + const SDL_Rect *rect = &renderer->clip_rect; data->glEnable(GL_SCISSOR_TEST); data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h); } else { diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index f0eb768f5f237..29d331fcbd584 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -347,11 +347,9 @@ SW_UpdateClipRect(SDL_Renderer * renderer) { SW_RenderData *data = (SW_RenderData *) renderer->driverdata; SDL_Surface *surface = data->surface; - const SDL_Rect *rect = &renderer->clip_rect; - if (surface) { - if (!SDL_RectEmpty(rect)) { - SDL_SetClipRect(surface, rect); + if (renderer->clipping_enabled) { + SDL_SetClipRect(surface, &renderer->clip_rect); } else { SDL_SetClipRect(surface, NULL); }