From da1909755b048bad876fc7bd248c8d3ea31b4eaa Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 May 2015 18:57:10 -0700 Subject: [PATCH] Fixed clip rectangle calculation when there is a viewport offset --- src/render/direct3d/SDL_render_d3d.c | 8 ++++---- src/render/direct3d11/SDL_render_d3d11.c | 12 +++++++++--- src/render/opengl/SDL_render_gl.c | 9 ++++++++- src/render/opengles/SDL_render_gles.c | 21 ++++++++++++++++++--- src/render/opengles2/SDL_render_gles2.c | 21 ++++++++++++++++++--- 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 92d2c3a0b09aa..6ebef67c04480 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -1269,10 +1269,10 @@ D3D_UpdateClipRect(SDL_Renderer * renderer) HRESULT result; IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE); - r.left = rect->x; - r.top = rect->y; - r.right = rect->x + rect->w; - r.bottom = rect->y + rect->h; + r.left = renderer->viewport.x + rect->x; + r.top = renderer->viewport.y + rect->y; + r.right = renderer->viewport.x + rect->x + rect->w; + r.bottom = renderer->viewport.y + rect->y + rect->h; result = IDirect3DDevice9_SetScissorRect(data->device, &r); if (result != D3D_OK) { diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index deb023e98abd5..78d67144fbe30 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -1356,7 +1356,7 @@ D3D11_GetRotationForCurrentRenderTarget(SDL_Renderer * renderer) } static int -D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRect, D3D11_RECT * outRect) +D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRect, D3D11_RECT * outRect, BOOL includeViewportOffset) { D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata; const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer); @@ -1366,6 +1366,12 @@ D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRec outRect->right = sdlRect->x + sdlRect->w; outRect->top = sdlRect->y; outRect->bottom = sdlRect->y + sdlRect->h; + if (includeViewportOffset) { + outRect->left += renderer->viewport.x; + outRect->right += renderer->viewport.x; + outRect->top += renderer->viewport.y; + outRect->bottom += renderer->viewport.y; + } break; case DXGI_MODE_ROTATION_ROTATE270: outRect->left = sdlRect->y; @@ -2280,7 +2286,7 @@ D3D11_UpdateClipRect(SDL_Renderer * renderer) ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 0, NULL); } else { D3D11_RECT scissorRect; - if (D3D11_GetViewportAlignedD3DRect(renderer, &renderer->clip_rect, &scissorRect) != 0) { + if (D3D11_GetViewportAlignedD3DRect(renderer, &renderer->clip_rect, &scissorRect, TRUE) != 0) { /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */ return -1; } @@ -2869,7 +2875,7 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, } /* Copy the desired portion of the back buffer to the staging texture: */ - if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &srcRect) != 0) { + if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &srcRect, FALSE) != 0) { /* D3D11_GetViewportAlignedD3DRect will have set the SDL error */ goto done; } diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index f9ce30c656baf..f5ac96d018d57 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -1046,7 +1046,14 @@ GL_UpdateClipRect(SDL_Renderer * renderer) 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); + if (renderer->target) { + data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h); + } else { + int w, h; + + SDL_GetRendererOutputSize(renderer, &w, &h); + data->glScissor(renderer->viewport.x + rect->x, (h - renderer->viewport.y - renderer->viewport.h) + rect->y, rect->w, rect->h); + } } else { data->glDisable(GL_SCISSOR_TEST); } diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index 81674b49d1977..b35fed73cbc03 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -680,8 +680,16 @@ GLES_UpdateViewport(SDL_Renderer * renderer) return 0; } - data->glViewport(renderer->viewport.x, renderer->viewport.y, - renderer->viewport.w, renderer->viewport.h); + if (renderer->target) { + data->glViewport(renderer->viewport.x, renderer->viewport.y, + renderer->viewport.w, renderer->viewport.h); + } else { + int w, h; + + SDL_GetRendererOutputSize(renderer, &w, &h); + data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h), + renderer->viewport.w, renderer->viewport.h); + } if (renderer->viewport.w && renderer->viewport.h) { data->glMatrixMode(GL_PROJECTION); @@ -707,7 +715,14 @@ GLES_UpdateClipRect(SDL_Renderer * renderer) 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); + if (renderer->target) { + data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h); + } else { + int w, h; + + SDL_GetRendererOutputSize(renderer, &w, &h); + data->glScissor(renderer->viewport.x + rect->x, (h - renderer->viewport.y - renderer->viewport.h) + rect->y, rect->w, rect->h); + } } else { data->glDisable(GL_SCISSOR_TEST); } diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index be16a4c222f25..c36539e959b3a 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -382,8 +382,16 @@ GLES2_UpdateViewport(SDL_Renderer * renderer) return 0; } - data->glViewport(renderer->viewport.x, renderer->viewport.y, - renderer->viewport.w, renderer->viewport.h); + if (renderer->target) { + data->glViewport(renderer->viewport.x, renderer->viewport.y, + renderer->viewport.w, renderer->viewport.h); + } else { + int w, h; + + SDL_GetRendererOutputSize(renderer, &w, &h); + data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h), + renderer->viewport.w, renderer->viewport.h); + } if (data->current_program) { GLES2_SetOrthographicProjection(renderer); @@ -404,7 +412,14 @@ GLES2_UpdateClipRect(SDL_Renderer * renderer) 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); + if (renderer->target) { + data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h); + } else { + int w, h; + + SDL_GetRendererOutputSize(renderer, &w, &h); + data->glScissor(renderer->viewport.x + rect->x, (h - renderer->viewport.y - renderer->viewport.h) + rect->y, rect->w, rect->h); + } } else { data->glDisable(GL_SCISSOR_TEST); }