software: Correctly track viewport and cliprect.
Fixes Bugzilla #4457.
parent
a2f2b73554
commit
04fedce0e8
|
@ -37,6 +37,13 @@
|
|||
|
||||
/* SDL surface based renderer implementation */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const SDL_Rect *viewport;
|
||||
const SDL_Rect *cliprect;
|
||||
SDL_bool surface_cliprect_dirty;
|
||||
} SW_DrawStateCache;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
@ -568,18 +575,44 @@ PrepTextureForCopy(const SDL_RenderCommand *cmd)
|
|||
SDL_SetSurfaceBlendMode(surface, blend);
|
||||
}
|
||||
|
||||
static void
|
||||
SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate)
|
||||
{
|
||||
if (drawstate->surface_cliprect_dirty) {
|
||||
const SDL_Rect *viewport = drawstate->viewport;
|
||||
const SDL_Rect *cliprect = drawstate->cliprect;
|
||||
SDL_assert(viewport != NULL); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */
|
||||
|
||||
if (cliprect != NULL) {
|
||||
SDL_Rect clip_rect;
|
||||
clip_rect.x = cliprect->x + viewport->x;
|
||||
clip_rect.y = cliprect->y + viewport->y;
|
||||
clip_rect.w = cliprect->w;
|
||||
clip_rect.h = cliprect->h;
|
||||
SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
|
||||
SDL_SetClipRect(surface, &clip_rect);
|
||||
} else {
|
||||
SDL_SetClipRect(surface, drawstate->viewport);
|
||||
}
|
||||
drawstate->surface_cliprect_dirty = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
|
||||
{
|
||||
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
|
||||
SDL_Surface *surface = SW_ActivateRenderer(renderer);
|
||||
const SDL_Rect *viewport = NULL;
|
||||
const SDL_Rect *cliprect = NULL;
|
||||
SW_DrawStateCache drawstate;
|
||||
|
||||
if (!surface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
drawstate.viewport = NULL;
|
||||
drawstate.cliprect = NULL;
|
||||
drawstate.surface_cliprect_dirty = SDL_TRUE;
|
||||
|
||||
while (cmd) {
|
||||
switch (cmd->command) {
|
||||
case SDL_RENDERCMD_SETDRAWCOLOR: {
|
||||
|
@ -587,25 +620,14 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
|
|||
}
|
||||
|
||||
case SDL_RENDERCMD_SETVIEWPORT: {
|
||||
viewport = &cmd->data.viewport.rect;
|
||||
SDL_SetClipRect(data->surface, viewport);
|
||||
drawstate.viewport = &cmd->data.viewport.rect;
|
||||
drawstate.surface_cliprect_dirty = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_SETCLIPRECT: {
|
||||
SDL_assert(viewport != NULL);
|
||||
cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
|
||||
if (cliprect) {
|
||||
SDL_Rect clip_rect;
|
||||
clip_rect.x = cliprect->x + viewport->x;
|
||||
clip_rect.y = cliprect->y + viewport->y;
|
||||
clip_rect.w = cliprect->w;
|
||||
clip_rect.h = cliprect->h;
|
||||
SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
|
||||
SDL_SetClipRect(surface, &clip_rect);
|
||||
} else {
|
||||
SDL_SetClipRect(surface, viewport);
|
||||
}
|
||||
drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
|
||||
drawstate.surface_cliprect_dirty = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -614,11 +636,10 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
|
|||
const Uint8 g = cmd->data.color.g;
|
||||
const Uint8 b = cmd->data.color.b;
|
||||
const Uint8 a = cmd->data.color.a;
|
||||
const SDL_Rect clip_rect = surface->clip_rect;
|
||||
/* By definition the clear ignores the clip rect */
|
||||
SDL_SetClipRect(surface, NULL);
|
||||
SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
SDL_SetClipRect(surface, &clip_rect);
|
||||
drawstate.surface_cliprect_dirty = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -630,6 +651,7 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
|
|||
const int count = (int) cmd->data.draw.count;
|
||||
const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
const SDL_BlendMode blend = cmd->data.draw.blend;
|
||||
SetDrawState(surface, &drawstate);
|
||||
if (blend == SDL_BLENDMODE_NONE) {
|
||||
SDL_DrawPoints(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
} else {
|
||||
|
@ -646,6 +668,7 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
|
|||
const int count = (int) cmd->data.draw.count;
|
||||
const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
const SDL_BlendMode blend = cmd->data.draw.blend;
|
||||
SetDrawState(surface, &drawstate);
|
||||
if (blend == SDL_BLENDMODE_NONE) {
|
||||
SDL_DrawLines(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
} else {
|
||||
|
@ -662,6 +685,7 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
|
|||
const int count = (int) cmd->data.draw.count;
|
||||
const SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
const SDL_BlendMode blend = cmd->data.draw.blend;
|
||||
SetDrawState(surface, &drawstate);
|
||||
if (blend == SDL_BLENDMODE_NONE) {
|
||||
SDL_FillRects(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
|
||||
} else {
|
||||
|
@ -677,6 +701,8 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
|
|||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
|
||||
|
||||
SetDrawState(surface, &drawstate);
|
||||
|
||||
PrepTextureForCopy(cmd);
|
||||
|
||||
if ( srcrect->w == dstrect->w && srcrect->h == dstrect->h ) {
|
||||
|
@ -693,6 +719,7 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
|
|||
|
||||
case SDL_RENDERCMD_COPY_EX: {
|
||||
const CopyExData *copydata = (CopyExData *) (((Uint8 *) vertices) + cmd->data.draw.first);
|
||||
SetDrawState(surface, &drawstate);
|
||||
PrepTextureForCopy(cmd);
|
||||
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, ©data->srcrect,
|
||||
©data->dstrect, copydata->angle, ©data->center, copydata->flip);
|
||||
|
|
Loading…
Reference in New Issue