diff --git a/include/SDL_render.h b/include/SDL_render.h index 4fa3473d1..19fdf5b64 100644 --- a/include/SDL_render.h +++ b/include/SDL_render.h @@ -363,6 +363,18 @@ extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_Texture * texture, */ extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture * texture); +/** + * \brief Set the clipping rectangle for rendering on the current target + * + * \param rect The rectangle to clip rendering to, or NULL to disable clipping. + * + * The contents of the window are not defined after calling + * SDL_RenderPresent(), so you should clear the clip rectangle and draw + * over the entire window each frame. + */ +extern DECLSPEC void SDLCALL SDL_RenderSetClipRect(SDL_Renderer * renderer, + const SDL_Rect * rect); + /** * \brief Set the color used for drawing operations (Fill and Line). * diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index d24be3dc8..34647c195 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -725,6 +725,14 @@ SDL_UnlockTexture(SDL_Texture * texture) } } +void +SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + CHECK_RENDERER_MAGIC(renderer, ); + + renderer->SetClipRect(renderer, rect); +} + int SDL_SetRenderDrawColor(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a) diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index f456f8848..b2d6d3846 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -78,6 +78,7 @@ struct SDL_Renderer int (*LockTexture) (SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch); void (*UnlockTexture) (SDL_Renderer * renderer, SDL_Texture * texture); + void (*SetClipRect) (SDL_Renderer * renderer, const SDL_Rect *rect); int (*RenderClear) (SDL_Renderer * renderer); int (*RenderDrawPoints) (SDL_Renderer * renderer, const SDL_Point * points, int count); diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 482a1e030..b3409c496 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -96,6 +96,7 @@ static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch); static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); +static void D3D_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect); static int D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count); static int D3D_RenderDrawLines(SDL_Renderer * renderer, @@ -308,6 +309,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTexture = D3D_UpdateTexture; renderer->LockTexture = D3D_LockTexture; renderer->UnlockTexture = D3D_UnlockTexture; + renderer->SetClipRect = D3D_SetClipRect; renderer->RenderDrawPoints = D3D_RenderDrawPoints; renderer->RenderDrawLines = D3D_RenderDrawLines; renderer->RenderFillRects = D3D_RenderFillRects; @@ -601,6 +603,27 @@ D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) IDirect3DTexture9_UnlockRect(data->texture, 0); } +static void +D3D_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; + + if (rect) { + RECT d3drect; + + d3drect.left = rect->x; + d3drect.right = rect->x + rect->w; + d3drect.top = rect->y; + d3drect.bottom = rect->y + rect->h; + IDirect3DDevice9_SetScissorRect(data->device, &d3drect); + IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, + TRUE); + } else { + IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, + FALSE); + } +} + static void D3D_SetBlendMode(D3D_RenderData * data, int blendMode) { diff --git a/src/render/opengl/SDL_glfuncs.h b/src/render/opengl/SDL_glfuncs.h index 3d9bdae93..b76f97145 100644 --- a/src/render/opengl/SDL_glfuncs.h +++ b/src/render/opengl/SDL_glfuncs.h @@ -337,8 +337,7 @@ SDL_PROC_UNUSED(void, glRotatef, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)) SDL_PROC_UNUSED(void, glScaled, (GLdouble x, GLdouble y, GLdouble z)) SDL_PROC_UNUSED(void, glScalef, (GLfloat x, GLfloat y, GLfloat z)) -SDL_PROC_UNUSED(void, glScissor, - (GLint x, GLint y, GLsizei width, GLsizei height)) +SDL_PROC(void, glScissor, (GLint x, GLint y, GLsizei width, GLsizei height)) SDL_PROC_UNUSED(void, glSelectBuffer, (GLsizei size, GLuint * buffer)) SDL_PROC_UNUSED(void, glShadeModel, (GLenum mode)) SDL_PROC_UNUSED(void, glStencilFunc, (GLenum func, GLint ref, GLuint mask)) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 500a7a033..eeac93e11 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -52,6 +52,7 @@ static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch); static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); +static void GL_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect); static int GL_RenderClear(SDL_Renderer * renderer); static int GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count); @@ -199,6 +200,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTexture = GL_UpdateTexture; renderer->LockTexture = GL_LockTexture; renderer->UnlockTexture = GL_UnlockTexture; + renderer->SetClipRect = GL_SetClipRect; renderer->RenderClear = GL_RenderClear; renderer->RenderDrawPoints = GL_RenderDrawPoints; renderer->RenderDrawLines = GL_RenderDrawLines; @@ -510,6 +512,24 @@ GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) renderdata->glDisable(data->type); } +static void +GL_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + GL_RenderData *data = (GL_RenderData *) renderer->driverdata; + + GL_ActivateRenderer(renderer); + + if (rect) { + int w, h; + + SDL_GetWindowSize(renderer->window, &w, &h); + data->glScissor(rect->x, (h-(rect->y+rect->h)), rect->w, rect->h); + data->glEnable(GL_SCISSOR_TEST); + } else { + data->glDisable(GL_SCISSOR_TEST); + } +} + static void GL_SetBlendMode(GL_RenderData * data, int blendMode) { diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index 680875964..941c83fdf 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -56,6 +56,7 @@ static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch); static void GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); +static void GLES_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect); static int GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count); static int GLES_RenderDrawLines(SDL_Renderer * renderer, @@ -172,6 +173,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTexture = GLES_UpdateTexture; renderer->LockTexture = GLES_LockTexture; renderer->UnlockTexture = GLES_UnlockTexture; + renderer->SetClipRect = GLES_SetClipRect; renderer->RenderDrawPoints = GLES_RenderDrawPoints; renderer->RenderDrawLines = GLES_RenderDrawLines; renderer->RenderFillRects = GLES_RenderFillRects; @@ -443,6 +445,22 @@ GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) glDisable(data->type); } +static void +GLES_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + GL_ActivateRenderer(renderer); + + if (rect) { + int w, h; + + SDL_GetWindowSize(renderer->window, &w, &h); + glScissor(rect->x, (h-(rect->y+rect->h)), rect->w, rect->h); + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } +} + static void GLES_SetBlendMode(GLES_RenderData * data, int blendMode) { diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index e171c8d3c..9b6d231fa 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -133,10 +133,10 @@ typedef struct GLES2_DriverContext * Renderer state APIs * *************************************************************************************************/ +static int GLES2_ActivateRenderer(SDL_Renderer *renderer); static void GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event); -static int GLES2_ActivateRenderer(SDL_Renderer *renderer); -static int GLES2_DisplayModeChanged(SDL_Renderer *renderer); +static void GLES2_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect); static void GLES2_DestroyRenderer(SDL_Renderer *renderer); static SDL_GLContext SDL_CurrentContext = NULL; @@ -178,6 +178,22 @@ GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) } } +static void +GLES2_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + GLES2_ActivateRenderer(renderer); + + if (rect) { + int w, h; + + SDL_GetWindowSize(renderer->window, &w, &h); + glScissor(rect->x, (h-(rect->y+rect->h)), rect->w, rect->h); + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } +} + static void GLES2_DestroyRenderer(SDL_Renderer *renderer) { @@ -761,6 +777,8 @@ GLES2_SetOrthographicProjection(SDL_Renderer *renderer) * Rendering functions * *************************************************************************************************/ +static const float inv255f = 1.0f / 255.0f; + static int GLES2_RenderClear(SDL_Renderer *renderer); static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int count); static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_Point *points, int count); @@ -772,10 +790,10 @@ static void GLES2_RenderPresent(SDL_Renderer *renderer); static int GLES2_RenderClear(SDL_Renderer *renderer) { - float r = (float)renderer->r / 255.0f; - float g = (float)renderer->g / 255.0f; - float b = (float)renderer->b / 255.0f; - float a = (float)renderer->a / 255.0f; + float r = (float)renderer->r * inv255f; + float g = (float)renderer->g * inv255f; + float b = (float)renderer->b * inv255f; + float a = (float)renderer->a * inv255f; GLES2_ActivateRenderer(renderer); @@ -832,10 +850,10 @@ GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int coun locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR]; glGetError(); glUniform4f(locColor, - renderer->r / 255.0f, - renderer->g / 255.0f, - renderer->b / 255.0f, - alpha / 255.0f); + renderer->r * inv255f, + renderer->g * inv255f, + renderer->b * inv255f, + alpha * inv255f); /* Configure the correct blend mode */ GLES2_SetBlendMode(blendMode); @@ -886,10 +904,10 @@ GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_Point *points, int count locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR]; glGetError(); glUniform4f(locColor, - renderer->r / 255.0f, - renderer->g / 255.0f, - renderer->b / 255.0f, - alpha / 255.0f); + renderer->r * inv255f, + renderer->g * inv255f, + renderer->b * inv255f, + alpha * inv255f); /* Configure the correct blend mode */ GLES2_SetBlendMode(blendMode); @@ -940,10 +958,10 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_Rect **rects, int count) locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR]; glGetError(); glUniform4f(locColor, - renderer->r / 255.0f, - renderer->g / 255.0f, - renderer->b / 255.0f, - alpha / 255.0f); + renderer->r * inv255f, + renderer->g * inv255f, + renderer->b * inv255f, + alpha * inv255f); /* Configure the correct blend mode */ GLES2_SetBlendMode(blendMode); @@ -1014,10 +1032,10 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s /* Configure color modulation */ locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION]; glUniform4f(locModulation, - texture->r / 255.0f, - texture->g / 255.0f, - texture->b / 255.0f, - alpha / 255.0f); + texture->r * inv255f, + texture->g * inv255f, + texture->b * inv255f, + alpha * inv255f); /* Emit the textured quad */ glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); @@ -1066,6 +1084,9 @@ GLES2_RenderPresent(SDL_Renderer *renderer) #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B +/* Used to re-create the window with OpenGL capability */ +extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); + static SDL_Renderer * GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) { @@ -1168,6 +1189,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->UpdateTexture = &GLES2_UpdateTexture; renderer->LockTexture = &GLES2_LockTexture; renderer->UnlockTexture = &GLES2_UnlockTexture; + renderer->SetClipRect = &GLES2_SetClipRect; renderer->RenderClear = &GLES2_RenderClear; renderer->RenderDrawPoints = &GLES2_RenderDrawPoints; renderer->RenderDrawLines = &GLES2_RenderDrawLines; diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index c70934f39..44e786abe 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -50,6 +50,7 @@ static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch); static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); +static void SW_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect); static int SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count); static int SW_RenderDrawLines(SDL_Renderer * renderer, @@ -125,6 +126,7 @@ SW_CreateRendererForSurface(SDL_Surface * surface) renderer->UpdateTexture = SW_UpdateTexture; renderer->LockTexture = SW_LockTexture; renderer->UnlockTexture = SW_UnlockTexture; + renderer->SetClipRect = SW_SetClipRect; renderer->DestroyTexture = SW_DestroyTexture; renderer->RenderDrawPoints = SW_RenderDrawPoints; renderer->RenderDrawLines = SW_RenderDrawLines; @@ -266,6 +268,17 @@ SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) { } +static void +SW_SetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect) +{ + SDL_Surface *surface = SW_ActivateRenderer(renderer); + + if (!surface) { + return; + } + SDL_SetClipRect(surface, rect); +} + static int SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count)