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
This commit is contained in:
J?rgen P. Tjern? 2014-04-19 13:15:41 -07:00
parent 36e11d87c8
commit defd90b6f6
11 changed files with 43 additions and 18 deletions

View file

@ -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.
*

View file

@ -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

View file

@ -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)

View file

@ -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)
{

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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);
}