diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 2585d4366..492a0c1ba 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -495,30 +495,34 @@ GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_t { GLuint id; GLint compileSuccessful = GL_FALSE; - int num_src = 0; - const GLchar *shader_src_list[4] = { 0 }; - const GLchar *shader_body = (const GLchar *)GLES2_GetShader(type); + int attempt, num_src; + const GLchar *shader_src_list[2]; + const GLchar *shader_body = GLES2_GetShader(type); if (!shader_body) { SDL_SetError("No shader body src"); return 0; } - if (shader_type == GL_FRAGMENT_SHADER) { - if (data->texcoord_precision_hint != GLES2_SHADER_FRAGMENT_INCLUDE_UNDEF_PRECISION) { - shader_src_list[num_src++] = (const GLchar*)GLES2_GetShaderInclude(GLES2_SHADER_FRAGMENT_INCLUDE_DEFAULT); + for (attempt = 0; attempt < 2 && !compileSuccessful; ++attempt) { + num_src = 0; + if (shader_type == GL_FRAGMENT_SHADER) { + if (attempt == 0) { + shader_src_list[num_src++] = GLES2_GetShaderInclude(data->texcoord_precision_hint); + } else { + shader_src_list[num_src++] = GLES2_GetShaderInclude(GLES2_SHADER_FRAGMENT_INCLUDE_UNDEF_PRECISION); + } } - shader_src_list[num_src++] = (const GLchar*)GLES2_GetShaderInclude(data->texcoord_precision_hint); + shader_src_list[num_src++] = shader_body; + + SDL_assert(num_src <= SDL_arraysize(shader_src_list)); + + /* Compile */ + id = data->glCreateShader(shader_type); + data->glShaderSource(id, num_src, shader_src_list, NULL); + data->glCompileShader(id); + data->glGetShaderiv(id, GL_COMPILE_STATUS, &compileSuccessful); } - shader_src_list[num_src++] = shader_body; - - SDL_assert(num_src < SDL_arraysize(shader_src_list)); - - /* Compile */ - id = data->glCreateShader(shader_type); - data->glShaderSource(id, num_src, shader_src_list, NULL); - data->glCompileShader(id); - data->glGetShaderiv(id, GL_COMPILE_STATUS, &compileSuccessful); if (!compileSuccessful) { SDL_bool isstack = SDL_FALSE; @@ -548,6 +552,27 @@ GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_t return id; } +static int GLES2_CacheShaders(GLES2_RenderData * data) +{ + int shader; + + data->texcoord_precision_hint = GLES2_GetTexCoordPrecisionEnumFromHint(); + + for (shader = 0; shader < GLES2_SHADER_COUNT; ++shader) { + GLenum shader_type; + + if (shader == GLES2_SHADER_VERTEX_DEFAULT) { + shader_type = GL_VERTEX_SHADER; + } else { + shader_type = GL_FRAGMENT_SHADER; + } + if (!GLES2_CacheShader(data, (GLES2_ShaderType) shader, shader_type)) { + return -1; + } + } + return 0; +} + static int GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int h) { @@ -2084,6 +2109,13 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) goto error; } + if (GLES2_CacheShaders(data) < 0) { + SDL_GL_DeleteContext(data->context); + SDL_free(renderer); + SDL_free(data); + goto error; + } + #if __WINRT__ /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync * is turned on. Not doing so will freeze the screen's contents to that @@ -2107,8 +2139,6 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) data->debug_enabled = SDL_TRUE; } - data->texcoord_precision_hint = GLES2_GetTexCoordPrecisionEnumFromHint(); - value = 0; data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); renderer->info.max_texture_width = value; diff --git a/src/render/opengles2/SDL_shaders_gles2.c b/src/render/opengles2/SDL_shaders_gles2.c index c61dc8345..4d48e36f4 100644 --- a/src/render/opengles2/SDL_shaders_gles2.c +++ b/src/render/opengles2/SDL_shaders_gles2.c @@ -32,35 +32,33 @@ * Vertex/fragment shader source * *************************************************************************************************/ -static const Uint8 GLES2_Fragment_Include_Default[] = "\n\ - #version 130\n\ - precision mediump float;\n\ -"; - -static const Uint8 GLES2_Fragment_Include_Best_Texture_Precision[] = "\n\ +static const char GLES2_Fragment_Include_Best_Texture_Precision[] = "\n\ #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ #define SDL_TEXCOORD_PRECISION highp\n\ #else\n\ #define SDL_TEXCOORD_PRECISION mediump\n\ #endif\n\ + precision mediump float;\n\ "; -static const Uint8 GLES2_Fragment_Include_Medium_Texture_Precision[] = "\n\ +static const char GLES2_Fragment_Include_Medium_Texture_Precision[] = "\n\ #define SDL_TEXCOORD_PRECISION mediump\n\ + precision mediump float;\n\ "; -static const Uint8 GLES2_Fragment_Include_High_Texture_Precision[] = "\n\ +static const char GLES2_Fragment_Include_High_Texture_Precision[] = "\n\ #define SDL_TEXCOORD_PRECISION highp\n\ + precision mediump float;\n\ "; -static const Uint8 GLES2_Fragment_Include_Undef_Precision[] = "\n\ +static const char GLES2_Fragment_Include_Undef_Precision[] = "\n\ #define mediump\n\ #define highp\n\ #define lowp\n\ #define SDL_TEXCOORD_PRECISION\n\ "; -static const Uint8 GLES2_Vertex_Default[] = " \ +static const char GLES2_Vertex_Default[] = " \ uniform mat4 u_projection; \ attribute vec2 a_position; \ attribute vec4 a_color; \ @@ -77,7 +75,7 @@ static const Uint8 GLES2_Vertex_Default[] = " \ } \ "; -static const Uint8 GLES2_Fragment_Solid[] = " \ +static const char GLES2_Fragment_Solid[] = " \ varying mediump vec4 v_color; \ \ void main() \ @@ -86,7 +84,7 @@ static const Uint8 GLES2_Fragment_Solid[] = " \ } \ "; -static const Uint8 GLES2_Fragment_TextureABGR[] = " \ +static const char GLES2_Fragment_TextureABGR[] = " \ uniform sampler2D u_texture; \ varying mediump vec4 v_color;\n\ varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ @@ -99,7 +97,7 @@ static const Uint8 GLES2_Fragment_TextureABGR[] = " \ "; /* ARGB to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureARGB[] = " \ +static const char GLES2_Fragment_TextureARGB[] = " \ uniform sampler2D u_texture; \ varying mediump vec4 v_color;\n\ varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ @@ -115,7 +113,7 @@ static const Uint8 GLES2_Fragment_TextureARGB[] = " \ "; /* RGB to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureRGB[] = " \ +static const char GLES2_Fragment_TextureRGB[] = " \ uniform sampler2D u_texture; \ varying mediump vec4 v_color;\n\ varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ @@ -132,7 +130,7 @@ static const Uint8 GLES2_Fragment_TextureRGB[] = " \ "; /* BGR to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureBGR[] = " \ +static const char GLES2_Fragment_TextureBGR[] = " \ uniform sampler2D u_texture; \ varying mediump vec4 v_color;\n\ varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ @@ -266,61 +264,61 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \ "}" \ /* YUV to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureYUVJPEG[] = \ +static const char GLES2_Fragment_TextureYUVJPEG[] = \ YUV_SHADER_PROLOGUE \ JPEG_SHADER_CONSTANTS \ YUV_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureYUVBT601[] = \ +static const char GLES2_Fragment_TextureYUVBT601[] = \ YUV_SHADER_PROLOGUE \ BT601_SHADER_CONSTANTS \ YUV_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureYUVBT709[] = \ +static const char GLES2_Fragment_TextureYUVBT709[] = \ YUV_SHADER_PROLOGUE \ BT709_SHADER_CONSTANTS \ YUV_SHADER_BODY \ ; /* NV12 to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureNV12JPEG[] = \ +static const char GLES2_Fragment_TextureNV12JPEG[] = \ YUV_SHADER_PROLOGUE \ JPEG_SHADER_CONSTANTS \ NV12_RA_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureNV12BT601_RA[] = \ +static const char GLES2_Fragment_TextureNV12BT601_RA[] = \ YUV_SHADER_PROLOGUE \ BT601_SHADER_CONSTANTS \ NV12_RA_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureNV12BT601_RG[] = \ +static const char GLES2_Fragment_TextureNV12BT601_RG[] = \ YUV_SHADER_PROLOGUE \ BT601_SHADER_CONSTANTS \ NV12_RG_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureNV12BT709_RA[] = \ +static const char GLES2_Fragment_TextureNV12BT709_RA[] = \ YUV_SHADER_PROLOGUE \ BT709_SHADER_CONSTANTS \ NV12_RA_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureNV12BT709_RG[] = \ +static const char GLES2_Fragment_TextureNV12BT709_RG[] = \ YUV_SHADER_PROLOGUE \ BT709_SHADER_CONSTANTS \ NV12_RG_SHADER_BODY \ ; /* NV21 to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureNV21JPEG[] = \ +static const char GLES2_Fragment_TextureNV21JPEG[] = \ YUV_SHADER_PROLOGUE \ JPEG_SHADER_CONSTANTS \ NV21_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureNV21BT601[] = \ +static const char GLES2_Fragment_TextureNV21BT601[] = \ YUV_SHADER_PROLOGUE \ BT601_SHADER_CONSTANTS \ NV21_SHADER_BODY \ ; -static const Uint8 GLES2_Fragment_TextureNV21BT709[] = \ +static const char GLES2_Fragment_TextureNV21BT709[] = \ YUV_SHADER_PROLOGUE \ BT709_SHADER_CONSTANTS \ NV21_SHADER_BODY \ @@ -328,7 +326,7 @@ static const Uint8 GLES2_Fragment_TextureNV21BT709[] = \ #endif /* Custom Android video format texture */ -static const Uint8 GLES2_Fragment_TextureExternalOES[] = " \ +static const char GLES2_Fragment_TextureExternalOES[] = " \ #extension GL_OES_EGL_image_external : require\n\ uniform samplerExternalOES u_texture; \ varying mediump vec4 v_color;\n\ @@ -346,10 +344,8 @@ static const Uint8 GLES2_Fragment_TextureExternalOES[] = " \ * Shader selector * *************************************************************************************************/ -const Uint8 *GLES2_GetShaderInclude(GLES2_ShaderIncludeType type) { +const char *GLES2_GetShaderInclude(GLES2_ShaderIncludeType type) { switch (type) { - case GLES2_SHADER_FRAGMENT_INCLUDE_DEFAULT: - return GLES2_Fragment_Include_Default; case GLES2_SHADER_FRAGMENT_INCLUDE_UNDEF_PRECISION: return GLES2_Fragment_Include_Undef_Precision; case GLES2_SHADER_FRAGMENT_INCLUDE_BEST_TEXCOORD_PRECISION: @@ -359,13 +355,13 @@ const Uint8 *GLES2_GetShaderInclude(GLES2_ShaderIncludeType type) { case GLES2_SHADER_FRAGMENT_INCLUDE_HIGH_TEXCOORD_PRECISION: return GLES2_Fragment_Include_High_Texture_Precision; default: - return (Uint8*)""; + return ""; } } GLES2_ShaderIncludeType GLES2_GetTexCoordPrecisionEnumFromHint() { const char *texcoord_hint = SDL_GetHint("SDL_RENDER_OPENGLES2_TEXCOORD_PRECISION"); - GLES2_ShaderIncludeType value = GLES2_SHADER_FRAGMENT_INCLUDE_BEST_TEXCOORD_PRECISION; // "best" + GLES2_ShaderIncludeType value = GLES2_SHADER_FRAGMENT_INCLUDE_BEST_TEXCOORD_PRECISION; if (texcoord_hint) { if (SDL_strcmp(texcoord_hint, "undefined") == 0) return GLES2_SHADER_FRAGMENT_INCLUDE_UNDEF_PRECISION; @@ -377,7 +373,7 @@ GLES2_ShaderIncludeType GLES2_GetTexCoordPrecisionEnumFromHint() { return value; } -const Uint8 *GLES2_GetShader(GLES2_ShaderType type) +const char *GLES2_GetShader(GLES2_ShaderType type) { switch (type) { case GLES2_SHADER_VERTEX_DEFAULT: diff --git a/src/render/opengles2/SDL_shaders_gles2.h b/src/render/opengles2/SDL_shaders_gles2.h index e975407ea..c3d59284e 100644 --- a/src/render/opengles2/SDL_shaders_gles2.h +++ b/src/render/opengles2/SDL_shaders_gles2.h @@ -28,7 +28,6 @@ typedef enum { GLES2_SHADER_FRAGMENT_INCLUDE_NONE = 0, - GLES2_SHADER_FRAGMENT_INCLUDE_DEFAULT, GLES2_SHADER_FRAGMENT_INCLUDE_BEST_TEXCOORD_PRECISION, GLES2_SHADER_FRAGMENT_INCLUDE_MEDIUM_TEXCOORD_PRECISION, GLES2_SHADER_FRAGMENT_INCLUDE_HIGH_TEXCOORD_PRECISION, @@ -61,8 +60,8 @@ typedef enum GLES2_SHADER_COUNT } GLES2_ShaderType; -const Uint8 *GLES2_GetShader(GLES2_ShaderType type); -const Uint8 *GLES2_GetShaderInclude(GLES2_ShaderIncludeType type); +const char *GLES2_GetShader(GLES2_ShaderType type); +const char *GLES2_GetShaderInclude(GLES2_ShaderIncludeType type); GLES2_ShaderIncludeType GLES2_GetTexCoordPrecisionEnumFromHint(void); #endif /* SDL_VIDEO_RENDER_OGL_ES2 */