From 4504356ddab34a680d0d19f5d4c130114f621ea3 Mon Sep 17 00:00:00 2001 From: Anton Obzhirov Date: Mon, 30 Mar 2015 13:49:01 +0100 Subject: [PATCH] gleffects: port all effects to GLES2.0 https://bugzilla.gnome.org/show_bug.cgi?id=745955 --- ext/gl/Makefile.am | 24 +- ext/gl/effects/gstgleffectbulge.c | 26 +- ext/gl/effects/gstgleffectfisheye.c | 26 +- ext/gl/effects/gstgleffectglow.c | 104 +++---- ext/gl/effects/gstgleffectidentity.c | 6 - ext/gl/effects/gstgleffectlumatocurve.c | 83 +++-- ext/gl/effects/gstgleffectmirror.c | 39 +-- ext/gl/effects/gstgleffectrgbtocurve.c | 85 +++-- ext/gl/effects/gstgleffectsin.c | 23 +- ext/gl/effects/gstgleffectsquare.c | 26 +- ext/gl/effects/gstgleffectsqueeze.c | 41 +-- ext/gl/effects/gstgleffectssources.c | 398 ++++++++++++++++++++++-- ext/gl/effects/gstgleffectssources.h | 56 ++-- ext/gl/effects/gstgleffectstretch.c | 27 +- ext/gl/effects/gstgleffecttunnel.c | 26 +- ext/gl/effects/gstgleffecttwirl.c | 26 +- ext/gl/effects/gstgleffectxray.c | 176 ++++------- ext/gl/gstgldifferencematte.c | 4 +- ext/gl/gstgleffects.c | 122 +++++--- ext/gl/gstgleffects.h | 8 + ext/gl/gstglfilterblur.c | 4 +- ext/gl/gstglfiltersobel.c | 8 +- 22 files changed, 812 insertions(+), 526 deletions(-) diff --git a/ext/gl/Makefile.am b/ext/gl/Makefile.am index 7dc104192..680eb38d5 100644 --- a/ext/gl/Makefile.am +++ b/ext/gl/Makefile.am @@ -17,6 +17,17 @@ libgstopengl_la_SOURCES = \ effects/gstgleffectidentity.c \ effects/gstgleffectmirror.c \ effects/gstgleffectsqueeze.c \ + effects/gstgleffectstretch.c \ + effects/gstgleffectfisheye.c \ + effects/gstgleffecttwirl.c \ + effects/gstgleffectbulge.c \ + effects/gstgleffecttunnel.c \ + effects/gstgleffectsquare.c \ + effects/gstgleffectlumatocurve.c \ + effects/gstgleffectrgbtocurve.c \ + effects/gstgleffectsin.c \ + effects/gstgleffectxray.c \ + effects/gstgleffectglow.c \ gstglcolorscale.c \ gstglmixer.c \ gstglvideomixer.c \ @@ -52,18 +63,7 @@ libgstopengl_la_SOURCES += \ gstgldeinterlace.c \ gltestsrc.c \ gstgltestsrc.c \ - gstglmosaic.c \ - effects/gstgleffectstretch.c \ - effects/gstgleffecttunnel.c \ - effects/gstgleffectfisheye.c \ - effects/gstgleffecttwirl.c \ - effects/gstgleffectbulge.c \ - effects/gstgleffectsquare.c \ - effects/gstgleffectlumatocurve.c \ - effects/gstgleffectrgbtocurve.c \ - effects/gstgleffectsin.c \ - effects/gstgleffectglow.c \ - effects/gstgleffectxray.c + gstglmosaic.c noinst_HEADERS += \ gstglfilterblur.h \ diff --git a/ext/gl/effects/gstgleffectbulge.c b/ext/gl/effects/gstgleffectbulge.c index 75b9e2fc1..2e210251e 100644 --- a/ext/gl/effects/gstgleffectbulge.c +++ b/ext/gl/effects/gstgleffectbulge.c @@ -33,23 +33,18 @@ gst_gl_effects_bulge_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "bulge0"); + shader = gst_gl_effects_get_fragment_shader (effects, "bulge", + bulge_fragment_source_gles2, bulge_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "bulge0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - bulge_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize bulge shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -59,9 +54,6 @@ gst_gl_effects_bulge_callback (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); - gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); - gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffectfisheye.c b/ext/gl/effects/gstgleffectfisheye.c index 524b65987..c94cd42c0 100644 --- a/ext/gl/effects/gstgleffectfisheye.c +++ b/ext/gl/effects/gstgleffectfisheye.c @@ -33,23 +33,18 @@ gst_gl_effects_fisheye_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "fisheye0"); + shader = gst_gl_effects_get_fragment_shader (effects, "fisheye", + fisheye_fragment_source_gles2, fisheye_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "fisheye0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - fisheye_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize fisheye shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -59,9 +54,6 @@ gst_gl_effects_fisheye_callback (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); - gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); - gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffectglow.c b/ext/gl/effects/gstgleffectglow.c index 4853fd91a..a4f67ceb2 100644 --- a/ext/gl/effects/gstgleffectglow.c +++ b/ext/gl/effects/gstgleffectglow.c @@ -36,24 +36,19 @@ gst_gl_effects_glow_step_one (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "glow0"); + shader = gst_gl_effects_get_fragment_shader (effects, "luma_threshold", + luma_threshold_fragment_source_gles2, + luma_threshold_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "glow0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - luma_threshold_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize luma threshold shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -76,28 +71,22 @@ gst_gl_effects_glow_step_two (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "glow1"); + shader = gst_gl_effects_get_fragment_shader (effects, "hconv7", + hconv7_fragment_source_gles2, hconv7_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "glow1", shader); - } + if (!shader) + return; if (!kernel_ready) { fill_gaussian_kernel (gauss_kernel, 7, 10.0); kernel_ready = TRUE; } - - if (!gst_gl_shader_compile_and_check (shader, - hconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize hconv7 shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); - return; +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); } - - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#endif gst_gl_shader_use (shader); @@ -108,7 +97,7 @@ gst_gl_effects_glow_step_two (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 1); gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "height", height); + gst_gl_shader_set_uniform_1f (shader, "gauss_width", height); gst_gl_filter_draw_texture (filter, texture, width, height); } @@ -123,23 +112,18 @@ gst_gl_effects_glow_step_three (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "glow2"); - - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "glow2", shader); - } + shader = gst_gl_effects_get_fragment_shader (effects, "vconv7", + vconv7_fragment_source_gles2, vconv7_fragment_source_opengl); - if (!gst_gl_shader_compile_and_check (shader, - vconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize vcon7 shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -150,7 +134,7 @@ gst_gl_effects_glow_step_three (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 1); gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "width", width); + gst_gl_shader_set_uniform_1f (shader, "gauss_height", width); gst_gl_filter_draw_texture (filter, texture, width, height); } @@ -165,23 +149,18 @@ gst_gl_effects_glow_step_four (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "glow3"); - - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "glow3", shader); - } + shader = gst_gl_effects_get_fragment_shader (effects, "sum", + sum_fragment_source_gles2, sum_fragment_source_opengl); - if (!gst_gl_shader_compile_and_check (shader, - sum_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize sum shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -190,7 +169,7 @@ gst_gl_effects_glow_step_four (gint width, gint height, guint texture, gl->BindTexture (GL_TEXTURE_2D, effects->intexture); gl->Disable (GL_TEXTURE_2D); - gst_gl_shader_set_uniform_1f (shader, "alpha", 1.0); + gst_gl_shader_set_uniform_1f (shader, "alpha", 1.0f); gst_gl_shader_set_uniform_1i (shader, "base", 2); gl->ActiveTexture (GL_TEXTURE1); @@ -212,11 +191,14 @@ gst_gl_effects_glow (GstGLEffects * effects) /* threshold */ gst_gl_filter_render_to_target (filter, TRUE, effects->intexture, effects->midtexture[0], gst_gl_effects_glow_step_one, effects); + /* blur */ gst_gl_filter_render_to_target (filter, FALSE, effects->midtexture[0], effects->midtexture[1], gst_gl_effects_glow_step_two, effects); + gst_gl_filter_render_to_target (filter, FALSE, effects->midtexture[1], effects->midtexture[2], gst_gl_effects_glow_step_three, effects); + /* add blurred luma to intexture */ gst_gl_filter_render_to_target (filter, FALSE, effects->midtexture[2], effects->outtexture, gst_gl_effects_glow_step_four, effects); diff --git a/ext/gl/effects/gstgleffectidentity.c b/ext/gl/effects/gstgleffectidentity.c index eec357eb3..58d005572 100644 --- a/ext/gl/effects/gstgleffectidentity.c +++ b/ext/gl/effects/gstgleffectidentity.c @@ -23,12 +23,6 @@ #include "../gstgleffects.h" -#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) -#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) -#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0)) -#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) -#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) - static void gst_gl_effects_identity_callback (gint width, gint height, guint texture, gpointer data) diff --git a/ext/gl/effects/gstgleffectlumatocurve.c b/ext/gl/effects/gstgleffectlumatocurve.c index 2ce1de37f..0a925fe3c 100644 --- a/ext/gl/effects/gstgleffectlumatocurve.c +++ b/ext/gl/effects/gstgleffectlumatocurve.c @@ -34,41 +34,53 @@ gst_gl_effects_luma_to_curve (GstGLEffects * effects, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "lumamap0"); + shader = gst_gl_effects_get_fragment_shader (effects, "luma_to_curve", + luma_to_curve_fragment_source_gles2, + luma_to_curve_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "lumamap0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - luma_to_curve_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize luma to curve shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); if (effects->curve[curve_index] == 0) { /* this parameters are needed to have a right, predictable, mapping */ gl->GenTextures (1, &effects->curve[curve_index]); - gl->Enable (GL_TEXTURE_1D); - gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); - gl->TexImage1D (GL_TEXTURE_1D, 0, curve->bytes_per_pixel, - curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->Enable (GL_TEXTURE_1D); + gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); - gl->Disable (GL_TEXTURE_1D); + gl->TexImage1D (GL_TEXTURE_1D, 0, curve->bytes_per_pixel, + curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); + + gl->Disable (GL_TEXTURE_1D); + } +#endif + if (USING_GLES2 (context) || USING_OPENGL3 (context)) { + gl->Enable (GL_TEXTURE_2D); + gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGB, + curve->width, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); + gl->Disable (GL_TEXTURE_2D); + } } gl->ActiveTexture (GL_TEXTURE2); @@ -79,13 +91,26 @@ gst_gl_effects_luma_to_curve (GstGLEffects * effects, gl->Disable (GL_TEXTURE_2D); - gl->ActiveTexture (GL_TEXTURE1); - gl->Enable (GL_TEXTURE_1D); - gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->ActiveTexture (GL_TEXTURE1); + gl->Enable (GL_TEXTURE_1D); + gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); - gst_gl_shader_set_uniform_1i (shader, "curve", 1); + gst_gl_shader_set_uniform_1i (shader, "curve", 1); - gl->Disable (GL_TEXTURE_1D); + gl->Disable (GL_TEXTURE_1D); + } +#endif + if (USING_GLES2 (context) || USING_OPENGL3 (context)) { + gl->ActiveTexture (GL_TEXTURE1); + gl->Enable (GL_TEXTURE_2D); + gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); + + gst_gl_shader_set_uniform_1i (shader, "curve", 1); + + gl->Disable (GL_TEXTURE_2D); + } gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffectmirror.c b/ext/gl/effects/gstgleffectmirror.c index 1713d54a5..7a88f07ab 100644 --- a/ext/gl/effects/gstgleffectmirror.c +++ b/ext/gl/effects/gstgleffectmirror.c @@ -23,12 +23,6 @@ #include "../gstgleffects.h" -#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) -#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) -#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0)) -#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) -#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) - static void gst_gl_effects_mirror_callback (gint width, gint height, guint texture, gpointer data) @@ -39,37 +33,12 @@ gst_gl_effects_mirror_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "mirror0"); - - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "mirror0", shader); + shader = gst_gl_effects_get_fragment_shader (effects, "mirror", + mirror_fragment_source_gles2, mirror_fragment_source_opengl); - if (USING_GLES2 (context) || USING_OPENGL3 (context)) { - if (!gst_gl_shader_compile_with_default_v_and_check (shader, - mirror_fragment_source_gles2, &filter->draw_attr_position_loc, - &filter->draw_attr_texture_loc)) { - /* gst gl context error is already set */ - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("Failed to initialize squeeze shader, %s", - gst_gl_context_get_error ()), (NULL)); - return; - } - } -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (context)) { - if (!gst_gl_shader_compile_and_check (shader, - mirror_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize mirror shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); - return; - } + if (!shader) + return; - } -#endif - } #if GST_GL_HAVE_OPENGL if (USING_OPENGL (context)) { gl->MatrixMode (GL_PROJECTION); diff --git a/ext/gl/effects/gstgleffectrgbtocurve.c b/ext/gl/effects/gstgleffectrgbtocurve.c index 18b09050b..b34a3f31b 100644 --- a/ext/gl/effects/gstgleffectrgbtocurve.c +++ b/ext/gl/effects/gstgleffectrgbtocurve.c @@ -34,41 +34,51 @@ gst_gl_effects_rgb_to_curve (GstGLEffects * effects, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "rgbmap0"); + shader = gst_gl_effects_get_fragment_shader (effects, "rgb_to_curve", + rgb_to_curve_fragment_source_gles2, rgb_to_curve_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "rgbmap0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - rgb_to_curve_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize rgb to curve shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); if (effects->curve[curve_index] == 0) { /* this parameters are needed to have a right, predictable, mapping */ gl->GenTextures (1, &effects->curve[curve_index]); - gl->Enable (GL_TEXTURE_1D); - gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); - gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); - - gl->TexImage1D (GL_TEXTURE_1D, 0, curve->bytes_per_pixel, - curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); - - gl->Disable (GL_TEXTURE_1D); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->Enable (GL_TEXTURE_1D); + gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + gl->TexImage1D (GL_TEXTURE_1D, 0, GL_RGB, + curve->width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); + + gl->Disable (GL_TEXTURE_1D); + } +#endif + if (USING_GLES2 (context) || USING_OPENGL3 (context)) { + gl->Enable (GL_TEXTURE_2D); + gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGB, + curve->width, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); + gl->Disable (GL_TEXTURE_2D); + } } gl->ActiveTexture (GL_TEXTURE0); @@ -79,13 +89,26 @@ gst_gl_effects_rgb_to_curve (GstGLEffects * effects, gl->Disable (GL_TEXTURE_2D); - gl->ActiveTexture (GL_TEXTURE1); - gl->Enable (GL_TEXTURE_1D); - gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->ActiveTexture (GL_TEXTURE1); + gl->Enable (GL_TEXTURE_1D); + gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); - gst_gl_shader_set_uniform_1i (shader, "curve", 1); + gst_gl_shader_set_uniform_1i (shader, "curve", 1); - gl->Disable (GL_TEXTURE_1D); + gl->Disable (GL_TEXTURE_1D); + } +#endif + if (USING_GLES2 (context) || USING_OPENGL3 (context)) { + gl->ActiveTexture (GL_TEXTURE1); + gl->Enable (GL_TEXTURE_2D); + gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); + + gst_gl_shader_set_uniform_1i (shader, "curve", 1); + + gl->Disable (GL_TEXTURE_2D); + } gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffectsin.c b/ext/gl/effects/gstgleffectsin.c index 8d6be5442..a28414d9f 100644 --- a/ext/gl/effects/gstgleffectsin.c +++ b/ext/gl/effects/gstgleffectsin.c @@ -33,23 +33,18 @@ gst_gl_effects_sin_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "sin0"); + shader = gst_gl_effects_get_fragment_shader (effects, "sin", + sin_fragment_source_gles2, sin_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "sin0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - sin_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize sin shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); diff --git a/ext/gl/effects/gstgleffectsquare.c b/ext/gl/effects/gstgleffectsquare.c index b1619c06b..40dd31369 100644 --- a/ext/gl/effects/gstgleffectsquare.c +++ b/ext/gl/effects/gstgleffectsquare.c @@ -33,23 +33,18 @@ gst_gl_effects_square_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "square0"); + shader = gst_gl_effects_get_fragment_shader (effects, "square", + square_fragment_source_gles2, square_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "square0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - square_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize square shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -59,9 +54,6 @@ gst_gl_effects_square_callback (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); - gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); - gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffectsqueeze.c b/ext/gl/effects/gstgleffectsqueeze.c index 863157a74..7ba5e52b0 100644 --- a/ext/gl/effects/gstgleffectsqueeze.c +++ b/ext/gl/effects/gstgleffectsqueeze.c @@ -23,12 +23,6 @@ #include "../gstgleffects.h" -#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) -#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) -#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0)) -#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) -#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) - static void gst_gl_effects_squeeze_callback (gint width, gint height, guint texture, gpointer data) @@ -39,36 +33,12 @@ gst_gl_effects_squeeze_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "squeeze0"); + shader = gst_gl_effects_get_fragment_shader (effects, "squeeze", + squeeze_fragment_source_gles2, squeeze_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "squeeze0", shader); + if (!shader) + return; - if (USING_GLES2 (context) || USING_OPENGL3 (context)) { - if (!gst_gl_shader_compile_with_default_v_and_check (shader, - squeeze_fragment_source_gles2, &filter->draw_attr_position_loc, - &filter->draw_attr_texture_loc)) { - /* gst gl context error is already set */ - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("Failed to initialize squeeze shader, %s", - gst_gl_context_get_error ()), (NULL)); - return; - } - } -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (context)) { - if (!gst_gl_shader_compile_and_check (shader, - squeeze_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize squeeze shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); - return; - } - } -#endif - } #if GST_GL_HAVE_OPENGL if (USING_OPENGL (context)) { gl->MatrixMode (GL_PROJECTION); @@ -79,8 +49,7 @@ gst_gl_effects_squeeze_callback (gint width, gint height, guint texture, gst_gl_shader_use (shader); gl->ActiveTexture (GL_TEXTURE0); - if (USING_OPENGL (context)) - gl->Enable (GL_TEXTURE_2D); + gl->Enable (GL_TEXTURE_2D); gl->BindTexture (GL_TEXTURE_2D, texture); gst_gl_shader_set_uniform_1i (shader, "tex", 0); diff --git a/ext/gl/effects/gstgleffectssources.c b/ext/gl/effects/gstgleffectssources.c index 378650331..6a86701d0 100644 --- a/ext/gl/effects/gstgleffectssources.c +++ b/ext/gl/effects/gstgleffectssources.c @@ -65,7 +65,6 @@ fill_gaussian_kernel (float *kernel, int size, float sigma) /* *INDENT-OFF* */ /* Mirror effect */ -#if GST_GL_HAVE_OPENGL const gchar *mirror_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" @@ -77,7 +76,7 @@ const gchar *mirror_fragment_source_opengl = " vec4 color = texture2D (tex, texturecoord);" " gl_FragColor = color * gl_Color;" "}"; -#endif + const gchar *mirror_fragment_source_gles2 = "#ifdef GL_ES\n" "precision mediump float;\n" @@ -93,7 +92,6 @@ const gchar *mirror_fragment_source_gles2 = "}"; /* Squeeze effect */ -#if GST_GL_HAVE_OPENGL const gchar *squeeze_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" @@ -105,7 +103,7 @@ const gchar *squeeze_fragment_source_opengl = " texturecoord = (normcoord + 0.5);" " gl_FragColor = texture2D (tex, texturecoord);" "}"; -#endif + const gchar *squeeze_fragment_source_gles2 = "#ifdef GL_ES\n" "precision mediump float;\n" @@ -123,7 +121,7 @@ const gchar *squeeze_fragment_source_gles2 = "}"; /* Stretch Effect */ -const gchar *stretch_fragment_source = +const gchar *stretch_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].xy;" @@ -136,8 +134,24 @@ const gchar *stretch_fragment_source = " gl_FragColor = color * gl_Color;" "}"; +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 () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec2 normcoord;" + " normcoord = texturecoord - 0.5;" + " float r = length (normcoord);" + " normcoord *= 2.0 - smoothstep(0.0, 0.35, r);" + " texturecoord = normcoord + 0.5;" + " gl_FragColor = texture2D (tex, texturecoord);" + "}"; + /* Light Tunnel effect */ -const gchar *tunnel_fragment_source = +const gchar *tunnel_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].xy;" @@ -152,8 +166,26 @@ const gchar *tunnel_fragment_source = " gl_FragColor = color;" "}"; +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 () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec2 normcoord;" + /* little trick with normalized coords to obtain a circle with + * rect textures */ + " normcoord = (texturecoord - 0.5);" + " float r = length(normcoord);" + " normcoord *= clamp (r, 0.0, 0.275) / r;" + " texturecoord = normcoord + 0.5;" + " gl_FragColor = texture2D (tex, texturecoord);" + "}"; + /* FishEye effect */ -const gchar *fisheye_fragment_source = +const gchar *fisheye_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].xy;" @@ -166,9 +198,24 @@ const gchar *fisheye_fragment_source = " gl_FragColor = color;" "}"; +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 () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec2 normcoord;" + " normcoord = texturecoord - 0.5;" + " float r = length (normcoord);" + " normcoord *= r * sqrt(2);" + " texturecoord = normcoord + 0.5;" + " gl_FragColor = texture2D (tex, texturecoord);" + "}"; /* Twirl effect */ -const gchar *twirl_fragment_source = +const gchar *twirl_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].xy;" @@ -188,9 +235,31 @@ const gchar *twirl_fragment_source = " gl_FragColor = color;" "}"; +const gchar *twirl_fragment_source_gles2 = + "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "varying vec2 v_texcoord;" + "uniform sampler2D tex;" + "void main () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec2 normcoord;" + " normcoord = texturecoord - 0.5;" + " float r = length (normcoord);" + /* calculate rotation angle: maximum (about pi/2) at the origin and + * gradually decrease it up to 0.6 of each quadrant */ + " float phi = (1.0 - smoothstep (0.0, 0.3, r)) * 1.6;" + /* precalculate sin phi and cos phi, save some alu */ + " float s = sin(phi);" + " float c = cos(phi);" + /* rotate */ + " normcoord *= mat2(c, s, -s, c);" + " texturecoord = normcoord + 0.5;" + " gl_FragColor = texture2D (tex, texturecoord);" + "}"; /* Bulge effect */ -const gchar *bulge_fragment_source = +const gchar *bulge_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].xy;" @@ -203,9 +272,24 @@ const gchar *bulge_fragment_source = " gl_FragColor = color;" "}"; +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 () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec2 normcoord;" + " normcoord = texturecoord - 0.5;" + " float r = length (normcoord);" + " normcoord *= smoothstep (-0.05, 0.25, r);" + " texturecoord = normcoord + 0.5;" + " gl_FragColor = texture2D (tex, texturecoord);" + "}"; /* Square Effect */ -const gchar *square_fragment_source = +const gchar *square_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].xy;" @@ -219,8 +303,24 @@ const gchar *square_fragment_source = " gl_FragColor = color * gl_Color;" "}"; +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 () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec2 normcoord;" + " normcoord = texturecoord - 0.5;" + " float r = length (normcoord);" + " normcoord *= 1.0 + smoothstep(0.125, 0.25, abs(normcoord));" + " normcoord /= 2.0; /* zoom amount */" + " texturecoord = normcoord + 0.5;" + " gl_FragColor = texture2D (tex, texturecoord);" + "}"; -const gchar *luma_threshold_fragment_source = +const gchar *luma_threshold_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].st;" @@ -229,7 +329,20 @@ const gchar *luma_threshold_fragment_source = " gl_FragColor = vec4 (vec3 (smoothstep (0.30, 0.50, luma)), color.a);" "}"; -const gchar *sep_sobel_length_fragment_source = +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 () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec4 color = texture2D(tex, texturecoord);" + " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" /* BT.709 (from orange book) */ + " gl_FragColor = vec4 (vec3 (smoothstep (0.30, 0.50, luma)), color.a);" + "}"; + +const gchar *sep_sobel_length_fragment_source_opengl = "uniform sampler2D tex;" "uniform bool invert;" "void main () {" @@ -242,7 +355,24 @@ const gchar *sep_sobel_length_fragment_source = " gl_FragColor = abs(vec4(vec3(float(invert) - len), 1.0));" "}"; -const gchar *desaturate_fragment_source = +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;" + "void main () {" + " vec4 g = texture2D (tex, v_texcoord.xy);" + /* restore black background with grey edges */ + " g -= vec4(0.5, 0.5, 0.0, 0.0);" + " float len = length (g);" + /* little trick to avoid IF operator */ + /* TODO: test if a standalone inverting pass is worth */ + " gl_FragColor = abs(vec4(vec3(float(invert) - len), 1.0));" + "}"; + +const gchar *desaturate_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec4 color = texture2D (tex, gl_TexCoord[0].st);" @@ -250,7 +380,19 @@ const gchar *desaturate_fragment_source = " gl_FragColor = vec4(vec3(luma), color.a);" "}"; -const gchar *sep_sobel_hconv3_fragment_source = +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 () {" + " vec4 color = texture2D (tex, v_texcoord.xy);" + " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" + " gl_FragColor = vec4(vec3(luma), color.a);" + "}"; + +const gchar *sep_sobel_hconv3_fragment_source_opengl = "uniform sampler2D tex;" "uniform float width;" "void main () {" @@ -277,7 +419,38 @@ const gchar *sep_sobel_hconv3_fragment_source = " gl_FragColor = sum + vec4(0.0, 0.5, 0.0, 0.0);" "}"; -const gchar *sep_sobel_vconv3_fragment_source = +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;" + "void main () {" + " float w = 1.0 / width;" + " vec2 texturecoord[3];" + " texturecoord[1] = v_texcoord.xy;" + " texturecoord[0] = texturecoord[1] - vec2(w, 0.0);" + " texturecoord[2] = texturecoord[1] + vec2(w, 0.0);" + " float grad_kern[3];" + " grad_kern[0] = 1.0;" + " grad_kern[1] = 0.0;" + " grad_kern[2] = -1.0;" + " float blur_kern[3];" + " blur_kern[0] = 0.25;" + " blur_kern[1] = 0.5;" + " blur_kern[2] = 0.25;" + " int i;" + " vec4 sum = vec4 (0.0);" + " for (i = 0; i < 3; i++) { " + " vec4 neighbor = texture2D(tex, texturecoord[i]); " + " sum.r = neighbor.r * blur_kern[i] + sum.r;" + " sum.g = neighbor.g * grad_kern[i] + sum.g;" + " }" + " gl_FragColor = sum + vec4(0.0, 0.5, 0.0, 0.0);" + "}"; + +const gchar *sep_sobel_vconv3_fragment_source_opengl = "uniform sampler2D tex;" "uniform float height;" "void main () {" @@ -304,13 +477,44 @@ const gchar *sep_sobel_vconv3_fragment_source = " gl_FragColor = sum + vec4(0.5, 0.0, 0.0, 0.0);" "}"; +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;" + "void main () {" + " float h = 1.0 / height;" + " vec2 texturecoord[3];" + " texturecoord[1] = v_texcoord.xy;" + " texturecoord[0] = texturecoord[1] - vec2(0.0, h);" + " texturecoord[2] = texturecoord[1] + vec2(0.0, h);" + " float grad_kern[3];" + " grad_kern[0] = 1.0;" + " grad_kern[1] = 0.0;" + " grad_kern[2] = -1.0;" + " float blur_kern[3];" + " blur_kern[0] = 0.25;" + " blur_kern[1] = 0.5;" + " blur_kern[2] = 0.25;" + " int i;" + " vec4 sum = vec4 (0.0);" + " for (i = 0; i < 3; i++) { " + " vec4 neighbor = texture2D(tex, texturecoord[i]); " + " sum.r = neighbor.r * grad_kern[i] + sum.r;" + " sum.g = neighbor.g * blur_kern[i] + sum.g;" + " }" + " gl_FragColor = sum + vec4(0.5, 0.0, 0.0, 0.0);" + "}"; + /* horizontal convolution 7x7 */ -const gchar *hconv7_fragment_source = +const gchar *hconv7_fragment_source_opengl = "uniform sampler2D tex;" "uniform float kernel[7];" - "uniform float width;" + "uniform float gauss_width;" "void main () {" - " float w = 1.0 / width;" + " float w = 1.0 / gauss_width;" " vec2 texturecoord[7];" " texturecoord[3] = gl_TexCoord[0].st;" " texturecoord[2] = texturecoord[3] - vec2(w, 0.0);" @@ -328,13 +532,40 @@ const gchar *hconv7_fragment_source = " gl_FragColor = sum;" "}"; +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];" + "uniform float gauss_width;" + "void main () {" + " float w = 1.0 / gauss_width;" + " vec2 texturecoord[7];" + " texturecoord[3] = v_texcoord.xy;" + " texturecoord[2] = texturecoord[3] - vec2(w, 0.0);" + " texturecoord[1] = texturecoord[2] - vec2(w, 0.0);" + " texturecoord[0] = texturecoord[1] - vec2(w, 0.0);" + " texturecoord[4] = texturecoord[3] + vec2(w, 0.0);" + " texturecoord[5] = texturecoord[4] + vec2(w, 0.0);" + " texturecoord[6] = texturecoord[5] + vec2(w, 0.0);" + " int i;" + " vec4 sum = vec4 (0.0);" + " for (i = 0; i < 7; i++) { " + " vec4 neighbor = texture2D(tex, texturecoord[i]); " + " sum += neighbor * kernel[i];" + " }" + " gl_FragColor = sum;" + "}"; + /* vertical convolution 7x7 */ -const gchar *vconv7_fragment_source = +const gchar *vconv7_fragment_source_opengl = "uniform sampler2D tex;" "uniform float kernel[7];" - "uniform float height;" + "uniform float gauss_height;" "void main () {" - " float h = 1.0 / height;" + " float h = 1.0 / gauss_height;" " vec2 texturecoord[7];" " texturecoord[3] = gl_TexCoord[0].st;" " texturecoord[2] = texturecoord[3] - vec2(0.0, h);" @@ -352,9 +583,35 @@ const gchar *vconv7_fragment_source = " gl_FragColor = sum;" "}"; +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];" + "uniform float gauss_height;" + "void main () {" + " float h = 1.0 / gauss_height;" + " vec2 texturecoord[7];" + " texturecoord[3] = v_texcoord.xy;" + " texturecoord[2] = texturecoord[3] - vec2(0.0, h);" + " texturecoord[1] = texturecoord[2] - vec2(0.0, h);" + " texturecoord[0] = texturecoord[1] - vec2(0.0, h);" + " texturecoord[4] = texturecoord[3] + vec2(0.0, h);" + " texturecoord[5] = texturecoord[4] + vec2(0.0, h);" + " texturecoord[6] = texturecoord[5] + vec2(0.0, h);" + " int i;" + " vec4 sum = vec4 (0.0);" + " for (i = 0; i < 7; i++) { " + " vec4 neighbor = texture2D(tex, texturecoord[i]);" + " sum += neighbor * kernel[i];" + " }" + " gl_FragColor = sum;" + "}"; /* TODO: support several blend modes */ -const gchar *sum_fragment_source = +const gchar *sum_fragment_source_opengl = "uniform sampler2D base;" "uniform sampler2D blend;" "uniform float alpha;" @@ -365,7 +622,22 @@ const gchar *sum_fragment_source = " gl_FragColor = alpha * basecolor + beta * blendcolor;" "}"; -const gchar *multiply_fragment_source = +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;" + "uniform float alpha;" + "uniform float beta;" + "void main () {" + " vec4 basecolor = texture2D (base, v_texcoord.xy);" + " vec4 blendcolor = texture2D (blend, v_texcoord.xy);" + " gl_FragColor = alpha * basecolor + beta * blendcolor;" + "}"; + +const gchar *multiply_fragment_source_opengl = "uniform sampler2D base;" "uniform sampler2D blend;" "uniform float alpha;" @@ -375,8 +647,22 @@ const gchar *multiply_fragment_source = " gl_FragColor = (1.0 - alpha) * basecolor + alpha * basecolor * blendcolor;" "}"; +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;" + "uniform float alpha;" + "void main () {" + " vec4 basecolor = texture2D (base, v_texcoord.xy);" + " vec4 blendcolor = texture2D (blend, v_texcoord.xy);" + " gl_FragColor = (1.0 - alpha) * basecolor + alpha * basecolor * blendcolor;" + "}"; + /* lut operations, map luma to tex1d, see orange book (chapter 19) */ -const gchar *luma_to_curve_fragment_source = +const gchar *luma_to_curve_fragment_source_opengl = "uniform sampler2D tex;" "uniform sampler1D curve;" "void main () {" @@ -387,9 +673,23 @@ const gchar *luma_to_curve_fragment_source = " gl_FragColor = color;" "}"; +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;" + "void main () {" + " vec2 texturecoord = v_texcoord.xy;" + " vec4 color = texture2D (tex, texturecoord);" + " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" + " color = texture2D (curve, vec2(luma, 0.0));" + " gl_FragColor = color;" + "}"; /* lut operations, map rgb to tex1d, see orange book (chapter 19) */ -const gchar *rgb_to_curve_fragment_source = +const gchar *rgb_to_curve_fragment_source_opengl = "uniform sampler2D tex;" "uniform sampler1D curve;" "void main () {" @@ -402,7 +702,24 @@ const gchar *rgb_to_curve_fragment_source = " gl_FragColor = outcolor;" "}"; -const gchar *sin_fragment_source = +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;" + "void main () {" + " vec4 color = texture2D (tex, v_texcoord.xy);" + " vec4 outcolor;" + " outcolor.r = texture2D (curve, vec2(color.r, 0.0)).r;" + " outcolor.g = texture2D (curve, vec2(color.g, 0.0)).g;" + " outcolor.b = texture2D (curve, vec2(color.b, 0.0)).b;" + " outcolor.a = color.a;" + " gl_FragColor = outcolor;" + "}"; + +const gchar *sin_fragment_source_opengl = "uniform sampler2D tex;" "void main () {" " vec4 color = texture2D (tex, vec2(gl_TexCoord[0].st));" @@ -427,6 +744,35 @@ const gchar *sin_fragment_source = " gl_FragColor = color * mix + luma * (1.0 - mix);" "}"; +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 () {" + " vec4 color = texture2D (tex, vec2(v_texcoord.xy));" + " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" +/* calculate hue with the Preucil formula */ + " float cosh = color.r - 0.5*(color.g + color.b);" +/* sqrt(3)/2 = 0.866 */ + " float sinh = 0.866*(color.g - color.b);" +/* hue = atan2 h */ + " float sch = (1.0-sinh)*cosh;" +/* ok this is a little trick I came up because I didn't find any + * detailed proof of the Preucil formula. The issue is that tan(h) is + * pi-periodic so the smoothstep thing gives both reds (h = 0) and + * cyans (h = 180). I don't want to use atan since it requires + * branching and doesn't work on i915. So take only the right half of + * the circle where cosine is positive */ +/* take a slightly purple color trying to get rid of human skin reds */ +/* tanh = +-1.0 for h = +-45, where yellow=60, magenta=-60 */ + " float a = smoothstep (0.3, 1.0, sch);" + " float b = smoothstep (-0.4, -0.1, sinh);" + " float mix = a * b;" + " gl_FragColor = color * mix + luma * (1.0 - mix);" + "}"; + const gchar *interpolate_fragment_source = "uniform sampler2D base;" "uniform sampler2D blend;" diff --git a/ext/gl/effects/gstgleffectssources.h b/ext/gl/effects/gstgleffectssources.h index 76f0b5e97..28a5c8577 100644 --- a/ext/gl/effects/gstgleffectssources.h +++ b/ext/gl/effects/gstgleffectssources.h @@ -21,35 +21,51 @@ #ifndef __GST_GL_EFFECTS_SOURCES_H__ #define __GST_GL_EFFECTS_SOURCES_H__ -#if GST_GL_HAVE_OPENGL extern const gchar *mirror_fragment_source_opengl; extern const gchar *squeeze_fragment_source_opengl; -#endif +extern const gchar *stretch_fragment_source_opengl; +extern const gchar *fisheye_fragment_source_opengl; +extern const gchar *twirl_fragment_source_opengl; +extern const gchar *bulge_fragment_source_opengl; +extern const gchar *tunnel_fragment_source_opengl; +extern const gchar *square_fragment_source_opengl; +extern const gchar *luma_threshold_fragment_source_opengl; +extern const gchar *hconv7_fragment_source_opengl; +extern const gchar *vconv7_fragment_source_opengl; +extern const gchar *sum_fragment_source_opengl; +extern const gchar *luma_to_curve_fragment_source_opengl; +extern const gchar *rgb_to_curve_fragment_source_opengl; +extern const gchar *sin_fragment_source_opengl; +extern const gchar *desaturate_fragment_source_opengl; +extern const gchar *sep_sobel_hconv3_fragment_source_opengl; +extern const gchar *sep_sobel_vconv3_fragment_source_opengl; +extern const gchar *sep_sobel_length_fragment_source_opengl; +extern const gchar *multiply_fragment_source_opengl; extern const gchar *mirror_fragment_source_gles2; extern const gchar *squeeze_fragment_source_gles2; +extern const gchar *stretch_fragment_source_gles2; +extern const gchar *fisheye_fragment_source_gles2; +extern const gchar *twirl_fragment_source_gles2; +extern const gchar *bulge_fragment_source_gles2; +extern const gchar *tunnel_fragment_source_gles2; +extern const gchar *square_fragment_source_gles2; +extern const gchar *luma_threshold_fragment_source_gles2; +extern const gchar *hconv7_fragment_source_gles2; +extern const gchar *vconv7_fragment_source_gles2; +extern const gchar *sum_fragment_source_gles2; +extern const gchar *luma_to_curve_fragment_source_gles2; +extern const gchar *rgb_to_curve_fragment_source_gles2; +extern const gchar *sin_fragment_source_gles2; +extern const gchar *desaturate_fragment_source_gles2; +extern const gchar *sep_sobel_hconv3_fragment_source_gles2; +extern const gchar *sep_sobel_vconv3_fragment_source_gles2; +extern const gchar *sep_sobel_length_fragment_source_gles2; +extern const gchar *multiply_fragment_source_gles2; -extern const gchar *stretch_fragment_source; -extern const gchar *tunnel_fragment_source; -extern const gchar *fisheye_fragment_source; -extern const gchar *twirl_fragment_source; -extern const gchar *bulge_fragment_source; -extern const gchar *square_fragment_source; -extern const gchar *luma_threshold_fragment_source; -extern const gchar *sep_sobel_length_fragment_source; -extern const gchar *desaturate_fragment_source; -extern const gchar *sep_sobel_hconv3_fragment_source; -extern const gchar *sep_sobel_vconv3_fragment_source; -extern const gchar *hconv7_fragment_source; -extern const gchar *vconv7_fragment_source; -extern const gchar *sum_fragment_source; -extern const gchar *luma_to_curve_fragment_source; -extern const gchar *rgb_to_curve_fragment_source; -extern const gchar *sin_fragment_source; extern const gchar *interpolate_fragment_source; extern const gchar *texture_interp_fragment_source; extern const gchar *difference_fragment_source; -extern const gchar *multiply_fragment_source; void fill_gaussian_kernel (float *kernel, int size, float sigma); diff --git a/ext/gl/effects/gstgleffectstretch.c b/ext/gl/effects/gstgleffectstretch.c index 206a097fd..0c645f98f 100644 --- a/ext/gl/effects/gstgleffectstretch.c +++ b/ext/gl/effects/gstgleffectstretch.c @@ -33,24 +33,18 @@ gst_gl_effects_stretch_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "stretch0"); + shader = gst_gl_effects_get_fragment_shader (effects, "stretch", + stretch_fragment_source_gles2, stretch_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "stretch0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - stretch_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize stretch shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); gl->ActiveTexture (GL_TEXTURE0); @@ -59,9 +53,6 @@ gst_gl_effects_stretch_callback (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); - gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); - gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffecttunnel.c b/ext/gl/effects/gstgleffecttunnel.c index b547436d2..3bacdae22 100644 --- a/ext/gl/effects/gstgleffecttunnel.c +++ b/ext/gl/effects/gstgleffecttunnel.c @@ -33,23 +33,18 @@ gst_gl_effects_tunnel_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "tunnel0"); + shader = gst_gl_effects_get_fragment_shader (effects, "tunnel", + tunnel_fragment_source_gles2, tunnel_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "tunnel0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - tunnel_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize tunnel shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -59,9 +54,6 @@ gst_gl_effects_tunnel_callback (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); - gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); - gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffecttwirl.c b/ext/gl/effects/gstgleffecttwirl.c index 3a9b3746f..2061c87cf 100644 --- a/ext/gl/effects/gstgleffecttwirl.c +++ b/ext/gl/effects/gstgleffecttwirl.c @@ -33,23 +33,18 @@ gst_gl_effects_twirl_callback (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "twirl0"); + shader = gst_gl_effects_get_fragment_shader (effects, "twirl", + twirl_fragment_source_gles2, twirl_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "twirl0", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - twirl_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize twirl shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -59,9 +54,6 @@ gst_gl_effects_twirl_callback (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); - gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); - gst_gl_filter_draw_texture (filter, texture, width, height); } diff --git a/ext/gl/effects/gstgleffectxray.c b/ext/gl/effects/gstgleffectxray.c index 79aeca131..5f104df00 100644 --- a/ext/gl/effects/gstgleffectxray.c +++ b/ext/gl/effects/gstgleffectxray.c @@ -48,28 +48,22 @@ gst_gl_effects_xray_step_two (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "xray1"); + shader = gst_gl_effects_get_fragment_shader (effects, "hconv7", + hconv7_fragment_source_gles2, hconv7_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "xray1", shader); - } + if (!shader) + return; if (!kernel_ready) { fill_gaussian_kernel (gauss_kernel, 7, 1.5); kernel_ready = TRUE; } - - if (!gst_gl_shader_compile_and_check (shader, - hconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize hconv7 shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); - return; +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); } - - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#endif gst_gl_shader_use (shader); @@ -80,7 +74,7 @@ gst_gl_effects_xray_step_two (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 1); gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "width", width); + gst_gl_shader_set_uniform_1f (shader, "gauss_width", width); gst_gl_filter_draw_texture (filter, texture, width, height); } @@ -95,23 +89,18 @@ gst_gl_effects_xray_step_three (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "xray2"); + shader = gst_gl_effects_get_fragment_shader (effects, "vconv7", + vconv7_fragment_source_gles2, vconv7_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "xray2", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - vconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize vconv7 shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -122,7 +111,7 @@ gst_gl_effects_xray_step_three (gint width, gint height, guint texture, gst_gl_shader_set_uniform_1i (shader, "tex", 1); gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "height", height); + gst_gl_shader_set_uniform_1f (shader, "gauss_height", height); gst_gl_filter_draw_texture (filter, texture, width, height); } @@ -138,24 +127,18 @@ gst_gl_effects_xray_desaturate (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "xray_desat"); - - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "xray_desat", shader); - } + shader = gst_gl_effects_get_fragment_shader (effects, "desaturate", + desaturate_fragment_source_gles2, desaturate_fragment_source_opengl); - if (!gst_gl_shader_compile_and_check (shader, - desaturate_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize desaturate shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -178,25 +161,19 @@ gst_gl_effects_xray_sobel_hconv (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_hconv"); - - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "xray_sob_hconv", - shader); - } + shader = gst_gl_effects_get_fragment_shader (effects, "sobel_hconv3", + sep_sobel_hconv3_fragment_source_gles2, + sep_sobel_hconv3_fragment_source_opengl); - if (!gst_gl_shader_compile_and_check (shader, - sep_sobel_hconv3_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize sobel hvonc3 shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -221,25 +198,19 @@ gst_gl_effects_xray_sobel_vconv (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_vconv"); - - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "xray_sob_vconv", - shader); - } + shader = gst_gl_effects_get_fragment_shader (effects, "sobel_vconv3", + sep_sobel_vconv3_fragment_source_gles2, + sep_sobel_vconv3_fragment_source_opengl); - if (!gst_gl_shader_compile_and_check (shader, - sep_sobel_vconv3_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize sobel vconv3 shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -264,25 +235,19 @@ gst_gl_effects_xray_sobel_length (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_len"); + shader = gst_gl_effects_get_fragment_shader (effects, "sobel_length", + sep_sobel_length_fragment_source_gles2, + sep_sobel_length_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "xray_sob_len", - shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - sep_sobel_length_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, - "Failed to initialize seobel length shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); @@ -308,23 +273,18 @@ gst_gl_effects_xray_step_five (gint width, gint height, guint texture, GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; GstGLFuncs *gl = context->gl_vtable; - shader = g_hash_table_lookup (effects->shaderstable, "xray4"); + shader = gst_gl_effects_get_fragment_shader (effects, "multiply", + multiply_fragment_source_gles2, multiply_fragment_source_opengl); - if (!shader) { - shader = gst_gl_shader_new (context); - g_hash_table_insert (effects->shaderstable, (gchar *) "xray4", shader); - } - - if (!gst_gl_shader_compile_and_check (shader, - multiply_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_context_set_error (context, "Failed to initialize multiply shader"); - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("%s", gst_gl_context_get_error ()), (NULL)); + if (!shader) return; - } - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (context)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + } +#endif gst_gl_shader_use (shader); diff --git a/ext/gl/gstgldifferencematte.c b/ext/gl/gstgldifferencematte.c index ce1b5130c..479358d22 100644 --- a/ext/gl/gstgldifferencematte.c +++ b/ext/gl/gstgldifferencematte.c @@ -109,7 +109,7 @@ gst_gl_differencematte_init_gl_resources (GstGLFilter * filter) } if (!gst_gl_shader_compile_and_check (differencematte->shader[1], - hconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { + hconv7_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) { gst_gl_context_set_error (GST_GL_BASE_FILTER (differencematte)->context, "Failed to initialize hconv7 shader"); GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, @@ -118,7 +118,7 @@ gst_gl_differencematte_init_gl_resources (GstGLFilter * filter) } if (!gst_gl_shader_compile_and_check (differencematte->shader[2], - vconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) { + vconv7_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) { gst_gl_context_set_error (GST_GL_BASE_FILTER (differencematte)->context, "Failed to initialize vconv7 shader"); GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, diff --git a/ext/gl/gstgleffects.c b/ext/gl/gstgleffects.c index a85e62485..d4e807391 100644 --- a/ext/gl/gstgleffects.c +++ b/ext/gl/gstgleffects.c @@ -102,12 +102,11 @@ gst_gl_effects_effect_get_type (void) {GST_GL_EFFECT_IDENTITY, "Do nothing Effect", "identity"}, {GST_GL_EFFECT_MIRROR, "Mirror Effect", "mirror"}, {GST_GL_EFFECT_SQUEEZE, "Squeeze Effect", "squeeze"}, -#if GST_GL_HAVE_OPENGL {GST_GL_EFFECT_STRETCH, "Stretch Effect", "stretch"}, + {GST_GL_EFFECT_TUNNEL, "Light Tunnel Effect", "tunnel"}, {GST_GL_EFFECT_FISHEYE, "FishEye Effect", "fisheye"}, {GST_GL_EFFECT_TWIRL, "Twirl Effect", "twirl"}, {GST_GL_EFFECT_BULGE, "Bulge Effect", "bulge"}, - {GST_GL_EFFECT_TUNNEL, "Light Tunnel Effect", "tunnel"}, {GST_GL_EFFECT_SQUARE, "Square Effect", "square"}, {GST_GL_EFFECT_HEAT, "Heat Signature Effect", "heat"}, {GST_GL_EFFECT_SEPIA, "Sepia Toning Effect", "sepia"}, @@ -116,7 +115,6 @@ gst_gl_effects_effect_get_type (void) {GST_GL_EFFECT_XRAY, "Glowing negative effect", "xray"}, {GST_GL_EFFECT_SIN, "All Grey but Red Effect", "sin"}, {GST_GL_EFFECT_GLOW, "Glow Lighting Effect", "glow"}, -#endif {0, NULL, NULL} }; @@ -131,7 +129,6 @@ static void gst_gl_effects_set_effect (GstGLEffects * effects, gint effect_type) { GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (effects); - GstGLContext *context = GST_GL_BASE_FILTER (effects)->context; switch (effect_type) { case GST_GL_EFFECT_IDENTITY: @@ -152,78 +149,88 @@ gst_gl_effects_set_effect (GstGLEffects * effects, gint effect_type) GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; effects->current_effect = effect_type; break; - } - - if (context - && (gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL) == - GST_GL_API_NONE) { - GST_ELEMENT_WARNING (effects, RESOURCE, SETTINGS, ("%s", - "cannot change effect type"), ("%s", - "the current OpenGL context does not support the GL API required")); - return; - } -#if GST_GL_HAVE_OPENGL - switch (effect_type) { - case GST_GL_EFFECT_IDENTITY: - case GST_GL_EFFECT_MIRROR: - case GST_GL_EFFECT_SQUEEZE: - break; case GST_GL_EFFECT_STRETCH: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_stretch; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_TUNNEL: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_tunnel; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_FISHEYE: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_fisheye; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_TWIRL: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_twirl; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_BULGE: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_bulge; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_SQUARE: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_square; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_HEAT: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_heat; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_SEPIA: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sepia; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_XPRO: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xpro; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_LUMA_XPRO: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_luma_xpro; - filter_class->supported_gl_api = GST_GL_API_OPENGL; - break; - case GST_GL_EFFECT_XRAY: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xray; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_SIN: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sin; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; + break; + case GST_GL_EFFECT_XRAY: + effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sin; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; case GST_GL_EFFECT_GLOW: effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_glow; - filter_class->supported_gl_api = GST_GL_API_OPENGL; + filter_class->supported_gl_api = + GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; + effects->current_effect = effect_type; break; default: g_assert_not_reached (); } -#endif + effects->current_effect = effect_type; } @@ -447,3 +454,44 @@ gst_gl_effects_filter_texture (GstGLFilter * filter, guint in_tex, return TRUE; } + +GstGLShader * +gst_gl_effects_get_fragment_shader (GstGLEffects * effects, + const gchar * shader_name, const gchar * shader_source_gles2, + const gchar * shader_source_opengl) +{ + GstGLShader *shader; + GstGLFilter *filter = GST_GL_FILTER (effects); + GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; + + shader = g_hash_table_lookup (effects->shaderstable, shader_name); + + if (!shader) { + shader = gst_gl_shader_new (context); + g_hash_table_insert (effects->shaderstable, (gchar *) shader_name, shader); + + if (USING_GLES2 (context) || USING_OPENGL3 (context)) { + if (!gst_gl_shader_compile_with_default_v_and_check (shader, + shader_source_gles2, &filter->draw_attr_position_loc, + &filter->draw_attr_texture_loc)) { + /* gst gl context error is already set */ + GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, + ("Failed to initialize %s shader, %s", + shader_name, gst_gl_context_get_error ()), (NULL)); + return NULL; + } + } +#if GST_GL_HAVE_OPENGL + if (!gst_gl_shader_compile_and_check (shader, + shader_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) { + gst_gl_context_set_error (context, "Failed to initialize %s shader", + shader_name); + GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, ("%s", + gst_gl_context_get_error ()), (NULL)); + return NULL; + } +#endif + } + + return shader; +} diff --git a/ext/gl/gstgleffects.h b/ext/gl/gstgleffects.h index 71bec2582..695a65683 100644 --- a/ext/gl/gstgleffects.h +++ b/ext/gl/gstgleffects.h @@ -34,6 +34,12 @@ G_BEGIN_DECLS #define GST_IS_GL_EFFECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) , GST_TYPE_GL_EFFECTS)) #define GST_GL_EFFECTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass)) +#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) +#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) +#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0)) +#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) +#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) + typedef struct _GstGLEffects GstGLEffects; typedef struct _GstGLEffectsClass GstGLEffectsClass; @@ -82,6 +88,8 @@ enum GType gst_gl_effects_get_type (void); +GstGLShader* gst_gl_effects_get_fragment_shader (GstGLEffects *effects, + const gchar * shader_name, const gchar * shader_source_gles2, const gchar * shader_source_opengl); void gst_gl_effects_identity (GstGLEffects *effects); void gst_gl_effects_mirror (GstGLEffects *effects); diff --git a/ext/gl/gstglfilterblur.c b/ext/gl/gstglfilterblur.c index 842a01410..c9a5d9538 100644 --- a/ext/gl/gstglfilterblur.c +++ b/ext/gl/gstglfilterblur.c @@ -181,12 +181,12 @@ gst_gl_filterblur_init_shader (GstGLFilter * filter) //blocking call, wait the opengl thread has compiled the shader if (!gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0, - hconv7_fragment_source, &blur_filter->shader0)) + hconv7_fragment_source_opengl, &blur_filter->shader0)) return FALSE; //blocking call, wait the opengl thread has compiled the shader if (!gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0, - vconv7_fragment_source, &blur_filter->shader1)) + vconv7_fragment_source_opengl, &blur_filter->shader1)) return FALSE; return TRUE; diff --git a/ext/gl/gstglfiltersobel.c b/ext/gl/gstglfiltersobel.c index f70b6d293..20d92f9dd 100644 --- a/ext/gl/gstglfiltersobel.c +++ b/ext/gl/gstglfiltersobel.c @@ -215,16 +215,16 @@ gst_gl_filtersobel_init_shader (GstGLFilter * filter) //blocking call, wait the opengl thread has compiled the shader ret = gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0, - desaturate_fragment_source, &filtersobel->desat); + desaturate_fragment_source_opengl, &filtersobel->desat); ret &= gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0, - sep_sobel_hconv3_fragment_source, &filtersobel->hconv); + sep_sobel_hconv3_fragment_source_opengl, &filtersobel->hconv); ret &= gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0, - sep_sobel_vconv3_fragment_source, &filtersobel->vconv); + sep_sobel_vconv3_fragment_source_opengl, &filtersobel->vconv); ret &= gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, 0, - sep_sobel_length_fragment_source, &filtersobel->len); + sep_sobel_length_fragment_source_opengl, &filtersobel->len); return ret; } -- 2.34.1