summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2010-08-10 20:12:49 +0100
committerDamien Lespiau <damien.lespiau@intel.com>2010-08-18 16:39:12 +0100
commit1618f75952e3813278edea7444c77e1d85f1e4a6 (patch)
tree49e5999a5146ed841da70d514446051615b26c4f
parent7ae59883a0311f21e783f933538e0aad9b434e27 (diff)
sink: Use consistent material management
This makes all the renderer code paths use the same approach to managing CoglMaterials. In the xyz_init callback they each create a "template" material associating any required CoglProgram with the template and adding n empty layers depending on how many planes are used for that format. Whenever we upload new texture data we derive a new "paint material" from the template, set the texture handles as layers and set the material on the ClutterTexture to be used for painting. This style is in line with the recommended way to manage CoglMaterials since it avoids repeated modification of materials.
-rw-r--r--clutter-gst/clutter-gst-video-sink.c330
1 files changed, 153 insertions, 177 deletions
diff --git a/clutter-gst/clutter-gst-video-sink.c b/clutter-gst/clutter-gst-video-sink.c
index 7d12b37..db9b254 100644
--- a/clutter-gst/clutter-gst-video-sink.c
+++ b/clutter-gst/clutter-gst-video-sink.c
@@ -197,10 +197,7 @@ typedef enum _ClutterGstRendererState
struct _ClutterGstVideoSinkPrivate
{
ClutterTexture *texture;
- CoglHandle u_tex;
- CoglHandle v_tex;
- CoglHandle program;
- CoglHandle shader;
+ CoglMaterial *material_template;
ClutterGstVideoFormat format;
gboolean bgr;
@@ -379,56 +376,19 @@ _string_array_to_char_array (char *dst,
}
#endif
-static void
-clutter_gst_video_sink_set_glsl_shader (ClutterGstVideoSink *sink,
- const gchar *shader_src)
-{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
-
- if (priv->program)
- {
- cogl_program_unref (priv->program);
- priv->program = NULL;
- }
-
- if (priv->shader)
- {
- cogl_handle_unref (priv->shader);
- priv->shader = NULL;
- }
-
- if (shader_src)
- {
- /* Create shader through COGL - necessary as we need to be able to set
- * integer uniform variables for multi-texturing.
- */
- priv->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
- cogl_shader_source (priv->shader, shader_src);
- cogl_shader_compile (priv->shader);
-
- priv->program = cogl_create_program ();
- cogl_program_attach_shader (priv->program, priv->shader);
- cogl_program_link (priv->program);
- }
-}
-
-/* some renderers don't need all the ClutterGstRenderer vtable */
-static void
-clutter_gst_dummy_init (ClutterGstVideoSink *sink)
-{
-}
-
-#ifdef CLUTTER_COGL_HAS_GL
static CoglHandle
-_create_arbfp_program (gchar *source)
+_create_cogl_program (const char *source)
{
CoglHandle shader;
CoglHandle program;
-
+
+ /* Create shader through Cogl - necessary as we need to be able to set
+ * integer uniform variables for multi-texturing.
+ */
shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
cogl_shader_source (shader, source);
cogl_shader_compile (shader);
-
+
program = cogl_create_program ();
cogl_program_attach_shader (program, shader);
cogl_program_link (program);
@@ -437,13 +397,98 @@ _create_arbfp_program (gchar *source)
return program;
}
-#endif
+
+static void
+_create_template_material (ClutterGstVideoSink *sink,
+ const char *source,
+ gboolean set_uniforms,
+ int n_layers)
+{
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglMaterial *template;
+ int i;
+
+ if (priv->material_template)
+ cogl_object_unref (priv->material_template);
+
+ template = cogl_material_new ();
+
+ if (source)
+ {
+ CoglHandle program = _create_cogl_program (source);
+
+ if (set_uniforms)
+ {
+ unsigned int location;
+
+ cogl_program_use (program);
+
+ location = cogl_program_get_uniform_location (program, "ytex");
+ cogl_program_uniform_1i (location, 0);
+ if (n_layers > 1)
+ {
+ location = cogl_program_get_uniform_location (program, "utex");
+ cogl_program_uniform_1i (location, 1);
+ }
+ if (n_layers > 2)
+ {
+ location = cogl_program_get_uniform_location (program, "vtex");
+ cogl_program_uniform_1i (location, 2);
+ }
+
+ cogl_program_use (COGL_INVALID_HANDLE);
+ }
+
+ cogl_material_set_user_program (template, program);
+ cogl_handle_unref (program);
+ }
+
+ for (i = 0; i < n_layers; i++)
+ cogl_material_set_layer (template, i, COGL_INVALID_HANDLE);
+
+ priv->material_template = template;
+}
+
+static void
+_create_paint_material (ClutterGstVideoSink *sink,
+ CoglHandle tex0,
+ CoglHandle tex1,
+ CoglHandle tex2)
+{
+ ClutterGstVideoSinkPrivate *priv= sink->priv;
+ CoglMaterial *material = cogl_material_copy (priv->material_template);
+
+ if (tex0 != COGL_INVALID_HANDLE)
+ {
+ cogl_material_set_layer (material, 0, tex0);
+ cogl_handle_unref (tex0);
+ }
+ if (tex1 != COGL_INVALID_HANDLE)
+ {
+ cogl_material_set_layer (material, 1, tex1);
+ cogl_handle_unref (tex1);
+ }
+ if (tex2 != COGL_INVALID_HANDLE)
+ {
+ cogl_material_set_layer (material, 2, tex2);
+ cogl_handle_unref (tex2);
+ }
+
+ clutter_texture_set_cogl_material (priv->texture, material);
+ cogl_object_unref (material);
+}
static void
clutter_gst_dummy_deinit (ClutterGstVideoSink *sink)
{
}
+static void
+clutter_gst_rgb_init (ClutterGstVideoSink *sink)
+{
+ _create_template_material (sink, NULL, FALSE, 1);
+}
+
/*
* RGB 24 / BGR 24
*
@@ -454,18 +499,20 @@ static void
clutter_gst_rgb24_upload (ClutterGstVideoSink *sink,
GstBuffer *buffer)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
-
- clutter_texture_set_from_rgb_data (priv->texture,
- GST_BUFFER_DATA (buffer),
- FALSE,
- priv->width,
- priv->height,
- GST_ROUND_UP_4 (3 * priv->width),
- 3,
- priv->bgr ?
- CLUTTER_TEXTURE_RGB_FLAG_BGR : 0,
- NULL);
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglHandle tex =
+ cogl_texture_new_from_data (priv->width,
+ priv->height,
+ CLUTTER_GST_TEXTURE_FLAGS,
+ COGL_PIXEL_FORMAT_RGB_888,
+ COGL_PIXEL_FORMAT_RGB_888,
+ GST_ROUND_UP_4 (3 * priv->width),
+ GST_BUFFER_DATA (buffer));
+
+ _create_paint_material (sink,
+ tex,
+ COGL_INVALID_HANDLE,
+ COGL_INVALID_HANDLE);
}
static ClutterGstRenderer rgb24_renderer =
@@ -474,7 +521,7 @@ static ClutterGstRenderer rgb24_renderer =
CLUTTER_GST_RGB24,
0,
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR),
- clutter_gst_dummy_init,
+ clutter_gst_rgb_init,
clutter_gst_dummy_deinit,
clutter_gst_rgb24_upload,
};
@@ -487,18 +534,20 @@ static void
clutter_gst_rgb32_upload (ClutterGstVideoSink *sink,
GstBuffer *buffer)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
-
- clutter_texture_set_from_rgb_data (priv->texture,
- GST_BUFFER_DATA (buffer),
- TRUE,
- priv->width,
- priv->height,
- GST_ROUND_UP_4 (4 * priv->width),
- 4,
- priv->bgr ?
- CLUTTER_TEXTURE_RGB_FLAG_BGR : 0,
- NULL);
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglHandle tex =
+ cogl_texture_new_from_data (priv->width,
+ priv->height,
+ CLUTTER_GST_TEXTURE_FLAGS,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ GST_ROUND_UP_4 (4 * priv->width),
+ GST_BUFFER_DATA (buffer));
+
+ _create_paint_material (sink,
+ tex,
+ COGL_INVALID_HANDLE,
+ COGL_INVALID_HANDLE);
}
static ClutterGstRenderer rgb32_renderer =
@@ -507,7 +556,7 @@ static ClutterGstRenderer rgb32_renderer =
CLUTTER_GST_RGB32,
0,
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA),
- clutter_gst_dummy_init,
+ clutter_gst_rgb_init,
clutter_gst_dummy_deinit,
clutter_gst_rgb32_upload,
};
@@ -525,9 +574,7 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
ClutterGstVideoSinkPrivate *priv = sink->priv;
gint y_row_stride = GST_ROUND_UP_4 (priv->width);
gint uv_row_stride = GST_ROUND_UP_4 (priv->width / 2);
- CoglHandle y_tex, u_tex, v_tex, material;
-
- material = clutter_texture_get_cogl_material (priv->texture);
+ CoglHandle y_tex, u_tex, v_tex;
y_tex = cogl_texture_new_from_data (priv->width,
priv->height,
@@ -537,9 +584,6 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
y_row_stride,
GST_BUFFER_DATA (buffer));
- clutter_texture_set_cogl_texture (priv->texture, y_tex);
- cogl_handle_unref (y_tex);
-
u_tex = cogl_texture_new_from_data (priv->width / 2,
priv->height / 2,
CLUTTER_GST_TEXTURE_FLAGS,
@@ -549,9 +593,6 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
GST_BUFFER_DATA (buffer) +
(y_row_stride * priv->height));
- cogl_material_set_layer (material, 1, u_tex);
- cogl_handle_unref (u_tex);
-
v_tex = cogl_texture_new_from_data (priv->width / 2,
priv->height / 2,
CLUTTER_GST_TEXTURE_FLAGS,
@@ -562,37 +603,13 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
+ (y_row_stride * priv->height)
+ (uv_row_stride * priv->height / 2));
- cogl_material_set_layer (material, 2, v_tex);
- cogl_handle_unref (v_tex);
+ _create_paint_material (sink, y_tex, u_tex, v_tex);
}
static void
clutter_gst_yv12_glsl_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
- GLint location;
- CoglMaterial *material;
-
- clutter_gst_video_sink_set_glsl_shader (sink, yv12_to_rgba_shader);
-
- cogl_program_use (priv->program);
- location = cogl_program_get_uniform_location (priv->program, "ytex");
- cogl_program_uniform_1i (location, 0);
- location = cogl_program_get_uniform_location (priv->program, "utex");
- cogl_program_uniform_1i (location, 1);
- location = cogl_program_get_uniform_location (priv->program, "vtex");
- cogl_program_uniform_1i (location, 2);
-
- cogl_program_use (COGL_INVALID_HANDLE);
-
- material = clutter_texture_get_cogl_material (priv->texture);
- cogl_material_set_user_program (material, priv->program);
-}
-
-static void
-clutter_gst_yv12_glsl_deinit (ClutterGstVideoSink *sink)
-{
- clutter_gst_video_sink_set_glsl_shader (sink, NULL);
+ _create_template_material (sink, yv12_to_rgba_shader, TRUE, 3);
}
@@ -603,7 +620,7 @@ static ClutterGstRenderer yv12_glsl_renderer =
CLUTTER_GST_GLSL | CLUTTER_GST_MULTI_TEXTURE,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YV12")),
clutter_gst_yv12_glsl_init,
- clutter_gst_yv12_glsl_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_yv12_upload,
};
@@ -617,27 +634,12 @@ static ClutterGstRenderer yv12_glsl_renderer =
static void
clutter_gst_yv12_fp_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
- CoglMaterial *material;
- CoglHandle program;
-
- gchar *shader;
-
- shader = g_malloc(YV12_FP_SZ + 1);
+ char *shader = g_malloc (YV12_FP_SZ + 1);
_string_array_to_char_array (shader, YV12_fp);
- material = clutter_texture_get_cogl_material (priv->texture);
-
- program = _create_arbfp_program (shader);
- cogl_material_set_user_program (material, program);
- cogl_handle_unref (program);
+ _create_template_material (sink, shader, FALSE, 3);
- g_free(shader);
-}
-
-static void
-clutter_gst_yv12_fp_deinit (ClutterGstVideoSink *sink)
-{
+ g_free (shader);
}
static ClutterGstRenderer yv12_fp_renderer =
@@ -647,7 +649,7 @@ static ClutterGstRenderer yv12_fp_renderer =
CLUTTER_GST_FP | CLUTTER_GST_MULTI_TEXTURE,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YV12")),
clutter_gst_yv12_fp_init,
- clutter_gst_yv12_fp_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_yv12_upload,
};
#endif
@@ -662,23 +664,7 @@ static ClutterGstRenderer yv12_fp_renderer =
static void
clutter_gst_i420_glsl_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
- GLint location;
- CoglMaterial *material;
-
- clutter_gst_video_sink_set_glsl_shader (sink, yv12_to_rgba_shader);
-
- cogl_program_use (priv->program);
- location = cogl_program_get_uniform_location (priv->program, "ytex");
- cogl_program_uniform_1i (location, 0);
- location = cogl_program_get_uniform_location (priv->program, "utex");
- cogl_program_uniform_1i (location, 1);
- location = cogl_program_get_uniform_location (priv->program, "vtex");
- cogl_program_uniform_1i (location, 2);
- cogl_program_use (COGL_INVALID_HANDLE);
-
- material = clutter_texture_get_cogl_material (priv->texture);
- cogl_material_set_user_program (material, priv->program);
+ _create_template_material (sink, yv12_to_rgba_shader, TRUE, 3);
}
static ClutterGstRenderer i420_glsl_renderer =
@@ -688,7 +674,7 @@ static ClutterGstRenderer i420_glsl_renderer =
CLUTTER_GST_GLSL | CLUTTER_GST_MULTI_TEXTURE,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")),
clutter_gst_i420_glsl_init,
- clutter_gst_yv12_glsl_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_yv12_upload,
};
@@ -703,19 +689,12 @@ static ClutterGstRenderer i420_glsl_renderer =
static void
clutter_gst_i420_fp_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
- CoglMaterial *material;
- CoglHandle program;
- gchar *shader;
-
- shader = g_malloc(I420_FP_SZ + 1);
+ char *shader = g_malloc(I420_FP_SZ + 1);
_string_array_to_char_array (shader, I420_fp);
- material = clutter_texture_get_cogl_material (priv->texture);
- program = _create_arbfp_program (shader);
- cogl_material_set_user_program (material, program);
- cogl_handle_unref (program);
- g_free(shader);
+ _create_template_material (sink, shader, FALSE, 3);
+
+ g_free (shader);
}
static ClutterGstRenderer i420_fp_renderer =
@@ -741,30 +720,27 @@ static ClutterGstRenderer i420_fp_renderer =
static void
clutter_gst_ayuv_glsl_init(ClutterGstVideoSink *sink)
{
- clutter_gst_video_sink_set_glsl_shader (sink, ayuv_to_rgba_shader);
-}
-
-static void
-clutter_gst_ayuv_glsl_deinit(ClutterGstVideoSink *sink)
-{
- clutter_gst_video_sink_set_glsl_shader (sink, NULL);
+ _create_template_material (sink, ayuv_to_rgba_shader, TRUE, 1);
}
static void
clutter_gst_ayuv_upload (ClutterGstVideoSink *sink,
GstBuffer *buffer)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
-
- clutter_texture_set_from_rgb_data (priv->texture,
- GST_BUFFER_DATA (buffer),
- TRUE,
- priv->width,
- priv->height,
- GST_ROUND_UP_4 (4 * priv->width),
- 4,
- 0,
- NULL);
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglHandle tex =
+ cogl_texture_new_from_data (priv->width,
+ priv->height,
+ CLUTTER_GST_TEXTURE_FLAGS,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ GST_ROUND_UP_4 (4 * priv->width),
+ GST_BUFFER_DATA (buffer));
+
+ _create_paint_material (sink,
+ tex,
+ COGL_INVALID_HANDLE,
+ COGL_INVALID_HANDLE);
}
static ClutterGstRenderer ayuv_glsl_renderer =
@@ -774,7 +750,7 @@ static ClutterGstRenderer ayuv_glsl_renderer =
CLUTTER_GST_GLSL,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")),
clutter_gst_ayuv_glsl_init,
- clutter_gst_ayuv_glsl_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_ayuv_upload,
};