Blame ext/gl/gstglfiltershader.c

Packit 971217
/*
Packit 971217
 * glshader gstreamer plugin
Packit 971217
 * Copyrithg (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
Packit 971217
 * Copyright (C) 2009 Luc Deschenaux <luc.deschenaux@freesurf.ch>
Packit 971217
 *
Packit 971217
 * This library is free software; you can redistribute it and/or
Packit 971217
 * modify it under the terms of the GNU Library General Public
Packit 971217
 * License as published by the Free Software Foundation; either
Packit 971217
 * version 2 of the License, or (at your option) any later version.
Packit 971217
 *
Packit 971217
 * This library is distributed in the hope that it will be useful,
Packit 971217
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 971217
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 971217
 * Library General Public License for more details.
Packit 971217
 *
Packit 971217
 * You should have received a copy of the GNU Library General Public
Packit 971217
 * License along with this library; if not, write to the
Packit 971217
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 971217
 * Boston, MA 02110-1301, USA.
Packit 971217
 */
Packit 971217
Packit 971217
/**
Packit 971217
 * SECTION:element-glshader
Packit 971217
 * @title: glshader
Packit 971217
 *
Packit 971217
 * OpenGL fragment shader filter
Packit 971217
 *
Packit 971217
 * ## Examples
Packit 971217
 * |[
Packit 971217
 * gst-launch-1.0 videotestsrc ! glupload ! glshader fragment="\"`cat myshader.frag`\"" ! glimagesink
Packit 971217
 * ]|
Packit 971217
 * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required.
Packit 971217
 * Depending on the exact OpenGL version chosen and the exact requirements of
Packit 971217
 * the OpenGL implementation, a #version header may be required.
Packit 971217
 *
Packit 971217
 * The following is a simple OpenGL ES (also usable with OpenGL 3 core contexts)
Packit 971217
 * passthrough shader with the required inputs.
Packit 971217
 * |[
Packit 971217
 * #version 100
Packit 971217
 * #ifdef GL_ES
Packit 971217
 * precision mediump float;
Packit 971217
 * #endif
Packit 971217
 * varying vec2 v_texcoord;
Packit 971217
 * uniform sampler2D tex;
Packit 971217
 * uniform float time;
Packit 971217
 * uniform float width;
Packit 971217
 * uniform float height;
Packit 971217
 *
Packit 971217
 * void main () {
Packit 971217
 *   gl_FragColor = texture2D( tex, v_texcoord );
Packit 971217
 * }
Packit 971217
 * ]|
Packit 971217
 *
Packit 971217
 */
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include <gst/gl/gstglfuncs.h>
Packit 971217
Packit 971217
#include "gstglfiltershader.h"
Packit 971217
#ifdef HAVE_GRAPHENE
Packit 971217
#include <graphene-gobject.h>
Packit 971217
#endif
Packit 971217
Packit 971217
enum
Packit 971217
{
Packit 971217
  PROP_0,
Packit 971217
  PROP_SHADER,
Packit 971217
  PROP_VERTEX,
Packit 971217
  PROP_FRAGMENT,
Packit 971217
  PROP_UNIFORMS,
Packit 971217
  PROP_UPDATE_SHADER,
Packit 971217
  PROP_LAST,
Packit 971217
};
Packit 971217
Packit 971217
enum
Packit 971217
{
Packit 971217
  SIGNAL_0,
Packit 971217
  SIGNAL_CREATE_SHADER,
Packit 971217
  SIGNAL_LAST,
Packit 971217
};
Packit 971217
Packit 971217
static guint gst_gl_shader_signals[SIGNAL_LAST] = { 0 };
Packit 971217
Packit 971217
#define GST_CAT_DEFAULT gst_gl_filtershader_debug
Packit 971217
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
Packit 971217
Packit 971217
#define DEBUG_INIT \
Packit 971217
  GST_DEBUG_CATEGORY_INIT (gst_gl_filtershader_debug, "glshader", 0, "glshader element");
Packit 971217
#define gst_gl_filtershader_parent_class parent_class
Packit 971217
G_DEFINE_TYPE_WITH_CODE (GstGLFilterShader, gst_gl_filtershader,
Packit 971217
    GST_TYPE_GL_FILTER, DEBUG_INIT);
Packit 971217
Packit 971217
static void gst_gl_filtershader_finalize (GObject * object);
Packit 971217
static void gst_gl_filtershader_set_property (GObject * object, guint prop_id,
Packit 971217
    const GValue * value, GParamSpec * pspec);
Packit 971217
static void gst_gl_filtershader_get_property (GObject * object, guint prop_id,
Packit 971217
    GValue * value, GParamSpec * pspec);
Packit 971217
static gboolean gst_gl_filtershader_gl_start (GstGLBaseFilter * base);
Packit 971217
static void gst_gl_filtershader_gl_stop (GstGLBaseFilter * base);
Packit 971217
static gboolean gst_gl_filtershader_filter (GstGLFilter * filter,
Packit 971217
    GstBuffer * inbuf, GstBuffer * outbuf);
Packit 971217
static gboolean gst_gl_filtershader_filter_texture (GstGLFilter * filter,
Packit 971217
    GstGLMemory * in_tex, GstGLMemory * out_tex);
Packit 971217
static gboolean gst_gl_filtershader_hcallback (GstGLFilter * filter,
Packit 971217
    GstGLMemory * in_tex, gpointer stuff);
Packit 971217
Packit 971217
static void
Packit 971217
gst_gl_filtershader_class_init (GstGLFilterShaderClass * klass)
Packit 971217
{
Packit 971217
  GObjectClass *gobject_class;
Packit 971217
  GstElementClass *element_class;
Packit 971217
Packit 971217
  gobject_class = (GObjectClass *) klass;
Packit 971217
  element_class = GST_ELEMENT_CLASS (klass);
Packit 971217
Packit 971217
  gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass));
Packit 971217
Packit 971217
  gobject_class->finalize = gst_gl_filtershader_finalize;
Packit 971217
  gobject_class->set_property = gst_gl_filtershader_set_property;
Packit 971217
  gobject_class->get_property = gst_gl_filtershader_get_property;
Packit 971217
Packit 971217
  g_object_class_install_property (gobject_class, PROP_SHADER,
Packit 971217
      g_param_spec_object ("shader", "Shader object",
Packit 971217
          "GstGLShader to use", GST_TYPE_GL_SHADER,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  g_object_class_install_property (gobject_class, PROP_VERTEX,
Packit 971217
      g_param_spec_string ("vertex", "Vertex Source",
Packit 971217
          "GLSL vertex source", NULL,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  g_object_class_install_property (gobject_class, PROP_FRAGMENT,
Packit 971217
      g_param_spec_string ("fragment", "Fragment Source",
Packit 971217
          "GLSL fragment source", NULL,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  /* FIXME: add other stages */
Packit 971217
Packit 971217
  g_object_class_install_property (gobject_class, PROP_UNIFORMS,
Packit 971217
      g_param_spec_boxed ("uniforms", "GLSL Uniforms",
Packit 971217
          "GLSL Uniforms", GST_TYPE_STRUCTURE,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  g_object_class_install_property (gobject_class, PROP_UPDATE_SHADER,
Packit 971217
      g_param_spec_boolean ("update-shader", "Update Shader",
Packit 971217
          "Emit the \'create-shader\' signal for the next frame",
Packit 971217
          FALSE, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  /*
Packit 971217
   * GstGLFilterShader::create-shader:
Packit 971217
   * @object: the #GstGLFilterShader
Packit 971217
   *
Packit 971217
   * Ask's the application for a shader to render with as a result of
Packit 971217
   * inititialization or setting the 'update-shader' property.
Packit 971217
   *
Packit 971217
   * Returns: a new #GstGLShader for use in the rendering pipeline
Packit 971217
   */
Packit 971217
  gst_gl_shader_signals[SIGNAL_CREATE_SHADER] =
Packit 971217
      g_signal_new ("create-shader", G_TYPE_FROM_CLASS (klass),
Packit 971217
      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic,
Packit 971217
      GST_TYPE_GL_SHADER, 0);
Packit 971217
Packit 971217
  gst_element_class_set_metadata (element_class,
Packit 971217
      "OpenGL fragment shader filter", "Filter/Effect",
Packit 971217
      "Perform operations with a GLSL shader", "<matthew@centricular.com>");
Packit 971217
Packit 971217
  GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filtershader_filter;
Packit 971217
  GST_GL_FILTER_CLASS (klass)->filter_texture =
Packit 971217
      gst_gl_filtershader_filter_texture;
Packit 971217
Packit 971217
  GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_filtershader_gl_start;
Packit 971217
  GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_filtershader_gl_stop;
Packit 971217
  GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api =
Packit 971217
      GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_gl_filtershader_init (GstGLFilterShader * filtershader)
Packit 971217
{
Packit 971217
  filtershader->new_source = TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_gl_filtershader_finalize (GObject * object)
Packit 971217
{
Packit 971217
  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object);
Packit 971217
Packit 971217
  g_free (filtershader->vertex);
Packit 971217
  filtershader->vertex = NULL;
Packit 971217
Packit 971217
  g_free (filtershader->fragment);
Packit 971217
  filtershader->fragment = NULL;
Packit 971217
Packit 971217
  if (filtershader->uniforms)
Packit 971217
    gst_structure_free (filtershader->uniforms);
Packit 971217
  filtershader->uniforms = NULL;
Packit 971217
Packit 971217
  G_OBJECT_CLASS (gst_gl_filtershader_parent_class)->finalize (object);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_gl_filtershader_set_property (GObject * object, guint prop_id,
Packit 971217
    const GValue * value, GParamSpec * pspec)
Packit 971217
{
Packit 971217
  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object);
Packit 971217
Packit 971217
  switch (prop_id) {
Packit 971217
    case PROP_SHADER:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      gst_object_replace ((GstObject **) & filtershader->shader,
Packit 971217
          g_value_dup_object (value));
Packit 971217
      filtershader->new_source = FALSE;
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    case PROP_VERTEX:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      g_free (filtershader->vertex);
Packit 971217
      filtershader->vertex = g_value_dup_string (value);
Packit 971217
      filtershader->new_source = TRUE;
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    case PROP_FRAGMENT:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      g_free (filtershader->fragment);
Packit 971217
      filtershader->fragment = g_value_dup_string (value);
Packit 971217
      filtershader->new_source = TRUE;
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    case PROP_UNIFORMS:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      if (filtershader->uniforms)
Packit 971217
        gst_structure_free (filtershader->uniforms);
Packit 971217
      filtershader->uniforms = g_value_dup_boxed (value);
Packit 971217
      filtershader->new_uniforms = TRUE;
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    case PROP_UPDATE_SHADER:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      filtershader->update_shader = g_value_get_boolean (value);
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_gl_filtershader_get_property (GObject * object, guint prop_id,
Packit 971217
    GValue * value, GParamSpec * pspec)
Packit 971217
{
Packit 971217
  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object);
Packit 971217
Packit 971217
  switch (prop_id) {
Packit 971217
    case PROP_SHADER:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      g_value_set_object (value, filtershader->shader);
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    case PROP_VERTEX:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      g_value_set_string (value, filtershader->vertex);
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    case PROP_FRAGMENT:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      g_value_set_string (value, filtershader->fragment);
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    case PROP_UNIFORMS:
Packit 971217
      GST_OBJECT_LOCK (filtershader);
Packit 971217
      g_value_set_boxed (value, filtershader->uniforms);
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_gl_filtershader_gl_stop (GstGLBaseFilter * base)
Packit 971217
{
Packit 971217
  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (base);
Packit 971217
Packit 971217
  if (filtershader->shader)
Packit 971217
    gst_object_unref (filtershader->shader);
Packit 971217
  filtershader->shader = NULL;
Packit 971217
Packit 971217
  GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base);
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_gl_filtershader_gl_start (GstGLBaseFilter * base)
Packit 971217
{
Packit 971217
  return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base);
Packit 971217
}
Packit 971217
Packit 971217
static inline gboolean
Packit 971217
_gst_clock_time_to_double (GstClockTime time, gdouble * result)
Packit 971217
{
Packit 971217
  if (!GST_CLOCK_TIME_IS_VALID (time))
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  *result = (gdouble) time / GST_SECOND;
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static inline gboolean
Packit 971217
_gint64_time_val_to_double (gint64 time, gdouble * result)
Packit 971217
{
Packit 971217
  if (time == -1)
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  *result = (gdouble) time / GST_USECOND;
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_gl_filtershader_filter (GstGLFilter * filter, GstBuffer * inbuf,
Packit 971217
    GstBuffer * outbuf)
Packit 971217
{
Packit 971217
  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
Packit 971217
Packit 971217
  if (!_gst_clock_time_to_double (GST_BUFFER_PTS (inbuf), &filtershader->time)) {
Packit 971217
    if (!_gst_clock_time_to_double (GST_BUFFER_DTS (inbuf),
Packit 971217
            &filtershader->time))
Packit 971217
      _gint64_time_val_to_double (g_get_monotonic_time (), &filtershader->time);
Packit 971217
  }
Packit 971217
Packit 971217
  return gst_gl_filter_filter_texture (filter, inbuf, outbuf);
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_gl_filtershader_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
Packit 971217
    GstGLMemory * out_tex)
Packit 971217
{
Packit 971217
  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
Packit 971217
Packit 971217
  gst_gl_filter_render_to_target (filter, in_tex, out_tex,
Packit 971217
      gst_gl_filtershader_hcallback, NULL);
Packit 971217
Packit 971217
  if (!filtershader->shader)
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
_set_uniform (GQuark field_id, const GValue * value, gpointer user_data)
Packit 971217
{
Packit 971217
  GstGLShader *shader = user_data;
Packit 971217
  const gchar *field_name = g_quark_to_string (field_id);
Packit 971217
Packit 971217
  if (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_INT)) {
Packit 971217
    gst_gl_shader_set_uniform_1i (shader, field_name, g_value_get_int (value));
Packit 971217
  } else if (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_FLOAT)) {
Packit 971217
    gst_gl_shader_set_uniform_1f (shader, field_name,
Packit 971217
        g_value_get_float (value));
Packit 971217
#ifdef HAVE_GRAPHENE
Packit 971217
  } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC2)) {
Packit 971217
    graphene_vec2_t *vec2 = g_value_get_boxed (value);
Packit 971217
    float x = graphene_vec2_get_x (vec2);
Packit 971217
    float y = graphene_vec2_get_y (vec2);
Packit 971217
    gst_gl_shader_set_uniform_2f (shader, field_name, x, y);
Packit 971217
  } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC3)) {
Packit 971217
    graphene_vec3_t *vec3 = g_value_get_boxed (value);
Packit 971217
    float x = graphene_vec3_get_x (vec3);
Packit 971217
    float y = graphene_vec3_get_y (vec3);
Packit 971217
    float z = graphene_vec3_get_z (vec3);
Packit 971217
    gst_gl_shader_set_uniform_3f (shader, field_name, x, y, z);
Packit 971217
  } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC4)) {
Packit 971217
    graphene_vec4_t *vec4 = g_value_get_boxed (value);
Packit 971217
    float x = graphene_vec4_get_x (vec4);
Packit 971217
    float y = graphene_vec4_get_y (vec4);
Packit 971217
    float z = graphene_vec4_get_z (vec4);
Packit 971217
    float w = graphene_vec4_get_w (vec4);
Packit 971217
    gst_gl_shader_set_uniform_4f (shader, field_name, x, y, z, w);
Packit 971217
  } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_MATRIX)) {
Packit 971217
    graphene_matrix_t *matrix = g_value_get_boxed (value);
Packit 971217
    float matrix_f[16];
Packit 971217
    graphene_matrix_to_float (matrix, matrix_f);
Packit 971217
    gst_gl_shader_set_uniform_matrix_4fv (shader, field_name, 1, FALSE,
Packit 971217
        matrix_f);
Packit 971217
#endif
Packit 971217
  } else {
Packit 971217
    /* FIXME: Add support for unsigned ints, non 4x4 matrices, etc */
Packit 971217
    GST_FIXME ("Don't know how to set the \'%s\' paramater.  Unknown type",
Packit 971217
        field_name);
Packit 971217
    return TRUE;
Packit 971217
  }
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
_update_uniforms (GstGLFilterShader * filtershader)
Packit 971217
{
Packit 971217
  if (filtershader->new_uniforms && filtershader->uniforms) {
Packit 971217
    gst_gl_shader_use (filtershader->shader);
Packit 971217
Packit 971217
    gst_structure_foreach (filtershader->uniforms,
Packit 971217
        (GstStructureForeachFunc) _set_uniform, filtershader->shader);
Packit 971217
    filtershader->new_uniforms = FALSE;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static GstGLShader *
Packit 971217
_maybe_recompile_shader (GstGLFilterShader * filtershader)
Packit 971217
{
Packit 971217
  GstGLContext *context = GST_GL_BASE_FILTER (filtershader)->context;
Packit 971217
  GstGLShader *shader;
Packit 971217
  GError *error = NULL;
Packit 971217
Packit 971217
  GST_OBJECT_LOCK (filtershader);
Packit 971217
Packit 971217
  if (!filtershader->shader || filtershader->update_shader) {
Packit 971217
    filtershader->update_shader = FALSE;
Packit 971217
    GST_OBJECT_UNLOCK (filtershader);
Packit 971217
    g_signal_emit (filtershader, gst_gl_shader_signals[SIGNAL_CREATE_SHADER], 0,
Packit 971217
        &shader);
Packit 971217
    GST_OBJECT_LOCK (filtershader);
Packit 971217
Packit 971217
    if (shader) {
Packit 971217
      if (filtershader->shader)
Packit 971217
        gst_object_unref (filtershader->shader);
Packit 971217
      filtershader->new_source = FALSE;
Packit 971217
      filtershader->shader = gst_object_ref (shader);
Packit 971217
      filtershader->new_uniforms = TRUE;
Packit 971217
      _update_uniforms (filtershader);
Packit 971217
      GST_OBJECT_UNLOCK (filtershader);
Packit 971217
      return shader;
Packit 971217
    }
Packit 971217
  }
Packit 971217
Packit 971217
  if (filtershader->shader) {
Packit 971217
    shader = gst_object_ref (filtershader->shader);
Packit 971217
    _update_uniforms (filtershader);
Packit 971217
    GST_OBJECT_UNLOCK (filtershader);
Packit 971217
    return shader;
Packit 971217
  }
Packit 971217
Packit 971217
  if (filtershader->new_source) {
Packit 971217
    GstGLSLStage *stage;
Packit 971217
Packit 971217
    shader = gst_gl_shader_new (context);
Packit 971217
Packit 971217
    if (filtershader->vertex) {
Packit 971217
      if (!(stage = gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
Packit 971217
                  GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE,
Packit 971217
                  filtershader->vertex))) {
Packit 971217
        g_set_error (&error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE,
Packit 971217
            "Failed to create shader vertex stage");
Packit 971217
        goto print_error;
Packit 971217
      }
Packit 971217
    } else {
Packit 971217
      stage = gst_glsl_stage_new_default_vertex (context);
Packit 971217
    }
Packit 971217
Packit 971217
    if (!gst_gl_shader_compile_attach_stage (shader, stage, &error)) {
Packit 971217
      gst_object_unref (stage);
Packit 971217
      goto print_error;
Packit 971217
    }
Packit 971217
Packit 971217
    if (filtershader->fragment) {
Packit 971217
      if (!(stage = gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
Packit 971217
                  GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE,
Packit 971217
                  filtershader->fragment))) {
Packit 971217
        g_set_error (&error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE,
Packit 971217
            "Failed to create shader fragment stage");
Packit 971217
        goto print_error;
Packit 971217
      }
Packit 971217
    } else {
Packit 971217
      stage = gst_glsl_stage_new_default_fragment (context);
Packit 971217
    }
Packit 971217
Packit 971217
    if (!gst_gl_shader_compile_attach_stage (shader, stage, &error)) {
Packit 971217
      gst_object_unref (stage);
Packit 971217
      goto print_error;
Packit 971217
    }
Packit 971217
Packit 971217
    if (!gst_gl_shader_link (shader, &error)) {
Packit 971217
      goto print_error;
Packit 971217
    }
Packit 971217
    if (filtershader->shader)
Packit 971217
      gst_object_unref (filtershader->shader);
Packit 971217
    filtershader->shader = gst_object_ref (shader);
Packit 971217
    filtershader->new_source = FALSE;
Packit 971217
    filtershader->new_uniforms = TRUE;
Packit 971217
    _update_uniforms (filtershader);
Packit 971217
Packit 971217
    GST_OBJECT_UNLOCK (filtershader);
Packit 971217
    return shader;
Packit 971217
  } else if (filtershader->shader) {
Packit 971217
    _update_uniforms (filtershader);
Packit 971217
    shader = gst_object_ref (filtershader->shader);
Packit 971217
    GST_OBJECT_UNLOCK (filtershader);
Packit 971217
    return shader;
Packit 971217
  }
Packit 971217
Packit 971217
  return NULL;
Packit 971217
Packit 971217
print_error:
Packit 971217
  if (shader) {
Packit 971217
    gst_object_unref (shader);
Packit 971217
    shader = NULL;
Packit 971217
  }
Packit 971217
Packit 971217
  GST_OBJECT_UNLOCK (filtershader);
Packit 971217
  GST_ELEMENT_ERROR (filtershader, RESOURCE, NOT_FOUND,
Packit 971217
      ("%s", error->message), (NULL));
Packit 971217
  return NULL;
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_gl_filtershader_hcallback (GstGLFilter * filter, GstGLMemory * in_tex,
Packit 971217
    gpointer stuff)
Packit 971217
{
Packit 971217
  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
Packit 971217
  GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
Packit 971217
  GstGLShader *shader;
Packit 971217
Packit 971217
  if (!(shader = _maybe_recompile_shader (filtershader)))
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  gl->ClearColor (0.0, 0.0, 0.0, 1.0);
Packit 971217
  gl->Clear (GL_COLOR_BUFFER_BIT);
Packit 971217
Packit 971217
  gst_gl_shader_use (shader);
Packit 971217
Packit 971217
  /* FIXME: propertise these */
Packit 971217
  gst_gl_shader_set_uniform_1i (shader, "tex", 0);
Packit 971217
  gst_gl_shader_set_uniform_1f (shader, "width",
Packit 971217
      GST_VIDEO_INFO_WIDTH (&filter->out_info));
Packit 971217
  gst_gl_shader_set_uniform_1f (shader, "height",
Packit 971217
      GST_VIDEO_INFO_HEIGHT (&filter->out_info));
Packit 971217
  gst_gl_shader_set_uniform_1f (shader, "time", filtershader->time);
Packit 971217
Packit 971217
  /* FIXME: propertise these */
Packit 971217
  filter->draw_attr_position_loc =
Packit 971217
      gst_gl_shader_get_attribute_location (shader, "a_position");
Packit 971217
  filter->draw_attr_texture_loc =
Packit 971217
      gst_gl_shader_get_attribute_location (shader, "a_texcoord");
Packit 971217
Packit 971217
  gl->ActiveTexture (GL_TEXTURE0);
Packit 971217
  gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex));
Packit 971217
Packit 971217
  gst_gl_filter_draw_fullscreen_quad (filter);
Packit 971217
Packit 971217
  gst_object_unref (shader);
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}