|
@@ -127,7 +127,7 @@ typedef struct GLES2_ProgramCacheEntry
|
|
|
GLuint fragment_shader;
|
|
GLuint fragment_shader;
|
|
|
GLuint uniform_locations[NUM_GLES2_UNIFORMS];
|
|
GLuint uniform_locations[NUM_GLES2_UNIFORMS];
|
|
|
GLfloat projection[4][4];
|
|
GLfloat projection[4][4];
|
|
|
- const float *shader_params;
|
|
|
|
|
|
|
+ float *shader_params;
|
|
|
struct GLES2_ProgramCacheEntry *prev;
|
|
struct GLES2_ProgramCacheEntry *prev;
|
|
|
struct GLES2_ProgramCacheEntry *next;
|
|
struct GLES2_ProgramCacheEntry *next;
|
|
|
} GLES2_ProgramCacheEntry;
|
|
} GLES2_ProgramCacheEntry;
|
|
@@ -466,6 +466,7 @@ static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuin
|
|
|
data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
|
|
data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
|
|
|
if (!linkSuccessful) {
|
|
if (!linkSuccessful) {
|
|
|
data->glDeleteProgram(entry->id);
|
|
data->glDeleteProgram(entry->id);
|
|
|
|
|
+ SDL_free(entry->shader_params);
|
|
|
SDL_free(entry);
|
|
SDL_free(entry);
|
|
|
SDL_SetError("Failed to link shader program");
|
|
SDL_SetError("Failed to link shader program");
|
|
|
return NULL;
|
|
return NULL;
|
|
@@ -505,12 +506,11 @@ static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuin
|
|
|
|
|
|
|
|
// Evict the last entry from the cache if we exceed the limit
|
|
// Evict the last entry from the cache if we exceed the limit
|
|
|
if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
|
|
if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
|
|
|
- data->glDeleteProgram(data->program_cache.tail->id);
|
|
|
|
|
- data->program_cache.tail = data->program_cache.tail->prev;
|
|
|
|
|
- if (data->program_cache.tail) {
|
|
|
|
|
- SDL_free(data->program_cache.tail->next);
|
|
|
|
|
- data->program_cache.tail->next = NULL;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ GLES2_ProgramCacheEntry *oldest = data->program_cache.tail;
|
|
|
|
|
+ data->program_cache.tail = oldest->prev;
|
|
|
|
|
+ data->glDeleteProgram(oldest->id);
|
|
|
|
|
+ SDL_free(oldest->shader_params);
|
|
|
|
|
+ SDL_free(oldest);
|
|
|
--data->program_cache.count;
|
|
--data->program_cache.count;
|
|
|
}
|
|
}
|
|
|
return entry;
|
|
return entry;
|
|
@@ -629,6 +629,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
GLES2_ProgramCacheEntry *program;
|
|
GLES2_ProgramCacheEntry *program;
|
|
|
GLES2_TextureData *tdata = texture ? (GLES2_TextureData *)texture->internal : NULL;
|
|
GLES2_TextureData *tdata = texture ? (GLES2_TextureData *)texture->internal : NULL;
|
|
|
const float *shader_params = NULL;
|
|
const float *shader_params = NULL;
|
|
|
|
|
+ int shader_params_len = 0;
|
|
|
|
|
|
|
|
// Select an appropriate shader pair for the specified modes
|
|
// Select an appropriate shader pair for the specified modes
|
|
|
vtype = GLES2_SHADER_VERTEX_DEFAULT;
|
|
vtype = GLES2_SHADER_VERTEX_DEFAULT;
|
|
@@ -644,10 +645,12 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
case SDL_SCALEMODE_LINEAR:
|
|
case SDL_SCALEMODE_LINEAR:
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR;
|
|
|
shader_params = tdata->texel_size;
|
|
shader_params = tdata->texel_size;
|
|
|
|
|
+ shader_params_len = 4 * sizeof(float);
|
|
|
break;
|
|
break;
|
|
|
case SDL_SCALEMODE_PIXELART:
|
|
case SDL_SCALEMODE_PIXELART:
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART;
|
|
|
shader_params = tdata->texel_size;
|
|
shader_params = tdata->texel_size;
|
|
|
|
|
+ shader_params_len = 4 * sizeof(float);
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
SDL_assert(!"Unknown scale mode");
|
|
SDL_assert(!"Unknown scale mode");
|
|
@@ -658,6 +661,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_PIXELART;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_PIXELART;
|
|
|
shader_params = tdata->texel_size;
|
|
shader_params = tdata->texel_size;
|
|
|
|
|
+ shader_params_len = 4 * sizeof(float);
|
|
|
} else {
|
|
} else {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR;
|
|
|
}
|
|
}
|
|
@@ -666,6 +670,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_PIXELART;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_PIXELART;
|
|
|
shader_params = tdata->texel_size;
|
|
shader_params = tdata->texel_size;
|
|
|
|
|
+ shader_params_len = 4 * sizeof(float);
|
|
|
} else {
|
|
} else {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB;
|
|
|
}
|
|
}
|
|
@@ -674,6 +679,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_PIXELART;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_PIXELART;
|
|
|
shader_params = tdata->texel_size;
|
|
shader_params = tdata->texel_size;
|
|
|
|
|
+ shader_params_len = 4 * sizeof(float);
|
|
|
} else {
|
|
} else {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB;
|
|
|
}
|
|
}
|
|
@@ -682,6 +688,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
if (scale_mode == SDL_SCALEMODE_PIXELART) {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_PIXELART;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_PIXELART;
|
|
|
shader_params = tdata->texel_size;
|
|
shader_params = tdata->texel_size;
|
|
|
|
|
+ shader_params_len = 4 * sizeof(float);
|
|
|
} else {
|
|
} else {
|
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR;
|
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR;
|
|
|
}
|
|
}
|
|
@@ -694,6 +701,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
SDL_SetError("Unsupported YUV colorspace");
|
|
SDL_SetError("Unsupported YUV colorspace");
|
|
|
goto fault;
|
|
goto fault;
|
|
|
}
|
|
}
|
|
|
|
|
+ shader_params_len = 16 * sizeof(float);
|
|
|
break;
|
|
break;
|
|
|
case GLES2_IMAGESOURCE_TEXTURE_NV12:
|
|
case GLES2_IMAGESOURCE_TEXTURE_NV12:
|
|
|
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
|
|
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
|
|
@@ -706,6 +714,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
SDL_SetError("Unsupported YUV colorspace");
|
|
SDL_SetError("Unsupported YUV colorspace");
|
|
|
goto fault;
|
|
goto fault;
|
|
|
}
|
|
}
|
|
|
|
|
+ shader_params_len = 16 * sizeof(float);
|
|
|
break;
|
|
break;
|
|
|
case GLES2_IMAGESOURCE_TEXTURE_NV21:
|
|
case GLES2_IMAGESOURCE_TEXTURE_NV21:
|
|
|
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
|
|
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
|
|
@@ -718,6 +727,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
SDL_SetError("Unsupported YUV colorspace");
|
|
SDL_SetError("Unsupported YUV colorspace");
|
|
|
goto fault;
|
|
goto fault;
|
|
|
}
|
|
}
|
|
|
|
|
+ shader_params_len = 16 * sizeof(float);
|
|
|
break;
|
|
break;
|
|
|
#endif // SDL_HAVE_YUV
|
|
#endif // SDL_HAVE_YUV
|
|
|
case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
|
|
case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
|
|
@@ -762,7 +772,11 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
// Select that program in OpenGL
|
|
// Select that program in OpenGL
|
|
|
data->glUseProgram(program->id);
|
|
data->glUseProgram(program->id);
|
|
|
|
|
|
|
|
- if (shader_params && shader_params != program->shader_params) {
|
|
|
|
|
|
|
+ SDL_assert(!shader_params || shader_params_len > 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (shader_params &&
|
|
|
|
|
+ (!program->shader_params ||
|
|
|
|
|
+ SDL_memcmp(shader_params, program->shader_params, shader_params_len) != 0)) {
|
|
|
#ifdef SDL_HAVE_YUV
|
|
#ifdef SDL_HAVE_YUV
|
|
|
if (ftype >= GLES2_SHADER_FRAGMENT_TEXTURE_YUV) {
|
|
if (ftype >= GLES2_SHADER_FRAGMENT_TEXTURE_YUV) {
|
|
|
// YUV shader params are Yoffset, 0, Rcoeff, 0, Gcoeff, 0, Bcoeff, 0
|
|
// YUV shader params are Yoffset, 0, Rcoeff, 0, Gcoeff, 0, Bcoeff, 0
|
|
@@ -789,7 +803,13 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL
|
|
|
if (shader_params) {
|
|
if (shader_params) {
|
|
|
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_TEXEL_SIZE], shader_params[0], shader_params[1], shader_params[2], shader_params[3]);
|
|
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_TEXEL_SIZE], shader_params[0], shader_params[1], shader_params[2], shader_params[3]);
|
|
|
}
|
|
}
|
|
|
- program->shader_params = shader_params;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (!program->shader_params) {
|
|
|
|
|
+ program->shader_params = (float *)SDL_malloc(shader_params_len);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (program->shader_params) {
|
|
|
|
|
+ SDL_memcpy(program->shader_params, shader_params, shader_params_len);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Set the current program
|
|
// Set the current program
|
|
@@ -1636,8 +1656,9 @@ static void GLES2_DestroyRenderer(SDL_Renderer *renderer)
|
|
|
GLES2_ProgramCacheEntry *next;
|
|
GLES2_ProgramCacheEntry *next;
|
|
|
entry = data->program_cache.head;
|
|
entry = data->program_cache.head;
|
|
|
while (entry) {
|
|
while (entry) {
|
|
|
- data->glDeleteProgram(entry->id);
|
|
|
|
|
next = entry->next;
|
|
next = entry->next;
|
|
|
|
|
+ data->glDeleteProgram(entry->id);
|
|
|
|
|
+ SDL_free(entry->shader_params);
|
|
|
SDL_free(entry);
|
|
SDL_free(entry);
|
|
|
entry = next;
|
|
entry = next;
|
|
|
}
|
|
}
|
|
@@ -2196,6 +2217,7 @@ static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|
|
|
|
|
|
|
if (data->drawstate.texture == texture) {
|
|
if (data->drawstate.texture == texture) {
|
|
|
data->drawstate.texture = NULL;
|
|
data->drawstate.texture = NULL;
|
|
|
|
|
+ data->drawstate.shader_params = NULL;
|
|
|
}
|
|
}
|
|
|
if (data->drawstate.target == texture) {
|
|
if (data->drawstate.target == texture) {
|
|
|
data->drawstate.target = NULL;
|
|
data->drawstate.target = NULL;
|