From 675415bf2ea9ddc75ea5e5b6eae9ae942c19d6dc Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 28 Feb 2019 16:17:37 +1100 Subject: [PATCH] gl: try to use highp precision where supported 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. --- docs/libs/gst-plugins-base-libs-sections.txt | 5 ++ ext/gl/effects/gstgleffectssources.c | 74 +--------------- ext/gl/gltestsrc.c | 89 +++++++++++-------- ext/gl/gstglalpha.c | 27 +++--- ext/gl/gstglcolorbalance.c | 56 ++++++------ ext/gl/gstgldeinterlace.c | 19 +++-- ext/gl/gstgldifferencematte.c | 34 +++++--- ext/gl/gstgleffects.c | 13 ++- ext/gl/gstglfiltercube.c | 19 +++-- ext/gl/gstglimagesink.c | 11 ++- ext/gl/gstgloverlay.c | 19 +++-- ext/gl/gstgltransformation.c | 16 +++- ext/gl/gstglvideomixer.c | 35 ++++++-- gst-libs/gst/gl/glprototypes/gles.h | 4 +- gst-libs/gst/gl/gstglcolorconvert.c | 14 +-- gst-libs/gst/gl/gstgloverlaycompositor.c | 26 +++--- gst-libs/gst/gl/gstglshaderstrings.c | 122 ++++++++++++++++++++++----- gst-libs/gst/gl/gstglshaderstrings.h | 24 +++++- gst-libs/gst/gl/gstglsl.c | 56 ++++++++++++ gst-libs/gst/gl/gstglsl.h | 9 ++ gst-libs/gst/gl/gstglslstage.c | 21 +++-- gst-libs/gst/gl/gstglviewconvert.c | 6 +- 22 files changed, 460 insertions(+), 239 deletions(-) diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index 6bbad3b..514d017 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -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 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 gst_glsl_error_quark diff --git a/ext/gl/effects/gstgleffectssources.c b/ext/gl/effects/gstgleffectssources.c index a79e257..b379356 100644 --- a/ext/gl/effects/gstgleffectssources.c +++ b/ext/gl/effects/gstgleffectssources.c @@ -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];" diff --git a/ext/gl/gltestsrc.c b/ext/gl/gltestsrc.c index c822103..78991bd 100644 --- a/ext/gl/gltestsrc.c +++ b/ext/gl/gltestsrc.c @@ -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; diff --git a/ext/gl/gstglalpha.c b/ext/gl/gstglalpha.c index bf09049..8f7d003 100644 --- a/ext/gl/gstglalpha.c +++ b/ext/gl/gstglalpha.c @@ -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")); diff --git a/ext/gl/gstglcolorbalance.c b/ext/gl/gstglcolorbalance.c index f448e9b..983f104 100644 --- a/ext/gl/gstglcolorbalance.c +++ b/ext/gl/gstglcolorbalance.c @@ -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"); diff --git a/ext/gl/gstgldeinterlace.c b/ext/gl/gstgldeinterlace.c index c422618..b8ffa3d 100644 --- a/ext/gl/gstgldeinterlace.c +++ b/ext/gl/gstgldeinterlace.c @@ -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)); } diff --git a/ext/gl/gstgldifferencematte.c b/ext/gl/gstgldifferencematte.c index e805770..69ac291 100644 --- a/ext/gl/gstgldifferencematte.c +++ b/ext/gl/gstgldifferencematte.c @@ -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; diff --git a/ext/gl/gstgleffects.c b/ext/gl/gstgleffects.c index 97a8dfe..02c5ca2 100644 --- a/ext/gl/gstgleffects.c +++ b/ext/gl/gstgleffects.c @@ -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)); } diff --git a/ext/gl/gstglfiltercube.c b/ext/gl/gstglfiltercube.c index 776aece..c0ea031 100644 --- a/ext/gl/gstglfiltercube.c +++ b/ext/gl/gstglfiltercube.c @@ -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 diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c index e56da14..38883c5 100644 --- a/ext/gl/gstglimagesink.c +++ b/ext/gl/gstglimagesink.c @@ -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); } diff --git a/ext/gl/gstgloverlay.c b/ext/gl/gstgloverlay.c index 72f6ff4..55ce4bc 100644 --- a/ext/gl/gstgloverlay.c +++ b/ext/gl/gstgloverlay.c @@ -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 */ diff --git a/ext/gl/gstgltransformation.c b/ext/gl/gstgltransformation.c index dba8733..66858a6 100644 --- a/ext/gl/gstgltransformation.c +++ b/ext/gl/gstgltransformation.c @@ -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; } diff --git a/ext/gl/gstglvideomixer.c b/ext/gl/gstglvideomixer.c index 1e14c5e..8eca6e0 100644 --- a/ext/gl/gstglvideomixer.c +++ b/ext/gl/gstglvideomixer.c @@ -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); diff --git a/gst-libs/gst/gl/glprototypes/gles.h b/gst-libs/gst/gl/glprototypes/gles.h index 7d1cd88..f8c833b 100644 --- a/gst-libs/gst/gl/glprototypes/gles.h +++ b/gst-libs/gst/gl/glprototypes/gles.h @@ -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, diff --git a/gst-libs/gst/gl/gstglcolorconvert.c b/gst-libs/gst/gl/gstglcolorconvert.c index 297d371..c319709 100644 --- a/gst-libs/gst/gl/gstglcolorconvert.c +++ b/gst-libs/gst/gl/gstglcolorconvert.c @@ -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; diff --git a/gst-libs/gst/gl/gstgloverlaycompositor.c b/gst-libs/gst/gl/gstgloverlaycompositor.c index dda34f8..b025e00 100644 --- a/gst-libs/gst/gl/gstgloverlaycompositor.c +++ b/gst-libs/gst/gl/gstgloverlaycompositor.c @@ -33,11 +33,8 @@ #include "gstgloverlaycompositor.h" -#include "gstglcontext.h" -#include "gstglfuncs.h" -#include "gstglmemory.h" -#include "gstglshader.h" -#include "gstglslstage.h" +#include +#include 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; diff --git a/gst-libs/gst/gl/gstglshaderstrings.c b/gst-libs/gst/gl/gstglshaderstrings.c index e6bf5f3..915268b 100644 --- a/gst-libs/gst/gl/gstglshaderstrings.c +++ b/gst-libs/gst/gl/gstglshaderstrings.c @@ -24,7 +24,23 @@ #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); +} diff --git a/gst-libs/gst/gl/gstglshaderstrings.h b/gst-libs/gst/gl/gstglshaderstrings.h index 2a02241..eba1b9e 100644 --- a/gst-libs/gst/gl/gstglshaderstrings.h +++ b/gst-libs/gst/gl/gstglshaderstrings.h @@ -23,21 +23,41 @@ #include #include +#include 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__ */ diff --git a/gst-libs/gst/gl/gstglsl.c b/gst-libs/gst/gl/gstglsl.c index cb43a26..257ab59 100644 --- a/gst-libs/gst/gl/gstglsl.c +++ b/gst-libs/gst/gl/gstglsl.c @@ -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; +} diff --git a/gst-libs/gst/gl/gstglsl.h b/gst-libs/gst/gl/gstglsl.h index d5d2235..4d47bce 100644 --- a/gst-libs/gst/gl/gstglsl.h +++ b/gst-libs/gst/gl/gstglsl.h @@ -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__ */ diff --git a/gst-libs/gst/gl/gstglslstage.c b/gst-libs/gst/gl/gstglslstage.c index b95c3fe..4d3c7ae 100644 --- a/gst-libs/gst/gl/gstglslstage.c +++ b/gst-libs/gst/gl/gstglslstage.c @@ -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; } /** diff --git a/gst-libs/gst/gl/gstglviewconvert.c b/gst-libs/gst/gl/gstglviewconvert.c index 63a6789..20a94d0 100644 --- a/gst-libs/gst/gl/gstglviewconvert.c +++ b/gst-libs/gst/gl/gstglviewconvert.c @@ -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 */ -- 2.7.4