mirror of https://github.com/encounter/SDL.git
Avoid redundant state changes in the GLES2 renderer.
This commit is contained in:
parent
500e4f6f9a
commit
5607cc45c5
|
@ -81,6 +81,7 @@ typedef struct GLES2_ShaderCacheEntry
|
|||
GLES2_ShaderType type;
|
||||
const GLES2_ShaderInstance *instance;
|
||||
int references;
|
||||
Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
|
||||
struct GLES2_ShaderCacheEntry *prev;
|
||||
struct GLES2_ShaderCacheEntry *next;
|
||||
} GLES2_ShaderCacheEntry;
|
||||
|
@ -98,6 +99,9 @@ typedef struct GLES2_ProgramCacheEntry
|
|||
GLES2_ShaderCacheEntry *vertex_shader;
|
||||
GLES2_ShaderCacheEntry *fragment_shader;
|
||||
GLuint uniform_locations[16];
|
||||
Uint8 color_r, color_g, color_b, color_a;
|
||||
Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
|
||||
GLfloat projection[4][4];
|
||||
struct GLES2_ProgramCacheEntry *prev;
|
||||
struct GLES2_ProgramCacheEntry *next;
|
||||
} GLES2_ProgramCacheEntry;
|
||||
|
@ -156,6 +160,7 @@ typedef struct GLES2_DriverContext
|
|||
GLES2_ShaderCache shader_cache;
|
||||
GLES2_ProgramCache program_cache;
|
||||
GLES2_ProgramCacheEntry *current_program;
|
||||
Uint8 clear_r, clear_g, clear_b, clear_a;
|
||||
} GLES2_DriverContext;
|
||||
|
||||
#define GLES2_MAX_CACHED_PROGRAMS 8
|
||||
|
@ -492,8 +497,6 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
return -1;
|
||||
}
|
||||
texture->driverdata = data;
|
||||
|
||||
renderdata->glActiveTexture(GL_TEXTURE0);
|
||||
renderdata->glBindTexture(data->texture_type, data->texture);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||
|
@ -549,9 +552,7 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
}
|
||||
|
||||
/* Create a texture subimage with the supplied data */
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
data->glTexSubImage2D(tdata->texture_type,
|
||||
0,
|
||||
rect->x,
|
||||
|
@ -720,7 +721,16 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
|
|||
entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
|
||||
data->glGetUniformLocation(entry->id, "u_modulation");
|
||||
entry->uniform_locations[GLES2_UNIFORM_COLOR] =
|
||||
rdata->glGetUniformLocation(entry->id, "u_color");
|
||||
data->glGetUniformLocation(entry->id, "u_color");
|
||||
|
||||
entry->modulation_r = entry->modulation_g = entry->modulation_b = entry->modulation_a = 1.0f;
|
||||
entry->color_r = entry->color_g = entry->color_b = entry->color_a = 1.0f;
|
||||
|
||||
data->glUseProgram(entry->id);
|
||||
data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
|
||||
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */
|
||||
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
/* Cache the linked program */
|
||||
if (data->program_cache.head)
|
||||
|
@ -959,7 +969,6 @@ GLES2_SetOrthographicProjection(SDL_Renderer *renderer)
|
|||
{
|
||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||
GLfloat projection[4][4];
|
||||
GLuint locProjection;
|
||||
|
||||
if (!renderer->viewport.w || !renderer->viewport.h) {
|
||||
return 0;
|
||||
|
@ -992,8 +1001,12 @@ GLES2_SetOrthographicProjection(SDL_Renderer *renderer)
|
|||
projection[3][3] = 1.0f;
|
||||
|
||||
/* Set the projection matrix */
|
||||
locProjection = data->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
|
||||
data->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
|
||||
if (SDL_memcmp(data->current_program->projection, projection, sizeof (projection)) != 0) {
|
||||
const GLuint locProjection = data->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
|
||||
data->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
|
||||
SDL_memcpy(data->current_program->projection, projection, sizeof (projection));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1024,10 +1037,18 @@ GLES2_RenderClear(SDL_Renderer * renderer)
|
|||
|
||||
GLES2_ActivateRenderer(renderer);
|
||||
|
||||
data->glClearColor((GLfloat) renderer->r * inv255f,
|
||||
(GLfloat) renderer->g * inv255f,
|
||||
(GLfloat) renderer->b * inv255f,
|
||||
(GLfloat) renderer->a * inv255f);
|
||||
/* !!! FIXME: it'd be nice to do a single 32-bit compare here. */
|
||||
if ( (data->clear_r != renderer->r) || (data->clear_g != renderer->g) ||
|
||||
(data->clear_b != renderer->b) || (data->clear_a != renderer->a) ) {
|
||||
data->glClearColor((GLfloat) renderer->r * inv255f,
|
||||
(GLfloat) renderer->g * inv255f,
|
||||
(GLfloat) renderer->b * inv255f,
|
||||
(GLfloat) renderer->a * inv255f);
|
||||
data->clear_r = renderer->r;
|
||||
data->clear_g = renderer->g;
|
||||
data->clear_b = renderer->b;
|
||||
data->clear_a = renderer->a;
|
||||
}
|
||||
|
||||
data->glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
@ -1077,8 +1098,9 @@ static int
|
|||
GLES2_SetDrawingState(SDL_Renderer * renderer)
|
||||
{
|
||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||
int blendMode = renderer->blendMode;
|
||||
GLuint locColor;
|
||||
const int blendMode = renderer->blendMode;
|
||||
GLES2_ProgramCacheEntry *program;
|
||||
Uint8 r, g, b, a;
|
||||
|
||||
GLES2_ActivateRenderer(renderer);
|
||||
|
||||
|
@ -1087,26 +1109,35 @@ GLES2_SetDrawingState(SDL_Renderer * renderer)
|
|||
GLES2_SetTexCoords(data, SDL_FALSE);
|
||||
|
||||
/* Activate an appropriate shader and set the projection matrix */
|
||||
if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
|
||||
if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Select the color to draw with */
|
||||
locColor = data->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
|
||||
g = renderer->g;
|
||||
a = renderer->a;
|
||||
|
||||
if (renderer->target &&
|
||||
(renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
|
||||
(renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
|
||||
renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
|
||||
data->glUniform4f(locColor,
|
||||
renderer->b * inv255f,
|
||||
renderer->g * inv255f,
|
||||
renderer->r * inv255f,
|
||||
renderer->a * inv255f);
|
||||
} else {
|
||||
data->glUniform4f(locColor,
|
||||
renderer->r * inv255f,
|
||||
renderer->g * inv255f,
|
||||
renderer->b * inv255f,
|
||||
renderer->a * inv255f);
|
||||
r = renderer->b;
|
||||
b = renderer->r;
|
||||
} else {
|
||||
r = renderer->r;
|
||||
b = renderer->b;
|
||||
}
|
||||
|
||||
program = data->current_program;
|
||||
/* !!! FIXME: it'd be nice to do a single 32-bit compare here. */
|
||||
if ( (program->color_r != r) || (program->color_g != g) || (program->color_b != b) || (program->color_a != a) ) {
|
||||
/* Select the color to draw with */
|
||||
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
|
||||
program->color_r = r;
|
||||
program->color_g = g;
|
||||
program->color_b = b;
|
||||
program->color_a = a;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1213,8 +1244,8 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
SDL_BlendMode blendMode;
|
||||
GLfloat vertices[8];
|
||||
GLfloat texCoords[8];
|
||||
GLuint locTexture;
|
||||
GLuint locModulation;
|
||||
GLES2_ProgramCacheEntry *program;
|
||||
Uint8 r, g, b, a;
|
||||
|
||||
GLES2_ActivateRenderer(renderer);
|
||||
|
||||
|
@ -1300,31 +1331,37 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
|
||||
|
||||
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Select the target texture */
|
||||
locTexture = data->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
data->glUniform1i(locTexture, 0);
|
||||
|
||||
/* Configure color modulation */
|
||||
locModulation = data->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
|
||||
g = texture->g;
|
||||
a = texture->a;
|
||||
|
||||
if (renderer->target &&
|
||||
(renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
|
||||
renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
|
||||
data->glUniform4f(locModulation,
|
||||
texture->b * inv255f,
|
||||
texture->g * inv255f,
|
||||
texture->r * inv255f,
|
||||
texture->a * inv255f);
|
||||
r = texture->b;
|
||||
b = texture->r;
|
||||
} else {
|
||||
data->glUniform4f(locModulation,
|
||||
texture->r * inv255f,
|
||||
texture->g * inv255f,
|
||||
texture->b * inv255f,
|
||||
texture->a * inv255f);
|
||||
r = texture->r;
|
||||
b = texture->b;
|
||||
}
|
||||
|
||||
program = data->current_program;
|
||||
|
||||
/* !!! FIXME: it'd be nice to do a single 32-bit compare here. */
|
||||
if ( (program->modulation_r != r) || (program->modulation_g != g) || (program->modulation_b != b) || (program->modulation_a != a) ) {
|
||||
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
|
||||
program->modulation_r = r;
|
||||
program->modulation_g = g;
|
||||
program->modulation_b = b;
|
||||
program->modulation_a = a;
|
||||
}
|
||||
|
||||
/* Configure texture blending */
|
||||
|
@ -1363,11 +1400,11 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||
GLES2_ProgramCacheEntry *program;
|
||||
Uint8 r, g, b, a;
|
||||
SDL_BlendMode blendMode;
|
||||
GLfloat vertices[8];
|
||||
GLfloat texCoords[8];
|
||||
GLuint locTexture;
|
||||
GLuint locModulation;
|
||||
GLfloat translate[8];
|
||||
GLfloat fAngle[4];
|
||||
GLfloat tmp;
|
||||
|
@ -1467,27 +1504,32 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
return -1;
|
||||
|
||||
/* Select the target texture */
|
||||
locTexture = data->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
data->glUniform1i(locTexture, 0);
|
||||
|
||||
/* Configure color modulation */
|
||||
locModulation = data->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
|
||||
/* !!! FIXME: grep for glUniform4f(), move that stuff to a subroutine, it's a lot of copy/paste. */
|
||||
g = texture->g;
|
||||
a = texture->a;
|
||||
|
||||
if (renderer->target &&
|
||||
(renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
|
||||
renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
|
||||
data->glUniform4f(locModulation,
|
||||
texture->b * inv255f,
|
||||
texture->g * inv255f,
|
||||
texture->r * inv255f,
|
||||
texture->a * inv255f);
|
||||
r = texture->b;
|
||||
b = texture->r;
|
||||
} else {
|
||||
data->glUniform4f(locModulation,
|
||||
texture->r * inv255f,
|
||||
texture->g * inv255f,
|
||||
texture->b * inv255f,
|
||||
texture->a * inv255f);
|
||||
r = texture->r;
|
||||
b = texture->b;
|
||||
}
|
||||
|
||||
program = data->current_program;
|
||||
|
||||
/* !!! FIXME: it'd be nice to do a single 32-bit compare here. */
|
||||
if ( (program->modulation_r != r) || (program->modulation_g != g) || (program->modulation_b != b) || (program->modulation_a != a) ) {
|
||||
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
|
||||
program->modulation_r = r;
|
||||
program->modulation_g = g;
|
||||
program->modulation_b = b;
|
||||
program->modulation_a = a;
|
||||
}
|
||||
|
||||
/* Configure texture blending */
|
||||
|
@ -1557,8 +1599,6 @@ GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
|||
|
||||
SDL_GetRendererOutputSize(renderer, &w, &h);
|
||||
|
||||
data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
|
||||
if (GL_CheckError("glReadPixels()", renderer) < 0) {
|
||||
|
@ -1650,6 +1690,15 @@ GLES2_ResetState(SDL_Renderer *renderer)
|
|||
data->current.blendMode = -1;
|
||||
data->current.tex_coords = SDL_FALSE;
|
||||
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
data->glClearColor((GLfloat) data->clear_r * inv255f,
|
||||
(GLfloat) data->clear_g * inv255f,
|
||||
(GLfloat) data->clear_b * inv255f,
|
||||
(GLfloat) data->clear_a * inv255f);
|
||||
|
||||
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
|
||||
data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
|
||||
|
||||
|
|
|
@ -121,6 +121,8 @@
|
|||
if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
/* end create buffers */
|
||||
|
||||
self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
|
||||
|
@ -148,6 +150,8 @@
|
|||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
|
||||
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
|
||||
}
|
||||
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
}
|
||||
|
||||
- (void)setAnimationCallback:(int)interval
|
||||
|
@ -197,7 +201,9 @@
|
|||
|
||||
- (void)swapBuffers
|
||||
{
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
/* viewRenderbuffer should always be bound here. Code that binds something
|
||||
else is responsible for rebinding viewRenderbuffer, to reduce
|
||||
duplicate state changes. */
|
||||
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue