Skip to content

Commit

Permalink
render: Make the GL backends cache and defer more state changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Oct 2, 2018
1 parent fcb4681 commit 0c2e10d
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 107 deletions.
84 changes: 53 additions & 31 deletions src/render/opengl/SDL_render_gl.c
Expand Up @@ -62,11 +62,17 @@ struct GL_FBOList

typedef struct
{
SDL_bool viewport_dirty;
SDL_Rect viewport;
SDL_Texture *texture;
SDL_Texture *target;
int drawablew;
int drawableh;
SDL_BlendMode blend;
GL_Shader shader;
SDL_bool cliprect_enabled_dirty;
SDL_bool cliprect_enabled;
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
Uint32 color;
Expand Down Expand Up @@ -934,6 +940,42 @@ SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader
{
const SDL_BlendMode blend = cmd->data.draw.blend;

if (data->drawstate.viewport_dirty) {
const SDL_bool istarget = data->drawstate.target != NULL;
const SDL_Rect *viewport = &data->drawstate.viewport;
data->glMatrixMode(GL_PROJECTION);
data->glLoadIdentity();
data->glViewport(viewport->x,
istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
viewport->w, viewport->h);
if (viewport->w && viewport->h) {
data->glOrtho((GLdouble) 0, (GLdouble) viewport->w,
(GLdouble) istarget ? 0 : viewport->h,
(GLdouble) istarget ? viewport->h : 0,
0.0, 1.0);
}
data->glMatrixMode(GL_MODELVIEW);
data->drawstate.viewport_dirty = SDL_FALSE;
}

if (data->drawstate.cliprect_enabled_dirty) {
if (!data->drawstate.cliprect_enabled) {
data->glDisable(GL_SCISSOR_TEST);
} else {
data->glEnable(GL_SCISSOR_TEST);
}
data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
}

if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
const SDL_Rect *rect = &data->drawstate.cliprect;
data->glScissor(viewport->x + rect->x,
data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
rect->w, rect->h);
data->drawstate.cliprect_dirty = SDL_FALSE;
}

if (blend != data->drawstate.blend) {
if (blend == SDL_BLENDMODE_NONE) {
data->glDisable(GL_BLEND);
Expand Down Expand Up @@ -1035,18 +1077,18 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
{
/* !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode... */
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
int drawablew = 0, drawableh = 0;
const SDL_bool istarget = renderer->target != NULL;
size_t i;

if (GL_ActivateRenderer(renderer) < 0) {
return -1;
}

if (!istarget) {
SDL_GL_GetDrawableSize(renderer->window, &drawablew, &drawableh);
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
}


while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_SETDRAWCOLOR: {
Expand All @@ -1069,18 +1111,7 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
SDL_Rect *viewport = &data->drawstate.viewport;
if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
data->glMatrixMode(GL_PROJECTION);
data->glLoadIdentity();
data->glViewport(viewport->x,
istarget ? viewport->y : (drawableh - viewport->y - viewport->h),
viewport->w, viewport->h);
if (viewport->w && viewport->h) {
data->glOrtho((GLdouble) 0, (GLdouble) viewport->w,
(GLdouble) istarget ? 0 : viewport->h,
(GLdouble) istarget ? viewport->h : 0,
0.0, 1.0);
}
data->glMatrixMode(GL_MODELVIEW);
data->drawstate.viewport_dirty = SDL_TRUE;
}
break;
}
Expand All @@ -1089,18 +1120,11 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
const SDL_Rect *rect = &cmd->data.cliprect.rect;
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
if (!data->drawstate.cliprect_enabled) {
data->glDisable(GL_SCISSOR_TEST);
} else {
const SDL_Rect *viewport = &data->drawstate.viewport;
data->glEnable(GL_SCISSOR_TEST);
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
data->glScissor(viewport->x + rect->x,
istarget ? viewport->y + rect->y : drawableh - viewport->y - rect->y - rect->h,
rect->w, rect->h);
SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
}
}
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
data->drawstate.cliprect_dirty = SDL_TRUE;
}
break;
}
Expand All @@ -1122,13 +1146,11 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic

if (data->drawstate.cliprect_enabled) {
data->glDisable(GL_SCISSOR_TEST);
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}

data->glClear(GL_COLOR_BUFFER_BIT);

if (data->drawstate.cliprect_enabled) {
data->glEnable(GL_SCISSOR_TEST);
}
break;
}

Expand Down
113 changes: 69 additions & 44 deletions src/render/opengles/SDL_render_gles.c
Expand Up @@ -64,9 +64,15 @@ struct GLES_FBOList
typedef struct
{
SDL_Rect viewport;
SDL_bool viewport_dirty;
SDL_Texture *texture;
SDL_Texture *target;
int drawablew;
int drawableh;
SDL_BlendMode blend;
SDL_bool cliprect_enabled_dirty;
SDL_bool cliprect_enabled;
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
Uint32 color;
Expand Down Expand Up @@ -692,6 +698,57 @@ static void
SetDrawState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
{
const SDL_BlendMode blend = cmd->data.draw.blend;
const Uint8 r = cmd->data.color.r;
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);

if (color != data->drawstate.color) {
const GLfloat fr = ((GLfloat) r) * inv255f;
const GLfloat fg = ((GLfloat) g) * inv255f;
const GLfloat fb = ((GLfloat) b) * inv255f;
const GLfloat fa = ((GLfloat) a) * inv255f;
data->glColor4f(fr, fg, fb, fa);
data->drawstate.color = color;
}

if (data->drawstate.viewport_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
const SDL_bool istarget = (data->drawstate.target != NULL);
data->glMatrixMode(GL_PROJECTION);
data->glLoadIdentity();
data->glViewport(viewport->x,
istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
viewport->w, viewport->h);
if (viewport->w && viewport->h) {
data->glOrthof((GLfloat) 0, (GLfloat) viewport->w,
(GLfloat) istarget ? 0 : viewport->h,
(GLfloat) istarget ? viewport->h : 0,
0.0, 1.0);
}
data->glMatrixMode(GL_MODELVIEW);
data->drawstate.viewport_dirty = SDL_FALSE;
}

if (data->drawstate.cliprect_enabled_dirty) {
if (data->drawstate.cliprect_enabled) {
data->glEnable(GL_SCISSOR_TEST);
} else {
data->glDisable(GL_SCISSOR_TEST);
}
data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
}

if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
const SDL_Rect *rect = &data->drawstate.cliprect;
const SDL_bool istarget = (data->drawstate.target != NULL);
data->glScissor(viewport->x + rect->x,
istarget ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
rect->w, rect->h);
data->drawstate.cliprect_dirty = SDL_FALSE;
}

if (blend != data->drawstate.blend) {
if (blend == SDL_BLENDMODE_NONE) {
Expand Down Expand Up @@ -747,52 +804,29 @@ static int
GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
int drawablew = 0, drawableh = 0;
const SDL_bool istarget = renderer->target != NULL;
size_t i;

if (GLES_ActivateRenderer(renderer) < 0) {
return -1;
}

if (!istarget) {
SDL_GL_GetDrawableSize(renderer->window, &drawablew, &drawableh);
data->drawstate.target = renderer->target;

if (!renderer->target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
}

while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_SETDRAWCOLOR: {
const Uint8 r = cmd->data.color.r;
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.color) {
data->glColor4f((GLfloat) r * inv255f,
(GLfloat) g * inv255f,
(GLfloat) b * inv255f,
(GLfloat) a * inv255f);
data->drawstate.color = color;
}
break;
break; /* not used in this render backend. */
}

case SDL_RENDERCMD_SETVIEWPORT: {
SDL_Rect *viewport = &data->drawstate.viewport;
if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
data->glMatrixMode(GL_PROJECTION);
data->glLoadIdentity();
data->glViewport(viewport->x,
istarget ? viewport->y : (drawableh - viewport->y - viewport->h),
viewport->w, viewport->h);
if (viewport->w && viewport->h) {
data->glOrthof((GLfloat) 0, (GLfloat) viewport->w,
(GLfloat) istarget ? 0 : viewport->h,
(GLfloat) istarget ? viewport->h : 0,
0.0, 1.0);
}
data->glMatrixMode(GL_MODELVIEW);
data->drawstate.viewport_dirty = SDL_TRUE;
}
break;
}
Expand All @@ -801,18 +835,11 @@ GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vert
const SDL_Rect *rect = &cmd->data.cliprect.rect;
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
if (!data->drawstate.cliprect_enabled) {
data->glDisable(GL_SCISSOR_TEST);
} else {
const SDL_Rect *viewport = &data->drawstate.viewport;
data->glEnable(GL_SCISSOR_TEST);
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
data->glScissor(viewport->x + rect->x,
istarget ? viewport->y + rect->y : drawableh - viewport->y - rect->y - rect->h,
rect->w, rect->h);
SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
}
}
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
data->drawstate.cliprect_dirty = SDL_TRUE;
}
break;
}
Expand All @@ -834,13 +861,11 @@ GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vert

if (data->drawstate.cliprect_enabled) {
data->glDisable(GL_SCISSOR_TEST);
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}

data->glClear(GL_COLOR_BUFFER_BIT);

if (data->drawstate.cliprect_enabled) {
data->glEnable(GL_SCISSOR_TEST);
}
break;
}

Expand Down

0 comments on commit 0c2e10d

Please sign in to comment.