gl: try to use highp precision where supported
authorMatthew Waters <matthew@centricular.com>
Thu, 28 Feb 2019 05:17:37 +0000 (16:17 +1100)
committerMatthew Waters <matthew@centricular.com>
Thu, 28 Feb 2019 06:26:32 +0000 (17:26 +1100)
The use of mediump as a specifier in GLSL shaders will have limited
resolution and when used as texture coordinates may become inaccurate
over texture sizes of 1024.

22 files changed:
docs/libs/gst-plugins-base-libs-sections.txt
ext/gl/effects/gstgleffectssources.c
ext/gl/gltestsrc.c
ext/gl/gstglalpha.c
ext/gl/gstglcolorbalance.c
ext/gl/gstgldeinterlace.c
ext/gl/gstgldifferencematte.c
ext/gl/gstgleffects.c
ext/gl/gstglfiltercube.c
ext/gl/gstglimagesink.c
ext/gl/gstgloverlay.c
ext/gl/gstgltransformation.c
ext/gl/gstglvideomixer.c
gst-libs/gst/gl/glprototypes/gles.h
gst-libs/gst/gl/gstglcolorconvert.c
gst-libs/gst/gl/gstgloverlaycompositor.c
gst-libs/gst/gl/gstglshaderstrings.c
gst-libs/gst/gl/gstglshaderstrings.h
gst-libs/gst/gl/gstglsl.c
gst-libs/gst/gl/gstglsl.h
gst-libs/gst/gl/gstglslstage.c
gst-libs/gst/gl/gstglviewconvert.c

index 6bbad3b..514d017 100644 (file)
@@ -4508,6 +4508,9 @@ gst_gl_shader_string_fragment_external_oes_default
 gst_gl_shader_string_vertex_default
 gst_gl_shader_string_vertex_mat4_texture_transform
 gst_gl_shader_string_vertex_mat4_vertex_transform
+gst_gl_shader_string_get_highest_precision
+gst_gl_shader_string_fragment_get_default
+gst_gl_shader_string_fragment_external_oes_get_default
 <SUBSECTION Standard>
 GstGLShaderPrivate
 GST_GL_SHADER
@@ -4536,6 +4539,8 @@ gst_glsl_version_profile_to_string
 gst_glsl_string_get_version_profile
 gst_gl_context_supports_glsl_profile_version
 gst_gl_version_to_glsl_version
+gst_gl_context_supports_precision
+gst_gl_context_supports_precision_highp
 <SUBSECTION Standard>
 gst_glsl_error_quark
 </SECTION>
index a79e257..b379356 100644 (file)
@@ -78,9 +78,6 @@ const gchar *mirror_fragment_source_opengl =
   "}";
 
 const gchar *mirror_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -92,9 +89,6 @@ const gchar *mirror_fragment_source_gles2 =
   "}";
 
 const gchar *squeeze_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -109,9 +103,6 @@ const gchar *squeeze_fragment_source_gles2 =
   "}";
 
 const gchar *stretch_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -125,9 +116,6 @@ const gchar *stretch_fragment_source_gles2 =
   "}";
 
 const gchar *tunnel_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -144,9 +132,6 @@ const gchar *tunnel_fragment_source_gles2 =
   "}";
 
 const gchar *fisheye_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -160,11 +145,8 @@ const gchar *fisheye_fragment_source_gles2 =
   "}";
 
 const gchar *twirl_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
-       "uniform sampler2D tex;"
+  "uniform sampler2D tex;"
   "void main () {"
   "  vec2 texturecoord = v_texcoord.xy;"
   "  vec2 normcoord;"
@@ -183,9 +165,6 @@ const gchar *twirl_fragment_source_gles2 =
   "}";
 
 const gchar *bulge_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -199,9 +178,6 @@ const gchar *bulge_fragment_source_gles2 =
   "}";
 
 const gchar *square_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -216,9 +192,6 @@ const gchar *square_fragment_source_gles2 =
   "}";
 
 const gchar *luma_threshold_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -229,9 +202,6 @@ const gchar *luma_threshold_fragment_source_gles2 =
   "}";
 
 const gchar *sep_sobel_length_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform bool invert;"
@@ -246,9 +216,6 @@ const gchar *sep_sobel_length_fragment_source_gles2 =
   "}";
 
 const gchar *desaturate_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -258,9 +225,6 @@ const gchar *desaturate_fragment_source_gles2 =
   "}";
 
 const gchar *sep_sobel_hconv3_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform float width;"
@@ -289,9 +253,6 @@ const gchar *sep_sobel_hconv3_fragment_source_gles2 =
   "}";
 
 const gchar *sep_sobel_vconv3_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform float height;"
@@ -320,9 +281,6 @@ const gchar *sep_sobel_vconv3_fragment_source_gles2 =
   "}";
 
 const gchar *hconv7_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform float kernel[7];"
@@ -348,9 +306,6 @@ const gchar *hconv7_fragment_source_gles2 =
 
 /* vertical convolution 7x7 */
 const gchar *vconv7_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform float kernel[7];"
@@ -376,9 +331,6 @@ const gchar *vconv7_fragment_source_gles2 =
 
 /* TODO: support several blend modes */
 const gchar *sum_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D base;"
   "uniform sampler2D blend;"
@@ -391,9 +343,6 @@ const gchar *sum_fragment_source_gles2 =
   "}";
 
 const gchar *multiply_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D base;"
   "uniform sampler2D blend;"
@@ -406,9 +355,6 @@ const gchar *multiply_fragment_source_gles2 =
 
 /* lut operations, map luma to tex1d, see orange book (chapter 19) */
 const gchar *luma_to_curve_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform sampler2D curve;"
@@ -422,9 +368,6 @@ const gchar *luma_to_curve_fragment_source_gles2 =
 
 /* lut operations, map rgb to tex1d, see orange book (chapter 19) */
 const gchar *rgb_to_curve_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform sampler2D curve;"
@@ -439,9 +382,6 @@ const gchar *rgb_to_curve_fragment_source_gles2 =
   "}";
 
 const gchar *sin_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "void main () {"
@@ -468,9 +408,6 @@ const gchar *sin_fragment_source_gles2 =
   "}";
 
 const gchar *interpolate_fragment_source =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D base;"
   "uniform sampler2D blend;"
@@ -482,9 +419,6 @@ const gchar *interpolate_fragment_source =
   "}";
 
 const gchar *texture_interp_fragment_source =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D base;"
   "uniform sampler2D blend;"
@@ -497,9 +431,6 @@ const gchar *texture_interp_fragment_source =
   "}";
 
 const gchar *difference_fragment_source =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D saved;"
   "uniform sampler2D current;"
@@ -515,9 +446,6 @@ const gchar *difference_fragment_source =
    kernel into the shader and remove unneeded zero multiplications in
    the convolution */
 const gchar *conv9_fragment_source_gles2 =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;"
   "uniform sampler2D tex;"
   "uniform float kernel[9];"
index c822103..78991bd 100644 (file)
@@ -265,9 +265,6 @@ static const gchar *smpte_vertex_src =
     "}";
 
 static const gchar *smpte_fragment_src =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "varying vec4 color;\n"
     "void main()\n"
     "{\n"
@@ -284,9 +281,6 @@ static const gchar *snow_vertex_src =
     "}";
 
 static const gchar *snow_fragment_src = 
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "uniform float time;\n"
     "varying vec2 out_uv;\n"
     "\n"
@@ -327,6 +321,7 @@ _src_smpte_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
   gushort *plane_indices;
   GError *error = NULL;
   int color_idx = 0;
+  const gchar *frags[2];
   int i;
 
   src->base.base.context = context;
@@ -447,20 +442,29 @@ _src_smpte_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
 
   if (src->color_shader)
     gst_object_unref (src->color_shader);
+
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frags[1] = smpte_fragment_src;
+
   src->color_shader = gst_gl_shader_new_link_with_stages (context, &error,
       gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
           GST_GLSL_VERSION_NONE,
           GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
           smpte_vertex_src),
-      gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+      gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
           GST_GLSL_VERSION_NONE,
-          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-          smpte_fragment_src), NULL);
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+          frags), NULL);
   if (!src->color_shader) {
     GST_ERROR_OBJECT (src->base.base.src, "%s", error->message);
     return FALSE;
   }
 
+  frags[1] = snow_fragment_src;
+
   if (src->snow_shader)
     gst_object_unref (src->snow_shader);
   src->snow_shader = gst_gl_shader_new_link_with_stages (context, &error,
@@ -468,10 +472,10 @@ _src_smpte_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
           GST_GLSL_VERSION_NONE,
           GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
           snow_vertex_src),
-      gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+      gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
           GST_GLSL_VERSION_NONE,
-          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-          snow_fragment_src), NULL);
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+          frags), NULL);
   if (!src->snow_shader) {
     GST_ERROR_OBJECT (src->base.base.src, "%s", error->message);
     return FALSE;
@@ -684,9 +688,6 @@ static const gchar *checkers_vertex_src = "attribute vec4 position;\n"
     "}";
 
 static const gchar *checkers_fragment_src =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "uniform float checker_width;\n"
     "uniform float width;\n"
     "uniform float height;\n"
@@ -714,9 +715,16 @@ _src_checkers_init (gpointer impl, GstGLContext * context,
 {
   struct SrcCheckers *src = impl;
   GError *error = NULL;
+  const gchar *frags[2];
 
   src->base.base.context = context;
 
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frags[1] = checkers_fragment_src;
+
   if (src->base.shader)
     gst_object_unref (src->base.shader);
   src->base.shader = gst_gl_shader_new_link_with_stages (context, &error,
@@ -724,10 +732,10 @@ _src_checkers_init (gpointer impl, GstGLContext * context,
           GST_GLSL_VERSION_NONE,
           GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
           checkers_vertex_src),
-      gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+      gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
           GST_GLSL_VERSION_NONE,
-          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-          checkers_fragment_src), NULL);
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+          frags), NULL);
   if (!src->base.shader) {
     GST_ERROR_OBJECT (src->base.base.src, "%s", error->message);
     return FALSE;
@@ -808,9 +816,16 @@ _src_snow_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
 {
   struct SrcShader *src = impl;
   GError *error = NULL;
+  const gchar *frags[2];
 
   src->base.context = context;
 
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frags[1] = snow_fragment_src;
+
   if (src->shader)
     gst_object_unref (src->shader);
   src->shader = gst_gl_shader_new_link_with_stages (context, &error,
@@ -818,10 +833,10 @@ _src_snow_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
           GST_GLSL_VERSION_NONE,
           GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
           snow_vertex_src),
-      gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+      gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
           GST_GLSL_VERSION_NONE,
-          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-          snow_fragment_src), NULL);
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+          frags), NULL);
   if (!src->shader) {
     GST_ERROR_OBJECT (src->base.src, "%s", error->message);
     return FALSE;
@@ -902,9 +917,6 @@ static const gchar *mandelbrot_vertex_src = "attribute vec4 position;\n"
     "}";
 
 static const gchar *mandelbrot_fragment_src = 
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "uniform float time;\n"
     "varying vec2 fractal_position;\n"
     "const vec4 K = vec4(1.0, 0.66, 0.33, 3.0);\n"
@@ -942,9 +954,16 @@ _src_mandelbrot_init (gpointer impl, GstGLContext * context,
 {
   struct SrcShader *src = impl;
   GError *error = NULL;
+  const gchar *frags[2];
 
   src->base.context = context;
 
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frags[1] = mandelbrot_fragment_src;
+
   if (src->shader)
     gst_object_unref (src->shader);
   src->shader = gst_gl_shader_new_link_with_stages (context, &error,
@@ -952,10 +971,10 @@ _src_mandelbrot_init (gpointer impl, GstGLContext * context,
           GST_GLSL_VERSION_NONE,
           GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
           mandelbrot_vertex_src),
-      gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+      gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
           GST_GLSL_VERSION_NONE,
-          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-          mandelbrot_fragment_src), NULL);
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+          frags), NULL);
   if (!src->shader) {
     GST_ERROR_OBJECT (src->base.src, "%s", error->message);
     return FALSE;
@@ -1041,9 +1060,6 @@ static const gchar *circular_vertex_src =
     "}";
 
 static const gchar *circular_fragment_src =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "uniform float aspect_ratio;\n"
     "varying vec2 uv;\n"
     "#define PI 3.14159265\n"
@@ -1065,9 +1081,16 @@ _src_circular_init (gpointer impl, GstGLContext * context,
 {
   struct SrcShader *src = impl;
   GError *error = NULL;
+  const gchar *frags[2];
 
   src->base.context = context;
 
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frags[1] = circular_fragment_src;
+
   if (src->shader)
     gst_object_unref (src->shader);
   src->shader = gst_gl_shader_new_link_with_stages (context, &error,
@@ -1075,10 +1098,10 @@ _src_circular_init (gpointer impl, GstGLContext * context,
           GST_GLSL_VERSION_NONE,
           GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
           circular_vertex_src),
-      gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+      gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
           GST_GLSL_VERSION_NONE,
-          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-          circular_fragment_src), NULL);
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+          frags), NULL);
   if (!src->shader) {
     GST_ERROR_OBJECT (src->base.src, "%s", error->message);
     return FALSE;
index bf09049..8f7d003 100644 (file)
@@ -104,9 +104,6 @@ enum
 
 /* *INDENT-OFF* */
 static const gchar *alpha_frag =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;\n"
   "uniform sampler2D tex;\n"
   "uniform float alpha;\n"
@@ -117,9 +114,6 @@ static const gchar *alpha_frag =
   "}\n";
 
 static const gchar *chroma_key_frag =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;\n"
   "uniform sampler2D tex;\n"
   "uniform float cb;\n"
@@ -344,17 +338,24 @@ _create_shader (GstGLAlpha * alpha)
   GstGLBaseFilter *base_filter = GST_GL_BASE_FILTER (alpha);
   GstGLFilter *filter = GST_GL_FILTER (alpha);
   GError *error = NULL;
+  const gchar *frags[2];
 
   if (alpha->alpha_shader)
     gst_object_unref (alpha->alpha_shader);
 
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (base_filter->context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frags[1] = alpha_frag;
+
   if (!(alpha->alpha_shader =
           gst_gl_shader_new_link_with_stages (base_filter->context, &error,
               gst_glsl_stage_new_default_vertex (base_filter->context),
-              gst_glsl_stage_new_with_string (base_filter->context,
+              gst_glsl_stage_new_with_strings (base_filter->context,
                   GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  alpha_frag), NULL))) {
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                  frags), NULL))) {
     GST_ELEMENT_ERROR (alpha, RESOURCE, NOT_FOUND, ("%s",
             "Failed to initialize alpha shader"), ("%s",
             error ? error->message : "Unknown error"));
@@ -364,13 +365,15 @@ _create_shader (GstGLAlpha * alpha)
   if (alpha->chroma_key_shader)
     gst_object_unref (alpha->chroma_key_shader);
 
+  frags[1] = chroma_key_frag;
+
   if (!(alpha->chroma_key_shader =
           gst_gl_shader_new_link_with_stages (base_filter->context, &error,
               gst_glsl_stage_new_default_vertex (base_filter->context),
-              gst_glsl_stage_new_with_string (base_filter->context,
+              gst_glsl_stage_new_with_strings (base_filter->context,
                   GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  chroma_key_frag), NULL))) {
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                  frags), NULL))) {
     GST_ELEMENT_ERROR (alpha, RESOURCE, NOT_FOUND, ("%s",
             "Failed to initialize chroma key shader"), ("%s",
             error ? error->message : "Unknown error"));
index f448e9b..983f104 100644 (file)
@@ -83,21 +83,16 @@ GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS (GST_GL_COLOR_BALANCE_VIDEO_CAPS));
 
 /* *INDENT-OFF* */
-static const gchar color_balance_frag_OES_preamble[] =
-    "#extension GL_OES_EGL_image_external : require\n"
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
+static const gchar glsl_external_image_extension[] =
+    "#extension GL_OES_EGL_image_external : require\n";
+
+static const gchar glsl_external_image_sampler[] =
     "uniform samplerExternalOES tex;\n";
 
-static const gchar color_balance_frag_2D_preamble[] =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
+static const gchar glsl_2D_image_sampler[] =
   "uniform sampler2D tex;\n";
 
 static const gchar color_balance_frag_templ[] =
-  "%s\n" // Preamble
   "uniform float brightness;\n"
   "uniform float contrast;\n"
   "uniform float saturation;\n"
@@ -229,35 +224,48 @@ _create_shader (GstGLColorBalance * balance)
   GstGLBaseFilter *base_filter = GST_GL_BASE_FILTER (balance);
   GstGLFilter *filter = GST_GL_FILTER (balance);
   GError *error = NULL;
-  gchar *frag_str;
+  gchar *frag_body;
+  const gchar *frags[4];
+  guint frag_i = 0;
 
   if (balance->shader)
     gst_object_unref (balance->shader);
 
+  if (filter->in_texture_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
+    frags[frag_i++] = glsl_external_image_extension;
+
+  frags[frag_i++] =
+      gst_gl_shader_string_get_highest_precision (base_filter->context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+
   /* Can support rectangle textures in the future if needed */
-  if (filter->in_texture_target == GST_GL_TEXTURE_TARGET_2D)
-    frag_str =
-        g_strdup_printf (color_balance_frag_templ,
-        color_balance_frag_2D_preamble, "texture2D");
-  else
-    frag_str =
-        g_strdup_printf (color_balance_frag_templ,
-        color_balance_frag_OES_preamble, "texture2D");
+  if (filter->in_texture_target == GST_GL_TEXTURE_TARGET_2D) {
+    frags[frag_i++] = glsl_2D_image_sampler;
+    frags[frag_i++] = frag_body =
+        g_strdup_printf (color_balance_frag_templ, "texture2D");
+  } else {
+    frags[frag_i++] = glsl_external_image_sampler;
+    frags[frag_i++] = frag_body =
+        g_strdup_printf (color_balance_frag_templ, "texture2D");
+  }
+
+  g_assert (frag_i <= G_N_ELEMENTS (frags));
 
   if (!(balance->shader =
           gst_gl_shader_new_link_with_stages (base_filter->context, &error,
               gst_glsl_stage_new_default_vertex (base_filter->context),
-              gst_glsl_stage_new_with_string (base_filter->context,
+              gst_glsl_stage_new_with_strings (base_filter->context,
                   GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  frag_str), NULL))) {
-    g_free (frag_str);
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, frag_i,
+                  frags), NULL))) {
+    g_free (frag_body);
     GST_ELEMENT_ERROR (balance, RESOURCE, NOT_FOUND, ("%s",
             "Failed to initialize colorbalance shader"), ("%s",
             error ? error->message : "Unknown error"));
     return FALSE;
   }
-  g_free (frag_str);
+  g_free (frag_body);
 
   filter->draw_attr_position_loc =
       gst_gl_shader_get_attribute_location (balance->shader, "a_position");
index c422618..b8ffa3d 100644 (file)
@@ -76,9 +76,6 @@ static gboolean gst_gl_deinterlace_greedyh_callback (GstGLFilter * filter,
 
 /* *INDENT-OFF* */
 static const gchar *greedyh_fragment_source =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "uniform sampler2D tex;\n"
   "uniform sampler2D tex_prev;\n"
   "uniform float max_comb;\n"
@@ -157,9 +154,6 @@ static const gchar *greedyh_fragment_source =
   "}\n";
 
 const gchar *vfir_fragment_source =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "uniform sampler2D tex;\n"
   "uniform float width;\n"
   "uniform float height;\n"
@@ -422,18 +416,25 @@ gst_gl_deinterlace_get_fragment_shader (GstGLFilter * filter,
   GstGLShader *shader = NULL;
   GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (filter);
   GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
+  const gchar *frags[2];
 
   shader = g_hash_table_lookup (deinterlace_filter->shaderstable, shader_name);
 
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frags[1] = shader_source;
+
   if (!shader) {
     GError *error = NULL;
 
     if (!(shader = gst_gl_shader_new_link_with_stages (context, &error,
                 gst_glsl_stage_new_default_vertex (context),
-                gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+                gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
                     GST_GLSL_VERSION_NONE,
-                    GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                    shader_source), NULL))) {
+                    GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                    frags), NULL))) {
       GST_ELEMENT_ERROR (deinterlace_filter, RESOURCE, NOT_FOUND,
           ("Failed to initialize %s shader", shader_name), (NULL));
     }
index e805770..69ac291 100644 (file)
@@ -86,6 +86,7 @@ gst_gl_differencematte_gl_start (GstGLBaseFilter * base_filter)
   GstGLBaseMemoryAllocator *tex_alloc;
   GstGLAllocationParams *params;
   GError *error = NULL;
+  const gchar *frags[2];
   gint i;
 
   if (!GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter))
@@ -110,49 +111,58 @@ gst_gl_differencematte_gl_start (GstGLBaseFilter * base_filter)
     return FALSE;
   }
 
+  frags[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+
+  frags[1] = difference_fragment_source;
   if (!(differencematte->shader[0] =
           gst_gl_shader_new_link_with_stages (context, &error,
               gst_glsl_stage_new_default_vertex (context),
-              gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+              gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
                   GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  difference_fragment_source), NULL))) {
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                  frags), NULL))) {
     GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
             "Failed to compile difference shader"), ("%s", error->message));
     return FALSE;
   }
 
+  frags[1] = hconv7_fragment_source_gles2;
   if (!(differencematte->shader[1] =
           gst_gl_shader_new_link_with_stages (context, &error,
               gst_glsl_stage_new_default_vertex (context),
-              gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+              gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
                   GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  hconv7_fragment_source_gles2), NULL))) {
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                  frags), NULL))) {
     GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
             "Failed to compile convolution shader"), ("%s", error->message));
     return FALSE;
   }
 
+  frags[1] = vconv7_fragment_source_gles2;
   if (!(differencematte->shader[2] =
           gst_gl_shader_new_link_with_stages (context, &error,
               gst_glsl_stage_new_default_vertex (context),
-              gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+              gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
                   GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  vconv7_fragment_source_gles2), NULL))) {
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                  frags), NULL))) {
     GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
             "Failed to compile convolution shader"), ("%s", error->message));
     return FALSE;
   }
 
+  frags[1] = texture_interp_fragment_source;
   if (!(differencematte->shader[3] =
           gst_gl_shader_new_link_with_stages (context, &error,
               gst_glsl_stage_new_default_vertex (context),
-              gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+              gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
                   GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  texture_interp_fragment_source), NULL))) {
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                  frags), NULL))) {
     GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
             "Failed to compile interpolation shader"), ("%s", error->message));
     return FALSE;
index 97a8dfe..02c5ca2 100644 (file)
@@ -557,13 +557,20 @@ gst_gl_effects_get_fragment_shader (GstGLEffects * effects,
 
   if (!shader) {
     GError *error = NULL;
+    const gchar *frag_strs[2];
+
+    frag_strs[0] =
+        gst_gl_shader_string_get_highest_precision (context,
+        GST_GLSL_VERSION_NONE,
+        GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+    frag_strs[1] = shader_source_gles2;
 
     if (!(shader = gst_gl_shader_new_link_with_stages (context, &error,
                 gst_glsl_stage_new_default_vertex (context),
-                gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+                gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
                     GST_GLSL_VERSION_NONE,
-                    GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                    shader_source_gles2), NULL))) {
+                    GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                    frag_strs), NULL))) {
       GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
           ("Failed to initialize %s shader", shader_name), (NULL));
     }
index 776aece..c0ea031 100644 (file)
@@ -116,9 +116,6 @@ static const gchar *cube_v_src =
 
 /* fragment source */
 static const gchar *cube_f_src =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "varying vec2 v_texcoord;                            \n"
     "uniform sampler2D s_texture;                        \n"
     "void main()                                         \n"
@@ -310,10 +307,22 @@ static gboolean
 gst_gl_filter_cube_gl_start (GstGLBaseFilter * filter)
 {
   GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter);
+  GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
+  gchar *frag_str;
+  gboolean ret;
+
+  frag_str =
+      g_strdup_printf ("%s%s",
+      gst_gl_shader_string_get_highest_precision (context,
+          GST_GLSL_VERSION_NONE,
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY), cube_f_src);
 
   /* blocking call, wait the opengl thread has compiled the shader */
-  return gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context,
-      cube_v_src, cube_f_src, &cube_filter->shader);
+  ret = gst_gl_context_gen_shader (context, cube_v_src, frag_str,
+      &cube_filter->shader);
+  g_free (frag_str);
+
+  return ret;
 }
 
 static gboolean
index e56da14..38883c5 100644 (file)
@@ -2014,10 +2014,17 @@ gst_glimage_sink_thread_init_redisplay (GstGLImageSink * gl_sink)
       GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
       gst_gl_shader_string_vertex_mat4_vertex_transform);
   if (gl_sink->texture_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
+    gchar *frag_str;
+    frag_str =
+        gst_gl_shader_string_fragment_external_oes_get_default
+        (gl_sink->context, GST_GLSL_VERSION_NONE,
+        GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+
     frag_stage = gst_glsl_stage_new_with_string (gl_sink->context,
         GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE,
-        GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-        gst_gl_shader_string_fragment_external_oes_default);
+        GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, frag_str);
+
+    g_free (frag_str);
   } else {
     frag_stage = gst_glsl_stage_new_default_fragment (gl_sink->context);
   }
index 72f6ff4..55ce4bc 100644 (file)
@@ -109,9 +109,6 @@ static const gchar *overlay_v_src =
 
 /* fragment source */
 static const gchar *overlay_f_src =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "uniform sampler2D texture;\n"
     "uniform float alpha;\n"
     "varying vec2 v_texcoord;\n"
@@ -127,12 +124,24 @@ static gboolean
 gst_gl_overlay_gl_start (GstGLBaseFilter * base_filter)
 {
   GstGLOverlay *overlay = GST_GL_OVERLAY (base_filter);
+  gchar *frag_str;
+  gboolean ret;
 
   if (!GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter))
     return FALSE;
 
-  return gst_gl_context_gen_shader (base_filter->context, overlay_v_src,
-      overlay_f_src, &overlay->shader);
+  frag_str =
+      g_strdup_printf ("%s%s",
+      gst_gl_shader_string_get_highest_precision (base_filter->context,
+          GST_GLSL_VERSION_NONE,
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY), overlay_f_src);
+
+  /* blocking call, wait the opengl thread has compiled the shader */
+  ret = gst_gl_context_gen_shader (base_filter->context, overlay_v_src,
+      frag_str, &overlay->shader);
+  g_free (frag_str);
+
+  return ret;
 }
 
 /* free resources that need a gl context */
index dba8733..66858a6 100644 (file)
@@ -762,10 +762,22 @@ gst_gl_transformation_gl_start (GstGLBaseFilter * base_filter)
     return FALSE;
 
   if (gst_gl_context_get_gl_api (base_filter->context)) {
+    gchar *frag_str;
+    gboolean ret;
+
+    frag_str =
+        gst_gl_shader_string_fragment_get_default (base_filter->context,
+        GST_GLSL_VERSION_NONE,
+        GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+
     /* blocking call, wait until the opengl thread has compiled the shader */
-    return gst_gl_context_gen_shader (base_filter->context,
+    ret = gst_gl_context_gen_shader (base_filter->context,
         gst_gl_shader_string_vertex_mat4_vertex_transform,
-        gst_gl_shader_string_fragment_default, &transformation->shader);
+        frag_str, &transformation->shader);
+
+    g_free (frag_str);
+
+    return ret;
   }
   return TRUE;
 }
index 1e14c5e..8eca6e0 100644 (file)
@@ -484,9 +484,6 @@ static gboolean gst_gl_video_mixer_callback (gpointer stuff);
 
 /* fragment source */
 static const gchar *video_mixer_f_src =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "uniform sampler2D texture;                     \n"
     "uniform float alpha;\n"
     "varying vec2 v_texcoord;                            \n"
@@ -506,9 +503,6 @@ static const gchar *checker_v_src =
 
 /* checker fragment source */
 static const gchar *checker_f_src =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
     "const float blocksize = 8.0;\n"
     "void main ()\n"
     "{\n"
@@ -1212,6 +1206,8 @@ static gboolean
 gst_gl_video_mixer_init_shader (GstGLMixer * mixer, GstCaps * outcaps)
 {
   GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mixer);
+  gchar *frag_str;
+  gboolean ret;
 
   if (video_mixer->shader)
     gst_object_unref (video_mixer->shader);
@@ -1219,9 +1215,18 @@ gst_gl_video_mixer_init_shader (GstGLMixer * mixer, GstCaps * outcaps)
   /* need reconfigure output geometry */
   video_mixer->output_geo_change = TRUE;
 
-  return gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context,
+  frag_str =
+      g_strdup_printf ("%s%s",
+      gst_gl_shader_string_get_highest_precision (GST_GL_BASE_MIXER
+          (mixer)->context, GST_GLSL_VERSION_NONE,
+          GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY),
+      video_mixer_f_src);
+
+  ret = gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context,
       gst_gl_shader_string_vertex_mat4_vertex_transform,
-      video_mixer_f_src, &video_mixer->shader);
+      frag_str, &video_mixer->shader);
+  g_free (frag_str);
+  return ret;
 }
 
 static void
@@ -1279,9 +1284,21 @@ _draw_checker_background (GstGLVideoMixer * video_mixer)
   /* *INDENT-ON* */
 
   if (!video_mixer->checker) {
+    gchar *frag_str;
+
+    frag_str =
+        g_strdup_printf ("%s%s",
+        gst_gl_shader_string_get_highest_precision (GST_GL_BASE_MIXER
+            (mixer)->context, GST_GLSL_VERSION_NONE,
+            GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY),
+        checker_f_src);
+
     if (!gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context,
-            checker_v_src, checker_f_src, &video_mixer->checker))
+            checker_v_src, frag_str, &video_mixer->checker)) {
+      g_free (frag_str);
       return FALSE;
+    }
+    g_free (frag_str);
   }
 
   gst_gl_shader_use (video_mixer->checker);
index 7d1cd88..f8c833b 100644 (file)
@@ -64,8 +64,8 @@ GST_GL_EXT_BEGIN (gles2_only_api,
                   GST_GL_API_GLES2,
                   255, 255,
                   2, 0,
-                  "\0",
-                  "\0")
+                  "ARB:\0",
+                  "ES2_compatibility\0")
 GST_GL_EXT_FUNCTION (void, ReleaseShaderCompiler, (void))
 GST_GL_EXT_FUNCTION (void, GetShaderPrecisionFormat,
                      (GLenum shadertype,
index 297d371..c319709 100644 (file)
@@ -126,9 +126,6 @@ static const gfloat from_rgb_bt709_vcoeff[] = {0.440654f, -0.400285f, -0.040370f
     "const vec2 compose_weight = vec2(0.996109, 0.003891);\n"
 
 #define DEFAULT_UNIFORMS         \
-    "#ifdef GL_ES\n"             \
-    "precision mediump float;\n" \
-    "#endif\n"                   \
     "uniform vec2 tex_scale0;\n" \
     "uniform vec2 tex_scale1;\n" \
     "uniform vec2 tex_scale2;\n" \
@@ -526,6 +523,8 @@ gst_gl_color_convert_finalize (GObject * object)
     convert->context = NULL;
   }
 
+  GST_ERROR_OBJECT (convert, "finalize");
+
   G_OBJECT_CLASS (gst_gl_color_convert_parent_class)->finalize (object);
 }
 
@@ -1877,7 +1876,7 @@ _create_shader (GstGLColorConvert * convert)
   GstGLSLVersion version;
   GstGLSLProfile profile;
   gchar *version_str, *tmp, *tmp1;
-  const gchar *strings[2];
+  const gchar *strings[3];
   GError *error = NULL;
   int i;
 
@@ -1997,9 +1996,12 @@ _create_shader (GstGLColorConvert * convert)
       &version, &profile);
   g_free (tmp);
 
-  strings[1] = info->frag_prog;
+  strings[1] =
+      gst_gl_shader_string_get_highest_precision (convert->context, version,
+      profile);
+  strings[2] = info->frag_prog;
   if (!(stage = gst_glsl_stage_new_with_strings (convert->context,
-              GL_FRAGMENT_SHADER, version, profile, 2, strings))) {
+              GL_FRAGMENT_SHADER, version, profile, 3, strings))) {
     GST_ERROR_OBJECT (convert, "Failed to create fragment stage");
     g_free (info->frag_prog);
     info->frag_prog = NULL;
index dda34f8..b025e00 100644 (file)
 
 #include "gstgloverlaycompositor.h"
 
-#include "gstglcontext.h"
-#include "gstglfuncs.h"
-#include "gstglmemory.h"
-#include "gstglshader.h"
-#include "gstglslstage.h"
+#include <gst/gl/gl.h>
+#include <gst/gl/gstglfuncs.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_gl_overlay_compositor_debug);
 #define GST_CAT_DEFAULT gst_gl_overlay_compositor_debug
@@ -58,9 +55,6 @@ static GType gst_gl_composition_overlay_get_type (void);
 
 /* *INDENT-OFF* */
 const gchar *fragment_shader =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "varying vec2 v_texcoord;\n"
   "uniform sampler2D tex;\n"
   "void main(void)\n"
@@ -463,7 +457,8 @@ enum
 #define DEFAULT_YINVERT                 FALSE
 
 G_DEFINE_TYPE_WITH_CODE (GstGLOverlayCompositor, gst_gl_overlay_compositor,
-    GST_TYPE_OBJECT, G_ADD_PRIVATE (GstGLOverlayCompositor); DEBUG_INIT);
+    GST_TYPE_OBJECT, G_ADD_PRIVATE (GstGLOverlayCompositor);
+    DEBUG_INIT);
 
 static void gst_gl_overlay_compositor_finalize (GObject * object);
 static void gst_gl_overlay_compositor_set_property (GObject * object,
@@ -545,14 +540,21 @@ gst_gl_overlay_compositor_init_gl (GstGLContext * context,
   GstGLOverlayCompositor *compositor =
       (GstGLOverlayCompositor *) compositor_pointer;
   GError *error = NULL;
+  const gchar *frag_strs[2];
+
+  frag_strs[0] =
+      gst_gl_shader_string_get_highest_precision (context,
+      GST_GLSL_VERSION_NONE,
+      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
+  frag_strs[1] = fragment_shader;
 
   if (!(compositor->shader =
           gst_gl_shader_new_link_with_stages (context, &error,
               gst_glsl_stage_new_default_vertex (context),
-              gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+              gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
                   GST_GLSL_VERSION_NONE,
-                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-                  fragment_shader), NULL))) {
+                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
+                  frag_strs), NULL))) {
     GST_ERROR_OBJECT (compositor, "could not initialize shader: %s",
         error->message);
     return;
index e6bf5f3..915268b 100644 (file)
 
 #include "gstglshaderstrings.h"
 
+#define MEDIUMP_PRECISION \
+   "#ifdef GL_ES\n" \
+   "precision mediump float;\n" \
+   "#endif\n"
+
+#define HIGHP_PRECISION \
+   "#ifdef GL_ES\n" \
+   "precision mediump float;\n" \
+   "#endif\n"
+
 /* *INDENT-OFF* */
+const gchar *gst_gl_shader_string_fragment_mediump_precision = 
+    MEDIUMP_PRECISION;
+
+const gchar *gst_gl_shader_string_fragment_highp_precision = 
+    HIGHP_PRECISION;
+
 const gchar *gst_gl_shader_string_vertex_default =
     "attribute vec4 a_position;\n"
     "attribute vec2 a_texcoord;\n"
@@ -57,26 +73,94 @@ const gchar *gst_gl_shader_string_vertex_mat4_vertex_transform =
     "   v_texcoord = a_texcoord;\n"
     "}\n";
 
+#define DEFAULT_FRAGMENT_BODY \
+    "varying vec2 v_texcoord;\n" \
+    "uniform sampler2D tex;\n" \
+    "void main()\n" \
+    "{\n" \
+    "  gl_FragColor = texture2D(tex, v_texcoord);\n" \
+    "}"
 const gchar *gst_gl_shader_string_fragment_default =
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
-    "varying vec2 v_texcoord;\n"
-    "uniform sampler2D tex;\n"
-    "void main()\n"
-    "{\n"
-    "  gl_FragColor = texture2D(tex, v_texcoord);\n"
-    "}";
+    MEDIUMP_PRECISION
+    DEFAULT_FRAGMENT_BODY;
 
+#define EXTERNAL_FRAGMENT_BODY \
+    "#extension GL_OES_EGL_image_external : require\n" \
+    "varying vec2 v_texcoord;\n" \
+    "uniform samplerExternalOES tex;\n" \
+    "void main()\n" \
+    "{\n" \
+    "  gl_FragColor = texture2D(tex, v_texcoord);\n" \
+    "}"
 const gchar *gst_gl_shader_string_fragment_external_oes_default =
-    "#extension GL_OES_EGL_image_external : require\n"
-    "#ifdef GL_ES\n"
-    "precision mediump float;\n"
-    "#endif\n"
-    "varying vec2 v_texcoord;\n"
-    "uniform samplerExternalOES tex;\n"
-    "void main()\n"
-    "{\n"
-    "  gl_FragColor = texture2D(tex, v_texcoord);\n"
-    "}";
+    MEDIUMP_PRECISION
+    EXTERNAL_FRAGMENT_BODY;
 /* *INDENT-ON* */
+
+/**
+ * gst_gl_shader_string_get_highest_precision:
+ * @context: a #GstGLContext
+ * @version: a #GstGLSLVersion
+ * @profile: a #GstGLSLProfile
+ *
+ * Generates a shader string that defines the precision of float types in
+ * GLSL shaders.  This is particularly needed for fragment shaders in a
+ * GLSL ES context where there is no default precision specified.
+ *
+ * Practically, this will return the string 'precision mediump float'
+ * or 'precision highp float' depending on if high precision floats are
+ * determined to be supported.
+ *
+ * Returns: a shader string defining the precision of float types based on
+ *      @context, @version and @profile
+ */
+const gchar *
+gst_gl_shader_string_get_highest_precision (GstGLContext * context,
+    GstGLSLVersion version, GstGLSLProfile profile)
+{
+  if (gst_gl_context_supports_precision (context, version, profile)) {
+    if (gst_gl_context_supports_precision_highp (context, version, profile))
+      return gst_gl_shader_string_fragment_highp_precision;
+    else
+      return gst_gl_shader_string_fragment_mediump_precision;
+  }
+  return "";
+}
+
+/**
+ * gst_gl_shader_string_fragment_get_default:
+ * @context: a #GstGLContext
+ * @version: a #GstGLSLVersion
+ * @profile: a #GstGLSLProfile
+ *
+ * Returns: a passthrough shader string for copying an input texture to
+ *          the output
+ */
+gchar *
+gst_gl_shader_string_fragment_get_default (GstGLContext * context,
+    GstGLSLVersion version, GstGLSLProfile profile)
+{
+  const gchar *precision =
+      gst_gl_shader_string_get_highest_precision (context, version, profile);
+
+  return g_strdup_printf ("%s%s", precision, DEFAULT_FRAGMENT_BODY);
+}
+
+/**
+ * gst_gl_shader_string_fragment_external_oes_get_default:
+ * @context: a #GstGLContext
+ * @version: a #GstGLSLVersion
+ * @profile: a #GstGLSLProfile
+ *
+ * Returns: a passthrough shader string for copying an input external-oes
+ *          texture to the output
+ */
+gchar *
+gst_gl_shader_string_fragment_external_oes_get_default (GstGLContext * context,
+    GstGLSLVersion version, GstGLSLProfile profile)
+{
+  const gchar *precision =
+      gst_gl_shader_string_get_highest_precision (context, version, profile);
+
+  return g_strdup_printf ("%s%s", precision, EXTERNAL_FRAGMENT_BODY);
+}
index 2a02241..eba1b9e 100644 (file)
 
 #include <gst/gst.h>
 #include <gst/gl/gl-prelude.h>
+#include <gst/gl/gl.h>
 
 G_BEGIN_DECLS
 
 GST_GL_API
-const gchar *gst_gl_shader_string_vertex_default;
+const gchar *gst_gl_shader_string_fragment_highp_precision;
+GST_GL_API
+const gchar *gst_gl_shader_string_fragment_mediump_precision;
+
 GST_GL_API
+const gchar *gst_gl_shader_string_vertex_default;
+GST_GL_API G_DEPRECATED_FOR(gst_gl_shader_string_fragment_get_default)
 const gchar *gst_gl_shader_string_fragment_default;
 
 GST_GL_API
 const gchar *gst_gl_shader_string_vertex_mat4_texture_transform;
 GST_GL_API
 const gchar *gst_gl_shader_string_vertex_mat4_vertex_transform;
-GST_GL_API
+GST_GL_API G_DEPRECATED_FOR(gst_gl_shader_string_fragment_external_oes_get_default)
 const gchar *gst_gl_shader_string_fragment_external_oes_default;
 
+GST_GL_API
+const gchar * gst_gl_shader_string_get_highest_precision        (GstGLContext * context,
+                                                                 GstGLSLVersion version,
+                                                                 GstGLSLProfile profile);
+
+GST_GL_API
+gchar * gst_gl_shader_string_fragment_get_default               (GstGLContext * context,
+                                                                 GstGLSLVersion version,
+                                                                 GstGLSLProfile profile);
+GST_GL_API
+gchar * gst_gl_shader_string_fragment_external_oes_get_default  (GstGLContext * context,
+                                                                 GstGLSLVersion version,
+                                                                 GstGLSLProfile profile);
+
 G_END_DECLS
 
 #endif /* __GST_GL_SHADER_STRINGS_H__ */
index cb43a26..257ab59 100644 (file)
@@ -929,3 +929,59 @@ _gst_glsl_mangle_shader (const gchar * str, guint shader_type,
   }
   return tmp;
 }
+
+/**
+ * gst_gl_context_supports_precision:
+ * @context: a #GstGLContext
+ * @version: a #GstGLSLVersion
+ * @profile: a #GstGLSLProfile
+ *
+ * Returns: whether @context supports the 'precision' specifier in GLSL shaders
+ */
+gboolean
+gst_gl_context_supports_precision (GstGLContext * context,
+    GstGLSLVersion version, GstGLSLProfile profile)
+{
+  gboolean es2 = FALSE;
+
+  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
+
+  if ((profile & GST_GLSL_PROFILE_ES) == 0)
+    return FALSE;
+
+  es2 = gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)
+      || gst_gl_context_check_feature (context, "GL_ARB_ES2_compatibility");
+
+  return es2 && context->gl_vtable->GetShaderPrecisionFormat;
+}
+
+/**
+ * gst_gl_context_supports_precision_highp:
+ * @context: a #GstGLContext
+ * @version: a #GstGLSLVersion
+ * @profile: a #GstGLSLProfile
+ *
+ * Returns: whether @context supports the 'precision highp' specifier in GLSL shaders
+ */
+gboolean
+gst_gl_context_supports_precision_highp (GstGLContext * context,
+    GstGLSLVersion version, GstGLSLProfile profile)
+{
+  gint v_range[2] = { 0, }
+  , v_precision = 0;
+  gint f_range[2] = { 0, }
+  , f_precision = 0;
+
+  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
+
+  if (!gst_gl_context_supports_precision (context, version, profile))
+    return FALSE;
+
+  context->gl_vtable->GetShaderPrecisionFormat (GL_VERTEX_SHADER, GL_HIGH_FLOAT,
+      v_range, &v_precision);
+  context->gl_vtable->GetShaderPrecisionFormat (GL_FRAGMENT_SHADER,
+      GL_HIGH_FLOAT, f_range, &f_precision);
+
+  return v_range[0] != 0 && v_range[1] != 0 && v_precision != 0 &&
+      f_range[0] != 0 && f_range[1] != 0 && f_precision != 0;
+}
index d5d2235..4d47bce 100644 (file)
@@ -155,6 +155,15 @@ gboolean       gst_gl_context_supports_glsl_profile_version (GstGLContext * cont
                                                              GstGLSLVersion version,
                                                              GstGLSLProfile profile);
 
+GST_GL_API
+gboolean       gst_gl_context_supports_precision        (GstGLContext * context,
+                                                         GstGLSLVersion version,
+                                                         GstGLSLProfile profile);
+GST_GL_API
+gboolean       gst_gl_context_supports_precision_highp  (GstGLContext * context,
+                                                         GstGLSLVersion version,
+                                                         GstGLSLProfile profile);
+
 G_END_DECLS
 
 #endif /* __GST_GLSL_H__ */
index b95c3fe..4d3c7ae 100644 (file)
@@ -72,8 +72,7 @@ struct _GstGLSLStagePrivate
 G_DEFINE_TYPE_WITH_CODE (GstGLSLStage, gst_glsl_stage, GST_TYPE_OBJECT,
     G_ADD_PRIVATE (GstGLSLStage)
     GST_DEBUG_CATEGORY_INIT (gst_glsl_stage_debug, "glslstage", 0,
-        "GLSL Stage");
-    );
+        "GLSL Stage"););
 
 static void
 gst_glsl_stage_finalize (GObject * object)
@@ -289,10 +288,20 @@ gst_glsl_stage_new_default_vertex (GstGLContext * context)
 GstGLSLStage *
 gst_glsl_stage_new_default_fragment (GstGLContext * context)
 {
-  return gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
-      GST_GLSL_VERSION_NONE,
-      GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
-      gst_gl_shader_string_fragment_default);
+  GstGLSLProfile profile = GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY;
+  GstGLSLVersion version = GST_GLSL_VERSION_NONE;
+  gchar *frag_str;
+  GstGLSLStage *stage;
+
+  frag_str =
+      gst_gl_shader_string_fragment_get_default (context, version, profile);
+
+  stage = gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+      version, profile, frag_str);
+
+  g_free (frag_str);
+
+  return stage;
 }
 
 /**
index 63a6789..20a94d0 100644 (file)
@@ -141,9 +141,6 @@ static gfloat identity_matrix[] = {
 
 /* *INDENT-OFF* */
 static const gchar *fragment_header =
-  "#ifdef GL_ES\n"
-  "precision mediump float;\n"
-  "#endif\n"
   "uniform sampler2D tex_l;\n"
   "uniform sampler2D tex_r;\n"
   "uniform float width;\n"
@@ -1516,6 +1513,9 @@ _get_shader_string (GstGLViewConvert * viewconvert, GstGLShader * shader,
   if (viewconvert->from_texture_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
     g_string_append (str, glsl_OES_extension_string);
 
+  g_string_append (str,
+      gst_gl_shader_string_get_highest_precision (viewconvert->context, version,
+          profile));
   g_string_append (str, fragment_header);
 
   /* GL 3.3+ and GL ES 3.x */