diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 112c1e8ac..2585d4366 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -169,6 +169,7 @@ typedef struct GLES2_RenderData #endif GLES2_DrawStateCache drawstate; + GLES2_ShaderIncludeType texcoord_precision_hint; } GLES2_RenderData; #define GLES2_MAX_CACHED_PROGRAMS 8 @@ -494,16 +495,28 @@ GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_t { GLuint id; GLint compileSuccessful = GL_FALSE; - const char *shader_src = (char *)GLES2_GetShader(type); + int num_src = 0; + const GLchar *shader_src_list[4] = { 0 }; + const GLchar *shader_body = (const GLchar *)GLES2_GetShader(type); - if (!shader_src) { - SDL_SetError("No shader src"); + 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); + } + 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, 1, &shader_src, NULL); + data->glShaderSource(id, num_src, shader_src_list, NULL); data->glCompileShader(id); data->glGetShaderiv(id, GL_COMPILE_STATUS, &compileSuccessful); @@ -2094,6 +2107,8 @@ 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 b6c187d7e..c61dc8345 100644 --- a/src/render/opengles2/SDL_shaders_gles2.c +++ b/src/render/opengles2/SDL_shaders_gles2.c @@ -22,24 +22,44 @@ #if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED +#include "SDL_hints.h" #include "SDL_video.h" #include "SDL_opengles2.h" #include "SDL_shaders_gles2.h" #include "SDL_stdinc.h" -#define SHADER_PRELOGUE "\n\ -#if GL_FRAGMENT_PRECISION_HIGH\n\ - precision mediump float;\n\ -#else\n\ - #define mediump\n\ - #define highp\n\ - #define lowp\n\ -#endif\n\ -" - /************************************************************************************************* * 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\ + #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ + #define SDL_TEXCOORD_PRECISION highp\n\ + #else\n\ + #define SDL_TEXCOORD_PRECISION mediump\n\ + #endif\n\ +"; + +static const Uint8 GLES2_Fragment_Include_Medium_Texture_Precision[] = "\n\ + #define SDL_TEXCOORD_PRECISION mediump\n\ +"; + +static const Uint8 GLES2_Fragment_Include_High_Texture_Precision[] = "\n\ + #define SDL_TEXCOORD_PRECISION highp\n\ +"; + +static const Uint8 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[] = " \ uniform mat4 u_projection; \ attribute vec2 a_position; \ @@ -57,8 +77,8 @@ static const Uint8 GLES2_Vertex_Default[] = " \ } \ "; -static const Uint8 GLES2_Fragment_Solid[] = SHADER_PRELOGUE" \ - varying vec4 v_color; \ +static const Uint8 GLES2_Fragment_Solid[] = " \ + varying mediump vec4 v_color; \ \ void main() \ { \ @@ -66,14 +86,10 @@ static const Uint8 GLES2_Fragment_Solid[] = SHADER_PRELOGUE" \ } \ "; -static const Uint8 GLES2_Fragment_TextureABGR[] = SHADER_PRELOGUE" \ +static const Uint8 GLES2_Fragment_TextureABGR[] = " \ uniform sampler2D u_texture; \ - varying vec4 v_color;\n\ - #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ - varying highp vec2 v_texCoord;\n\ - #else\n\ - varying vec2 v_texCoord;\n\ - #endif\n\ + varying mediump vec4 v_color;\n\ + varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ \ void main() \ { \ @@ -83,18 +99,14 @@ static const Uint8 GLES2_Fragment_TextureABGR[] = SHADER_PRELOGUE" \ "; /* ARGB to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureARGB[] = SHADER_PRELOGUE" \ +static const Uint8 GLES2_Fragment_TextureARGB[] = " \ uniform sampler2D u_texture; \ - varying vec4 v_color;\n\ - #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ - varying highp vec2 v_texCoord;\n\ - #else\n\ - varying vec2 v_texCoord;\n\ - #endif\n\ + varying mediump vec4 v_color;\n\ + varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ \ void main() \ { \ - vec4 abgr = texture2D(u_texture, v_texCoord); \ + mediump vec4 abgr = texture2D(u_texture, v_texCoord); \ gl_FragColor = abgr; \ gl_FragColor.r = abgr.b; \ gl_FragColor.b = abgr.r; \ @@ -103,18 +115,14 @@ static const Uint8 GLES2_Fragment_TextureARGB[] = SHADER_PRELOGUE" \ "; /* RGB to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureRGB[] = SHADER_PRELOGUE" \ +static const Uint8 GLES2_Fragment_TextureRGB[] = " \ uniform sampler2D u_texture; \ - varying vec4 v_color;\n\ - #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ - varying highp vec2 v_texCoord;\n\ - #else\n\ - varying vec2 v_texCoord;\n\ - #endif\n\ + varying mediump vec4 v_color;\n\ + varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ \ void main() \ { \ - vec4 abgr = texture2D(u_texture, v_texCoord); \ + mediump vec4 abgr = texture2D(u_texture, v_texCoord); \ gl_FragColor = abgr; \ gl_FragColor.r = abgr.b; \ gl_FragColor.b = abgr.r; \ @@ -124,18 +132,14 @@ static const Uint8 GLES2_Fragment_TextureRGB[] = SHADER_PRELOGUE" \ "; /* BGR to ABGR conversion */ -static const Uint8 GLES2_Fragment_TextureBGR[] = SHADER_PRELOGUE" \ +static const Uint8 GLES2_Fragment_TextureBGR[] = " \ uniform sampler2D u_texture; \ - varying vec4 v_color;\n\ - #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ - varying highp vec2 v_texCoord;\n\ - #else\n\ - varying vec2 v_texCoord;\n\ - #endif\n\ + varying mediump vec4 v_color;\n\ + varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ \ void main() \ { \ - vec4 abgr = texture2D(u_texture, v_texCoord); \ + mediump vec4 abgr = texture2D(u_texture, v_texCoord); \ gl_FragColor = abgr; \ gl_FragColor.a = 1.0; \ gl_FragColor *= v_color; \ @@ -173,16 +177,11 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = SHADER_PRELOGUE" \ #define YUV_SHADER_PROLOGUE \ -SHADER_PRELOGUE \ "uniform sampler2D u_texture;\n" \ "uniform sampler2D u_texture_u;\n" \ "uniform sampler2D u_texture_v;\n" \ -"varying vec4 v_color;\n" \ -"#ifdef GL_FRAGMENT_PRECISION_HIGH\n" \ -"varying highp vec2 v_texCoord;\n" \ -"#else\n" \ -"varying vec2 v_texCoord;\n" \ -"#endif\n" \ +"varying mediump vec4 v_color;\n" \ +"varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n" \ "\n" \ #define YUV_SHADER_BODY \ @@ -331,14 +330,9 @@ static const Uint8 GLES2_Fragment_TextureNV21BT709[] = \ /* Custom Android video format texture */ static const Uint8 GLES2_Fragment_TextureExternalOES[] = " \ #extension GL_OES_EGL_image_external : require\n\ - precision mediump float; \ uniform samplerExternalOES u_texture; \ - varying vec4 v_color;\n\ - #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ - varying highp vec2 v_texCoord;\n\ - #else\n\ - varying vec2 v_texCoord;\n\ - #endif\n\ + varying mediump vec4 v_color;\n\ + varying SDL_TEXCOORD_PRECISION vec2 v_texCoord;\n\ \ void main() \ { \ @@ -352,6 +346,37 @@ static const Uint8 GLES2_Fragment_TextureExternalOES[] = " \ * Shader selector * *************************************************************************************************/ +const Uint8 *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: + return GLES2_Fragment_Include_Best_Texture_Precision; + case GLES2_SHADER_FRAGMENT_INCLUDE_MEDIUM_TEXCOORD_PRECISION: + return GLES2_Fragment_Include_Medium_Texture_Precision; + case GLES2_SHADER_FRAGMENT_INCLUDE_HIGH_TEXCOORD_PRECISION: + return GLES2_Fragment_Include_High_Texture_Precision; + default: + return (Uint8*)""; + } +} + +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" + if (texcoord_hint) { + if (SDL_strcmp(texcoord_hint, "undefined") == 0) + return GLES2_SHADER_FRAGMENT_INCLUDE_UNDEF_PRECISION; + if (SDL_strcmp(texcoord_hint, "high") == 0) + return GLES2_SHADER_FRAGMENT_INCLUDE_HIGH_TEXCOORD_PRECISION; + if (SDL_strcmp(texcoord_hint, "medium") == 0) + return GLES2_SHADER_FRAGMENT_INCLUDE_MEDIUM_TEXCOORD_PRECISION; + } + return value; +} + const Uint8 *GLES2_GetShader(GLES2_ShaderType type) { switch (type) { diff --git a/src/render/opengles2/SDL_shaders_gles2.h b/src/render/opengles2/SDL_shaders_gles2.h index 09780239d..df1f4441d 100644 --- a/src/render/opengles2/SDL_shaders_gles2.h +++ b/src/render/opengles2/SDL_shaders_gles2.h @@ -25,6 +25,16 @@ #if SDL_VIDEO_RENDER_OGL_ES2 +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, + GLES2_SHADER_FRAGMENT_INCLUDE_UNDEF_PRECISION, + GLES2_SHADER_FRAGMENT_INCLUDE_COUNT +} GLES2_ShaderIncludeType; typedef enum { @@ -52,6 +62,8 @@ typedef enum } GLES2_ShaderType; const Uint8 *GLES2_GetShader(GLES2_ShaderType type); +const Uint8 *GLES2_GetShaderInclude(GLES2_ShaderIncludeType type); +GLES2_ShaderIncludeType GLES2_GetTexCoordPrecisionEnumFromHint(); #endif /* SDL_VIDEO_RENDER_OGL_ES2 */