Beispiel #1
0
static void
gst_gl_effects_xray_step_three (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLShader *shader;

  shader = g_hash_table_lookup (effects->shaderstable, "xray2");

  if (!shader) {
    shader = gst_gl_shader_new ();
    g_hash_table_insert (effects->shaderstable, "xray2", shader);
  }

  g_return_if_fail (gst_gl_shader_compile_and_check (shader,
          vconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();

  gst_gl_shader_use (shader);

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

  gst_gl_shader_set_uniform_1i (shader, "tex", 1);
  gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel);

  gst_gl_effects_draw_texture (effects, texture);
}
static void
gst_gl_effects_sobel_callback_vconv (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader = NULL;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);

  if (NULL != (shader = gst_gl_effects_get_fragment_shader (effects, "vconv0",
              sep_sobel_vconv3_fragment_source_gles2,
              sep_sobel_vconv3_fragment_source_opengl))) {
    GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;

#if GST_GL_HAVE_OPENGL
    if (USING_OPENGL (GST_GL_BASE_FILTER (filter)->context)) {
      gl->MatrixMode (GL_PROJECTION);
      gl->LoadIdentity ();
    }
#endif

    gst_gl_shader_use (shader);

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

    gst_gl_shader_set_uniform_1i (shader, "tex", 0);
    gst_gl_shader_set_uniform_1f (shader, "height", height);

    gst_gl_filter_draw_texture (filter, texture, width, height);
  }
}
static void
gst_gl_effects_twirl_callback (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = GST_GL_BASE_FILTER (filter)->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = gst_gl_effects_get_fragment_shader (effects, "twirl",
      twirl_fragment_source_gles2);

  if (!shader)
    return;

#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);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (shader, "tex", 0);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static void
gst_gl_effects_squeeze_callback (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLFilter *filter = GST_GL_FILTER (data);
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "squeeze0");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, (gchar *) "squeeze0", shader);

    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);
    gl->LoadIdentity ();
  }
#endif

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE0);
  if (USING_OPENGL (context))
    gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (shader, "tex", 0);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static void
gst_gl_effects_heat_callback (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLEffects *effects = GST_GL_EFFECTS (data);

  gst_gl_effects_luma_to_curve (effects, heat_curve, GST_GL_EFFECTS_CURVE_HEAT,
      width, height, texture);
}
Beispiel #6
0
static void
gst_gl_effects_xray_step_one (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLEffects *effects = GST_GL_EFFECTS (data);

  gst_gl_effects_luma_to_curve (effects, xray_curve, GST_GL_EFFECTS_CURVE_XRAY,
      width, height, texture);
}
Beispiel #7
0
static void
gst_gl_effects_init_resources (GstGLFilter * filter)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);
  gint i;

  effects->shaderstable = g_hash_table_new (g_str_hash, g_str_equal);

  for (i = 0; i < NEEDED_TEXTURES; i++) {
    effects->midtexture[i] = 0;
  }
  for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) {
    effects->curve[i] = 0;
  }
}
Beispiel #8
0
/* free resources that need a gl context */
static void
gst_gl_effects_reset_gl_resources (GstGLFilter * filter)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);
  gint i;

  for (i = 0; i < 10; i++) {
    glDeleteTextures (1, &effects->midtexture[i]);
    effects->midtexture[i] = 0;
  }
  for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) {
    glDeleteTextures (1, &effects->curve[i]);
    effects->curve[i] = 0;
  }
}
Beispiel #9
0
static void
gst_gl_effects_reset_resources (GstGLFilter * filter)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);

  /* release shaders in the gl thread */
  g_hash_table_foreach (effects->shaderstable, gst_gl_effects_ghash_func_clean,
      filter);

  /* clean the htable without calling values destructors
   * because shaders have been released in the glthread
   * through the foreach func */
  g_hash_table_unref (effects->shaderstable);
  effects->shaderstable = NULL;
}
Beispiel #10
0
static gboolean
gst_gl_effects_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
    GstGLBuffer * outbuf)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);

  effects->intexture = inbuf->texture;
  effects->outtexture = outbuf->texture;

  if (effects->horizontal_swap == TRUE)
    gst_gl_display_thread_add (filter->display, set_horizontal_swap, effects);

  effects->effect (effects);

  return TRUE;
}
Beispiel #11
0
static gboolean
gst_gl_effects_filter_texture (GstGLFilter * filter, guint in_tex,
    guint out_tex)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);

  effects->intexture = in_tex;
  effects->outtexture = out_tex;

  if (effects->horizontal_swap == TRUE)
    gst_gl_context_thread_add (filter->context, set_horizontal_swap, effects);

  effects->effect (effects);

  return TRUE;
}
Beispiel #12
0
/* free resources that need a gl context */
static void
gst_gl_effects_reset_gl_resources (GstGLFilter * filter)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);
  GstGLFuncs *gl = filter->context->gl_vtable;
  gint i = 0;

  for (i = 0; i < NEEDED_TEXTURES; i++) {
    gl->DeleteTextures (1, &effects->midtexture[i]);
    effects->midtexture[i] = 0;
  }
  for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) {
    gl->DeleteTextures (1, &effects->curve[i]);
    effects->curve[i] = 0;
  }
}
void
gst_gl_effects_xray_step_five (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "xray4");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, "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));
    return;
  }

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

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE2);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, effects->midtexture[2]);
  gl->Disable (GL_TEXTURE_2D);

  gst_gl_shader_set_uniform_1i (shader, "base", 2);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);
  gl->Disable (GL_TEXTURE_2D);

  gst_gl_shader_set_uniform_1f (shader, "alpha", (gfloat) 0.5f);
  gst_gl_shader_set_uniform_1i (shader, "blend", 1);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static void
gst_gl_effects_xray_step_two (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "xray1");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, "xray1", shader);
  }

  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;
  }

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

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);
  gl->Disable (GL_TEXTURE_2D);

  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_filter_draw_texture (filter, texture, width, height);
}
Beispiel #15
0
void
gst_gl_effects_xray_step_five (gint width, gint height, guint texture,
    gpointer stuff)
{
  GstGLEffects *effects = GST_GL_EFFECTS (stuff);
  GstGLShader *shader;

  shader = g_hash_table_lookup (effects->shaderstable, "xray4");

  if (!shader) {
    shader = gst_gl_shader_new ();
    g_hash_table_insert (effects->shaderstable, "xray4", shader);
  }

  if (!gst_gl_shader_compile_and_check (shader,
          multiply_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
    gst_gl_display_set_error (GST_GL_FILTER (effects)->display,
        "Failed to initialize multiply shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        GST_GL_DISPLAY_ERR_MSG (GST_GL_FILTER (effects)->display), (NULL));
    return;
  }

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();

  gst_gl_shader_use (shader);

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

  gst_gl_shader_set_uniform_1i (shader, "base", 2);

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

  gst_gl_shader_set_uniform_1f (shader, "alpha", (gfloat) 0.5f);
  gst_gl_shader_set_uniform_1i (shader, "blend", 1);

  gst_gl_effects_draw_texture (effects, texture);
}
Beispiel #16
0
static void
gst_gl_effects_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstGLEffects *effects = GST_GL_EFFECTS (object);

  switch (prop_id) {
    case PROP_EFFECT:
      g_value_set_enum (value, effects->current_effect);
      break;
    case PROP_HSWAP:
      g_value_set_boolean (value, effects->horizontal_swap);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
/* init resources that need a gl context */
static void
gst_gl_effects_init_gl_resources (GstGLFilter * filter)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);
  gint i;

  for (i = 0; i < NEEDED_TEXTURES; i++) {
    glGenTextures (1, &effects->midtexture[i]);
    glBindTexture (GL_TEXTURE_2D, effects->midtexture[i]);
    glTexImage2D (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);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  }
}
Beispiel #18
0
static void
gst_gl_effects_xray_step_two (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLShader *shader;

  shader = g_hash_table_lookup (effects->shaderstable, "xray1");

  if (!shader) {
    shader = gst_gl_shader_new ();
    g_hash_table_insert (effects->shaderstable, "xray1", shader);
  }

  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_display_set_error (GST_GL_FILTER (effects)->display,
        "Failed to initialize hconv7 shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        GST_GL_DISPLAY_ERR_MSG (GST_GL_FILTER (effects)->display), (NULL));
    return;
  }

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();

  gst_gl_shader_use (shader);

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

  gst_gl_shader_set_uniform_1i (shader, "tex", 1);
  gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel);

  gst_gl_effects_draw_texture (effects, texture);
}
static void
gst_gl_effects_square_callback (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "square0");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, "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));
    return;
  }

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

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE0);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, 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);
}
static void
gst_gl_effects_xray_sobel_length (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_len");

  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));
    return;
  }

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

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);
  gl->Disable (GL_TEXTURE_2D);

  gst_gl_shader_set_uniform_1i (shader, "tex", 1);
  gst_gl_shader_set_uniform_1i (shader, "invert", TRUE);
  gst_gl_filter_draw_texture (filter, texture, width, height);
}
Beispiel #21
0
/* init resources that need a gl context */
static void
gst_gl_effects_init_gl_resources (GstGLFilter * filter)
{
  GstGLEffects *effects = GST_GL_EFFECTS (filter);
  gint i;

  for (i = 0; i < NEEDED_TEXTURES; i++) {
    glGenTextures (1, &effects->midtexture[i]);
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, effects->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);
  }
}
Beispiel #22
0
static void
gst_gl_effects_stretch_callback (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLEffects *effects = GST_GL_EFFECTS (data);

  GstGLShader *shader;

  shader = g_hash_table_lookup (effects->shaderstable, "stretch0");

  if (!shader) {
    shader = gst_gl_shader_new ();
    g_hash_table_insert (effects->shaderstable, "stretch0", shader);
  }

  if (!gst_gl_shader_compile_and_check (shader,
          stretch_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
    gst_gl_display_set_error (GST_GL_FILTER (effects)->display,
        "Failed to initialize stretch shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        GST_GL_DISPLAY_ERR_MSG (GST_GL_FILTER (effects)->display), (NULL));
    return;
  }

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();

  gst_gl_shader_use (shader);

  glActiveTexture (GL_TEXTURE0);
  glEnable (GL_TEXTURE_RECTANGLE_ARB);
  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 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_effects_draw_texture (effects, texture);
}
Beispiel #23
0
void
gst_gl_effects_xray_step_five (gint width, gint height, guint texture,
    gpointer stuff)
{
  GstGLEffects *effects = GST_GL_EFFECTS (stuff);
  GstGLShader *shader;

  shader = g_hash_table_lookup (effects->shaderstable, "xray4");

  if (!shader) {
    shader = gst_gl_shader_new ();
    g_hash_table_insert (effects->shaderstable, "xray4", shader);
  }

  g_return_if_fail (gst_gl_shader_compile_and_check (shader,
          multiply_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();

  gst_gl_shader_use (shader);

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

  gst_gl_shader_set_uniform_1i (shader, "base", 2);

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

  gst_gl_shader_set_uniform_1f (shader, "alpha", (gfloat) 0.5f);
  gst_gl_shader_set_uniform_1i (shader, "blend", 1);

  gst_gl_effects_draw_texture (effects, texture);
}