[gnome-shell/wip/cogl-deprecations] Fix most of the Cogl deprecation warnings



commit d8009fd8260f0286f04f1a76c817bba71592a8ba
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Sep 10 16:03:21 2013 -0400

    Fix most of the Cogl deprecation warnings

 src/Makefile-st.am                  |    3 +
 src/Makefile.am                     |    3 +
 src/gnome-shell-plugin.c            |    2 -
 src/shell-app.c                     |   12 +-
 src/shell-invert-lightness-effect.c |   10 +-
 src/shell-invert-lightness-effect.h |    1 -
 src/shell-recorder.c                |   22 +-
 src/shell-screenshot.c              |    3 -
 src/shell-slicer.c                  |   18 +-
 src/st/st-box-layout.c              |   36 ++--
 src/st/st-drawing-area.c            |   58 ++---
 src/st/st-icon.c                    |   59 ++----
 src/st/st-label.c                   |   39 +---
 src/st/st-private.c                 |  192 ++++++++-------
 src/st/st-private.h                 |   13 +-
 src/st/st-shadow.c                  |   21 +-
 src/st/st-texture-cache.c           |  101 ++++-----
 src/st/st-texture-cache.h           |   20 +-
 src/st/st-theme-node-drawing.c      |  448 ++++++++++++++++-------------------
 src/st/st-theme-node-private.h      |   10 +-
 src/st/st-theme-node-transition.c   |  165 +++++--------
 src/st/st-theme-node-transition.h   |    1 +
 src/st/st-theme-node.c              |   20 +--
 src/st/st-theme-node.h              |    9 +-
 src/st/st-widget.c                  |    3 +
 25 files changed, 572 insertions(+), 697 deletions(-)
---
diff --git a/src/Makefile-st.am b/src/Makefile-st.am
index 7cbdfd8..040334e 100644
--- a/src/Makefile-st.am
+++ b/src/Makefile-st.am
@@ -1,4 +1,7 @@
 st_cflags =                                    \
+       -DCLUTTER_ENABLE_EXPERIMENTAL_API       \
+       -DCOGL_ENABLE_EXPERIMENTAL_API          \
+       -DCOGL_ENABLE_EXPERIMENTAL_2_0_API      \
        -I$(top_srcdir)/src                     \
        -DPREFIX=\""$(prefix)"\"                \
        -DLIBDIR=\""$(libdir)"\"                \
diff --git a/src/Makefile.am b/src/Makefile.am
index 8041052..5f61fe5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,6 +68,9 @@ include Makefile-calendar-server.am
 include Makefile-hotplug-sniffer.am
 
 gnome_shell_cflags =                           \
+       -DCLUTTER_ENABLE_EXPERIMENTAL_API       \
+       -DCOGL_ENABLE_EXPERIMENTAL_API          \
+       -DCOGL_ENABLE_EXPERIMENTAL_2_0_API      \
        $(GNOME_SHELL_CFLAGS)                   \
        -I$(srcdir)/tray                        \
        -DVERSION=\"$(VERSION)\"                \
diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c
index 631e373..0df570b 100644
--- a/src/gnome-shell-plugin.c
+++ b/src/gnome-shell-plugin.c
@@ -28,8 +28,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define CLUTTER_ENABLE_EXPERIMENTAL_API
-#define COGL_ENABLE_EXPERIMENTAL_API
 #include <clutter/clutter.h>
 #include <clutter/x11/clutter-x11.h>
 #include <gjs/gjs.h>
diff --git a/src/shell-app.c b/src/shell-app.c
index 1f5017d..d2a90a9 100644
--- a/src/shell-app.c
+++ b/src/shell-app.c
@@ -217,7 +217,7 @@ typedef struct {
   ClutterTextDirection direction;
 } CreateFadedIconData;
 
-static CoglHandle
+static CoglTexture *
 shell_app_create_faded_icon_cpu (StTextureCache *cache,
                                  const char     *key,
                                  void           *datap,
@@ -227,7 +227,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
   ShellApp *app;
   GdkPixbuf *pixbuf;
   int size;
-  CoglHandle texture;
+  CoglTexture *texture;
   gint width, height, rowstride;
   guint8 n_channels;
   gboolean have_alpha;
@@ -263,13 +263,13 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
     }
 
   if (info == NULL)
-    return COGL_INVALID_HANDLE;
+    return NULL;
 
   pixbuf = gtk_icon_info_load_icon (info, NULL);
   g_object_unref (info);
 
   if (pixbuf == NULL)
-    return COGL_INVALID_HANDLE;
+    return NULL;
 
   width = gdk_pixbuf_get_width (pixbuf);
   height = gdk_pixbuf_get_height (pixbuf);
@@ -338,7 +338,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
 ClutterActor *
 shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection direction)
 {
-  CoglHandle texture;
+  CoglTexture *texture;
   ClutterActor *result;
   char *cache_key;
   CreateFadedIconData data;
@@ -367,7 +367,7 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
                                    NULL);
   g_free (cache_key);
 
-  if (texture != COGL_INVALID_HANDLE)
+  if (texture != NULL)
     {
       result = clutter_texture_new ();
       clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (result), texture);
diff --git a/src/shell-invert-lightness-effect.c b/src/shell-invert-lightness-effect.c
index 4d6c27e..b3a2ca4 100644
--- a/src/shell-invert-lightness-effect.c
+++ b/src/shell-invert-lightness-effect.c
@@ -35,8 +35,6 @@
 #define SHELL_IS_INVERT_EFFECT_CLASS(klass)           (G_TYPE_CHECK_CLASS_TYPE ((klass), 
SHELL_TYPE_INVERT_LIGHTNESS_EFFECT))
 #define SHELL_INVERT_LIGHTNESS_EFFECT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
SHELL_TYPE_INVERT_LIGHTNESS_EFFEC, ShellInvertLightnessEffectClass))
 
-#define CLUTTER_ENABLE_EXPERIMENTAL_API
-
 #include "shell-invert-lightness-effect.h"
 
 #include <cogl/cogl.h>
@@ -124,6 +122,7 @@ shell_invert_lightness_effect_paint_target (ClutterOffscreenEffect *effect)
   ShellInvertLightnessEffect *self = SHELL_INVERT_LIGHTNESS_EFFECT (effect);
   ClutterActor *actor;
   guint8 paint_opacity;
+  CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
 
   actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
   paint_opacity = clutter_actor_get_paint_opacity (actor);
@@ -133,11 +132,8 @@ shell_invert_lightness_effect_paint_target (ClutterOffscreenEffect *effect)
                               paint_opacity,
                               paint_opacity,
                               paint_opacity);
-  cogl_push_source (self->pipeline);
-
-  cogl_rectangle (0, 0, self->tex_width, self->tex_height);
-
-  cogl_pop_source ();
+  cogl_framebuffer_draw_rectangle (fb, self->pipeline,
+                                   0, 0, self->tex_width, self->tex_height);
 }
 
 static void
diff --git a/src/shell-invert-lightness-effect.h b/src/shell-invert-lightness-effect.h
index a7bedd5..3d7cf3a 100644
--- a/src/shell-invert-lightness-effect.h
+++ b/src/shell-invert-lightness-effect.h
@@ -21,7 +21,6 @@
 #ifndef __SHELL_INVERT_LIGHTNESS_EFFECT_H__
 #define __SHELL_INVERT_LIGHTNESS_EFFECT_H__
 
-#define COGL_ENABLE_EXPERIMENTAL_API
 #include <clutter/clutter.h>
 
 G_BEGIN_DECLS
diff --git a/src/shell-recorder.c b/src/shell-recorder.c
index 23f2c07..f88ca55 100644
--- a/src/shell-recorder.c
+++ b/src/shell-recorder.c
@@ -441,15 +441,19 @@ recorder_record_frame (ShellRecorder *recorder)
   recorder->last_frame_time = now;
 
   size = recorder->area.width * recorder->area.height * 4;
-
-  data = g_malloc (recorder->area.width * 4 * recorder->area.height);
-  cogl_read_pixels (recorder->area.x,
-                    recorder->area.y,
-                    recorder->area.width,
-                    recorder->area.height,
-                    COGL_READ_PIXELS_COLOR_BUFFER,
-                    CLUTTER_CAIRO_FORMAT_ARGB32,
-                    data);
+  data = g_malloc (size);
+  if (!cogl_framebuffer_read_pixels (cogl_get_draw_framebuffer (),
+                                     recorder->area.x,
+                                     recorder->area.y,
+                                     recorder->area.width,
+                                     recorder->area.height,
+                                     CLUTTER_CAIRO_FORMAT_ARGB32,
+                                     data))
+    {
+      g_warning ("Could not retrieve pixel data");
+      g_free (data);
+      return;
+    }
 
   buffer = gst_buffer_new();
   gst_buffer_insert_memory (buffer, -1,
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c
index 991a554..db1fd9e 100644
--- a/src/shell-screenshot.c
+++ b/src/shell-screenshot.c
@@ -1,8 +1,5 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 
-#define COGL_ENABLE_EXPERIMENTAL_API
-#define CLUTTER_ENABLE_EXPERIMENTAL_API
-
 #include <clutter/clutter.h>
 #include <cogl/cogl.h>
 #include <meta/display.h>
diff --git a/src/shell-slicer.c b/src/shell-slicer.c
index 2d2cb84..a33a222 100644
--- a/src/shell-slicer.c
+++ b/src/shell-slicer.c
@@ -97,6 +97,7 @@ shell_slicer_paint_child (ShellSlicer *self)
   float width, height, child_width, child_height;
   StAlign x_align, y_align;
   double x_align_factor, y_align_factor;
+  CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
 
   child = st_bin_get_child (ST_BIN (self));
 
@@ -115,18 +116,17 @@ shell_slicer_paint_child (ShellSlicer *self)
   child_width = child_box.x2 - child_box.x1;
   child_height = child_box.y2 - child_box.y1;
 
-  cogl_push_matrix ();
-
-  cogl_clip_push_rectangle (0, 0, width, height);
-  cogl_translate ((int)(0.5 + x_align_factor * (width - child_width)),
-                  (int)(0.5 + y_align_factor * (height - child_height)),
-                  0);
+  cogl_framebuffer_push_matrix (fb);
+  cogl_framebuffer_push_rectangle_clip (fb, 0, 0, width, height);
+  cogl_framebuffer_translate (fb,
+                              (int)(0.5 + x_align_factor * (width - child_width)),
+                              (int)(0.5 + y_align_factor * (height - child_height)),
+                              0);
 
   clutter_actor_paint (child);
 
-  cogl_clip_pop ();
-
-  cogl_pop_matrix ();
+  cogl_framebuffer_pop_clip (fb);
+  cogl_framebuffer_pop_matrix (fb);
 }
 
 static void
diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c
index 91e93a5..0078d53 100644
--- a/src/st/st-box-layout.c
+++ b/src/st/st-box-layout.c
@@ -387,19 +387,20 @@ st_box_layout_paint (ClutterActor *actor)
   ClutterActorBox allocation_box;
   ClutterActorBox content_box;
   ClutterActor *child;
+  CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
 
   get_border_paint_offsets (self, &x, &y);
   if (x != 0 || y != 0)
     {
-      cogl_push_matrix ();
-      cogl_translate ((int)x, (int)y, 0);
+      cogl_framebuffer_push_matrix (fb);
+      cogl_framebuffer_translate (fb, (int)x, (int)y, 0);
     }
 
   st_widget_paint_background (ST_WIDGET (actor));
 
   if (x != 0 || y != 0)
     {
-      cogl_pop_matrix ();
+      cogl_framebuffer_pop_matrix (fb);
     }
 
   if (clutter_actor_get_n_children (actor) == 0)
@@ -417,10 +418,11 @@ st_box_layout_paint (ClutterActor *actor)
    * the borders and background stay in place; after drawing the borders and
    * background, we clip to the content area */
   if (priv->hadjustment || priv->vadjustment)
-    cogl_clip_push_rectangle ((int)content_box.x1,
-                              (int)content_box.y1,
-                              (int)content_box.x2,
-                              (int)content_box.y2);
+    cogl_framebuffer_push_rectangle_clip (fb,
+                                          (int)content_box.x1,
+                                          (int)content_box.y1,
+                                          (int)content_box.x2,
+                                          (int)content_box.y2);
 
   for (child = clutter_actor_get_first_child (actor);
        child != NULL;
@@ -428,7 +430,7 @@ st_box_layout_paint (ClutterActor *actor)
     clutter_actor_paint (child);
 
   if (priv->hadjustment || priv->vadjustment)
-    cogl_clip_pop ();
+    cogl_framebuffer_pop_clip (fb);
 }
 
 static void
@@ -442,19 +444,20 @@ st_box_layout_pick (ClutterActor       *actor,
   ClutterActorBox allocation_box;
   ClutterActorBox content_box;
   ClutterActor *child;
+  CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
 
   get_border_paint_offsets (self, &x, &y);
   if (x != 0 || y != 0)
     {
-      cogl_push_matrix ();
-      cogl_translate ((int)x, (int)y, 0);
+      cogl_framebuffer_push_matrix (fb);
+      cogl_framebuffer_translate (fb, (int)x, (int)y, 0);
     }
 
   CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor, color);
 
   if (x != 0 || y != 0)
     {
-      cogl_pop_matrix ();
+      cogl_framebuffer_pop_matrix (fb);
     }
 
   if (clutter_actor_get_n_children (actor) == 0)
@@ -469,10 +472,11 @@ st_box_layout_pick (ClutterActor       *actor,
   content_box.y2 += y;
 
   if (priv->hadjustment || priv->vadjustment)
-    cogl_clip_push_rectangle ((int)content_box.x1,
-                              (int)content_box.y1,
-                              (int)content_box.x2,
-                              (int)content_box.y2);
+    cogl_framebuffer_push_rectangle_clip (fb,
+                                          (int)content_box.x1,
+                                          (int)content_box.y1,
+                                          (int)content_box.x2,
+                                          (int)content_box.y2);
 
   for (child = clutter_actor_get_first_child (actor);
        child != NULL;
@@ -480,7 +484,7 @@ st_box_layout_pick (ClutterActor       *actor,
     clutter_actor_paint (child);
 
   if (priv->hadjustment || priv->vadjustment)
-    cogl_clip_pop ();
+    cogl_framebuffer_pop_clip (fb);
 }
 
 static gboolean
diff --git a/src/st/st-drawing-area.c b/src/st/st-drawing-area.c
index f044cbf..5faf7dd 100644
--- a/src/st/st-drawing-area.c
+++ b/src/st/st-drawing-area.c
@@ -39,8 +39,8 @@
 G_DEFINE_TYPE(StDrawingArea, st_drawing_area, ST_TYPE_WIDGET);
 
 struct _StDrawingAreaPrivate {
-  CoglHandle texture;
-  CoglHandle material;
+  CoglTexture *texture;
+  CoglPipeline *pipeline;
   cairo_t *context;
   guint needs_repaint : 1;
   guint in_repaint : 1;
@@ -61,17 +61,8 @@ st_drawing_area_dispose (GObject *object)
   StDrawingArea *area = ST_DRAWING_AREA (object);
   StDrawingAreaPrivate *priv = area->priv;
 
-  if (priv->material != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (priv->material);
-      priv->material = COGL_INVALID_HANDLE;
-    }
-
-  if (priv->texture != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (priv->texture);
-      priv->texture = COGL_INVALID_HANDLE;
-    }
+  g_clear_pointer (&priv->pipeline, cogl_object_unref);
+  g_clear_pointer (&priv->texture, cogl_object_unref);
 
   G_OBJECT_CLASS (st_drawing_area_parent_class)->dispose (object);
 }
@@ -85,8 +76,6 @@ st_drawing_area_paint (ClutterActor *self)
   ClutterActorBox allocation_box;
   ClutterActorBox content_box;
   int width, height;
-  CoglColor color;
-  guint8 paint_opacity;
 
   (CLUTTER_ACTOR_CLASS (st_drawing_area_parent_class))->paint (self);
 
@@ -96,20 +85,25 @@ st_drawing_area_paint (ClutterActor *self)
   width = (int)(0.5 + content_box.x2 - content_box.x1);
   height = (int)(0.5 + content_box.y2 - content_box.y1);
 
-  if (priv->material == COGL_INVALID_HANDLE)
-    priv->material = cogl_material_new ();
+  if (priv->pipeline == NULL)
+    {
+      CoglContext *ctx =
+        clutter_backend_get_cogl_context (clutter_get_default_backend ());
+
+      priv->pipeline = cogl_pipeline_new (ctx);
+    }
 
-  if (priv->texture != COGL_INVALID_HANDLE &&
+  if (priv->texture != NULL &&
       (width != cogl_texture_get_width (priv->texture) ||
        height != cogl_texture_get_height (priv->texture)))
     {
-      cogl_handle_unref (priv->texture);
-      priv->texture = COGL_INVALID_HANDLE;
+      cogl_object_unref (priv->texture);
+      priv->texture = NULL;
     }
 
   if (width > 0 && height > 0)
     {
-      if (priv->texture == COGL_INVALID_HANDLE)
+      if (priv->texture == NULL)
         {
           priv->texture = cogl_texture_new_with_size (width, height,
                                                       COGL_TEXTURE_NONE,
@@ -141,19 +135,21 @@ st_drawing_area_paint (ClutterActor *self)
         }
     }
 
-  cogl_material_set_layer (priv->material, 0, priv->texture);
+  cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->texture);
 
   if (priv->texture)
     {
+      CoglColor color;
+      guint8 paint_opacity;
+      CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
+
       paint_opacity = clutter_actor_get_paint_opacity (self);
-      cogl_color_set_from_4ub (&color,
-                               paint_opacity, paint_opacity, paint_opacity, paint_opacity);
-      cogl_material_set_color (priv->material, &color);
-
-      cogl_set_source (priv->material);
-      cogl_rectangle_with_texture_coords (content_box.x1, content_box.y1,
-                                          content_box.x2, content_box.y2,
-                                          0.0f, 0.0f, 1.0f, 1.0f);
+      cogl_color_init_from_4ub (&color, paint_opacity, paint_opacity, paint_opacity, paint_opacity);
+      cogl_pipeline_set_color (priv->pipeline, &color);
+
+      cogl_framebuffer_draw_rectangle (fb, priv->pipeline,
+                                       content_box.x1, content_box.y1,
+                                       content_box.x2, content_box.y2);
     }
 }
 
@@ -195,7 +191,7 @@ st_drawing_area_init (StDrawingArea *area)
 {
   area->priv = G_TYPE_INSTANCE_GET_PRIVATE (area, ST_TYPE_DRAWING_AREA,
                                             StDrawingAreaPrivate);
-  area->priv->texture = COGL_INVALID_HANDLE;
+  area->priv->texture = NULL;
 }
 
 /**
diff --git a/src/st/st-icon.c b/src/st/st-icon.c
index fac474a..2b7b7ec 100644
--- a/src/st/st-icon.c
+++ b/src/st/st-icon.c
@@ -56,7 +56,7 @@ struct _StIconPrivate
   gint          theme_icon_size; /* icon size from theme node */
   gint          icon_size;       /* icon size we are using */
 
-  CoglHandle    shadow_material;
+  CoglPipeline *shadow_pipeline;
   float         shadow_width;
   float         shadow_height;
   StShadow     *shadow_spec;
@@ -141,23 +141,9 @@ st_icon_dispose (GObject *gobject)
       priv->pending_texture = NULL;
     }
 
-  if (priv->gicon)
-    {
-      g_object_unref (priv->gicon);
-      priv->gicon = NULL;
-    }
-
-  if (priv->shadow_material)
-    {
-      cogl_handle_unref (priv->shadow_material);
-      priv->shadow_material = COGL_INVALID_HANDLE;
-    }
-
-  if (priv->shadow_spec)
-    {
-      st_shadow_unref (priv->shadow_spec);
-      priv->shadow_spec = NULL;
-    }
+  g_clear_object (&priv->gicon);
+  g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
+  g_clear_pointer (&priv->shadow_spec, st_shadow_unref);
 
   G_OBJECT_CLASS (st_icon_parent_class)->dispose (gobject);
 }
@@ -241,7 +227,7 @@ st_icon_paint (ClutterActor *actor)
 
   if (priv->icon_texture)
     {
-      if (priv->shadow_material)
+      if (priv->shadow_pipeline)
         {
           ClutterActorBox allocation;
           float width, height;
@@ -250,7 +236,8 @@ st_icon_paint (ClutterActor *actor)
           clutter_actor_box_get_size (&allocation, &width, &height);
 
           _st_paint_shadow_with_opacity (priv->shadow_spec,
-                                         priv->shadow_material,
+                                         priv->shadow_pipeline,
+                                         cogl_get_draw_framebuffer (),
                                          &allocation,
                                          clutter_actor_get_paint_opacity (priv->icon_texture));
         }
@@ -266,17 +253,8 @@ st_icon_style_changed (StWidget *widget)
   StThemeNode *theme_node = st_widget_get_theme_node (widget);
   StIconPrivate *priv = self->priv;
 
-  if (priv->shadow_spec)
-    {
-      st_shadow_unref (priv->shadow_spec);
-      priv->shadow_spec = NULL;
-    }
-
-  if (priv->shadow_material)
-    {
-      cogl_handle_unref (priv->shadow_material);
-      priv->shadow_material = COGL_INVALID_HANDLE;
-    }
+  g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
+  g_clear_pointer (&priv->shadow_spec, st_shadow_unref);
 
   priv->shadow_spec = st_theme_node_get_shadow (theme_node, "icon-shadow");
 
@@ -343,33 +321,26 @@ st_icon_init (StIcon *self)
   self->priv->icon_size = DEFAULT_ICON_SIZE;
   self->priv->prop_icon_size = -1;
 
-  self->priv->shadow_material = COGL_INVALID_HANDLE;
+  self->priv->shadow_pipeline = NULL;
   self->priv->shadow_width = -1;
   self->priv->shadow_height = -1;
 }
 
 static void
-st_icon_update_shadow_material (StIcon *icon)
+st_icon_update_shadow_pipeline (StIcon *icon)
 {
   StIconPrivate *priv = icon->priv;
 
-  if (priv->shadow_material)
-    {
-      cogl_handle_unref (priv->shadow_material);
-      priv->shadow_material = COGL_INVALID_HANDLE;
-    }
+  g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
 
   if (priv->shadow_spec)
    {
-     CoglHandle material;
      gint width, height;
 
      clutter_texture_get_base_size (CLUTTER_TEXTURE (priv->icon_texture),
                                     &width, &height);
 
-     material = _st_create_shadow_material_from_actor (priv->shadow_spec,
-                                                       priv->icon_texture);
-     priv->shadow_material = material;
+     priv->shadow_pipeline = _st_create_shadow_pipeline_from_actor (priv->shadow_spec, priv->icon_texture);
      priv->shadow_width = width;
      priv->shadow_height = height;
    }
@@ -379,7 +350,7 @@ static void
 on_pixbuf_changed (ClutterTexture *texture,
                    StIcon         *icon)
 {
-  st_icon_update_shadow_material (icon);
+  st_icon_update_shadow_pipeline (icon);
 }
 
 static void
@@ -402,7 +373,7 @@ st_icon_finish_update (StIcon *icon)
       /* Remove the temporary ref we added */
       g_object_unref (priv->icon_texture);
 
-      st_icon_update_shadow_material (icon);
+      st_icon_update_shadow_pipeline (icon);
 
       /* "pixbuf-change" is actually a misnomer for "texture-changed" */
       g_signal_connect_object (priv->icon_texture, "pixbuf-change",
diff --git a/src/st/st-label.c b/src/st/st-label.c
index 9833b83..2d887d8 100644
--- a/src/st/st-label.c
+++ b/src/st/st-label.c
@@ -60,7 +60,7 @@ struct _StLabelPrivate
 {
   ClutterActor *label;
 
-  CoglHandle    text_shadow_material;
+  CoglPipeline *text_shadow_pipeline;
   float         shadow_width;
   float         shadow_height;
 };
@@ -118,11 +118,7 @@ st_label_style_changed (StWidget *self)
 {
   StLabelPrivate *priv = ST_LABEL(self)->priv;
 
-  if (priv->text_shadow_material != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (priv->text_shadow_material);
-      priv->text_shadow_material = COGL_INVALID_HANDLE;
-    }
+  g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
 
   _st_set_text_from_style ((ClutterText *)priv->label, st_widget_get_theme_node (self));
 
@@ -192,11 +188,7 @@ st_label_dispose (GObject   *object)
       priv->label = NULL;
     }
 
-  if (priv->text_shadow_material != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (priv->text_shadow_material);
-      priv->text_shadow_material = COGL_INVALID_HANDLE;
-    }
+  g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
 
   G_OBJECT_CLASS (st_label_parent_class)->dispose (object);
 }
@@ -218,26 +210,21 @@ st_label_paint (ClutterActor *actor)
       clutter_actor_get_allocation_box (priv->label, &allocation);
       clutter_actor_box_get_size (&allocation, &width, &height);
 
-      if (priv->text_shadow_material == COGL_INVALID_HANDLE ||
+      if (priv->text_shadow_pipeline == NULL ||
           width != priv->shadow_width ||
           height != priv->shadow_height)
         {
-          CoglHandle material;
-
-          if (priv->text_shadow_material != COGL_INVALID_HANDLE)
-            cogl_handle_unref (priv->text_shadow_material);
-
-          material = _st_create_shadow_material_from_actor (shadow_spec,
-                                                            priv->label);
+          g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
 
           priv->shadow_width = width;
           priv->shadow_height = height;
-          priv->text_shadow_material = material;
+          priv->text_shadow_pipeline = _st_create_shadow_pipeline_from_actor (shadow_spec, priv->label);
         }
 
-      if (priv->text_shadow_material != COGL_INVALID_HANDLE)
+      if (priv->text_shadow_pipeline != NULL)
         _st_paint_shadow_with_opacity (shadow_spec,
-                                       priv->text_shadow_material,
+                                       priv->text_shadow_pipeline,
+                                       cogl_get_draw_framebuffer (),
                                        &allocation,
                                        clutter_actor_get_paint_opacity (priv->label));
     }
@@ -292,7 +279,7 @@ st_label_init (StLabel *label)
   label->priv->label = g_object_new (CLUTTER_TYPE_TEXT,
                                      "ellipsize", PANGO_ELLIPSIZE_END,
                                      NULL);
-  label->priv->text_shadow_material = COGL_INVALID_HANDLE;
+  label->priv->text_shadow_pipeline = NULL;
   label->priv->shadow_width = -1.;
   label->priv->shadow_height = -1.;
 
@@ -357,11 +344,7 @@ st_label_set_text (StLabel     *label,
   if (clutter_text_get_editable (ctext) ||
       g_strcmp0 (clutter_text_get_text (ctext), text) != 0)
     {
-      if (priv->text_shadow_material != COGL_INVALID_HANDLE)
-        {
-          cogl_handle_unref (priv->text_shadow_material);
-          priv->text_shadow_material = COGL_INVALID_HANDLE;
-        }
+      g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
 
       clutter_text_set_text (ctext, text);
 
diff --git a/src/st/st-private.c b/src/st/st-private.c
index e3307b0..7a347e5 100644
--- a/src/st/st-private.c
+++ b/src/st/st-private.c
@@ -162,47 +162,41 @@ _st_set_text_from_style (ClutterText *text,
 }
 
 /**
- * _st_create_texture_material:
- * @src_texture: The CoglTexture for the material
+ * _st_create_texture_pipeline:
+ * @src_texture: The CoglTexture for the pipeline
  *
- * Creates a simple material which contains the given texture as a
+ * Creates a simple pipeline which contains the given texture as a
  * single layer.
  */
-CoglHandle
-_st_create_texture_material (CoglHandle src_texture)
+CoglPipeline *
+_st_create_texture_pipeline (CoglTexture *src_texture)
 {
-  static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
-  CoglHandle material;
-
-  g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
-                        COGL_INVALID_HANDLE);
-
-  /* We use a material that has a dummy texture as a base for all
-     texture materials. The idea is that only the Cogl texture object
-     would be different in the children so it is likely that Cogl will
-     be able to share GL programs between all the textures. */
-  if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
+  static CoglPipeline *texture_pipeline_template = NULL;
+  CoglPipeline *pipeline;
+
+  g_return_val_if_fail (src_texture != NULL, NULL);
+
+  /* The only state used in the pipeline that would affect the shader
+     generation is the texture type on the layer. Therefore we create
+     a template pipeline which sets this state and all texture
+     pipelines are created as a copy of this. That way Cogl can find
+     the shader state for the pipeline more quickly by looking at the
+     pipeline ancestry instead of resorting to the shader cache. */
+  if (G_UNLIKELY (texture_pipeline_template == NULL))
     {
-      static const guint8 white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
-      CoglHandle dummy_texture;
-
-      dummy_texture =
-        cogl_texture_new_from_data (1, 1,
-                                    COGL_TEXTURE_NONE,
-                                    COGL_PIXEL_FORMAT_RGBA_8888_PRE,
-                                    COGL_PIXEL_FORMAT_ANY,
-                                    4, white_pixel);
-
-      texture_material_template = cogl_material_new ();
-      cogl_material_set_layer (texture_material_template, 0, dummy_texture);
-      cogl_handle_unref (dummy_texture);
-    }
+      CoglContext *ctx =
+        clutter_backend_get_cogl_context (clutter_get_default_backend ());
 
-  material = cogl_material_copy (texture_material_template);
+      texture_pipeline_template = cogl_pipeline_new (ctx);
+      cogl_pipeline_set_layer_null_texture (texture_pipeline_template,
+                                            0, /* layer */
+                                            COGL_TEXTURE_TYPE_2D);
+    }
 
-  cogl_material_set_layer (material, 0, src_texture);
+  pipeline = cogl_pipeline_copy (texture_pipeline_template);
+  cogl_pipeline_set_layer_texture (pipeline, 0, src_texture);
 
-  return material;
+  return pipeline;
 }
 
 /*****
@@ -345,21 +339,20 @@ blur_pixels (guchar  *pixels_in,
   return pixels_out;
 }
 
-CoglHandle
-_st_create_shadow_material (StShadow   *shadow_spec,
-                            CoglHandle  src_texture)
+CoglPipeline *
+_st_create_shadow_pipeline (StShadow    *shadow_spec,
+                            CoglTexture *src_texture)
 {
-  static CoglHandle shadow_material_template = COGL_INVALID_HANDLE;
+  static CoglPipeline *shadow_pipeline_template = NULL;
 
-  CoglHandle  material;
-  CoglHandle  texture;
-  guchar     *pixels_in, *pixels_out;
-  gint        width_in, height_in, rowstride_in;
-  gint        width_out, height_out, rowstride_out;
+  CoglPipeline *pipeline;
+  CoglTexture *texture;
+  guchar *pixels_in, *pixels_out;
+  gint width_in, height_in, rowstride_in;
+  gint width_out, height_out, rowstride_out;
 
-  g_return_val_if_fail (shadow_spec != NULL, COGL_INVALID_HANDLE);
-  g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
-                        COGL_INVALID_HANDLE);
+  g_return_val_if_fail (shadow_spec != NULL, NULL);
+  g_return_val_if_fail (src_texture != NULL, NULL);
 
   width_in  = cogl_texture_get_width  (src_texture);
   height_in = cogl_texture_get_height (src_texture);
@@ -385,84 +378,99 @@ _st_create_shadow_material (StShadow   *shadow_spec,
 
   g_free (pixels_out);
 
-  if (G_UNLIKELY (shadow_material_template == COGL_INVALID_HANDLE))
+  if (G_UNLIKELY (shadow_pipeline_template == NULL))
     {
-      shadow_material_template = cogl_material_new ();
+      CoglContext *ctx =
+        clutter_backend_get_cogl_context (clutter_get_default_backend ());
+
+      shadow_pipeline_template = cogl_pipeline_new (ctx);
 
-      /* We set up the material to blend the shadow texture with the combine
+      /* We set up the pipeline to blend the shadow texture with the combine
        * constant, but defer setting the latter until painting, so that we can
        * take the actor's overall opacity into account. */
-      cogl_material_set_layer_combine (shadow_material_template, 0,
+      cogl_pipeline_set_layer_combine (shadow_pipeline_template, 0,
                                        "RGBA = MODULATE (CONSTANT, TEXTURE[A])",
                                        NULL);
     }
 
-  material = cogl_material_copy (shadow_material_template);
-
-  cogl_material_set_layer (material, 0, texture);
-
-  cogl_handle_unref (texture);
-
-  return material;
+  pipeline = cogl_pipeline_copy (shadow_pipeline_template);
+  cogl_pipeline_set_layer_texture (pipeline, 0, texture);
+  cogl_object_unref (texture);
+  return pipeline;
 }
 
-CoglHandle
-_st_create_shadow_material_from_actor (StShadow     *shadow_spec,
+CoglPipeline *
+_st_create_shadow_pipeline_from_actor (StShadow     *shadow_spec,
                                        ClutterActor *actor)
 {
-  CoglHandle shadow_material = COGL_INVALID_HANDLE;
+  CoglPipeline *shadow_pipeline = NULL;
 
   if (CLUTTER_IS_TEXTURE (actor))
     {
-      CoglHandle texture;
+      CoglTexture *texture;
 
       texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));
-      shadow_material = _st_create_shadow_material (shadow_spec, texture);
+      shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, texture);
     }
   else
     {
-      CoglHandle buffer, offscreen;
+      CoglTexture *buffer;
+      CoglOffscreen *offscreen;
+      CoglFramebuffer *fb;
       ClutterActorBox box;
       CoglColor clear_color;
       float width, height;
+      CoglError *catch_error = NULL;
 
       clutter_actor_get_allocation_box (actor, &box);
       clutter_actor_box_get_size (&box, &width, &height);
 
       if (width == 0 || height == 0)
-        return COGL_INVALID_HANDLE;
+        return NULL;
 
       buffer = cogl_texture_new_with_size (width,
                                            height,
                                            COGL_TEXTURE_NO_SLICING,
                                            COGL_PIXEL_FORMAT_ANY);
 
-      if (buffer == COGL_INVALID_HANDLE)
-        return COGL_INVALID_HANDLE;
+      if (buffer == NULL)
+        return NULL;
 
-      offscreen = cogl_offscreen_new_to_texture (buffer);
+      offscreen = cogl_offscreen_new_with_texture (buffer);
+      fb = COGL_FRAMEBUFFER (offscreen);
 
-      if (offscreen == COGL_INVALID_HANDLE)
+      if (!cogl_framebuffer_allocate (fb, &catch_error))
         {
-          cogl_handle_unref (buffer);
-          return COGL_INVALID_HANDLE;
+          cogl_error_free (catch_error);
+          cogl_object_unref (buffer);
+          return NULL;
         }
 
-      cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
-      cogl_push_framebuffer (offscreen);
-      cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
-      cogl_translate (-box.x1, -box.y1, 0);
-      cogl_ortho (0, width, height, 0, 0, 1.0);
+      cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
+
+      /* XXX: There's no way to render a ClutterActor to an offscreen
+       * as it uses the implicit API. */
+      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+      cogl_push_framebuffer (fb);
+      G_GNUC_END_IGNORE_DEPRECATIONS;
+
+      cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
+      cogl_framebuffer_translate (fb, -box.x1, -box.y1, 0);
+      cogl_framebuffer_orthographic (fb, 0, width, height, 0, 0, 1.0);
       clutter_actor_paint (actor);
+
+      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
       cogl_pop_framebuffer ();
-      cogl_handle_unref (offscreen);
+      G_GNUC_END_IGNORE_DEPRECATIONS;
 
-      shadow_material = _st_create_shadow_material (shadow_spec, buffer);
+      cogl_object_unref (fb);
 
-      cogl_handle_unref (buffer);
+      shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, buffer);
+
+      cogl_object_unref (buffer);
     }
 
-  return shadow_material;
+  return shadow_pipeline;
 }
 
 /**
@@ -610,29 +618,27 @@ _st_create_shadow_cairo_pattern (StShadow        *shadow_spec,
 
 void
 _st_paint_shadow_with_opacity (StShadow        *shadow_spec,
-                               CoglHandle       shadow_material,
+                               CoglPipeline    *shadow_pipeline,
+                               CoglFramebuffer *fb,
                                ClutterActorBox *box,
                                guint8           paint_opacity)
 {
   ClutterActorBox shadow_box;
-  CoglColor       color;
+  CoglColor color;
 
   g_return_if_fail (shadow_spec != NULL);
-  g_return_if_fail (shadow_material != COGL_INVALID_HANDLE);
+  g_return_if_fail (shadow_pipeline != NULL);
 
   st_shadow_get_box (shadow_spec, box, &shadow_box);
 
-  cogl_color_set_from_4ub (&color,
-                           shadow_spec->color.red   * paint_opacity / 255,
-                           shadow_spec->color.green * paint_opacity / 255,
-                           shadow_spec->color.blue  * paint_opacity / 255,
-                           shadow_spec->color.alpha * paint_opacity / 255);
+  cogl_color_init_from_4ub (&color,
+                            shadow_spec->color.red   * paint_opacity / 255,
+                            shadow_spec->color.green * paint_opacity / 255,
+                            shadow_spec->color.blue  * paint_opacity / 255,
+                            shadow_spec->color.alpha * paint_opacity / 255);
   cogl_color_premultiply (&color);
-
-  cogl_material_set_layer_combine_constant (shadow_material, 0, &color);
-
-  cogl_set_source (shadow_material);
-  cogl_rectangle_with_texture_coords (shadow_box.x1, shadow_box.y1,
-                                      shadow_box.x2, shadow_box.y2,
-                                      0, 0, 1, 1);
+  cogl_pipeline_set_layer_combine_constant (shadow_pipeline, 0, &color);
+  cogl_framebuffer_draw_rectangle (fb, shadow_pipeline,
+                                   shadow_box.x1, shadow_box.y1,
+                                   shadow_box.x2, shadow_box.y2);
 }
diff --git a/src/st/st-private.h b/src/st/st-private.h
index 05fa634..5c44998 100644
--- a/src/st/st-private.h
+++ b/src/st/st-private.h
@@ -59,18 +59,19 @@ void _st_actor_get_preferred_height (ClutterActor *actor,
 void _st_set_text_from_style (ClutterText *text,
                               StThemeNode *theme_node);
 
-CoglHandle _st_create_texture_material (CoglHandle src_texture);
+CoglPipeline * _st_create_texture_pipeline (CoglTexture *src_texture);
 
 /* Helper for widgets which need to draw additional shadows */
-CoglHandle _st_create_shadow_material (StShadow   *shadow_spec,
-                                       CoglHandle  src_texture);
-CoglHandle _st_create_shadow_material_from_actor (StShadow     *shadow_spec,
-                                                  ClutterActor *actor);
+CoglPipeline * _st_create_shadow_pipeline (StShadow    *shadow_spec,
+                                           CoglTexture *src_texture);
+CoglPipeline * _st_create_shadow_pipeline_from_actor (StShadow     *shadow_spec,
+                                                      ClutterActor *actor);
 cairo_pattern_t *_st_create_shadow_cairo_pattern (StShadow        *shadow_spec,
                                                   cairo_pattern_t *src_pattern);
 
 void _st_paint_shadow_with_opacity (StShadow        *shadow_spec,
-                                    CoglHandle       shadow_material,
+                                    CoglPipeline    *shadow_pipeline,
+                                    CoglFramebuffer *fb,
                                     ClutterActorBox *box,
                                     guint8           paint_opacity);
 
diff --git a/src/st/st-shadow.c b/src/st/st-shadow.c
index 4a2ff00..605d394 100644
--- a/src/st/st-shadow.c
+++ b/src/st/st-shadow.c
@@ -190,7 +190,7 @@ st_shadow_get_box (StShadow              *shadow,
 
 struct _StShadowHelper {
   StShadow     *shadow;
-  CoglMaterial *material;
+  CoglPipeline *pipeline;
 
   gfloat        width;
   gfloat        height;
@@ -224,14 +224,14 @@ st_shadow_helper_update (StShadowHelper *helper,
 
   clutter_actor_get_size (source, &width, &height);
 
-  if (helper->material == NULL ||
+  if (helper->pipeline == NULL ||
       helper->width != width ||
       helper->height != height)
     {
-      if (helper->material)
-        cogl_object_unref (helper->material);
+      if (helper->pipeline)
+        cogl_object_unref (helper->pipeline);
 
-      helper->material = _st_create_shadow_material_from_actor (helper->shadow, source);
+      helper->pipeline = _st_create_shadow_pipeline_from_actor (helper->shadow, source);
       helper->width = width;
       helper->height = height;
     }
@@ -250,8 +250,8 @@ st_shadow_helper_copy (StShadowHelper *helper)
 
   copy = g_slice_new (StShadowHelper);
   *copy = *helper;
-  if (copy->material)
-    cogl_object_ref (copy->material);
+  if (copy->pipeline)
+    cogl_object_ref (copy->pipeline);
   st_shadow_ref (copy->shadow);
 
   return copy;
@@ -266,8 +266,8 @@ st_shadow_helper_copy (StShadowHelper *helper)
 void
 st_shadow_helper_free (StShadowHelper *helper)
 {
-  if (helper->material)
-    cogl_object_unref (helper->material);
+  if (helper->pipeline)
+    cogl_object_unref (helper->pipeline);
   st_shadow_unref (helper->shadow);
 
   g_slice_free (StShadowHelper, helper);
@@ -293,7 +293,8 @@ st_shadow_helper_paint (StShadowHelper  *helper,
   clutter_actor_box_get_size (actor_box, &width, &height);
 
   _st_paint_shadow_with_opacity (helper->shadow,
-                                 helper->material,
+                                 helper->pipeline,
+                                 cogl_get_draw_framebuffer (),
                                  &allocation,
                                  paint_opacity);
 }
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index 17cb068..dd9a67b 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -60,7 +60,7 @@ static guint signals[LAST_SIGNAL] = { 0, };
 G_DEFINE_TYPE(StTextureCache, st_texture_cache, G_TYPE_OBJECT);
 
 /* We want to preserve the aspect ratio by default, also the default
- * material for an empty texture is full opacity white, which we
+ * pipeline for an empty texture is full opacity white, which we
  * definitely don't want.  Skip that by setting 0 opacity.
  */
 static ClutterTexture *
@@ -73,7 +73,7 @@ create_default_texture (void)
 
 /* Reverse the opacity we added while loading */
 static void
-set_texture_cogl_texture (ClutterTexture *clutter_texture, CoglHandle cogl_texture)
+set_texture_cogl_texture (ClutterTexture *clutter_texture, CoglTexture *cogl_texture)
 {
   clutter_texture_set_cogl_texture (clutter_texture, cogl_texture);
   g_object_set (clutter_texture, "opacity", 255, NULL);
@@ -144,7 +144,7 @@ st_texture_cache_init (StTextureCache *self)
                     G_CALLBACK (on_icon_theme_changed), self);
 
   self->priv->keyed_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                                   g_free, cogl_handle_unref);
+                                                   g_free, cogl_object_unref);
   self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                             g_free, NULL);
   self->priv->file_monitors = g_hash_table_new_full (g_str_hash, g_str_equal,
@@ -516,16 +516,15 @@ load_pixbuf_async_finish (StTextureCache *cache, GAsyncResult *result, GError **
   return g_simple_async_result_get_op_res_gpointer (simple);
 }
 
-static CoglHandle
-data_to_cogl_handle (const guchar *data,
-                     gboolean      has_alpha,
-                     int           width,
-                     int           height,
-                     int           rowstride,
-                     gboolean      add_padding)
+static CoglTexture *
+data_to_cogl_texture (const guchar *data,
+                      gboolean      has_alpha,
+                      int           width,
+                      int           height,
+                      int           rowstride,
+                      gboolean      add_padding)
 {
-  CoglHandle texture, offscreen;
-  CoglColor clear_color;
+  CoglTexture *texture;
   guint size;
 
   size = MAX (width, height);
@@ -543,13 +542,6 @@ data_to_cogl_handle (const guchar *data,
                                         COGL_TEXTURE_NO_SLICING,
                                         COGL_PIXEL_FORMAT_ANY);
 
-  offscreen = cogl_offscreen_new_to_texture (texture);
-  cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
-  cogl_push_framebuffer (offscreen);
-  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
-  cogl_pop_framebuffer ();
-  cogl_handle_unref (offscreen);
-
   cogl_texture_set_region (texture,
                            0, 0,
                            (size - width) / 2, (size - height) / 2,
@@ -561,16 +553,16 @@ data_to_cogl_handle (const guchar *data,
   return texture;
 }
 
-static CoglHandle
-pixbuf_to_cogl_handle (GdkPixbuf *pixbuf,
+static CoglTexture *
+pixbuf_to_cogl_texture (GdkPixbuf *pixbuf,
                        gboolean   add_padding)
 {
-  return data_to_cogl_handle (gdk_pixbuf_get_pixels (pixbuf),
-                              gdk_pixbuf_get_has_alpha (pixbuf),
-                              gdk_pixbuf_get_width (pixbuf),
-                              gdk_pixbuf_get_height (pixbuf),
-                              gdk_pixbuf_get_rowstride (pixbuf),
-                              add_padding);
+  return data_to_cogl_texture (gdk_pixbuf_get_pixels (pixbuf),
+                               gdk_pixbuf_get_has_alpha (pixbuf),
+                               gdk_pixbuf_get_width (pixbuf),
+                               gdk_pixbuf_get_height (pixbuf),
+                               gdk_pixbuf_get_rowstride (pixbuf),
+                               add_padding);
 }
 
 static cairo_surface_t *
@@ -600,7 +592,7 @@ finish_texture_load (AsyncTextureLoadData *data,
 {
   GSList *iter;
   StTextureCache *cache;
-  CoglHandle texdata = NULL;
+  CoglTexture *texdata = NULL;
 
   cache = data->cache;
 
@@ -609,7 +601,7 @@ finish_texture_load (AsyncTextureLoadData *data,
   if (pixbuf == NULL)
     goto out;
 
-  texdata = pixbuf_to_cogl_handle (pixbuf, data->enforced_square);
+  texdata = pixbuf_to_cogl_texture (pixbuf, data->enforced_square);
 
   if (data->policy != ST_TEXTURE_CACHE_POLICY_NONE)
     {
@@ -618,7 +610,7 @@ finish_texture_load (AsyncTextureLoadData *data,
       if (!g_hash_table_lookup_extended (cache->priv->keyed_cache, data->key,
                                          &orig_key, &value))
         {
-          cogl_handle_ref (texdata);
+          cogl_object_ref (texdata);
           g_hash_table_insert (cache->priv->keyed_cache, g_strdup (data->key),
                                texdata);
         }
@@ -632,7 +624,7 @@ finish_texture_load (AsyncTextureLoadData *data,
 
 out:
   if (texdata)
-    cogl_handle_unref (texdata);
+    cogl_object_unref (texdata);
 
   texture_load_data_free (data);
 }
@@ -723,7 +715,7 @@ st_texture_cache_reset_texture (StTextureCachePropertyBind *bind,
                                 const char                 *propname)
 {
   GdkPixbuf *pixbuf;
-  CoglHandle texdata;
+  CoglTexture *texdata;
 
   g_object_get (bind->source, propname, &pixbuf, NULL);
 
@@ -731,11 +723,11 @@ st_texture_cache_reset_texture (StTextureCachePropertyBind *bind,
 
   if (pixbuf != NULL)
     {
-      texdata = pixbuf_to_cogl_handle (pixbuf, FALSE);
+      texdata = pixbuf_to_cogl_texture (pixbuf, FALSE);
       g_object_unref (pixbuf);
 
       clutter_texture_set_cogl_texture (bind->texture, texdata);
-      cogl_handle_unref (texdata);
+      cogl_object_unref (texdata);
 
       clutter_actor_set_opacity (CLUTTER_ACTOR (bind->texture), 255);
     }
@@ -778,7 +770,7 @@ st_texture_cache_free_bind (gpointer data)
  *
  * Create a #ClutterTexture which tracks the #GdkPixbuf value of a GObject property
  * named by @property_name.  Unlike other methods in StTextureCache, the underlying
- * CoglHandle is not shared by default with other invocations to this method.
+ * #CoglTexture is not shared by default with other invocations to this method.
  *
  * If the source object is destroyed, the texture will continue to show the last
  * value of the property.
@@ -829,7 +821,7 @@ st_texture_cache_bind_pixbuf_property (StTextureCache    *cache,
  *
  * Returns: (transfer full): A newly-referenced handle to the texture
  */
-CoglHandle
+CoglTexture *
 st_texture_cache_load (StTextureCache       *cache,
                        const char           *key,
                        StTextureCachePolicy  policy,
@@ -837,7 +829,7 @@ st_texture_cache_load (StTextureCache       *cache,
                        void                 *data,
                        GError              **error)
 {
-  CoglHandle texture;
+  CoglTexture *texture;
 
   texture = g_hash_table_lookup (cache->priv->keyed_cache, key);
   if (!texture)
@@ -846,9 +838,10 @@ st_texture_cache_load (StTextureCache       *cache,
       if (texture)
         g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), texture);
       else
-        return COGL_INVALID_HANDLE;
+        return NULL;
     }
-  cogl_handle_ref (texture);
+
+  cogl_object_ref (texture);
   return texture;
 }
 
@@ -873,7 +866,7 @@ ensure_request (StTextureCache        *cache,
                 AsyncTextureLoadData **request,
                 ClutterActor          *texture)
 {
-  CoglHandle texdata;
+  CoglTexture *texdata;
   AsyncTextureLoadData *pending;
   gboolean had_pending;
 
@@ -1005,7 +998,7 @@ static ClutterActor *
 load_from_pixbuf (GdkPixbuf *pixbuf)
 {
   ClutterTexture *texture;
-  CoglHandle texdata;
+  CoglTexture *texdata;
   int width = gdk_pixbuf_get_width (pixbuf);
   int height = gdk_pixbuf_get_height (pixbuf);
 
@@ -1013,11 +1006,11 @@ load_from_pixbuf (GdkPixbuf *pixbuf)
 
   clutter_actor_set_size (CLUTTER_ACTOR (texture), width, height);
 
-  texdata = pixbuf_to_cogl_handle (pixbuf, FALSE);
+  texdata = pixbuf_to_cogl_texture (pixbuf, FALSE);
 
   set_texture_cogl_texture (texture, texdata);
 
-  cogl_handle_unref (texdata);
+  cogl_object_unref (texdata);
   return CLUTTER_ACTOR (texture);
 }
 
@@ -1256,7 +1249,7 @@ st_texture_cache_load_uri_async (StTextureCache *cache,
   return CLUTTER_ACTOR (texture);
 }
 
-static CoglHandle
+static CoglTexture *
 st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
                                                 StTextureCachePolicy policy,
                                                 const gchar    *uri,
@@ -1264,7 +1257,7 @@ st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
                                                 int             available_height,
                                                 GError         **error)
 {
-  CoglHandle texdata;
+  CoglTexture *texdata;
   GdkPixbuf *pixbuf;
   char *key;
 
@@ -1278,17 +1271,17 @@ st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
       if (!pixbuf)
         goto out;
 
-      texdata = pixbuf_to_cogl_handle (pixbuf, FALSE);
+      texdata = pixbuf_to_cogl_texture (pixbuf, FALSE);
       g_object_unref (pixbuf);
 
       if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
         {
-          cogl_handle_ref (texdata);
+          cogl_object_ref (texdata);
           g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), texdata);
         }
     }
   else
-    cogl_handle_ref (texdata);
+    cogl_object_ref (texdata);
 
   ensure_monitor_for_uri (cache, uri);
 
@@ -1339,21 +1332,21 @@ out:
 }
 
 /**
- * st_texture_cache_load_file_to_cogl_texture:
+ * st_texture_cache_load_file_to_cogl_texture: (skip)
  * @cache: A #StTextureCache
  * @file_path: Path to a file in supported image format
  *
  * This function synchronously loads the given file path
  * into a COGL texture.  On error, a warning is emitted
- * and %COGL_INVALID_HANDLE is returned.
+ * and %NULL is returned.
  *
- * Returns: (transfer full): a new #CoglHandle
+ * Returns: (transfer full): a new #CoglTexture
  */
-CoglHandle
+CoglTexture *
 st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
                                             const gchar    *file_path)
 {
-  CoglHandle texture;
+  CoglTexture *texture;
   GFile *file;
   char *uri;
   GError *error = NULL;
@@ -1370,7 +1363,7 @@ st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
     {
       g_warning ("Failed to load %s: %s", file_path, error->message);
       g_clear_error (&error);
-      return COGL_INVALID_HANDLE;
+      return NULL;
     }
   return texture;
 }
diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h
index fa9746c..a88bbf3 100644
--- a/src/st/st-texture-cache.h
+++ b/src/st/st-texture-cache.h
@@ -90,8 +90,8 @@ ClutterActor *st_texture_cache_load_uri_async (StTextureCache    *cache,
                                                int                available_width,
                                                int                available_height);
 
-CoglHandle    st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
-                                                          const gchar    *file_path);
+CoglTexture     *st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
+                                                             const gchar    *file_path);
 
 cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
                                                               const gchar    *file_path);
@@ -107,13 +107,13 @@ cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *ca
  * texture handle for the given key, or set @error.
  *
  */
-typedef CoglHandle (*StTextureCacheLoader) (StTextureCache *cache, const char *key, void *data, GError 
**error);
-
-CoglHandle st_texture_cache_load (StTextureCache       *cache,
-                                  const char           *key,
-                                  StTextureCachePolicy  policy,
-                                  StTextureCacheLoader  load,
-                                  void                 *data,
-                                  GError              **error);
+typedef CoglTexture * (*StTextureCacheLoader) (StTextureCache *cache, const char *key, void *data, GError 
**error);
+
+CoglTexture * st_texture_cache_load (StTextureCache       *cache,
+                                     const char           *key,
+                                     StTextureCachePolicy  policy,
+                                     StTextureCacheLoader  load,
+                                     void                 *data,
+                                     GError              **error);
 
 #endif /* __ST_TEXTURE_CACHE_H__ */
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index dc5b817..e31630f 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -66,10 +66,10 @@ elliptical_arc (cairo_t *cr,
   cairo_restore (cr);
 }
 
-static CoglHandle
-create_corner_material (StCornerSpec *corner)
+static CoglTexture *
+create_corner_texture (StCornerSpec *corner)
 {
-  CoglHandle texture;
+  CoglTexture *texture;
   cairo_t *cr;
   cairo_surface_t *surface;
   guint rowstride;
@@ -173,7 +173,7 @@ create_corner_material (StCornerSpec *corner)
                                         rowstride,
                                         data);
   g_free (data);
-  g_assert (texture != COGL_INVALID_HANDLE);
+  g_assert (texture != NULL);
 
   return texture;
 }
@@ -190,13 +190,13 @@ corner_to_string (StCornerSpec *corner)
                           corner->border_width_2);
 }
 
-static CoglHandle
+static CoglTexture *
 load_corner (StTextureCache  *cache,
              const char      *key,
              void            *datap,
              GError         **error)
 {
-  return create_corner_material ((StCornerSpec *) datap);
+  return create_corner_texture ((StCornerSpec *) datap);
 }
 
 /* To match the CSS specification, we want the border to look like it was
@@ -337,13 +337,14 @@ st_theme_node_get_corner_border_widths (StThemeNode *node,
     }
 }
 
-static CoglHandle
+static CoglPipeline *
 st_theme_node_lookup_corner (StThemeNode    *node,
                              float           width,
                              float           height,
                              StCorner        corner_id)
 {
-  CoglHandle texture, material;
+  CoglTexture *texture;
+  CoglPipeline *pipeline;
   char *key;
   StTextureCache *cache;
   StCornerSpec corner;
@@ -354,7 +355,7 @@ st_theme_node_lookup_corner (StThemeNode    *node,
   st_theme_node_reduce_border_radius (node, width, height, radius);
 
   if (radius[corner_id] == 0)
-    return COGL_INVALID_HANDLE;
+    return NULL;
 
   corner.radius = radius[corner_id];
   corner.color = node->background_color;
@@ -385,16 +386,16 @@ st_theme_node_lookup_corner (StThemeNode    *node,
   if (corner.color.alpha == 0 &&
       corner.border_color_1.alpha == 0 &&
       corner.border_color_2.alpha == 0)
-    return COGL_INVALID_HANDLE;
+    return NULL;
 
   key = corner_to_string (&corner);
   texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_NONE, load_corner, &corner, NULL);
-  material = _st_create_texture_material (texture);
-  cogl_handle_unref (texture);
+  pipeline = _st_create_texture_pipeline (texture);
+  cogl_object_unref (texture);
 
   g_free (key);
 
-  return material;
+  return pipeline;
 }
 
 static void
@@ -934,13 +935,13 @@ paint_inset_box_shadow_to_cairo_context (StThemeNode     *node,
  * we need to use cairo.  This function is a slow fallback path for those
  * cases (gradients, background images, etc).
  */
-static CoglHandle
+static CoglTexture *
 st_theme_node_prerender_background (StThemeNode *node,
                                     float        actor_width,
                                     float        actor_height)
 {
   StBorderImage *border_image;
-  CoglHandle texture;
+  CoglTexture *texture;
   guint radius[4];
   int i;
   cairo_t *cr;
@@ -1268,30 +1269,17 @@ st_theme_node_prerender_background (StThemeNode *node,
   return texture;
 }
 
-static void st_theme_node_paint_borders (StThemeNodePaintState *state,
-                                         const ClutterActorBox *box,
-                                         guint8                 paint_opacity);
-
 void
 st_theme_node_invalidate_border_image (StThemeNode *node)
 {
-  if (node->border_slices_texture != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (node->border_slices_texture);
-      node->border_slices_texture = COGL_INVALID_HANDLE;
-    }
-
-  if (node->border_slices_material != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (node->border_slices_material);
-      node->border_slices_material = COGL_INVALID_HANDLE;
-    }
+  g_clear_pointer (&node->border_slices_texture, cogl_object_unref);
+  g_clear_pointer (&node->border_slices_pipeline, cogl_object_unref);
 }
 
 static gboolean
 st_theme_node_load_border_image (StThemeNode *node)
 {
-  if (node->border_slices_texture == COGL_INVALID_HANDLE)
+  if (node->border_slices_texture == NULL)
     {
       StBorderImage *border_image;
 
@@ -1303,42 +1291,28 @@ st_theme_node_load_border_image (StThemeNode *node)
       filename = st_border_image_get_filename (border_image);
       node->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default 
(),
                                                                                 filename);
-      if (node->border_slices_texture == COGL_INVALID_HANDLE)
+      if (node->border_slices_texture == NULL)
         goto out;
 
-      node->border_slices_material = _st_create_texture_material (node->border_slices_texture);
+      node->border_slices_pipeline = _st_create_texture_pipeline (node->border_slices_texture);
     }
 
  out:
-  return node->border_slices_texture != COGL_INVALID_HANDLE;
+  return node->border_slices_pipeline != NULL;
 }
 
 void
 st_theme_node_invalidate_background_image (StThemeNode *node)
 {
-  if (node->background_texture != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (node->background_texture);
-      node->background_texture = COGL_INVALID_HANDLE;
-    }
-
-  if (node->background_material != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (node->background_material);
-      node->background_material = COGL_INVALID_HANDLE;
-    }
-
-  if (node->background_shadow_material != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (node->background_shadow_material);
-      node->background_shadow_material = COGL_INVALID_HANDLE;
-    }
+  g_clear_pointer (&node->background_texture, cogl_object_unref);
+  g_clear_pointer (&node->background_pipeline, cogl_object_unref);
+  g_clear_pointer (&node->background_shadow_pipeline, cogl_object_unref);
 }
 
 static gboolean
 st_theme_node_load_background_image (StThemeNode *node)
 {
-  if (node->background_texture == COGL_INVALID_HANDLE)
+  if (node->background_texture == NULL)
     {
       const char *background_image;
       StShadow *background_image_shadow_spec;
@@ -1350,27 +1324,38 @@ st_theme_node_load_background_image (StThemeNode *node)
       background_image_shadow_spec = st_theme_node_get_background_image_shadow (node);
       node->background_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (),
                                                                              background_image);
-      if (node->background_texture == COGL_INVALID_HANDLE)
+      if (node->background_texture == NULL)
         goto out;
 
-      node->background_material = _st_create_texture_material (node->background_texture);
+      node->background_pipeline = _st_create_texture_pipeline (node->background_texture);
 
       if (node->background_repeat)
-        cogl_material_set_layer_wrap_mode (node->background_material, 0, COGL_MATERIAL_WRAP_MODE_REPEAT);
+        cogl_pipeline_set_layer_wrap_mode (node->background_pipeline, 0, COGL_PIPELINE_WRAP_MODE_REPEAT);
 
       if (background_image_shadow_spec)
         {
-          node->background_shadow_material = _st_create_shadow_material (background_image_shadow_spec,
+          node->background_shadow_pipeline = _st_create_shadow_pipeline (background_image_shadow_spec,
                                                                          node->background_texture);
         }
     }
 
  out:
-  return node->background_texture != COGL_INVALID_HANDLE;
+  return node->background_texture != NULL;
 }
 
 static void st_theme_node_prerender_shadow (StThemeNodePaintState *state);
 
+static CoglPipeline *
+get_color_pipeline (guint8 r, guint8 g, guint8 b, guint8 a)
+{
+  CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+  CoglPipeline *pipeline;
+
+  pipeline = cogl_pipeline_new (ctx);
+  cogl_pipeline_set_color4ub (pipeline, r, g, b, a);
+  return pipeline;
+}
+
 static void
 st_theme_node_render_resources (StThemeNodePaintState *state,
                                 StThemeNode           *node,
@@ -1438,13 +1423,13 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
     }
   }
 
-  state->corner_material[ST_CORNER_TOPLEFT] =
+  state->corner_pipeline[ST_CORNER_TOPLEFT] =
     st_theme_node_lookup_corner (node, width, height, ST_CORNER_TOPLEFT);
-  state->corner_material[ST_CORNER_TOPRIGHT] =
+  state->corner_pipeline[ST_CORNER_TOPRIGHT] =
     st_theme_node_lookup_corner (node, width, height, ST_CORNER_TOPRIGHT);
-  state->corner_material[ST_CORNER_BOTTOMRIGHT] =
+  state->corner_pipeline[ST_CORNER_BOTTOMRIGHT] =
     st_theme_node_lookup_corner (node, width, height, ST_CORNER_BOTTOMRIGHT);
-  state->corner_material[ST_CORNER_BOTTOMLEFT] =
+  state->corner_pipeline[ST_CORNER_BOTTOMLEFT] =
     st_theme_node_lookup_corner (node, width, height, ST_CORNER_BOTTOMLEFT);
 
   /* Use cairo to prerender the node if there is a gradient, or
@@ -1463,17 +1448,17 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
     state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
 
   if (state->prerendered_texture)
-    state->prerendered_material = _st_create_texture_material (state->prerendered_texture);
+    state->prerendered_pipeline = _st_create_texture_pipeline (state->prerendered_texture);
   else
-    state->prerendered_material = COGL_INVALID_HANDLE;
+    state->prerendered_pipeline = NULL;
 
   if (box_shadow_spec && !has_inset_box_shadow)
     {
       if (st_theme_node_load_border_image (node))
-        state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
+        state->box_shadow_pipeline = _st_create_shadow_pipeline (box_shadow_spec,
                                                                  node->border_slices_texture);
-      else if (state->prerendered_texture != COGL_INVALID_HANDLE)
-        state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
+      else if (state->prerendered_texture != NULL)
+        state->box_shadow_pipeline = _st_create_shadow_pipeline (box_shadow_spec,
                                                                  state->prerendered_texture);
       else if (node->background_color.alpha > 0 || has_border)
         st_theme_node_prerender_shadow (state);
@@ -1483,7 +1468,7 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
      them. */
   if (!node->cached_textures)
     {
-      if (state->prerendered_material == COGL_INVALID_HANDLE &&
+      if (state->prerendered_pipeline == NULL &&
           width >= node->box_shadow_min_width &&
           height >= node->box_shadow_min_height)
         {
@@ -1505,23 +1490,23 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
 
   g_return_if_fail (width > 0 && height > 0);
 
-  /* Free handles we can't reuse */
-  if (state->prerendered_texture != COGL_INVALID_HANDLE)
+  /* Free objects we can't reuse */
+  if (state->prerendered_texture != NULL)
     {
-      cogl_handle_unref (state->prerendered_texture);
-      state->prerendered_texture = COGL_INVALID_HANDLE;
+      cogl_object_unref (state->prerendered_texture);
+      state->prerendered_texture = NULL;
       had_prerendered_texture = TRUE;
     }
-  if (state->prerendered_material != COGL_INVALID_HANDLE)
+  if (state->prerendered_pipeline != NULL)
     {
-      cogl_handle_unref (state->prerendered_material);
-      state->prerendered_material = COGL_INVALID_HANDLE;
+      cogl_object_unref (state->prerendered_pipeline);
+      state->prerendered_pipeline = NULL;
 
-      if (node->border_slices_texture == COGL_INVALID_HANDLE &&
-          state->box_shadow_material != COGL_INVALID_HANDLE)
+      if (node->border_slices_texture == NULL &&
+          state->box_shadow_pipeline != NULL)
         {
-          cogl_handle_unref (state->box_shadow_material);
-          state->box_shadow_material = COGL_INVALID_HANDLE;
+          cogl_object_unref (state->box_shadow_pipeline);
+          state->box_shadow_pipeline = NULL;
           had_box_shadow = TRUE;
         }
     }
@@ -1535,43 +1520,26 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
   if (had_prerendered_texture)
     {
       state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
-      state->prerendered_material = _st_create_texture_material (state->prerendered_texture);
+      state->prerendered_pipeline = _st_create_texture_pipeline (state->prerendered_texture);
     }
   else
     {
       int corner_id;
 
       for (corner_id = 0; corner_id < 4; corner_id++)
-        if (state->corner_material[corner_id] == COGL_INVALID_HANDLE)
-          state->corner_material[corner_id] =
+        if (state->corner_pipeline[corner_id] == NULL)
+          state->corner_pipeline[corner_id] =
             st_theme_node_lookup_corner (node, width, height, corner_id);
     }
 
   if (had_box_shadow)
-    state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
+    state->box_shadow_pipeline = _st_create_shadow_pipeline (box_shadow_spec,
                                                              state->prerendered_texture);
 }
 
 static void
-paint_material_with_opacity (CoglHandle       material,
-                             ClutterActorBox *box,
-                             ClutterActorBox *coords,
-                             guint8           paint_opacity)
-{
-  cogl_material_set_color4ub (material,
-                              paint_opacity, paint_opacity, paint_opacity, paint_opacity);
-
-  cogl_set_source (material);
-
-  if (coords)
-    cogl_rectangle_with_texture_coords (box->x1, box->y1, box->x2, box->y2,
-                                        coords->x1, coords->y1, coords->x2, coords->y2);
-  else
-    cogl_rectangle (box->x1, box->y1, box->x2, box->y2);
-}
-
-static void
 st_theme_node_paint_borders (StThemeNodePaintState *state,
+                             CoglFramebuffer       *fb,
                              const ClutterActorBox *box,
                              guint8                 paint_opacity)
 {
@@ -1624,10 +1592,7 @@ st_theme_node_paint_borders (StThemeNodePaintState *state,
 
       if (alpha > 0)
         {
-          cogl_set_source_color4ub (effective_border.red,
-                                    effective_border.green,
-                                    effective_border.blue,
-                                    alpha);
+          CoglPipeline *pipeline;
 
           /* NORTH */
           skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
@@ -1670,7 +1635,12 @@ st_theme_node_paint_borders (StThemeNodePaintState *state,
           rects[15] = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMLEFT]
                              : height - border_width[ST_SIDE_BOTTOM];
 
-          cogl_rectangles (rects, 4);
+          pipeline = get_color_pipeline (effective_border.red,
+                                         effective_border.green,
+                                         effective_border.blue,
+                                         alpha);
+          cogl_framebuffer_draw_rectangles (fb, pipeline, rects, 4);
+          cogl_object_unref (pipeline);
         }
     }
 
@@ -1679,35 +1649,40 @@ st_theme_node_paint_borders (StThemeNodePaintState *state,
     {
       for (corner_id = 0; corner_id < 4; corner_id++)
         {
-          if (state->corner_material[corner_id] == COGL_INVALID_HANDLE)
+          CoglPipeline *pipeline = state->corner_pipeline[corner_id];
+
+          if (pipeline == NULL)
             continue;
 
-          cogl_material_set_color4ub (state->corner_material[corner_id],
+          cogl_pipeline_set_color4ub (pipeline,
                                       paint_opacity, paint_opacity,
                                       paint_opacity, paint_opacity);
-          cogl_set_source (state->corner_material[corner_id]);
 
           switch (corner_id)
             {
               case ST_CORNER_TOPLEFT:
-                cogl_rectangle_with_texture_coords (0, 0,
-                                                    max_width_radius[ST_CORNER_TOPLEFT], 
max_width_radius[ST_CORNER_TOPLEFT],
-                                                    0, 0, 0.5, 0.5);
+                cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
+                                                          0, 0,
+                                                          max_width_radius[ST_CORNER_TOPLEFT], 
max_width_radius[ST_CORNER_TOPLEFT],
+                                                          0, 0, 0.5, 0.5);
                 break;
               case ST_CORNER_TOPRIGHT:
-                cogl_rectangle_with_texture_coords (width - max_width_radius[ST_CORNER_TOPRIGHT], 0,
-                                                    width, max_width_radius[ST_CORNER_TOPRIGHT],
-                                                    0.5, 0, 1, 0.5);
+                cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
+                                                          width - max_width_radius[ST_CORNER_TOPRIGHT], 0,
+                                                          width, max_width_radius[ST_CORNER_TOPRIGHT],
+                                                          0.5, 0, 1, 0.5);
                 break;
               case ST_CORNER_BOTTOMRIGHT:
-                cogl_rectangle_with_texture_coords (width - max_width_radius[ST_CORNER_BOTTOMRIGHT], height 
- max_width_radius[ST_CORNER_BOTTOMRIGHT],
-                                                    width, height,
-                                                    0.5, 0.5, 1, 1);
+                cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
+                                                          width - max_width_radius[ST_CORNER_BOTTOMRIGHT], 
height - max_width_radius[ST_CORNER_BOTTOMRIGHT],
+                                                          width, height,
+                                                          0.5, 0.5, 1, 1);
                 break;
               case ST_CORNER_BOTTOMLEFT:
-                cogl_rectangle_with_texture_coords (0, height - max_width_radius[ST_CORNER_BOTTOMLEFT],
-                                                    max_width_radius[ST_CORNER_BOTTOMLEFT], height,
-                                                    0, 0.5, 0.5, 1);
+                cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
+                                                          0, height - max_width_radius[ST_CORNER_BOTTOMLEFT],
+                                                          max_width_radius[ST_CORNER_BOTTOMLEFT], height,
+                                                          0, 0.5, 0.5, 1);
                 break;
             }
         }
@@ -1717,10 +1692,12 @@ st_theme_node_paint_borders (StThemeNodePaintState *state,
   alpha = paint_opacity * node->background_color.alpha / 255;
   if (alpha > 0)
     {
-      cogl_set_source_color4ub (node->background_color.red,
-                                node->background_color.green,
-                                node->background_color.blue,
-                                alpha);
+      CoglPipeline *pipeline;
+
+      pipeline = get_color_pipeline (node->background_color.red,
+                                     node->background_color.green,
+                                     node->background_color.blue,
+                                     alpha);
 
       /* We add padding to each corner, so that all corners end up as if they
        * had a border-radius of max_border_radius, which allows us to treat
@@ -1803,8 +1780,9 @@ st_theme_node_paint_borders (StThemeNodePaintState *state,
                     verts[7] = height - border_width[ST_SIDE_BOTTOM];
                   }
                 break;
+
+                cogl_framebuffer_draw_rectangles (fb, pipeline, verts, 4);
             }
-          cogl_rectangles (verts, n_rects);
         }
 
       /* Once we've drawn the borders and corners, if the corners are bigger
@@ -1819,25 +1797,31 @@ st_theme_node_paint_borders (StThemeNodePaintState *state,
        * necessary, then the main rectangle
        */
       if (max_border_radius > border_width[ST_SIDE_TOP])
-        cogl_rectangle (MAX(max_border_radius, border_width[ST_SIDE_LEFT]),
-                        border_width[ST_SIDE_TOP],
-                        width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]),
-                        max_border_radius);
+        cogl_framebuffer_draw_rectangle (fb, pipeline,
+                                         MAX(max_border_radius, border_width[ST_SIDE_LEFT]),
+                                         border_width[ST_SIDE_TOP],
+                                         width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]),
+                                         max_border_radius);
       if (max_border_radius > border_width[ST_SIDE_BOTTOM])
-        cogl_rectangle (MAX(max_border_radius, border_width[ST_SIDE_LEFT]),
-                        height - max_border_radius,
-                        width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]),
-                        height - border_width[ST_SIDE_BOTTOM]);
-
-      cogl_rectangle (border_width[ST_SIDE_LEFT],
-                      MAX(border_width[ST_SIDE_TOP], max_border_radius),
-                      width - border_width[ST_SIDE_RIGHT],
-                      height - MAX(border_width[ST_SIDE_BOTTOM], max_border_radius));
+        cogl_framebuffer_draw_rectangle (fb, pipeline,
+                                         MAX(max_border_radius, border_width[ST_SIDE_LEFT]),
+                                         height - max_border_radius,
+                                         width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]),
+                                         height - border_width[ST_SIDE_BOTTOM]);
+
+      cogl_framebuffer_draw_rectangle (fb, pipeline,
+                                       border_width[ST_SIDE_LEFT],
+                                       MAX(border_width[ST_SIDE_TOP], max_border_radius),
+                                       width - border_width[ST_SIDE_RIGHT],
+                                       height - MAX(border_width[ST_SIDE_BOTTOM], max_border_radius));
+
+      cogl_object_unref (pipeline);
     }
 }
 
 static void
 st_theme_node_paint_sliced_shadow (StThemeNodePaintState *state,
+                                   CoglFramebuffer       *fb,
                                    const ClutterActorBox *box,
                                    guint8                 paint_opacity)
 {
@@ -1943,16 +1927,14 @@ st_theme_node_paint_sliced_shadow (StThemeNodePaintState *state,
   right += xoffset;
 
   /* Setup pipeline */
-  cogl_color_set_from_4ub (&color,
-                           box_shadow_spec->color.red   * paint_opacity / 255,
-                           box_shadow_spec->color.green * paint_opacity / 255,
-                           box_shadow_spec->color.blue  * paint_opacity / 255,
-                           box_shadow_spec->color.alpha * paint_opacity / 255);
+  cogl_color_init_from_4ub (&color,
+                            box_shadow_spec->color.red   * paint_opacity / 255,
+                            box_shadow_spec->color.green * paint_opacity / 255,
+                            box_shadow_spec->color.blue  * paint_opacity / 255,
+                            box_shadow_spec->color.alpha * paint_opacity / 255);
   cogl_color_premultiply (&color);
 
-  cogl_material_set_layer_combine_constant (state->box_shadow_material, 0, &color);
-
-  cogl_set_source (state->box_shadow_material);
+  cogl_pipeline_set_layer_combine_constant (state->box_shadow_pipeline, 0, &color);
 
   idx = 0;
 
@@ -2080,36 +2062,8 @@ st_theme_node_paint_sliced_shadow (StThemeNodePaintState *state,
         }
     }
 
-  cogl_rectangles_with_texture_coords (rectangles, idx / 8);
-
-#if 0
-  /* Visual feedback on shadow's 9-slice and orignal offscreen buffer,
-     for debug purposes */
-  cogl_rectangle (xend, yoffset, xend + shadow_width, yoffset + shadow_height);
-
-  cogl_set_source_color4ub (0xff, 0x0, 0x0, 0xff);
-
-  cogl_rectangle (xoffset, top, xend, top + 1);
-  cogl_rectangle (xoffset, bottom, xend, bottom + 1);
-  cogl_rectangle (left, yoffset, left + 1, yend);
-  cogl_rectangle (right, yoffset, right + 1, yend);
-
-  cogl_rectangle (xend, yoffset, xend + shadow_width, yoffset + 1);
-  cogl_rectangle (xend, yoffset + shadow_height, xend + shadow_width, yoffset + shadow_height + 1);
-  cogl_rectangle (xend, yoffset, xend + 1, yoffset + shadow_height);
-  cogl_rectangle (xend + shadow_width, yoffset, xend + shadow_width + 1, yoffset + shadow_height);
-
-  s_top *= shadow_height;
-  s_bottom *= shadow_height;
-  s_left *= shadow_width;
-  s_right *= shadow_width;
-
-  cogl_rectangle (xend, yoffset + s_top, xend + shadow_width, yoffset + s_top + 1);
-  cogl_rectangle (xend, yoffset + s_bottom, xend + shadow_width, yoffset + s_bottom + 1);
-  cogl_rectangle (xend + s_left, yoffset, xend + s_left + 1, yoffset + shadow_height);
-  cogl_rectangle (xend + s_right, yoffset, xend + s_right + 1, yoffset + shadow_height);
-
-#endif
+  cogl_framebuffer_draw_textured_rectangles (fb, state->box_shadow_pipeline,
+                                             rectangles, idx / 4);
 }
 
 static void
@@ -2119,7 +2073,8 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state)
   guint border_radius[4];
   int max_borders[4];
   int center_radius, corner_id;
-  CoglHandle buffer, offscreen;
+  CoglTexture *buffer;
+  CoglOffscreen *offscreen;
 
   /* Get infos from the node */
   if (state->alloc_width < node->box_shadow_min_width ||
@@ -2160,33 +2115,32 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state)
                                        state->box_shadow_height,
                                        COGL_TEXTURE_NO_SLICING,
                                        COGL_PIXEL_FORMAT_ANY);
-  offscreen = cogl_offscreen_new_to_texture (buffer);
+  offscreen = cogl_offscreen_new_with_texture (buffer);
 
-  if (offscreen != COGL_INVALID_HANDLE)
+  if (offscreen != NULL)
     {
+      CoglFramebuffer *fb = COGL_FRAMEBUFFER (offscreen);
       ClutterActorBox box = { 0, 0, state->box_shadow_width, state->box_shadow_height};
       CoglColor clear_color;
 
-      cogl_push_framebuffer (offscreen);
-      cogl_ortho (0, state->box_shadow_width, state->box_shadow_height, 0, 0, 1.0);
+      cogl_framebuffer_orthographic (fb, 0, state->box_shadow_width, state->box_shadow_height, 0, 0, 1.0);
+      cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
+      cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
+      st_theme_node_paint_borders (state, fb, &box, 0xFF);
+      cogl_object_unref (offscreen);
 
-      cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
-      cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
-
-      st_theme_node_paint_borders (state, &box, 0xFF);
-      cogl_pop_framebuffer ();
-      cogl_handle_unref (offscreen);
-
-      state->box_shadow_material = _st_create_shadow_material (st_theme_node_get_box_shadow (node),
+      state->box_shadow_pipeline = _st_create_shadow_pipeline (st_theme_node_get_box_shadow (node),
                                                                buffer);
     }
-  cogl_handle_unref (buffer);
+
+  cogl_object_unref (buffer);
 }
 
 static void
 st_theme_node_paint_sliced_border_image (StThemeNode           *node,
                                          float                  width,
                                          float                  height,
+                                         CoglFramebuffer       *fb,
                                          guint8                 paint_opacity)
 {
   gfloat ex, ey;
@@ -2194,7 +2148,7 @@ st_theme_node_paint_sliced_border_image (StThemeNode           *node,
   gint border_left, border_right, border_top, border_bottom;
   float img_width, img_height;
   StBorderImage *border_image;
-  CoglHandle material;
+  CoglPipeline *pipeline;
 
   border_image = st_theme_node_get_border_image (node);
   g_assert (border_image != NULL);
@@ -2218,11 +2172,8 @@ st_theme_node_paint_sliced_border_image (StThemeNode           *node,
   if (ey < 0)
     ey = border_bottom;          /* FIXME ? */
 
-  material = node->border_slices_material;
-  cogl_material_set_color4ub (material,
-                              paint_opacity, paint_opacity, paint_opacity, paint_opacity);
-
-  cogl_set_source (material);
+  pipeline = node->border_slices_pipeline;
+  cogl_pipeline_set_color4ub (pipeline, paint_opacity, paint_opacity, paint_opacity, paint_opacity);
 
   {
     float rectangles[] =
@@ -2273,12 +2224,14 @@ st_theme_node_paint_sliced_border_image (StThemeNode           *node,
       1.0, 1.0
     };
 
-    cogl_rectangles_with_texture_coords (rectangles, 9);
+    cogl_framebuffer_draw_textured_rectangles (fb, pipeline,
+                                               rectangles, 9);
   }
 }
 
 static void
 st_theme_node_paint_outline (StThemeNode           *node,
+                             CoglFramebuffer       *fb,
                              const ClutterActorBox *box,
                              guint8                 paint_opacity)
 
@@ -2287,6 +2240,7 @@ st_theme_node_paint_outline (StThemeNode           *node,
   int outline_width;
   float rects[16];
   ClutterColor outline_color, effective_outline;
+  CoglPipeline *pipeline;
 
   width = box->x2 - box->x1;
   height = box->y2 - box->y1;
@@ -2298,10 +2252,10 @@ st_theme_node_paint_outline (StThemeNode           *node,
   st_theme_node_get_outline_color (node, &outline_color);
   over (&outline_color, &node->background_color, &effective_outline);
 
-  cogl_set_source_color4ub (effective_outline.red,
-                            effective_outline.green,
-                            effective_outline.blue,
-                            paint_opacity * effective_outline.alpha / 255);
+  pipeline = get_color_pipeline (effective_outline.red,
+                                 effective_outline.green,
+                                 effective_outline.blue,
+                                 paint_opacity * effective_outline.alpha / 255);
 
   /* The outline is drawn just outside the border, which means just
    * outside the allocation box. This means that in some situations
@@ -2333,7 +2287,8 @@ st_theme_node_paint_outline (StThemeNode           *node,
   rects[14] = 0;
   rects[15] = height;
 
-  cogl_rectangles (rects, 4);
+  cogl_framebuffer_draw_rectangles (fb, pipeline, rects, 16);
+  cogl_object_unref (pipeline);
 }
 
 static gboolean
@@ -2373,9 +2328,13 @@ st_theme_node_needs_new_box_shadow_for_size (StThemeNodePaintState *state,
   return FALSE;
 }
 
+/**
+ * st_theme_node_paint: (skip)
+ */
 void
 st_theme_node_paint (StThemeNode           *node,
                      StThemeNodePaintState *state,
+                     CoglFramebuffer       *fb,
                      const ClutterActorBox *box,
                      guint8                 paint_opacity)
 {
@@ -2441,24 +2400,26 @@ st_theme_node_paint (StThemeNode           *node,
    *    such that it's aligned to the outside edges)
    */
 
-  if (state->box_shadow_material)
+  if (state->box_shadow_pipeline)
     {
       if (state->alloc_width < node->box_shadow_min_width ||
           state->alloc_height < node->box_shadow_min_height)
         _st_paint_shadow_with_opacity (node->box_shadow,
-                                       state->box_shadow_material,
+                                       state->box_shadow_pipeline,
+                                       fb,
                                        &allocation,
                                        paint_opacity);
       else
         st_theme_node_paint_sliced_shadow (state,
+                                           fb,
                                            &allocation,
                                            paint_opacity);
     }
 
-  if (state->prerendered_material != COGL_INVALID_HANDLE ||
+  if (state->prerendered_pipeline != NULL ||
       st_theme_node_load_border_image (node))
     {
-      if (state->prerendered_material != COGL_INVALID_HANDLE)
+      if (state->prerendered_pipeline != NULL)
         {
           ClutterActorBox paint_box;
 
@@ -2466,23 +2427,24 @@ st_theme_node_paint (StThemeNode           *node,
                                                   &allocation,
                                                   &paint_box);
 
-          paint_material_with_opacity (state->prerendered_material,
-                                       &paint_box,
-                                       NULL,
-                                       paint_opacity);
+          cogl_pipeline_set_color4ub (state->prerendered_pipeline,
+                                      paint_opacity, paint_opacity, paint_opacity, paint_opacity);
+          cogl_framebuffer_draw_rectangle (fb, state->prerendered_pipeline,
+                                           paint_box.x1, paint_box.y1,
+                                           paint_box.x2, paint_box.y2);
         }
 
-      if (node->border_slices_material != COGL_INVALID_HANDLE)
-        st_theme_node_paint_sliced_border_image (node, width, height, paint_opacity);
+      if (node->border_slices_pipeline != NULL)
+        st_theme_node_paint_sliced_border_image (node, width, height, fb, paint_opacity);
     }
   else
     {
-      st_theme_node_paint_borders (state, box, paint_opacity);
+      st_theme_node_paint_borders (state, fb, box, paint_opacity);
     }
 
-  st_theme_node_paint_outline (node, box, paint_opacity);
+  st_theme_node_paint_outline (node, fb, box, paint_opacity);
 
-  if (state->prerendered_material == COGL_INVALID_HANDLE &&
+  if (state->prerendered_pipeline == NULL &&
       st_theme_node_load_background_image (node))
     {
       ClutterActorBox background_box;
@@ -2498,7 +2460,7 @@ st_theme_node_paint (StThemeNode           *node,
       get_background_position (node, &allocation, &background_box, &texture_coords);
 
       if (has_visible_outline || node->background_repeat)
-        cogl_clip_push_rectangle (allocation.x1, allocation.y1, allocation.x2, allocation.y2);
+        cogl_framebuffer_push_rectangle_clip (fb, allocation.x1, allocation.y1, allocation.x2, 
allocation.y2);
 
       /* CSS based drop shadows
        *
@@ -2513,19 +2475,23 @@ st_theme_node_paint (StThemeNode           *node,
        * there is nothing (like a border, or the edge of the background color)
        * to logically confine it.
        */
-      if (node->background_shadow_material != COGL_INVALID_HANDLE)
+      if (node->background_shadow_pipeline != NULL)
         _st_paint_shadow_with_opacity (node->background_image_shadow,
-                                       node->background_shadow_material,
+                                       node->background_shadow_pipeline,
+                                       fb,
                                        &background_box,
                                        paint_opacity);
 
-      paint_material_with_opacity (node->background_material,
-                                   &background_box,
-                                   &texture_coords,
-                                   paint_opacity);
+      cogl_pipeline_set_color4ub (node->background_pipeline,
+                                  paint_opacity, paint_opacity, paint_opacity, paint_opacity);
+      cogl_framebuffer_draw_textured_rectangle (fb, node->background_pipeline,
+                                                background_box.x1, background_box.y1,
+                                                background_box.x2, background_box.y2,
+                                                texture_coords.x1, texture_coords.x2,
+                                                texture_coords.y1, texture_coords.y2);
 
       if (has_visible_outline || node->background_repeat)
-        cogl_clip_pop ();
+        cogl_framebuffer_pop_clip (fb);
     }
 }
 
@@ -2535,16 +2501,11 @@ st_theme_node_paint_state_node_free_internal (StThemeNodePaintState *state,
 {
   int corner_id;
 
-  if (state->prerendered_texture != COGL_INVALID_HANDLE)
-    cogl_handle_unref (state->prerendered_texture);
-  if (state->prerendered_material != COGL_INVALID_HANDLE)
-    cogl_handle_unref (state->prerendered_material);
-  if (state->box_shadow_material != COGL_INVALID_HANDLE)
-    cogl_handle_unref (state->box_shadow_material);
-
+  g_clear_pointer (&state->prerendered_texture, cogl_object_unref);
+  g_clear_pointer (&state->prerendered_pipeline, cogl_object_unref);
+  g_clear_pointer (&state->box_shadow_pipeline, cogl_object_unref);
   for (corner_id = 0; corner_id < 4; corner_id++)
-    if (state->corner_material[corner_id] != COGL_INVALID_HANDLE)
-      cogl_handle_unref (state->corner_material[corner_id]);
+    g_clear_pointer (&state->corner_pipeline[corner_id], cogl_object_unref);
 
   if (unref_node)
     st_theme_node_paint_state_set_node (state, NULL);
@@ -2587,12 +2548,11 @@ st_theme_node_paint_state_init (StThemeNodePaintState *state)
   state->alloc_width = 0;
   state->alloc_height = 0;
   state->node = NULL;
-  state->box_shadow_material = COGL_INVALID_HANDLE;
-  state->prerendered_texture = COGL_INVALID_HANDLE;
-  state->prerendered_material = COGL_INVALID_HANDLE;
-
+  state->box_shadow_pipeline = NULL;
+  state->prerendered_texture = NULL;
+  state->prerendered_pipeline = NULL;
   for (corner_id = 0; corner_id < 4; corner_id++)
-    state->corner_material[corner_id] = COGL_INVALID_HANDLE;
+    state->corner_pipeline[corner_id] = NULL;
 }
 
 void
@@ -2613,15 +2573,15 @@ st_theme_node_paint_state_copy (StThemeNodePaintState *state,
   state->box_shadow_width = other->box_shadow_width;
   state->box_shadow_height = other->box_shadow_height;
 
-  if (other->box_shadow_material)
-    state->box_shadow_material = cogl_handle_ref (other->box_shadow_material);
+  if (other->box_shadow_pipeline)
+    state->box_shadow_pipeline = cogl_object_ref (other->box_shadow_pipeline);
   if (other->prerendered_texture)
-    state->prerendered_texture = cogl_handle_ref (other->prerendered_texture);
-  if (other->prerendered_material)
-    state->prerendered_material = cogl_handle_ref (other->prerendered_material);
+    state->prerendered_texture = cogl_object_ref (other->prerendered_texture);
+  if (other->prerendered_pipeline)
+    state->prerendered_pipeline = cogl_object_ref (other->prerendered_pipeline);
   for (corner_id = 0; corner_id < 4; corner_id++)
-    if (other->corner_material[corner_id])
-      state->corner_material[corner_id] = cogl_handle_ref (other->corner_material[corner_id]);
+    if (other->corner_pipeline[corner_id])
+      state->corner_pipeline[corner_id] = cogl_object_ref (other->corner_pipeline[corner_id]);
 }
 
 void
diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h
index aba58a3..b608492 100644
--- a/src/st/st-theme-node-private.h
+++ b/src/st/st-theme-node-private.h
@@ -105,11 +105,11 @@ struct _StThemeNode {
   int box_shadow_min_width;
   int box_shadow_min_height;
 
-  CoglHandle border_slices_texture;
-  CoglHandle border_slices_material;
-  CoglHandle background_texture;
-  CoglHandle background_material;
-  CoglHandle background_shadow_material;
+  CoglTexture *border_slices_texture;
+  CoglPipeline *border_slices_pipeline;
+  CoglTexture *background_texture;
+  CoglPipeline *background_pipeline;
+  CoglPipeline *background_shadow_pipeline;
 
   StThemeNodePaintState cached_state;
 };
diff --git a/src/st/st-theme-node-transition.c b/src/st/st-theme-node-transition.c
index a84c887..0bb6ec1 100644
--- a/src/st/st-theme-node-transition.c
+++ b/src/st/st-theme-node-transition.c
@@ -36,13 +36,13 @@ struct _StThemeNodeTransitionPrivate {
   StThemeNodePaintState old_paint_state;
   StThemeNodePaintState new_paint_state;
 
-  CoglHandle old_texture;
-  CoglHandle new_texture;
+  CoglTexture *old_texture;
+  CoglTexture *new_texture;
 
-  CoglHandle old_offscreen;
-  CoglHandle new_offscreen;
+  CoglOffscreen *old_offscreen;
+  CoglOffscreen *new_offscreen;
 
-  CoglHandle material;
+  CoglPipeline *pipeline;
 
   ClutterTimeline *timeline;
 
@@ -237,9 +237,10 @@ setup_framebuffers (StThemeNodeTransition *transition,
   StThemeNodeTransitionPrivate *priv = transition->priv;
   CoglColor clear_color = { 0, 0, 0, 0 };
   guint width, height;
+  CoglFramebuffer *fb;
 
-  /* template material to avoid unnecessary shader compilation */
-  static CoglHandle material_template = COGL_INVALID_HANDLE;
+  /* template pipeline to avoid unnecessary shader compilation */
+  static CoglPipeline *pipeline_template = NULL;
 
   width  = priv->offscreen_box.x2 - priv->offscreen_box.x1;
   height = priv->offscreen_box.y2 - priv->offscreen_box.y1;
@@ -248,77 +249,72 @@ setup_framebuffers (StThemeNodeTransition *transition,
   g_return_val_if_fail (height > 0, FALSE);
 
   if (priv->old_texture)
-    cogl_handle_unref (priv->old_texture);
+    cogl_object_unref (priv->old_texture);
   priv->old_texture = cogl_texture_new_with_size (width, height,
                                                   COGL_TEXTURE_NO_SLICING,
                                                   COGL_PIXEL_FORMAT_ANY);
 
   if (priv->new_texture)
-    cogl_handle_unref (priv->new_texture);
+    cogl_object_unref (priv->new_texture);
   priv->new_texture = cogl_texture_new_with_size (width, height,
                                                   COGL_TEXTURE_NO_SLICING,
                                                   COGL_PIXEL_FORMAT_ANY);
 
-  g_return_val_if_fail (priv->old_texture != COGL_INVALID_HANDLE, FALSE);
-  g_return_val_if_fail (priv->new_texture != COGL_INVALID_HANDLE, FALSE);
+  g_return_val_if_fail (priv->old_texture != NULL, FALSE);
+  g_return_val_if_fail (priv->new_texture != NULL, FALSE);
 
   if (priv->old_offscreen)
-    cogl_handle_unref (priv->old_offscreen);
-  priv->old_offscreen = cogl_offscreen_new_to_texture (priv->old_texture);
+    cogl_object_unref (priv->old_offscreen);
+  priv->old_offscreen = cogl_offscreen_new_with_texture (priv->old_texture);
 
   if (priv->new_offscreen)
-    cogl_handle_unref (priv->new_offscreen);
-  priv->new_offscreen = cogl_offscreen_new_to_texture (priv->new_texture);
+    cogl_object_unref (priv->new_offscreen);
+  priv->new_offscreen = cogl_offscreen_new_with_texture (priv->new_texture);
 
-  g_return_val_if_fail (priv->old_offscreen != COGL_INVALID_HANDLE, FALSE);
-  g_return_val_if_fail (priv->new_offscreen != COGL_INVALID_HANDLE, FALSE);
+  g_return_val_if_fail (priv->old_offscreen != NULL, FALSE);
+  g_return_val_if_fail (priv->new_offscreen != NULL, FALSE);
 
-  if (priv->material == NULL)
+  if (priv->pipeline == NULL)
     {
-      if (G_UNLIKELY (material_template == COGL_INVALID_HANDLE))
+      if (G_UNLIKELY (pipeline_template == NULL))
         {
-          material_template = cogl_material_new ();
-
-          cogl_material_set_layer_combine (material_template, 0,
-                                           "RGBA = REPLACE (TEXTURE)",
-                                           NULL);
-          cogl_material_set_layer_combine (material_template, 1,
-                                           "RGBA = INTERPOLATE (PREVIOUS, "
-                                                               "TEXTURE, "
-                                                               "CONSTANT[A])",
-                                           NULL);
-          cogl_material_set_layer_combine (material_template, 2,
-                                           "RGBA = MODULATE (PREVIOUS, "
-                                                            "PRIMARY)",
-                                           NULL);
+          CoglContext *ctx =
+            clutter_backend_get_cogl_context (clutter_get_default_backend ());
+
+          pipeline_template = cogl_pipeline_new (ctx);
+
+          cogl_pipeline_set_layer_combine (pipeline_template, 0, "RGBA = REPLACE (TEXTURE)", NULL);
+          cogl_pipeline_set_layer_combine (pipeline_template, 1, "RGBA = INTERPOLATE (PREVIOUS, TEXTURE, 
CONSTANT[A])", NULL);
+          cogl_pipeline_set_layer_combine (pipeline_template, 2, "RGBA = MODULATE (PREVIOUS, PRIMARY)", 
NULL);
         }
-      priv->material = cogl_material_copy (material_template);
+      priv->pipeline = cogl_pipeline_copy (pipeline_template);
     }
 
-  cogl_material_set_layer (priv->material, 0, priv->new_texture);
-  cogl_material_set_layer (priv->material, 1, priv->old_texture);
-
-  cogl_push_framebuffer (priv->old_offscreen);
-  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
-  cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
-              priv->offscreen_box.y2, priv->offscreen_box.y1,
-              0.0, 1.0);
-  st_theme_node_paint (priv->old_theme_node, &priv->old_paint_state, allocation, 255);
-  cogl_pop_framebuffer ();
-
-  cogl_push_framebuffer (priv->new_offscreen);
-  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
-  cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
-              priv->offscreen_box.y2, priv->offscreen_box.y1,
-              0.0, 1.0);
-  st_theme_node_paint (priv->new_theme_node, &priv->new_paint_state, allocation, 255);
-  cogl_pop_framebuffer ();
+  cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->new_texture);
+  cogl_pipeline_set_layer_texture (priv->pipeline, 1, priv->old_texture);
+
+  fb = COGL_FRAMEBUFFER (priv->old_offscreen);
+  cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
+  cogl_framebuffer_orthographic (fb,
+                                 priv->offscreen_box.x1, priv->offscreen_box.x2,
+                                 priv->offscreen_box.y2, priv->offscreen_box.y1,
+                                 0.0, 1.0);
+  st_theme_node_paint (priv->old_theme_node, &priv->old_paint_state, fb, allocation, 255);
+
+  fb = COGL_FRAMEBUFFER (priv->new_offscreen);
+  cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
+  cogl_framebuffer_orthographic (fb,
+                                 priv->offscreen_box.x1, priv->offscreen_box.x2,
+                                 priv->offscreen_box.y2, priv->offscreen_box.y1,
+                                 0.0, 1.0);
+  st_theme_node_paint (priv->new_theme_node, &priv->new_paint_state, fb, allocation, 255);
 
   return TRUE;
 }
 
 void
 st_theme_node_transition_paint (StThemeNodeTransition *transition,
+                                CoglFramebuffer       *fb,
                                 ClutterActorBox       *allocation,
                                 guint8                 paint_opacity)
 {
@@ -347,20 +343,20 @@ st_theme_node_transition_paint (StThemeNodeTransition *transition,
         return;
     }
 
-  cogl_color_set_from_4f (&constant, 0., 0., 0.,
-                          clutter_timeline_get_progress (priv->timeline));
-  cogl_material_set_layer_combine_constant (priv->material, 1, &constant);
+  cogl_color_init_from_4f (&constant, 0., 0., 0.,
+                           clutter_timeline_get_progress (priv->timeline));
+  cogl_pipeline_set_layer_combine_constant (priv->pipeline, 1, &constant);
 
-  cogl_material_set_color4ub (priv->material,
+  cogl_pipeline_set_color4ub (priv->pipeline,
                               paint_opacity, paint_opacity,
                               paint_opacity, paint_opacity);
 
-  cogl_set_source (priv->material);
-  cogl_rectangle_with_multitexture_coords (priv->offscreen_box.x1,
-                                           priv->offscreen_box.y1,
-                                           priv->offscreen_box.x2,
-                                           priv->offscreen_box.y2,
-                                           tex_coords, 8);
+  cogl_framebuffer_draw_multitextured_rectangle (fb, priv->pipeline,
+                                                 priv->offscreen_box.x1,
+                                                 priv->offscreen_box.y1,
+                                                 priv->offscreen_box.x2,
+                                                 priv->offscreen_box.y2,
+                                                 tex_coords, 8);
 }
 
 static void
@@ -368,47 +364,16 @@ st_theme_node_transition_dispose (GObject *object)
 {
   StThemeNodeTransitionPrivate *priv = ST_THEME_NODE_TRANSITION (object)->priv;
 
-  if (priv->old_theme_node)
-    {
-      g_object_unref (priv->old_theme_node);
-      priv->old_theme_node = NULL;
-    }
+  g_clear_object (&priv->old_theme_node);
+  g_clear_object (&priv->new_theme_node);
 
-  if (priv->new_theme_node)
-    {
-      g_object_unref (priv->new_theme_node);
-      priv->new_theme_node = NULL;
-    }
+  g_clear_pointer (&priv->old_texture, cogl_object_unref);
+  g_clear_pointer (&priv->new_texture, cogl_object_unref);
 
-  if (priv->old_texture)
-    {
-      cogl_handle_unref (priv->old_texture);
-      priv->old_texture = NULL;
-    }
+  g_clear_pointer (&priv->old_offscreen, cogl_object_unref);
+  g_clear_pointer (&priv->new_offscreen, cogl_object_unref);
 
-  if (priv->new_texture)
-    {
-      cogl_handle_unref (priv->new_texture);
-      priv->new_texture = NULL;
-    }
-
-  if (priv->old_offscreen)
-    {
-      cogl_handle_unref (priv->old_offscreen);
-      priv->old_offscreen = NULL;
-    }
-
-  if (priv->new_offscreen)
-    {
-      cogl_handle_unref (priv->new_offscreen);
-      priv->new_offscreen = NULL;
-    }
-
-  if (priv->material)
-    {
-      cogl_handle_unref (priv->material);
-      priv->material = NULL;
-    }
+  g_clear_pointer (&priv->pipeline, cogl_object_unref);
 
   if (priv->timeline)
     {
diff --git a/src/st/st-theme-node-transition.h b/src/st/st-theme-node-transition.h
index e78389e..2a50d8f 100644
--- a/src/st/st-theme-node-transition.h
+++ b/src/st/st-theme-node-transition.h
@@ -63,6 +63,7 @@ void  st_theme_node_transition_update   (StThemeNodeTransition *transition,
                                          StThemeNode           *new_node);
 
 void  st_theme_node_transition_paint    (StThemeNodeTransition *transition,
+                                         CoglFramebuffer       *fb,
                                          ClutterActorBox       *allocation,
                                          guint8                 paint_opacity);
 
diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c
index 22b3833..cdfe279 100644
--- a/src/st/st-theme-node.c
+++ b/src/st/st-theme-node.c
@@ -49,11 +49,6 @@ static void
 st_theme_node_init (StThemeNode *node)
 {
   node->transition_duration = -1;
-  node->background_texture = COGL_INVALID_HANDLE;
-  node->background_material = COGL_INVALID_HANDLE;
-  node->background_shadow_material = COGL_INVALID_HANDLE;
-  node->border_slices_texture = COGL_INVALID_HANDLE;
-  node->border_slices_material = COGL_INVALID_HANDLE;
 
   st_theme_node_paint_state_init (&node->cached_state);
 }
@@ -160,16 +155,11 @@ st_theme_node_finalize (GObject *object)
   if (node->background_image)
     g_free (node->background_image);
 
-  if (node->background_texture != COGL_INVALID_HANDLE)
-    cogl_handle_unref (node->background_texture);
-  if (node->background_material != COGL_INVALID_HANDLE)
-    cogl_handle_unref (node->background_material);
-  if (node->background_shadow_material != COGL_INVALID_HANDLE)
-    cogl_handle_unref (node->background_shadow_material);
-  if (node->border_slices_texture != COGL_INVALID_HANDLE)
-    cogl_handle_unref (node->border_slices_texture);
-  if (node->border_slices_material != COGL_INVALID_HANDLE)
-    cogl_handle_unref (node->border_slices_material);
+  g_clear_pointer (&node->background_texture, cogl_object_unref);
+  g_clear_pointer (&node->background_pipeline, cogl_object_unref);
+  g_clear_pointer (&node->background_shadow_pipeline, cogl_object_unref);
+  g_clear_pointer (&node->border_slices_texture, cogl_object_unref);
+  g_clear_pointer (&node->border_slices_pipeline, cogl_object_unref);
 
   G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
 }
diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h
index 5fffa63..8bf78c5 100644
--- a/src/st/st-theme-node.h
+++ b/src/st/st-theme-node.h
@@ -105,10 +105,10 @@ struct _StThemeNodePaintState {
   float box_shadow_width;
   float box_shadow_height;
 
-  CoglHandle box_shadow_material;
-  CoglHandle prerendered_texture;
-  CoglHandle prerendered_material;
-  CoglHandle corner_material[4];
+  CoglPipeline *box_shadow_pipeline;
+  CoglTexture *prerendered_texture;
+  CoglPipeline *prerendered_pipeline;
+  CoglPipeline *corner_pipeline[4];
 };
 
 GType st_theme_node_get_type (void) G_GNUC_CONST;
@@ -268,6 +268,7 @@ gboolean st_theme_node_paint_equal    (StThemeNode *node,
 
 void st_theme_node_paint (StThemeNode            *node,
                           StThemeNodePaintState  *state,
+                          CoglFramebuffer        *fb,
                           const ClutterActorBox  *box,
                           guint8                  paint_opacity);
 
diff --git a/src/st/st-widget.c b/src/st/st-widget.c
index 15f45f6..a522674 100644
--- a/src/st/st-widget.c
+++ b/src/st/st-widget.c
@@ -465,6 +465,7 @@ st_widget_paint_background (StWidget *widget)
   StThemeNode *theme_node;
   ClutterActorBox allocation;
   guint8 opacity;
+  CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
 
   theme_node = st_widget_get_theme_node (widget);
 
@@ -474,11 +475,13 @@ st_widget_paint_background (StWidget *widget)
 
   if (widget->priv->transition_animation)
     st_theme_node_transition_paint (widget->priv->transition_animation,
+                                    fb,
                                     &allocation,
                                     opacity);
   else
     st_theme_node_paint (theme_node,
                          current_paint_state (widget),
+                         fb,
                          &allocation,
                          opacity);
 }


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