[cogl/wip/cogl-gst: 27/27] gst: Cache the shader snippets



commit bdaeefefc6083ce29962a7d67448be071ae22d5d
Author: Neil Roberts <neil linux intel com>
Date:   Tue Mar 5 15:12:56 2013 +0000

    gst: Cache the shader snippets
    
    Previously every time the renderer is initialised it will create a new
    snippet. This will cause Cogl to compile a new GLSL program. Cogl
    currently never destroys GLSL programs because they are always retained
    in the pipeline cache so if the application ends up playing a lot of
    videos it could end up with a lot of identical GLSL programs floating
    around.
    
    If we make it reuse the same snippets instead then it should be able to
    take advantage of the pipeline cache and avoid creating a new program
    object. The snippets are always created with a small set of static
    strings and snippets can be constructed without a context so this patch
    makes it just store the snippet in a static variable in renderer init
    functions.

 cogl-gst/cogl-gst-video-sink.c |   78 ++++++++++++++++++++++++++++------------
 1 files changed, 55 insertions(+), 23 deletions(-)
---
diff --git a/cogl-gst/cogl-gst-video-sink.c b/cogl-gst/cogl-gst-video-sink.c
index fae22c5..1e49b9a 100644
--- a/cogl-gst/cogl-gst-video-sink.c
+++ b/cogl-gst/cogl-gst-video-sink.c
@@ -198,9 +198,20 @@ cogl_gst_video_sink_set_priority (CoglGstVideoSink *sink,
     g_source_set_priority ((GSource*) sink->priv->source, priority);
 }
 
+/* We want to cache the snippets instead of recreating a new one every
+ * time we initialise a pipeline so that if we end up recreating the
+ * same pipeline again then Cogl will be able to use the pipeline
+ * cache to avoid linking a redundant identical shader program */
+typedef struct
+{
+  CoglSnippet *vertex_snippet;
+  CoglSnippet *fragment_snippet;
+} SnippetCache;
+
 static void
 create_template_pipeline (CoglGstVideoSink *sink,
                           const char *decl,
+                          SnippetCache *snippet_cache,
                           int n_layers)
 {
   CoglGstVideoSinkPrivate *priv = sink->priv;
@@ -212,34 +223,41 @@ create_template_pipeline (CoglGstVideoSink *sink,
 
   if (decl)
     {
-      CoglSnippet *snippet;
+      static CoglSnippet *default_sample_snippet = NULL;
 
       /* The global sampling function gets added to both the fragment
        * and vertex stages. The hope is that the GLSL compiler will
        * easily remove the dead code if it's not actually used */
-      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
-                                  decl,
-                                  NULL /* post */);
-      cogl_pipeline_add_snippet (priv->pipeline, snippet);
-      cogl_object_unref (snippet);
-
-      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
-                                  decl,
-                                  NULL /* post */);
-      cogl_pipeline_add_snippet (priv->pipeline, snippet);
-      cogl_object_unref (snippet);
+      if (snippet_cache->vertex_snippet == NULL)
+        snippet_cache->vertex_snippet =
+          cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
+                            decl,
+                            NULL /* post */);
+      cogl_pipeline_add_snippet (priv->pipeline,
+                                 snippet_cache->vertex_snippet);
+
+      if (snippet_cache->fragment_snippet == NULL)
+        snippet_cache->fragment_snippet =
+          cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
+                            decl,
+                            NULL /* post */);
+      cogl_pipeline_add_snippet (priv->pipeline,
+                                 snippet_cache->fragment_snippet);
 
       /* Set the replace string for the last layer so that no
        * redundant code for the previous layers will be generated. The
        * application can also replace this default sampling by adding
        * another layer */
-      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
-                                  NULL,
-                                  NULL);
-      cogl_snippet_set_replace (snippet,
-                                _cogl_gst_shader_default_sample);
-      cogl_pipeline_add_layer_snippet (priv->pipeline, n_layers - 1, snippet);
-      cogl_object_unref (snippet);
+      if (default_sample_snippet == NULL)
+        {
+          default_sample_snippet =
+            cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT, NULL, NULL);
+          cogl_snippet_set_replace (default_sample_snippet,
+                                    _cogl_gst_shader_default_sample);
+        }
+      cogl_pipeline_add_layer_snippet (priv->pipeline,
+                                       n_layers - 1,
+                                       default_sample_snippet);
     }
 
   g_signal_emit (sink, video_sink_signals[PIPELINE_READY_SIGNAL], 0, NULL);
@@ -285,11 +303,16 @@ cogl_gst_rgb_init (CoglGstVideoSink *sink)
   CoglGstVideoSinkPrivate *priv = sink->priv;
 
   if (cogl_has_feature (priv->ctx, COGL_FEATURE_ID_GLSL))
-    create_template_pipeline (sink,
-                              _cogl_gst_shader_rgba_to_rgba_decl,
-                              1);
+    {
+      static SnippetCache snippet_cache;
+
+      create_template_pipeline (sink,
+                                _cogl_gst_shader_rgba_to_rgba_decl,
+                                &snippet_cache,
+                                1);
+    }
   else
-    create_template_pipeline (sink, NULL, 1);
+    create_template_pipeline (sink, NULL, NULL, 1);
 }
 
 static CoglBool
@@ -434,8 +457,11 @@ map_fail:
 static void
 cogl_gst_yv12_glsl_init (CoglGstVideoSink *sink)
 {
+  static SnippetCache snippet_cache;
+
   create_template_pipeline (sink,
                             _cogl_gst_shader_yv12_to_rgba_decl,
+                            &snippet_cache,
                             3);
 }
 
@@ -453,8 +479,11 @@ static CoglGstRenderer yv12_glsl_renderer =
 static void
 cogl_gst_i420_glsl_init (CoglGstVideoSink *sink)
 {
+  static SnippetCache snippet_cache;
+
   create_template_pipeline (sink,
                             _cogl_gst_shader_yv12_to_rgba_decl,
+                            &snippet_cache,
                             3);
 }
 
@@ -472,8 +501,11 @@ static CoglGstRenderer i420_glsl_renderer =
 static void
 cogl_gst_ayuv_glsl_init (CoglGstVideoSink *sink)
 {
+  static SnippetCache snippet_cache;
+
   create_template_pipeline (sink,
                             _cogl_gst_shader_ayuv_to_rgba_decl,
+                            &snippet_cache,
                             1);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]