static void
init_pixbuf_texture (GstGLContext * context, gpointer data)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (data);
  GstGLFilter *filter = GST_GL_FILTER (data);
  const GstGLFuncs *gl = context->gl_vtable;
  guint internal_format =
      gst_gl_sized_gl_format_from_gl_format_type (context, GL_RGBA,
      GL_UNSIGNED_BYTE);

  gl->DeleteTextures (1, &differencematte->newbgtexture);
  gl->GenTextures (1, &differencematte->newbgtexture);
  gl->BindTexture (GL_TEXTURE_2D, differencematte->newbgtexture);
  gl->TexImage2D (GL_TEXTURE_2D, 0, internal_format,
      (gint) differencematte->pbuf_width, (gint) differencematte->pbuf_height,
      0, GL_RGBA, GL_UNSIGNED_BYTE, differencematte->pixbuf);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  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);

  if (differencematte->savedbgtexture == 0) {
    gl->GenTextures (1, &differencematte->savedbgtexture);
    gl->BindTexture (GL_TEXTURE_2D, differencematte->savedbgtexture);
    gl->TexImage2D (GL_TEXTURE_2D, 0, internal_format,
        GST_VIDEO_INFO_WIDTH (&filter->out_info),
        GST_VIDEO_INFO_HEIGHT (&filter->out_info),
        0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    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);
  }
}
/* free resources that need a gl context */
static void
gst_gl_differencematte_reset_gl_resources (GstGLFilter * filter)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
  gint i;

  gl->DeleteTextures (1, &differencematte->savedbgtexture);
  gl->DeleteTextures (1, &differencematte->newbgtexture);
  for (i = 0; i < 4; i++) {
    if (differencematte->identity_shader) {
      gst_object_unref (differencematte->identity_shader);
      differencematte->identity_shader = NULL;
    }

    if (differencematte->shader[i]) {
      gst_object_unref (differencematte->shader[i]);
      differencematte->shader[i] = NULL;
    }
    if (differencematte->midtexture[i]) {
      gl->DeleteTextures (1, &differencematte->midtexture[i]);
      differencematte->midtexture[i] = 0;
    }
  }
  differencematte->location = NULL;
  differencematte->pixbuf = NULL;
  differencematte->savedbgtexture = 0;
  differencematte->newbgtexture = 0;
  differencematte->bg_has_changed = FALSE;
}
Esempio n. 3
0
/* init resources that need a gl context */
static void
gst_gl_differencematte_init_gl_resources (GstGLFilter * filter)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
    gint i;

    for (i = 0; i < 4; i++) {
        glGenTextures (1, &differencematte->midtexture[i]);
        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->midtexture[i]);
        glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
                      filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
                         GL_LINEAR);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
                         GL_LINEAR);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
                         GL_CLAMP_TO_EDGE);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
                         GL_CLAMP_TO_EDGE);
        differencematte->shader[i] = gst_gl_shader_new ();
    }

    g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[0],
                      difference_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
    g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[1],
                      hconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));

    g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[2],
                      vconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));

    g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[3],
                      texture_interp_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
}
static void
gst_gl_differencematte_diff (gint width, gint height, guint texture,
    gpointer stuff)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
  GstGLFilter *filter = GST_GL_FILTER (stuff);
  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;

  gl->MatrixMode (GL_PROJECTION);
  gl->LoadIdentity ();

  gst_gl_shader_use (differencematte->shader[0]);

  gl->ActiveTexture (GL_TEXTURE0);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (differencematte->shader[0], "current", 0);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->BindTexture (GL_TEXTURE_2D, differencematte->savedbgtexture);

  gst_gl_shader_set_uniform_1i (differencematte->shader[0], "saved", 1);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
Esempio n. 5
0
static void
gst_gl_differencematte_interp (gint width, gint height, guint texture,
                               gpointer stuff)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);

    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();

    gst_gl_shader_use (differencematte->shader[3]);

    glActiveTexture (GL_TEXTURE0);
    glEnable (GL_TEXTURE_RECTANGLE_ARB);
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
    glDisable (GL_TEXTURE_RECTANGLE_ARB);

    gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 0);

    glActiveTexture (GL_TEXTURE1);
    glEnable (GL_TEXTURE_RECTANGLE_ARB);
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture);
    glDisable (GL_TEXTURE_RECTANGLE_ARB);

    gst_gl_shader_set_uniform_1i (differencematte->shader[3], "base", 1);

    glActiveTexture (GL_TEXTURE2);
    glEnable (GL_TEXTURE_RECTANGLE_ARB);
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->midtexture[2]);
    glDisable (GL_TEXTURE_RECTANGLE_ARB);

    gst_gl_shader_set_uniform_1i (differencematte->shader[3], "alpha", 2);

    gst_gl_differencematte_draw_texture (differencematte, texture);
}
Esempio n. 6
0
static void
init_pixbuf_texture (GstGLDisplay * display, gpointer data)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (data);
    GstGLFilter *filter = GST_GL_FILTER (data);

    glDeleteTextures (1, &differencematte->newbgtexture);
    glGenTextures (1, &differencematte->newbgtexture);
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture);
    glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
                  filter->width, filter->height, 0,
                  GL_RGBA, GL_UNSIGNED_BYTE, differencematte->pixbuf);

    if (differencematte->savedbgtexture == 0) {
        glGenTextures (1, &differencematte->savedbgtexture);
        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture);
        glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
                      filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
                         GL_LINEAR);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
                         GL_LINEAR);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
                         GL_CLAMP_TO_EDGE);
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
                         GL_CLAMP_TO_EDGE);
    }
}
Esempio n. 7
0
static void
gst_gl_differencematte_vblur (gint width, gint height, guint texture,
                              gpointer stuff)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
    gfloat gauss_kernel[9] = {
        0.026995f, 0.064759f, 0.120985f,
        0.176033f, 0.199471f, 0.176033f,
        0.120985f, 0.064759f, 0.026995f
    };

    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();

    gst_gl_shader_use (differencematte->shader[2]);

    glActiveTexture (GL_TEXTURE0);
    glEnable (GL_TEXTURE_RECTANGLE_ARB);
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
    glDisable (GL_TEXTURE_RECTANGLE_ARB);

    gst_gl_shader_set_uniform_1i (differencematte->shader[2], "tex", 0);

    gst_gl_shader_set_uniform_1fv (differencematte->shader[2], "kernel", 9,
                                   gauss_kernel);
    gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_const",
                                  0.977016f);
    gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_offset",
                                  0.0f);

    gst_gl_differencematte_draw_texture (differencematte, texture);
}
static void
gst_gl_differencematte_interp (gint width, gint height, guint texture,
    gpointer stuff)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
  GstGLFilter *filter = GST_GL_FILTER (stuff);
  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;

  gst_gl_shader_use (differencematte->shader[3]);

  gl->ActiveTexture (GL_TEXTURE0);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 0);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->BindTexture (GL_TEXTURE_2D, differencematte->newbgtexture);

  gst_gl_shader_set_uniform_1i (differencematte->shader[3], "base", 1);

  gl->ActiveTexture (GL_TEXTURE2);
  gl->BindTexture (GL_TEXTURE_2D, differencematte->midtexture[2]);

  gst_gl_shader_set_uniform_1i (differencematte->shader[3], "alpha", 2);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
Esempio n. 9
0
static gboolean
gst_gl_differencematte_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
                               GstGLBuffer * outbuf)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);

    differencematte->intexture = inbuf->texture;

    if (differencematte->bg_has_changed && (differencematte->location != NULL)) {

        if (!gst_gl_differencematte_loader (filter))
            differencematte->pixbuf = NULL;

        /* if loader failed then display is turned off */
        gst_gl_display_thread_add (filter->display, init_pixbuf_texture,
                                   differencematte);

        /* save current frame, needed to calculate difference between
         * this frame and next ones */
        gst_gl_filter_render_to_target (filter, inbuf->texture,
                                        differencematte->savedbgtexture,
                                        gst_gl_differencematte_save_texture, differencematte);

        if (differencematte->pixbuf) {
            free (differencematte->pixbuf);
            differencematte->pixbuf = NULL;
        }

        differencematte->bg_has_changed = FALSE;
    }

    if (differencematte->savedbgtexture != 0) {
        gst_gl_filter_render_to_target (filter,
                                        inbuf->texture,
                                        differencematte->midtexture[0],
                                        gst_gl_differencematte_diff, differencematte);
        gst_gl_filter_render_to_target (filter,
                                        differencematte->midtexture[0],
                                        differencematte->midtexture[1],
                                        gst_gl_differencematte_hblur, differencematte);
        gst_gl_filter_render_to_target (filter,
                                        differencematte->midtexture[1],
                                        differencematte->midtexture[2],
                                        gst_gl_differencematte_vblur, differencematte);
        gst_gl_filter_render_to_target (filter,
                                        inbuf->texture,
                                        outbuf->texture, gst_gl_differencematte_interp, differencematte);
    } else {
        gst_gl_filter_render_to_target (filter,
                                        inbuf->texture,
                                        outbuf->texture, gst_gl_differencematte_identity, differencematte);
    }

    return TRUE;
}
Esempio n. 10
0
static void
gst_gl_differencematte_identity (gint width, gint height, guint texture,
                                 gpointer stuff)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);

    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();

    gst_gl_differencematte_draw_texture (differencematte, texture);
}
static void
gst_gl_differencematte_identity (gint width, gint height, guint texture,
    gpointer stuff)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
  GstGLFilter *filter = GST_GL_FILTER (differencematte);
  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;

  gl->MatrixMode (GL_PROJECTION);
  gl->LoadIdentity ();

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static gboolean
gst_gl_differencematte_filter_texture (GstGLFilter * filter, guint in_tex,
    guint out_tex)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);

  differencematte->intexture = in_tex;

  if (differencematte->bg_has_changed && (differencematte->location != NULL)) {

    if (!gst_gl_differencematte_loader (filter))
      differencematte->pixbuf = NULL;

    /* if loader failed then context is turned off */
    gst_gl_context_thread_add (GST_GL_BASE_FILTER (filter)->context,
        init_pixbuf_texture, differencematte);

    /* save current frame, needed to calculate difference between
     * this frame and next ones */
    gst_gl_filter_render_to_target (filter, TRUE, in_tex,
        differencematte->savedbgtexture,
        gst_gl_differencematte_identity, differencematte);

    if (differencematte->pixbuf) {
      free (differencematte->pixbuf);
      differencematte->pixbuf = NULL;
    }

    differencematte->bg_has_changed = FALSE;
  }

  if (differencematte->savedbgtexture != 0) {
    gst_gl_filter_render_to_target (filter, TRUE, in_tex,
        differencematte->midtexture[0], gst_gl_differencematte_diff,
        differencematte);
    gst_gl_filter_render_to_target (filter, FALSE,
        differencematte->midtexture[0], differencematte->midtexture[1],
        gst_gl_differencematte_hblur, differencematte);
    gst_gl_filter_render_to_target (filter, FALSE,
        differencematte->midtexture[1], differencematte->midtexture[2],
        gst_gl_differencematte_vblur, differencematte);
    gst_gl_filter_render_to_target (filter, TRUE, in_tex, out_tex,
        gst_gl_differencematte_interp, differencematte);
  } else {
    gst_gl_filter_render_to_target (filter, TRUE, in_tex, out_tex,
        gst_gl_differencematte_identity, differencematte);
  }

  return TRUE;
}
Esempio n. 13
0
static void
gst_gl_differencematte_get_property (GObject * object, guint prop_id,
                                     GValue * value, GParamSpec * pspec)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object);

    switch (prop_id) {
    case PROP_LOCATION:
        g_value_set_string (value, differencematte->location);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}
static void
gst_gl_differencematte_identity (gint width, gint height, guint texture,
    gpointer stuff)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
  GstGLFilter *filter = GST_GL_FILTER (differencematte);
  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;

  gst_gl_shader_use (differencematte->identity_shader);

  gl->ActiveTexture (GL_TEXTURE0);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (differencematte->identity_shader, "tex", 0);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
Esempio n. 15
0
static void
gst_gl_differencematte_set_property (GObject * object, guint prop_id,
                                     const GValue * value, GParamSpec * pspec)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object);

    switch (prop_id) {
    case PROP_LOCATION:
        if (differencematte->location != NULL)
            g_free (differencematte->location);
        differencematte->bg_has_changed = TRUE;
        differencematte->location = g_value_dup_string (value);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}
Esempio n. 16
0
/* free resources that need a gl context */
static void
gst_gl_differencematte_reset_gl_resources (GstGLFilter * filter)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
    gint i;

    glDeleteTextures (1, &differencematte->savedbgtexture);
    glDeleteTextures (1, &differencematte->newbgtexture);
    for (i = 0; i < 4; i++) {
        g_object_unref (differencematte->shader[i]);
        differencematte->shader[i] = NULL;
        glDeleteTextures (1, &differencematte->midtexture[i]);
    }
    differencematte->location = NULL;
    differencematte->pixbuf = NULL;
    differencematte->savedbgtexture = 0;
    differencematte->newbgtexture = 0;
    differencematte->bg_has_changed = FALSE;
}
static void
gst_gl_differencematte_vblur (gint width, gint height, guint texture,
    gpointer stuff)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
  GstGLFilter *filter = GST_GL_FILTER (stuff);
  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;

  gst_gl_shader_use (differencematte->shader[2]);

  gl->ActiveTexture (GL_TEXTURE0);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (differencematte->shader[2], "tex", 0);

  gst_gl_shader_set_uniform_1fv (differencematte->shader[2], "kernel", 7,
      differencematte->kernel);
  gst_gl_shader_set_uniform_1f (differencematte->shader[2], "gauss_height",
      height);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
Esempio n. 18
0
static gboolean
gst_gl_differencematte_loader (GstGLFilter * filter)
{
    GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);

    png_structp png_ptr;
    png_infop info_ptr;
    guint sig_read = 0;
    png_uint_32 width = 0;
    png_uint_32 height = 0;
    gint bit_depth = 0;
    gint color_type = 0;
    gint interlace_type = 0;
    png_FILE_p fp = NULL;
    guint y = 0;
    guchar **rows = NULL;

    if (!filter->display)
        return TRUE;

    if ((fp = fopen (differencematte->location, "rb")) == NULL)
        LOAD_ERROR ("file not found");

    png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (png_ptr == NULL) {
        fclose (fp);
        LOAD_ERROR ("failed to initialize the png_struct");
    }

    png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn);

    info_ptr = png_create_info_struct (png_ptr);
    if (info_ptr == NULL) {
        fclose (fp);
        png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
        LOAD_ERROR ("failed to initialize the memory for image information");
    }

    png_init_io (png_ptr, fp);

    png_set_sig_bytes (png_ptr, sig_read);

    png_read_info (png_ptr, info_ptr);

    png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                  &interlace_type, int_p_NULL, int_p_NULL);

    if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
        fclose (fp);
        png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
        LOAD_ERROR ("color type is not rgb");
    }

    filter->width = width;
    filter->height = height;

    differencematte->pixbuf =
        (guchar *) malloc (sizeof (guchar) * width * height * 4);

    rows = (guchar **) malloc (sizeof (guchar *) * height);

    for (y = 0; y < height; ++y)
        rows[y] = (guchar *) (differencematte->pixbuf + y * width * 4);

    png_read_image (png_ptr, rows);

    free (rows);

    png_read_end (png_ptr, info_ptr);
    png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
    fclose (fp);

    return TRUE;
}
/* init resources that need a gl context */
static void
gst_gl_differencematte_init_gl_resources (GstGLFilter * filter)
{
  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
  GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
  const GstGLFuncs *gl = context->gl_vtable;
  GError *error = NULL;
  gint i;

  for (i = 0; i < 4; i++) {
    gl->GenTextures (1, &differencematte->midtexture[i]);
    gl->BindTexture (GL_TEXTURE_2D, differencematte->midtexture[i]);
    gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8,
        GST_VIDEO_INFO_WIDTH (&filter->out_info),
        GST_VIDEO_INFO_HEIGHT (&filter->out_info),
        0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    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);
  }

  if (!(differencematte->identity_shader =
          gst_gl_shader_new_default (context, &error))) {
    GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
            "Failed to compile identity shader"), ("%s", error->message));
    return;
  }

  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_VERSION_NONE,
                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
                  difference_fragment_source), NULL))) {
    GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
            "Failed to compile difference shader"), ("%s", error->message));
    return;
  }

  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_VERSION_NONE,
                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
                  hconv7_fragment_source_gles2), NULL))) {
    GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
            "Failed to compile convolution shader"), ("%s", error->message));
    return;
  }

  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_VERSION_NONE,
                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
                  vconv7_fragment_source_gles2), NULL))) {
    GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
            "Failed to compile convolution shader"), ("%s", error->message));
    return;
  }

  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_VERSION_NONE,
                  GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
                  texture_interp_fragment_source), NULL))) {
    GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s",
            "Failed to compile interpolation shader"), ("%s", error->message));
    return;
  }

  /* FIXME: this should really be per shader */
  filter->draw_attr_position_loc =
      gst_gl_shader_get_attribute_location (differencematte->shader[2],
      "a_position");
  filter->draw_attr_texture_loc =
      gst_gl_shader_get_attribute_location (differencematte->shader[2],
      "a_texcoord");
}