diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index b5d91ae0f..be9fd1673 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -67,7 +67,6 @@ cogl_public_h = \
 	$(srcdir)/cogl-fixed.h 			\
 	$(srcdir)/cogl-depth-state.h 		\
 	$(srcdir)/cogl-material-compat.h 	\
-	$(srcdir)/cogl-pipeline.h 		\
 	$(srcdir)/cogl-vector.h 		\
 	$(srcdir)/cogl-euler.h 			\
 	$(srcdir)/cogl-quaternion.h 		\
@@ -99,6 +98,8 @@ cogl_experimental_h = \
 	$(srcdir)/cogl-onscreen-template.h 	\
 	$(srcdir)/cogl-display.h 		\
 	$(srcdir)/cogl-context.h 		\
+	$(srcdir)/cogl-pipeline.h 		\
+	$(srcdir)/cogl-pipeline-state.h 	\
 	$(srcdir)/cogl2-path.h 			\
 	$(srcdir)/cogl2-clip-state.h		\
 	$(srcdir)/cogl2-experimental.h		\
@@ -244,6 +245,8 @@ cogl_sources_c = \
 	$(srcdir)/cogl-depth-state-private.h		\
 	$(srcdir)/cogl-pipeline.c			\
 	$(srcdir)/cogl-pipeline-private.h		\
+	$(srcdir)/cogl-pipeline-state.c			\
+	$(srcdir)/cogl-pipeline-state-private.h		\
 	$(srcdir)/cogl-pipeline-opengl.c		\
 	$(srcdir)/cogl-pipeline-opengl-private.h	\
 	$(srcdir)/cogl-pipeline-fragend-glsl.c		\
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index 6e8fc359d..628ba355a 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -610,6 +610,21 @@ typedef struct
   CoglPipelineLayer *layer;
 } CoglPipelineLayerCacheEntry;
 
+/* Sometimes when evaluating pipelines, either during comparisons or
+ * if calculating a hash value we need to tweak the evaluation
+ * semantics */
+typedef enum _CoglPipelineEvalFlags
+{
+  COGL_PIPELINE_EVAL_FLAG_NONE = 0
+} CoglPipelineEvalFlags;
+
+typedef struct _CoglPipelineHashState
+{
+  unsigned long layer_differences;
+  CoglPipelineEvalFlags flags;
+  unsigned int hash;
+} CoglPipelineHashState;
+
 /*
  * CoglPipelineDestroyCallback
  * @pipeline: The #CoglPipeline that has been destroyed
@@ -842,6 +857,27 @@ _cogl_pipeline_get_authority (CoglPipeline *pipeline,
   return authority;
 }
 
+typedef gboolean (*CoglPipelineStateComparitor) (CoglPipeline *authority0,
+                                                 CoglPipeline *authority1);
+
+void
+_cogl_pipeline_update_authority (CoglPipeline *pipeline,
+                                 CoglPipeline *authority,
+                                 CoglPipelineState state,
+                                 CoglPipelineStateComparitor comparitor);
+
+void
+_cogl_pipeline_pre_change_notify (CoglPipeline     *pipeline,
+                                  CoglPipelineState change,
+                                  const CoglColor  *new_color,
+                                  gboolean          from_layer_change);
+
+void
+_cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline);
+
+void _cogl_pipeline_update_blend_enable (CoglPipeline *pipeline,
+                                         CoglPipelineState changes);
+
 /*
  * SECTION:cogl-pipeline-internals
  * @short_description: Functions for creating custom primitives that make use
@@ -1069,14 +1105,6 @@ unsigned long
 _cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
                                     CoglPipeline *pipeline1);
 
-/* Sometimes when evaluating pipelines, either during comparisons or
- * if calculating a hash value we need to tweak the evaluation
- * semantics */
-typedef enum _CoglPipelineEvalFlags
-{
-  COGL_PIPELINE_EVAL_FLAG_NONE = 0
-} CoglPipelineEvalFlags;
-
 gboolean
 _cogl_pipeline_equal (CoglPipeline *pipeline0,
                       CoglPipeline *pipeline1,
diff --git a/cogl/cogl-pipeline-state-private.h b/cogl/cogl-pipeline-state-private.h
new file mode 100644
index 000000000..b6c41588b
--- /dev/null
+++ b/cogl/cogl-pipeline-state-private.h
@@ -0,0 +1,126 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2008,2009,2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ *
+ * Authors:
+ *   Robert Bragg <robert@linux.intel.com>
+ */
+
+#ifndef __COGL_PIPELINE_STATE_PRIVATE_H
+#define __COGL_PIPELINE_STATE_PRIVATE_H
+
+CoglPipeline *
+_cogl_pipeline_get_user_program (CoglPipeline *pipeline);
+
+void
+_cogl_pipeline_set_fog_state (CoglPipeline *pipeline,
+                              const CoglPipelineFogState *fog_state);
+
+gboolean
+_cogl_pipeline_color_equal (CoglPipeline *authority0,
+                            CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_lighting_state_equal (CoglPipeline *authority0,
+                                     CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0,
+                                       CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_alpha_func_reference_state_equal (CoglPipeline *authority0,
+                                                 CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
+                                  CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_depth_state_equal (CoglPipeline *authority0,
+                                  CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_fog_state_equal (CoglPipeline *authority0,
+                                CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_point_size_equal (CoglPipeline *authority0,
+                                 CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0,
+                                      CoglPipeline *authority1);
+
+gboolean
+_cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
+                                  CoglPipeline *authority1);
+
+void
+_cogl_pipeline_hash_color_state (CoglPipeline *authority,
+                                 CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_blend_enable_state (CoglPipeline *authority,
+                                        CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_layers_state (CoglPipeline *authority,
+                                  CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_lighting_state (CoglPipeline *authority,
+                                    CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_alpha_func_state (CoglPipeline *authority,
+                                      CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_alpha_func_reference_state (CoglPipeline *authority,
+                                                CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_blend_state (CoglPipeline *authority,
+                                 CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_user_shader_state (CoglPipeline *authority,
+                                       CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_depth_state (CoglPipeline *authority,
+                                 CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_fog_state (CoglPipeline *authority,
+                               CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_point_size_state (CoglPipeline *authority,
+                                      CoglPipelineHashState *state);
+
+void
+_cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority,
+                                     CoglPipelineHashState *state);
+
+#endif /* __COGL_PIPELINE_STATE_PRIVATE_H */
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
new file mode 100644
index 000000000..9a1888c14
--- /dev/null
+++ b/cogl/cogl-pipeline-state.c
@@ -0,0 +1,1367 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2008,2009,2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ *
+ * Authors:
+ *   Robert Bragg <robert@linux.intel.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl-context-private.h"
+#include "cogl-color-private.h"
+#include "cogl-blend-string.h"
+#include "cogl-util.h"
+#include "cogl-depth-state-private.h"
+#include "cogl-pipeline-private.h"
+
+#include "string.h"
+
+#ifndef GL_FUNC_ADD
+#define GL_FUNC_ADD 0x8006
+#endif
+
+CoglPipeline *
+_cogl_pipeline_get_user_program (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER);
+
+  return authority->big_state->user_program;
+}
+
+gboolean
+_cogl_pipeline_color_equal (CoglPipeline *authority0,
+                            CoglPipeline *authority1)
+{
+  return cogl_color_equal (&authority0->color, &authority1->color);
+}
+
+gboolean
+_cogl_pipeline_lighting_state_equal (CoglPipeline *authority0,
+                                     CoglPipeline *authority1)
+{
+  CoglPipelineLightingState *state0 = &authority0->big_state->lighting_state;
+  CoglPipelineLightingState *state1 = &authority1->big_state->lighting_state;
+
+  if (memcmp (state0->ambient, state1->ambient, sizeof (float) * 4) != 0)
+    return FALSE;
+  if (memcmp (state0->diffuse, state1->diffuse, sizeof (float) * 4) != 0)
+    return FALSE;
+  if (memcmp (state0->specular, state1->specular, sizeof (float) * 4) != 0)
+    return FALSE;
+  if (memcmp (state0->emission, state1->emission, sizeof (float) * 4) != 0)
+    return FALSE;
+  if (state0->shininess != state1->shininess)
+    return FALSE;
+
+  return TRUE;
+}
+
+gboolean
+_cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0,
+                                       CoglPipeline *authority1)
+{
+  CoglPipelineAlphaFuncState *alpha_state0 =
+    &authority0->big_state->alpha_state;
+  CoglPipelineAlphaFuncState *alpha_state1 =
+    &authority1->big_state->alpha_state;
+
+  return alpha_state0->alpha_func == alpha_state1->alpha_func;
+}
+
+gboolean
+_cogl_pipeline_alpha_func_reference_state_equal (CoglPipeline *authority0,
+                                                 CoglPipeline *authority1)
+{
+  CoglPipelineAlphaFuncState *alpha_state0 =
+    &authority0->big_state->alpha_state;
+  CoglPipelineAlphaFuncState *alpha_state1 =
+    &authority1->big_state->alpha_state;
+
+  return (alpha_state0->alpha_func_reference ==
+          alpha_state1->alpha_func_reference);
+}
+
+gboolean
+_cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
+                                  CoglPipeline *authority1)
+{
+  CoglPipelineBlendState *blend_state0 = &authority0->big_state->blend_state;
+  CoglPipelineBlendState *blend_state1 = &authority1->big_state->blend_state;
+
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES1)
+    {
+      if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb)
+        return FALSE;
+      if (blend_state0->blend_equation_alpha !=
+          blend_state1->blend_equation_alpha)
+        return FALSE;
+      if (blend_state0->blend_src_factor_alpha !=
+          blend_state1->blend_src_factor_alpha)
+        return FALSE;
+      if (blend_state0->blend_dst_factor_alpha !=
+          blend_state1->blend_dst_factor_alpha)
+        return FALSE;
+    }
+#endif
+  if (blend_state0->blend_src_factor_rgb !=
+      blend_state1->blend_src_factor_rgb)
+    return FALSE;
+  if (blend_state0->blend_dst_factor_rgb !=
+      blend_state1->blend_dst_factor_rgb)
+    return FALSE;
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES1 &&
+      (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+       blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
+       blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+       blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR))
+    {
+      if (!cogl_color_equal (&blend_state0->blend_constant,
+                             &blend_state1->blend_constant))
+        return FALSE;
+    }
+#endif
+
+  return TRUE;
+}
+
+gboolean
+_cogl_pipeline_depth_state_equal (CoglPipeline *authority0,
+                                  CoglPipeline *authority1)
+{
+  if (authority0->big_state->depth_state.test_enabled == FALSE &&
+      authority1->big_state->depth_state.test_enabled == FALSE)
+    return TRUE;
+  else
+    {
+      CoglDepthState *s0 = &authority0->big_state->depth_state;
+      CoglDepthState *s1 = &authority1->big_state->depth_state;
+      return s0->test_enabled == s1->test_enabled &&
+             s0->test_function == s1->test_function &&
+             s0->write_enabled == s1->write_enabled &&
+             s0->range_near == s1->range_near &&
+             s0->range_far == s1->range_far;
+    }
+}
+
+gboolean
+_cogl_pipeline_fog_state_equal (CoglPipeline *authority0,
+                                CoglPipeline *authority1)
+{
+  CoglPipelineFogState *fog_state0 = &authority0->big_state->fog_state;
+  CoglPipelineFogState *fog_state1 = &authority1->big_state->fog_state;
+
+  if (fog_state0->enabled == fog_state1->enabled &&
+      cogl_color_equal (&fog_state0->color, &fog_state1->color) &&
+      fog_state0->mode == fog_state1->mode &&
+      fog_state0->density == fog_state1->density &&
+      fog_state0->z_near == fog_state1->z_near &&
+      fog_state0->z_far == fog_state1->z_far)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+gboolean
+_cogl_pipeline_point_size_equal (CoglPipeline *authority0,
+                                 CoglPipeline *authority1)
+{
+  return authority0->big_state->point_size == authority1->big_state->point_size;
+}
+
+gboolean
+_cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0,
+                                      CoglPipeline *authority1)
+{
+  CoglPipelineLogicOpsState *logic_ops_state0 = &authority0->big_state->logic_ops_state;
+  CoglPipelineLogicOpsState *logic_ops_state1 = &authority1->big_state->logic_ops_state;
+
+  return logic_ops_state0->color_mask == logic_ops_state1->color_mask;
+}
+
+gboolean
+_cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
+                                  CoglPipeline *authority1)
+{
+  return (authority0->big_state->user_program ==
+          authority1->big_state->user_program);
+}
+
+void
+cogl_pipeline_get_color (CoglPipeline *pipeline,
+                         CoglColor    *color)
+{
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
+
+  *color = authority->color;
+}
+
+/* This is used heavily by the cogl journal when logging quads */
+void
+_cogl_pipeline_get_colorubv (CoglPipeline *pipeline,
+                             guint8       *color)
+{
+  CoglPipeline *authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
+
+  _cogl_color_get_rgba_4ubv (&authority->color, color);
+}
+
+void
+cogl_pipeline_set_color (CoglPipeline    *pipeline,
+			 const CoglColor *color)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_COLOR;
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  if (cogl_color_equal (color, &authority->color))
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, color, FALSE);
+
+  pipeline->color = *color;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_color_equal);
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+}
+
+void
+cogl_pipeline_set_color4ub (CoglPipeline *pipeline,
+			    guint8 red,
+                            guint8 green,
+                            guint8 blue,
+                            guint8 alpha)
+{
+  CoglColor color;
+  cogl_color_init_from_4ub (&color, red, green, blue, alpha);
+  cogl_pipeline_set_color (pipeline, &color);
+}
+
+void
+cogl_pipeline_set_color4f (CoglPipeline *pipeline,
+			   float red,
+                           float green,
+                           float blue,
+                           float alpha)
+{
+  CoglColor color;
+  cogl_color_init_from_4f (&color, red, green, blue, alpha);
+  cogl_pipeline_set_color (pipeline, &color);
+}
+
+CoglPipelineBlendEnable
+_cogl_pipeline_get_blend_enabled (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND_ENABLE);
+  return authority->blend_enable;
+}
+
+gboolean
+_cogl_pipeline_blend_enable_equal (CoglPipeline *authority0,
+                                   CoglPipeline *authority1)
+{
+  return authority0->blend_enable == authority1->blend_enable ? TRUE : FALSE;
+}
+
+void
+_cogl_pipeline_set_blend_enabled (CoglPipeline *pipeline,
+                                  CoglPipelineBlendEnable enable)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_BLEND_ENABLE;
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+  g_return_if_fail (enable > 1 &&
+                    "don't pass TRUE or FALSE to _set_blend_enabled!");
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  if (authority->blend_enable == enable)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  pipeline->blend_enable = enable;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_blend_enable_equal);
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+}
+
+void
+cogl_pipeline_get_ambient (CoglPipeline *pipeline,
+                           CoglColor    *ambient)
+{
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
+
+  cogl_color_init_from_4fv (ambient,
+                            authority->big_state->lighting_state.ambient);
+}
+
+void
+cogl_pipeline_set_ambient (CoglPipeline *pipeline,
+			   const CoglColor *ambient)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
+  CoglPipeline *authority;
+  CoglPipelineLightingState *lighting_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  lighting_state = &authority->big_state->lighting_state;
+  if (cogl_color_equal (ambient, &lighting_state->ambient))
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  lighting_state = &pipeline->big_state->lighting_state;
+  lighting_state->ambient[0] = cogl_color_get_red_float (ambient);
+  lighting_state->ambient[1] = cogl_color_get_green_float (ambient);
+  lighting_state->ambient[2] = cogl_color_get_blue_float (ambient);
+  lighting_state->ambient[3] = cogl_color_get_alpha_float (ambient);
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_lighting_state_equal);
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+}
+
+void
+cogl_pipeline_get_diffuse (CoglPipeline *pipeline,
+                           CoglColor    *diffuse)
+{
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
+
+  cogl_color_init_from_4fv (diffuse,
+                            authority->big_state->lighting_state.diffuse);
+}
+
+void
+cogl_pipeline_set_diffuse (CoglPipeline *pipeline,
+			   const CoglColor *diffuse)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
+  CoglPipeline *authority;
+  CoglPipelineLightingState *lighting_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  lighting_state = &authority->big_state->lighting_state;
+  if (cogl_color_equal (diffuse, &lighting_state->diffuse))
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  lighting_state = &pipeline->big_state->lighting_state;
+  lighting_state->diffuse[0] = cogl_color_get_red_float (diffuse);
+  lighting_state->diffuse[1] = cogl_color_get_green_float (diffuse);
+  lighting_state->diffuse[2] = cogl_color_get_blue_float (diffuse);
+  lighting_state->diffuse[3] = cogl_color_get_alpha_float (diffuse);
+
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_lighting_state_equal);
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+}
+
+void
+cogl_pipeline_set_ambient_and_diffuse (CoglPipeline *pipeline,
+				       const CoglColor *color)
+{
+  cogl_pipeline_set_ambient (pipeline, color);
+  cogl_pipeline_set_diffuse (pipeline, color);
+}
+
+void
+cogl_pipeline_get_specular (CoglPipeline *pipeline,
+                            CoglColor    *specular)
+{
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
+
+  cogl_color_init_from_4fv (specular,
+                            authority->big_state->lighting_state.specular);
+}
+
+void
+cogl_pipeline_set_specular (CoglPipeline *pipeline, const CoglColor *specular)
+{
+  CoglPipeline *authority;
+  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
+  CoglPipelineLightingState *lighting_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  lighting_state = &authority->big_state->lighting_state;
+  if (cogl_color_equal (specular, &lighting_state->specular))
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  lighting_state = &pipeline->big_state->lighting_state;
+  lighting_state->specular[0] = cogl_color_get_red_float (specular);
+  lighting_state->specular[1] = cogl_color_get_green_float (specular);
+  lighting_state->specular[2] = cogl_color_get_blue_float (specular);
+  lighting_state->specular[3] = cogl_color_get_alpha_float (specular);
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_lighting_state_equal);
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+}
+
+float
+cogl_pipeline_get_shininess (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
+
+  return authority->big_state->lighting_state.shininess;
+}
+
+void
+cogl_pipeline_set_shininess (CoglPipeline *pipeline,
+			     float shininess)
+{
+  CoglPipeline *authority;
+  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
+  CoglPipelineLightingState *lighting_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  if (shininess < 0.0)
+    {
+      g_warning ("Out of range shininess %f supplied for pipeline\n",
+                 shininess);
+      return;
+    }
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  lighting_state = &authority->big_state->lighting_state;
+
+  if (lighting_state->shininess == shininess)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  lighting_state = &pipeline->big_state->lighting_state;
+  lighting_state->shininess = shininess;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_lighting_state_equal);
+}
+
+void
+cogl_pipeline_get_emission (CoglPipeline *pipeline,
+                            CoglColor    *emission)
+{
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
+
+  cogl_color_init_from_4fv (emission,
+                            authority->big_state->lighting_state.emission);
+}
+
+void
+cogl_pipeline_set_emission (CoglPipeline *pipeline, const CoglColor *emission)
+{
+  CoglPipeline *authority;
+  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
+  CoglPipelineLightingState *lighting_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  lighting_state = &authority->big_state->lighting_state;
+  if (cogl_color_equal (emission, &lighting_state->emission))
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  lighting_state = &pipeline->big_state->lighting_state;
+  lighting_state->emission[0] = cogl_color_get_red_float (emission);
+  lighting_state->emission[1] = cogl_color_get_green_float (emission);
+  lighting_state->emission[2] = cogl_color_get_blue_float (emission);
+  lighting_state->emission[3] = cogl_color_get_alpha_float (emission);
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_lighting_state_equal);
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+}
+
+static void
+_cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
+                                        CoglPipelineAlphaFunc alpha_func)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC;
+  CoglPipeline *authority;
+  CoglPipelineAlphaFuncState *alpha_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  alpha_state = &authority->big_state->alpha_state;
+  if (alpha_state->alpha_func == alpha_func)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  alpha_state = &pipeline->big_state->alpha_state;
+  alpha_state->alpha_func = alpha_func;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_alpha_func_state_equal);
+}
+
+static void
+_cogl_pipeline_set_alpha_test_function_reference (CoglPipeline *pipeline,
+                                                  float alpha_reference)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE;
+  CoglPipeline *authority;
+  CoglPipelineAlphaFuncState *alpha_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  alpha_state = &authority->big_state->alpha_state;
+  if (alpha_state->alpha_func_reference == alpha_reference)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  alpha_state = &pipeline->big_state->alpha_state;
+  alpha_state->alpha_func_reference = alpha_reference;
+
+  _cogl_pipeline_update_authority
+    (pipeline, authority, state,
+     _cogl_pipeline_alpha_func_reference_state_equal);
+}
+
+void
+cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
+				       CoglPipelineAlphaFunc alpha_func,
+				       float alpha_reference)
+{
+  _cogl_pipeline_set_alpha_test_function (pipeline, alpha_func);
+  _cogl_pipeline_set_alpha_test_function_reference (pipeline, alpha_reference);
+}
+
+CoglPipelineAlphaFunc
+cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC);
+
+  return authority->big_state->alpha_state.alpha_func;
+}
+
+float
+cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0.0f);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline,
+                                  COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE);
+
+  return authority->big_state->alpha_state.alpha_func_reference;
+}
+
+GLenum
+arg_to_gl_blend_factor (CoglBlendStringArgument *arg)
+{
+  if (arg->source.is_zero)
+    return GL_ZERO;
+  if (arg->factor.is_one)
+    return GL_ONE;
+  else if (arg->factor.is_src_alpha_saturate)
+    return GL_SRC_ALPHA_SATURATE;
+  else if (arg->factor.source.info->type ==
+           COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR)
+    {
+      if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
+        {
+          if (arg->factor.source.one_minus)
+            return GL_ONE_MINUS_SRC_COLOR;
+          else
+            return GL_SRC_COLOR;
+        }
+      else
+        {
+          if (arg->factor.source.one_minus)
+            return GL_ONE_MINUS_SRC_ALPHA;
+          else
+            return GL_SRC_ALPHA;
+        }
+    }
+  else if (arg->factor.source.info->type ==
+           COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR)
+    {
+      if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
+        {
+          if (arg->factor.source.one_minus)
+            return GL_ONE_MINUS_DST_COLOR;
+          else
+            return GL_DST_COLOR;
+        }
+      else
+        {
+          if (arg->factor.source.one_minus)
+            return GL_ONE_MINUS_DST_ALPHA;
+          else
+            return GL_DST_ALPHA;
+        }
+    }
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  else if (arg->factor.source.info->type ==
+           COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
+    {
+      if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
+        {
+          if (arg->factor.source.one_minus)
+            return GL_ONE_MINUS_CONSTANT_COLOR;
+          else
+            return GL_CONSTANT_COLOR;
+        }
+      else
+        {
+          if (arg->factor.source.one_minus)
+            return GL_ONE_MINUS_CONSTANT_ALPHA;
+          else
+            return GL_CONSTANT_ALPHA;
+        }
+    }
+#endif
+
+  g_warning ("Unable to determine valid blend factor from blend string\n");
+  return GL_ONE;
+}
+
+void
+setup_blend_state (CoglBlendStringStatement *statement,
+                   GLenum *blend_equation,
+                   GLint *blend_src_factor,
+                   GLint *blend_dst_factor)
+{
+  switch (statement->function->type)
+    {
+    case COGL_BLEND_STRING_FUNCTION_ADD:
+      *blend_equation = GL_FUNC_ADD;
+      break;
+    /* TODO - add more */
+    default:
+      g_warning ("Unsupported blend function given");
+      *blend_equation = GL_FUNC_ADD;
+    }
+
+  *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]);
+  *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]);
+}
+
+gboolean
+cogl_pipeline_set_blend (CoglPipeline *pipeline,
+                         const char *blend_description,
+                         GError **error)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
+  CoglPipeline *authority;
+  CoglBlendStringStatement statements[2];
+  CoglBlendStringStatement *rgb;
+  CoglBlendStringStatement *a;
+  GError *internal_error = NULL;
+  int count;
+  CoglPipelineBlendState *blend_state;
+
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
+
+  count =
+    _cogl_blend_string_compile (blend_description,
+                                COGL_BLEND_STRING_CONTEXT_BLENDING,
+                                statements,
+                                &internal_error);
+  if (!count)
+    {
+      if (error)
+	g_propagate_error (error, internal_error);
+      else
+	{
+	  g_warning ("Cannot compile blend description: %s\n",
+		     internal_error->message);
+	  g_error_free (internal_error);
+	}
+      return FALSE;
+    }
+
+  if (count == 1)
+    rgb = a = statements;
+  else
+    {
+      rgb = &statements[0];
+      a = &statements[1];
+    }
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, state);
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  blend_state = &pipeline->big_state->blend_state;
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
+  if (ctx->driver != COGL_DRIVER_GLES1)
+    {
+      setup_blend_state (rgb,
+                         &blend_state->blend_equation_rgb,
+                         &blend_state->blend_src_factor_rgb,
+                         &blend_state->blend_dst_factor_rgb);
+      setup_blend_state (a,
+                         &blend_state->blend_equation_alpha,
+                         &blend_state->blend_src_factor_alpha,
+                         &blend_state->blend_dst_factor_alpha);
+    }
+  else
+#endif
+    {
+      setup_blend_state (rgb,
+                         NULL,
+                         &blend_state->blend_src_factor_rgb,
+                         &blend_state->blend_dst_factor_rgb);
+    }
+
+  /* If we are the current authority see if we can revert to one of our
+   * ancestors being the authority */
+  if (pipeline == authority &&
+      _cogl_pipeline_get_parent (authority) != NULL)
+    {
+      CoglPipeline *parent = _cogl_pipeline_get_parent (authority);
+      CoglPipeline *old_authority =
+        _cogl_pipeline_get_authority (parent, state);
+
+      if (_cogl_pipeline_blend_state_equal (authority, old_authority))
+        pipeline->differences &= ~state;
+    }
+
+  /* If we weren't previously the authority on this state then we need
+   * to extended our differences mask and so it's possible that some
+   * of our ancestry will now become redundant, so we aim to reparent
+   * ourselves if that's true... */
+  if (pipeline != authority)
+    {
+      pipeline->differences |= state;
+      _cogl_pipeline_prune_redundant_ancestry (pipeline);
+    }
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+
+  return TRUE;
+}
+
+void
+cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
+                                  const CoglColor *constant_color)
+{
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  if (ctx->driver == COGL_DRIVER_GLES1)
+    return;
+
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  {
+    CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
+    CoglPipeline *authority;
+    CoglPipelineBlendState *blend_state;
+
+    authority = _cogl_pipeline_get_authority (pipeline, state);
+
+    blend_state = &authority->big_state->blend_state;
+    if (cogl_color_equal (constant_color, &blend_state->blend_constant))
+      return;
+
+    /* - Flush journal primitives referencing the current state.
+     * - Make sure the pipeline has no dependants so it may be modified.
+     * - If the pipeline isn't currently an authority for the state being
+     *   changed, then initialize that state from the current authority.
+     */
+    _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+    blend_state = &pipeline->big_state->blend_state;
+    blend_state->blend_constant = *constant_color;
+
+    _cogl_pipeline_update_authority (pipeline, authority, state,
+                                     _cogl_pipeline_blend_state_equal);
+
+    _cogl_pipeline_update_blend_enable (pipeline, state);
+  }
+#endif
+}
+
+CoglHandle
+cogl_pipeline_get_user_program (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), COGL_INVALID_HANDLE);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER);
+
+  return authority->big_state->user_program;
+}
+
+/* XXX: for now we don't mind if the program has vertex shaders
+ * attached but if we ever make a similar API public we should only
+ * allow attaching of programs containing fragment shaders. Eventually
+ * we will have a CoglPipeline abstraction to also cover vertex
+ * processing.
+ */
+void
+cogl_pipeline_set_user_program (CoglPipeline *pipeline,
+                                CoglHandle program)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_USER_SHADER;
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  if (authority->big_state->user_program == program)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  if (program != COGL_INVALID_HANDLE)
+    {
+      _cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_DEFAULT);
+      _cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_DEFAULT);
+    }
+
+  /* If we are the current authority see if we can revert to one of our
+   * ancestors being the authority */
+  if (pipeline == authority &&
+      _cogl_pipeline_get_parent (authority) != NULL)
+    {
+      CoglPipeline *parent = _cogl_pipeline_get_parent (authority);
+      CoglPipeline *old_authority =
+        _cogl_pipeline_get_authority (parent, state);
+
+      if (old_authority->big_state->user_program == program)
+        pipeline->differences &= ~state;
+    }
+  else if (pipeline != authority)
+    {
+      /* If we weren't previously the authority on this state then we
+       * need to extended our differences mask and so it's possible
+       * that some of our ancestry will now become redundant, so we
+       * aim to reparent ourselves if that's true... */
+      pipeline->differences |= state;
+      _cogl_pipeline_prune_redundant_ancestry (pipeline);
+    }
+
+  if (program != COGL_INVALID_HANDLE)
+    cogl_handle_ref (program);
+  if (authority == pipeline &&
+      pipeline->big_state->user_program != COGL_INVALID_HANDLE)
+    cogl_handle_unref (pipeline->big_state->user_program);
+  pipeline->big_state->user_program = program;
+
+  _cogl_pipeline_update_blend_enable (pipeline, state);
+}
+
+gboolean
+cogl_pipeline_set_depth_state (CoglPipeline *pipeline,
+                               const CoglDepthState *depth_state,
+                               GError **error)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_DEPTH;
+  CoglPipeline *authority;
+  CoglDepthState *orig_state;
+
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
+  g_return_val_if_fail (depth_state->magic == COGL_DEPTH_STATE_MAGIC, FALSE);
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  orig_state = &authority->big_state->depth_state;
+  if (orig_state->test_enabled == depth_state->test_enabled &&
+      orig_state->write_enabled == depth_state->write_enabled &&
+      orig_state->test_function == depth_state->test_function &&
+      orig_state->range_near == depth_state->range_near &&
+      orig_state->range_far == depth_state->range_far)
+    return TRUE;
+
+  if (ctx->driver == COGL_DRIVER_GLES1 &&
+      (depth_state->range_near != 0 ||
+       depth_state->range_far != 1))
+    {
+      g_set_error (error,
+                   COGL_ERROR,
+                   COGL_ERROR_UNSUPPORTED,
+                   "glDepthRange not available on GLES 1");
+      return FALSE;
+    }
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  pipeline->big_state->depth_state = *depth_state;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_depth_state_equal);
+
+  return TRUE;
+}
+
+void
+cogl_pipeline_get_depth_state (CoglPipeline *pipeline,
+                               CoglDepthState *state)
+{
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
+  *state = authority->big_state->depth_state;
+}
+
+CoglColorMask
+cogl_pipeline_get_color_mask (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LOGIC_OPS);
+
+  return authority->big_state->logic_ops_state.color_mask;
+}
+
+void
+cogl_pipeline_set_color_mask (CoglPipeline *pipeline,
+                              CoglColorMask color_mask)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_LOGIC_OPS;
+  CoglPipeline *authority;
+  CoglPipelineLogicOpsState *logic_ops_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  logic_ops_state = &authority->big_state->logic_ops_state;
+  if (logic_ops_state->color_mask == color_mask)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  logic_ops_state = &pipeline->big_state->logic_ops_state;
+  logic_ops_state->color_mask = color_mask;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_logic_ops_state_equal);
+}
+
+void
+_cogl_pipeline_set_fog_state (CoglPipeline *pipeline,
+                              const CoglPipelineFogState *fog_state)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_FOG;
+  CoglPipeline *authority;
+  CoglPipelineFogState *current_fog_state;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  current_fog_state = &authority->big_state->fog_state;
+
+  if (current_fog_state->enabled == fog_state->enabled &&
+      cogl_color_equal (&current_fog_state->color, &fog_state->color) &&
+      current_fog_state->mode == fog_state->mode &&
+      current_fog_state->density == fog_state->density &&
+      current_fog_state->z_near == fog_state->z_near &&
+      current_fog_state->z_far == fog_state->z_far)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  pipeline->big_state->fog_state = *fog_state;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_fog_state_equal);
+}
+
+float
+cogl_pipeline_get_point_size (CoglPipeline *pipeline)
+{
+  CoglPipeline *authority;
+
+  g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
+
+  authority =
+    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);
+
+  return authority->big_state->point_size;
+}
+
+void
+cogl_pipeline_set_point_size (CoglPipeline *pipeline,
+                              float point_size)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_POINT_SIZE;
+  CoglPipeline *authority;
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  if (authority->big_state->point_size == point_size)
+    return;
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  pipeline->big_state->point_size = point_size;
+
+  _cogl_pipeline_update_authority (pipeline, authority, state,
+                                   _cogl_pipeline_point_size_equal);
+}
+
+void
+_cogl_pipeline_hash_color_state (CoglPipeline *authority,
+                                 CoglPipelineHashState *state)
+{
+  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &authority->color,
+                                               _COGL_COLOR_DATA_SIZE);
+}
+
+void
+_cogl_pipeline_hash_blend_enable_state (CoglPipeline *authority,
+                                        CoglPipelineHashState *state)
+{
+  guint8 blend_enable = authority->blend_enable;
+  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &blend_enable, 1);
+}
+
+void
+_cogl_pipeline_hash_lighting_state (CoglPipeline *authority,
+                                    CoglPipelineHashState *state)
+{
+  CoglPipelineLightingState *lighting_state =
+    &authority->big_state->lighting_state;
+  state->hash =
+    _cogl_util_one_at_a_time_hash (state->hash, lighting_state,
+                                   sizeof (CoglPipelineLightingState));
+}
+
+void
+_cogl_pipeline_hash_alpha_func_state (CoglPipeline *authority,
+                                      CoglPipelineHashState *state)
+{
+  CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state;
+  state->hash =
+    _cogl_util_one_at_a_time_hash (state->hash, &alpha_state->alpha_func,
+                                   sizeof (alpha_state->alpha_func));
+}
+
+void
+_cogl_pipeline_hash_alpha_func_reference_state (CoglPipeline *authority,
+                                                CoglPipelineHashState *state)
+{
+  CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state;
+  float ref = alpha_state->alpha_func_reference;
+  state->hash =
+    _cogl_util_one_at_a_time_hash (state->hash, &ref, sizeof (float));
+}
+
+void
+_cogl_pipeline_hash_blend_state (CoglPipeline *authority,
+                                 CoglPipelineHashState *state)
+{
+  CoglPipelineBlendState *blend_state = &authority->big_state->blend_state;
+  unsigned int hash;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  if (!authority->real_blend_enable)
+    return;
+
+  hash = state->hash;
+
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES1)
+    {
+      hash =
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb,
+                                       sizeof (blend_state->blend_equation_rgb));
+      hash =
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha,
+                                       sizeof (blend_state->blend_equation_alpha));
+      hash =
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha,
+                                       sizeof (blend_state->blend_src_factor_alpha));
+      hash =
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha,
+                                       sizeof (blend_state->blend_dst_factor_alpha));
+
+      if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+          blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
+          blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+          blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
+        {
+          hash =
+            _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant,
+                                           sizeof (blend_state->blend_constant));
+        }
+    }
+#endif
+
+  hash =
+    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_rgb,
+                                   sizeof (blend_state->blend_src_factor_rgb));
+  hash =
+    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_rgb,
+                                   sizeof (blend_state->blend_dst_factor_rgb));
+
+  state->hash = hash;
+}
+
+void
+_cogl_pipeline_hash_user_shader_state (CoglPipeline *authority,
+                                       CoglPipelineHashState *state)
+{
+  CoglHandle user_program = authority->big_state->user_program;
+  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &user_program,
+                                               sizeof (user_program));
+}
+
+void
+_cogl_pipeline_hash_depth_state (CoglPipeline *authority,
+                                 CoglPipelineHashState *state)
+{
+  CoglDepthState *depth_state = &authority->big_state->depth_state;
+  unsigned int hash = state->hash;
+
+  if (depth_state->test_enabled)
+    {
+      guint8 enabled = depth_state->test_enabled;
+      CoglDepthTestFunction function = depth_state->test_function;
+      hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled));
+      hash = _cogl_util_one_at_a_time_hash (hash, &function, sizeof (function));
+    }
+
+  if (depth_state->write_enabled)
+    {
+      guint8 enabled = depth_state->write_enabled;
+      float near_val = depth_state->range_near;
+      float far_val = depth_state->range_far;
+      hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled));
+      hash = _cogl_util_one_at_a_time_hash (hash, &near_val, sizeof (near_val));
+      hash = _cogl_util_one_at_a_time_hash (hash, &far_val, sizeof (far_val));
+    }
+
+  state->hash = hash;
+}
+
+void
+_cogl_pipeline_hash_fog_state (CoglPipeline *authority,
+                               CoglPipelineHashState *state)
+{
+  CoglPipelineFogState *fog_state = &authority->big_state->fog_state;
+  unsigned long hash = state->hash;
+
+  if (!fog_state->enabled)
+    hash = _cogl_util_one_at_a_time_hash (hash, &fog_state->enabled,
+                                          sizeof (fog_state->enabled));
+  else
+    hash = _cogl_util_one_at_a_time_hash (hash, &fog_state,
+                                          sizeof (CoglPipelineFogState));
+
+  state->hash = hash;
+}
+
+void
+_cogl_pipeline_hash_point_size_state (CoglPipeline *authority,
+                                      CoglPipelineHashState *state)
+{
+  float point_size = authority->big_state->point_size;
+  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &point_size,
+                                               sizeof (point_size));
+}
+
+void
+_cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority,
+                                     CoglPipelineHashState *state)
+{
+  CoglPipelineLogicOpsState *logic_ops_state = &authority->big_state->logic_ops_state;
+  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &logic_ops_state->color_mask,
+                                               sizeof (CoglColorMask));
+}
diff --git a/cogl/cogl-pipeline-state.h b/cogl/cogl-pipeline-state.h
new file mode 100644
index 000000000..7015b00c0
--- /dev/null
+++ b/cogl/cogl-pipeline-state.h
@@ -0,0 +1,693 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009,2011 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <cogl/cogl.h> can be included directly."
+#endif
+
+#ifndef __COGL_PIPELINE_STATE_H__
+#define __COGL_PIPELINE_STATE_H__
+
+#include <cogl/cogl-pipeline.h>
+#include <cogl/cogl-color.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#ifdef COGL_ENABLE_EXPERIMENTAL_API
+
+#define cogl_pipeline_set_color cogl_pipeline_set_color_EXP
+/**
+ * cogl_pipeline_set_color:
+ * @pipeline: A #CoglPipeline object
+ * @color: The components of the color
+ *
+ * Sets the basic color of the pipeline, used when no lighting is enabled.
+ *
+ * Note that if you don't add any layers to the pipeline then the color
+ * will be blended unmodified with the destination; the default blend
+ * expects premultiplied colors: for example, use (0.5, 0.0, 0.0, 0.5) for
+ * semi-transparent red. See cogl_color_premultiply().
+ *
+ * The default value is (1.0, 1.0, 1.0, 1.0)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_color (CoglPipeline    *pipeline,
+                         const CoglColor *color);
+
+#define cogl_pipeline_set_color4ub cogl_pipeline_set_color4ub_EXP
+/**
+ * cogl_pipeline_set_color4ub:
+ * @pipeline: A #CoglPipeline object
+ * @red: The red component
+ * @green: The green component
+ * @blue: The blue component
+ * @alpha: The alpha component
+ *
+ * Sets the basic color of the pipeline, used when no lighting is enabled.
+ *
+ * The default value is (0xff, 0xff, 0xff, 0xff)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_color4ub (CoglPipeline *pipeline,
+			    guint8        red,
+                            guint8        green,
+                            guint8        blue,
+                            guint8        alpha);
+
+#define cogl_pipeline_set_color4f cogl_pipeline_set_color4f_EXP
+/**
+ * cogl_pipeline_set_color4f:
+ * @pipeline: A #CoglPipeline object
+ * @red: The red component
+ * @green: The green component
+ * @blue: The blue component
+ * @alpha: The alpha component
+ *
+ * Sets the basic color of the pipeline, used when no lighting is enabled.
+ *
+ * The default value is (1.0, 1.0, 1.0, 1.0)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_color4f (CoglPipeline *pipeline,
+                           float         red,
+                           float         green,
+                           float         blue,
+                           float         alpha);
+
+#define cogl_pipeline_get_color cogl_pipeline_get_color_EXP
+/**
+ * cogl_pipeline_get_color:
+ * @pipeline: A #CoglPipeline object
+ * @color: (out): The location to store the color
+ *
+ * Retrieves the current pipeline color.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_get_color (CoglPipeline *pipeline,
+                         CoglColor    *color);
+
+#define cogl_pipeline_set_ambient cogl_pipeline_set_ambient_EXP
+/**
+ * cogl_pipeline_set_ambient:
+ * @pipeline: A #CoglPipeline object
+ * @ambient: The components of the desired ambient color
+ *
+ * Sets the pipeline's ambient color, in the standard OpenGL lighting
+ * model. The ambient color affects the overall color of the object.
+ *
+ * Since the diffuse color will be intense when the light hits the surface
+ * directly, the ambient will be most apparent where the light hits at a
+ * slant.
+ *
+ * The default value is (0.2, 0.2, 0.2, 1.0)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_ambient (CoglPipeline    *pipeline,
+			   const CoglColor *ambient);
+
+#define cogl_pipeline_get_ambient cogl_pipeline_get_ambient_EXP
+/**
+ * cogl_pipeline_get_ambient:
+ * @pipeline: A #CoglPipeline object
+ * @ambient: The location to store the ambient color
+ *
+ * Retrieves the current ambient color for @pipeline
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_get_ambient (CoglPipeline *pipeline,
+                           CoglColor    *ambient);
+
+#define cogl_pipeline_set_diffuse cogl_pipeline_set_diffuse_EXP
+/**
+ * cogl_pipeline_set_diffuse:
+ * @pipeline: A #CoglPipeline object
+ * @diffuse: The components of the desired diffuse color
+ *
+ * Sets the pipeline's diffuse color, in the standard OpenGL lighting
+ * model. The diffuse color is most intense where the light hits the
+ * surface directly - perpendicular to the surface.
+ *
+ * The default value is (0.8, 0.8, 0.8, 1.0)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_diffuse (CoglPipeline    *pipeline,
+			   const CoglColor *diffuse);
+
+#define cogl_pipeline_get_diffuse cogl_pipeline_get_diffuse_EXP
+/**
+ * cogl_pipeline_get_diffuse:
+ * @pipeline: A #CoglPipeline object
+ * @diffuse: The location to store the diffuse color
+ *
+ * Retrieves the current diffuse color for @pipeline
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_get_diffuse (CoglPipeline *pipeline,
+                           CoglColor    *diffuse);
+
+#define cogl_pipeline_set_ambient_and_diffuse \
+  cogl_pipeline_set_ambient_and_diffuse_EXP
+/**
+ * cogl_pipeline_set_ambient_and_diffuse:
+ * @pipeline: A #CoglPipeline object
+ * @color: The components of the desired ambient and diffuse colors
+ *
+ * Conveniently sets the diffuse and ambient color of @pipeline at the same
+ * time. See cogl_pipeline_set_ambient() and cogl_pipeline_set_diffuse().
+ *
+ * The default ambient color is (0.2, 0.2, 0.2, 1.0)
+ *
+ * The default diffuse color is (0.8, 0.8, 0.8, 1.0)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_ambient_and_diffuse (CoglPipeline    *pipeline,
+				       const CoglColor *color);
+
+#define cogl_pipeline_set_specular cogl_pipeline_set_specular_EXP
+/**
+ * cogl_pipeline_set_specular:
+ * @pipeline: A #CoglPipeline object
+ * @specular: The components of the desired specular color
+ *
+ * Sets the pipeline's specular color, in the standard OpenGL lighting
+ * model. The intensity of the specular color depends on the viewport
+ * position, and is brightest along the lines of reflection.
+ *
+ * The default value is (0.0, 0.0, 0.0, 1.0)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_specular (CoglPipeline    *pipeline,
+			    const CoglColor *specular);
+
+#define cogl_pipeline_get_specular cogl_pipeline_get_specular_EXP
+/**
+ * cogl_pipeline_get_specular:
+ * @pipeline: A #CoglPipeline object
+ * @specular: The location to store the specular color
+ *
+ * Retrieves the pipelines current specular color.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_get_specular (CoglPipeline *pipeline,
+                            CoglColor    *specular);
+
+#define cogl_pipeline_set_shininess cogl_pipeline_set_shininess_EXP
+/**
+ * cogl_pipeline_set_shininess:
+ * @pipeline: A #CoglPipeline object
+ * @shininess: The desired shininess; must be >= 0.0
+ *
+ * Sets the shininess of the pipeline, in the standard OpenGL lighting
+ * model, which determines the size of the specular highlights. A
+ * higher @shininess will produce smaller highlights which makes the
+ * object appear more shiny.
+ *
+ * The default value is 0.0
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_shininess (CoglPipeline *pipeline,
+			     float         shininess);
+
+#define cogl_pipeline_get_shininess cogl_pipeline_get_shininess_EXP
+/**
+ * cogl_pipeline_get_shininess:
+ * @pipeline: A #CoglPipeline object
+ *
+ * Retrieves the pipelines current emission color.
+ *
+ * Return value: The pipelines current shininess value
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+float
+cogl_pipeline_get_shininess (CoglPipeline *pipeline);
+
+#define cogl_pipeline_set_emission cogl_pipeline_set_emission_EXP
+/**
+ * cogl_pipeline_set_emission:
+ * @pipeline: A #CoglPipeline object
+ * @emission: The components of the desired emissive color
+ *
+ * Sets the pipeline's emissive color, in the standard OpenGL lighting
+ * model. It will look like the surface is a light source emitting this
+ * color.
+ *
+ * The default value is (0.0, 0.0, 0.0, 1.0)
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_emission (CoglPipeline    *pipeline,
+			    const CoglColor *emission);
+
+#define cogl_pipeline_get_emission cogl_pipeline_get_emission_EXP
+/**
+ * cogl_pipeline_get_emission:
+ * @pipeline: A #CoglPipeline object
+ * @emission: The location to store the emission color
+ *
+ * Retrieves the pipelines current emission color.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_get_emission (CoglPipeline *pipeline,
+                            CoglColor    *emission);
+
+/**
+ * CoglPipelineAlphaFunc:
+ * @COGL_PIPELINE_ALPHA_FUNC_NEVER: Never let the fragment through.
+ * @COGL_PIPELINE_ALPHA_FUNC_LESS: Let the fragment through if the incoming
+ *   alpha value is less than the reference alpha value
+ * @COGL_PIPELINE_ALPHA_FUNC_EQUAL: Let the fragment through if the incoming
+ *   alpha value equals the reference alpha value
+ * @COGL_PIPELINE_ALPHA_FUNC_LEQUAL: Let the fragment through if the incoming
+ *   alpha value is less than or equal to the reference alpha value
+ * @COGL_PIPELINE_ALPHA_FUNC_GREATER: Let the fragment through if the incoming
+ *   alpha value is greater than the reference alpha value
+ * @COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL: Let the fragment through if the incoming
+ *   alpha value does not equal the reference alpha value
+ * @COGL_PIPELINE_ALPHA_FUNC_GEQUAL: Let the fragment through if the incoming
+ *   alpha value is greater than or equal to the reference alpha value.
+ * @COGL_PIPELINE_ALPHA_FUNC_ALWAYS: Always let the fragment through.
+ *
+ * Alpha testing happens before blending primitives with the framebuffer and
+ * gives an opportunity to discard fragments based on a comparison with the
+ * incoming alpha value and a reference alpha value. The #CoglPipelineAlphaFunc
+ * determines how the comparison is done.
+ */
+typedef enum {
+  COGL_PIPELINE_ALPHA_FUNC_NEVER    = 0x0200,
+  COGL_PIPELINE_ALPHA_FUNC_LESS	    = 0x0201,
+  COGL_PIPELINE_ALPHA_FUNC_EQUAL    = 0x0202,
+  COGL_PIPELINE_ALPHA_FUNC_LEQUAL   = 0x0203,
+  COGL_PIPELINE_ALPHA_FUNC_GREATER  = 0x0204,
+  COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL = 0x0205,
+  COGL_PIPELINE_ALPHA_FUNC_GEQUAL   = 0x0206,
+  COGL_PIPELINE_ALPHA_FUNC_ALWAYS   = 0x0207
+} CoglPipelineAlphaFunc;
+/* NB: these values come from the equivalents in gl.h */
+
+#define cogl_pipeline_set_alpha_test_function \
+  cogl_pipeline_set_alpha_test_function_EXP
+/**
+ * cogl_pipeline_set_alpha_test_function:
+ * @pipeline: A #CoglPipeline object
+ * @alpha_func: A @CoglPipelineAlphaFunc constant
+ * @alpha_reference: A reference point that the chosen alpha function uses
+ *   to compare incoming fragments to.
+ *
+ * Before a primitive is blended with the framebuffer, it goes through an
+ * alpha test stage which lets you discard fragments based on the current
+ * alpha value. This function lets you change the function used to evaluate
+ * the alpha channel, and thus determine which fragments are discarded
+ * and which continue on to the blending stage.
+ *
+ * The default is %COGL_PIPELINE_ALPHA_FUNC_ALWAYS
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_alpha_test_function (CoglPipeline         *pipeline,
+				       CoglPipelineAlphaFunc alpha_func,
+				       float                 alpha_reference);
+
+#define cogl_pipeline_get_alpha_test_function \
+  cogl_pipeline_get_alpha_test_function_EXP
+/**
+ * cogl_pipeline_get_alpha_test_function:
+ * @pipeline: A #CoglPipeline object
+ *
+ * Return value: The alpha test function of @pipeline.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+CoglPipelineAlphaFunc
+cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline);
+
+#define cogl_pipeline_get_alpha_test_reference \
+  cogl_pipeline_get_alpha_test_reference_EXP
+/**
+ * cogl_pipeline_get_alpha_test_reference:
+ * @pipeline: A #CoglPipeline object
+ *
+ * Return value: The alpha test reference value of @pipeline.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+float
+cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline);
+
+#define cogl_pipeline_set_blend cogl_pipeline_set_blend_EXP
+/**
+ * cogl_pipeline_set_blend:
+ * @pipeline: A #CoglPipeline object
+ * @blend_string: A <link linkend="cogl-Blend-Strings">Cogl blend string</link>
+ *   describing the desired blend function.
+ * @error: return location for a #GError that may report lack of driver
+ *   support if you give separate blend string statements for the alpha
+ *   channel and RGB channels since some drivers, or backends such as
+ *   GLES 1.1, don't support this feature. May be %NULL, in which case a
+ *   warning will be printed out using GLib's logging facilities if an
+ *   error is encountered.
+ *
+ * If not already familiar; please refer <link linkend="cogl-Blend-Strings">here</link>
+ * for an overview of what blend strings are, and their syntax.
+ *
+ * Blending occurs after the alpha test function, and combines fragments with
+ * the framebuffer.
+
+ * Currently the only blend function Cogl exposes is ADD(). So any valid
+ * blend statements will be of the form:
+ *
+ * |[
+ *   &lt;channel-mask&gt;=ADD(SRC_COLOR*(&lt;factor&gt;), DST_COLOR*(&lt;factor&gt;))
+ * ]|
+ *
+ * This is the list of source-names usable as blend factors:
+ * <itemizedlist>
+ *   <listitem><para>SRC_COLOR: The color of the in comming fragment</para></listitem>
+ *   <listitem><para>DST_COLOR: The color of the framebuffer</para></listitem>
+ *   <listitem><para>CONSTANT: The constant set via cogl_pipeline_set_blend_constant()</para></listitem>
+ * </itemizedlist>
+ *
+ * The source names can be used according to the
+ * <link linkend="cogl-Blend-String-syntax">color-source and factor syntax</link>,
+ * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would
+ * "(CONSTANT[RGB])"
+ *
+ * These can also be used as factors:
+ * <itemizedlist>
+ *   <listitem>0: (0, 0, 0, 0)</listitem>
+ *   <listitem>1: (1, 1, 1, 1)</listitem>
+ *   <listitem>SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1) where f = MIN(SRC_COLOR[A],1-DST_COLOR[A])</listitem>
+ * </itemizedlist>
+ *
+ * <note>Remember; all color components are normalized to the range [0, 1]
+ * before computing the result of blending.</note>
+ *
+ * <example id="cogl-Blend-Strings-blend-unpremul">
+ *   <title>Blend Strings/1</title>
+ *   <para>Blend a non-premultiplied source over a destination with
+ *   premultiplied alpha:</para>
+ *   <programlisting>
+ * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))"
+ * "A   = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
+ *   </programlisting>
+ * </example>
+ *
+ * <example id="cogl-Blend-Strings-blend-premul">
+ *   <title>Blend Strings/2</title>
+ *   <para>Blend a premultiplied source over a destination with
+ *   premultiplied alpha</para>
+ *   <programlisting>
+ * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
+ *   </programlisting>
+ * </example>
+ *
+ * The default blend string is:
+ * |[
+ *    RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))
+ * ]|
+ *
+ * That gives normal alpha-blending when the calculated color for the pipeline
+ * is in premultiplied form.
+ *
+ * Return value: %TRUE if the blend string was successfully parsed, and the
+ *   described blending is supported by the underlying driver/hardware. If
+ *   there was an error, %FALSE is returned and @error is set accordingly (if
+ *   present).
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+gboolean
+cogl_pipeline_set_blend (CoglPipeline *pipeline,
+                         const char   *blend_string,
+                         GError      **error);
+
+#define cogl_pipeline_set_blend_constant cogl_pipeline_set_blend_constant_EXP
+/**
+ * cogl_pipeline_set_blend_constant:
+ * @pipeline: A #CoglPipeline object
+ * @constant_color: The constant color you want
+ *
+ * When blending is setup to reference a CONSTANT blend factor then
+ * blending will depend on the constant set with this function.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
+                                  const CoglColor *constant_color);
+
+#define cogl_pipeline_set_point_size cogl_pipeline_set_point_size_EXP
+/**
+ * cogl_pipeline_set_point_size:
+ * @pipeline: a #CoglPipeline pointer
+ * @point_size: the new point size.
+ *
+ * Changes the size of points drawn when %COGL_VERTICES_MODE_POINTS is
+ * used with the vertex buffer API. Note that typically the GPU will
+ * only support a limited minimum and maximum range of point sizes. If
+ * the chosen point size is outside that range then the nearest value
+ * within that range will be used instead. The size of a point is in
+ * screen space so it will be the same regardless of any
+ * transformations. The default point size is 1.0.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_point_size (CoglPipeline *pipeline,
+                              float point_size);
+
+#define cogl_pipeline_get_point_size cogl_pipeline_get_point_size_EXP
+/**
+ * cogl_pipeline_get_point_size:
+ * @pipeline: a #CoglPipeline pointer
+ *
+ * Get the size of points drawn when %COGL_VERTICES_MODE_POINTS is
+ * used with the vertex buffer API.
+ *
+ * Return value: the point size of the @pipeline.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+float
+cogl_pipeline_get_point_size (CoglPipeline *pipeline);
+
+#define cogl_pipeline_get_color_mask cogl_pipeline_get_color_mask_EXP
+/**
+ * cogl_pipeline_get_color_mask:
+ * @pipeline: a #CoglPipeline object.
+ *
+ * Gets the current #CoglColorMask of which channels would be written to the
+ * current framebuffer. Each bit set in the mask means that the
+ * corresponding color would be written.
+ *
+ * Returns: A #CoglColorMask
+ * Since: 1.8
+ * Stability: unstable
+ */
+CoglColorMask
+cogl_pipeline_get_color_mask (CoglPipeline *pipeline);
+
+#define cogl_pipeline_set_color_mask cogl_pipeline_set_color_mask_EXP
+/**
+ * cogl_pipeline_set_color_mask:
+ * @pipeline: a #CoglPipeline object.
+ * @color_mask: A #CoglColorMask of which color channels to write to
+ *              the current framebuffer.
+ *
+ * Defines a bit mask of which color channels should be written to the
+ * current framebuffer. If a bit is set in @color_mask that means that
+ * color will be written.
+ *
+ * Since: 1.8
+ * Stability: unstable
+ */
+void
+cogl_pipeline_set_color_mask (CoglPipeline *pipeline,
+                              CoglColorMask color_mask);
+
+#define cogl_pipeline_get_user_program cogl_pipeline_get_user_program_EXP
+/**
+ * cogl_pipeline_get_user_program:
+ * @pipeline: a #CoglPipeline object.
+ *
+ * Queries what user program has been associated with the given
+ * @pipeline using cogl_pipeline_set_user_program().
+ *
+ * Return value: The current user program or %COGL_INVALID_HANDLE.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+CoglHandle
+cogl_pipeline_get_user_program (CoglPipeline *pipeline);
+
+#define cogl_pipeline_set_user_program cogl_pipeline_set_user_program_EXP
+/**
+ * cogl_pipeline_set_user_program:
+ * @pipeline: a #CoglPipeline object.
+ * @program: A #CoglHandle to a linked CoglProgram
+ *
+ * Associates a linked CoglProgram with the given pipeline so that the
+ * program can take full control of vertex and/or fragment processing.
+ *
+ * This is an example of how it can be used to associate an ARBfp
+ * program with a #CoglPipeline:
+ * |[
+ * CoglHandle shader;
+ * CoglHandle program;
+ * CoglPipeline *pipeline;
+ *
+ * shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
+ * cogl_shader_source (shader,
+ *                     "!!ARBfp1.0\n"
+ *                     "MOV result.color,fragment.color;\n"
+ *                     "END\n");
+ * cogl_shader_compile (shader);
+ *
+ * program = cogl_create_program ();
+ * cogl_program_attach_shader (program, shader);
+ * cogl_program_link (program);
+ *
+ * pipeline = cogl_pipeline_new ();
+ * cogl_pipeline_set_user_program (pipeline, program);
+ *
+ * cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
+ * cogl_rectangle (0, 0, 100, 100);
+ * ]|
+ *
+ * It is possibly worth keeping in mind that this API is not part of
+ * the long term design for how we want to expose shaders to Cogl
+ * developers (We are planning on deprecating the cogl_program and
+ * cogl_shader APIs in favour of a "snippet" framework) but in the
+ * meantime we hope this will handle most practical GLSL and ARBfp
+ * requirements.
+ *
+ * Also remember you need to check for either the
+ * %COGL_FEATURE_SHADERS_GLSL or %COGL_FEATURE_SHADERS_ARBFP before
+ * using the cogl_program or cogl_shader API.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_set_user_program (CoglPipeline *pipeline,
+                                CoglHandle program);
+
+#define cogl_pipeline_set_depth_state cogl_pipeline_set_depth_state_EXP
+/**
+ * cogl_pipeline_set_depth_state:
+ * @pipeline: A #CoglPipeline object
+ * @state: A #CoglDepthState struct
+ * @error: A #GError to report failures to setup the given @state.
+ *
+ * This commits all the depth state configured in @state struct to the
+ * given @pipeline. The configuration values are copied into the
+ * pipeline so there is no requirement to keep the #CoglDepthState
+ * struct around if you don't need it any more.
+ *
+ * Note: Since some platforms do not support the depth range feature
+ * it is possible for this function to fail and report an @error.
+ *
+ * Returns: TRUE if the GPU supports all the given @state else %FALSE
+ *          and returns an @error.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+gboolean
+cogl_pipeline_set_depth_state (CoglPipeline *pipeline,
+                               const CoglDepthState *state,
+                               GError **error);
+
+#define cogl_pipeline_get_depth_state cogl_pipeline_get_depth_state_EXP
+/**
+ * cogl_pipeline_get_depth_state
+ * @pipeline: A #CoglPipeline object
+ * @state: A destination #CoglDepthState struct
+ *
+ * Retrieves the current depth state configuration for the given
+ * @pipeline as previously set using cogl_pipeline_set_depth_state().
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+void
+cogl_pipeline_get_depth_state (CoglPipeline *pipeline,
+                               CoglDepthState *state_out);
+
+#endif /* COGL_ENABLE_EXPERIMENTAL_API */
+
+G_END_DECLS
+
+#endif /* __COGL_PIPELINE_STATE_H__ */
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 8b87a2ea8..384b646d7 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -37,6 +37,7 @@
 
 #include "cogl-pipeline-private.h"
 #include "cogl-pipeline-opengl-private.h"
+#include "cogl-pipeline-state-private.h"
 #include "cogl-texture-private.h"
 #include "cogl-blend-string.h"
 #include "cogl-journal-private.h"
@@ -49,13 +50,6 @@
 #include <glib/gprintf.h>
 #include <string.h>
 
-#ifndef GL_FUNC_ADD
-#define GL_FUNC_ADD 0x8006
-#endif
-
-typedef gboolean (*CoglPipelineStateComparitor) (CoglPipeline *authority0,
-                                                 CoglPipeline *authority1);
-
 static CoglPipelineLayer *_cogl_pipeline_layer_copy (CoglPipelineLayer *layer);
 
 static void _cogl_pipeline_free (CoglPipeline *tex);
@@ -63,8 +57,6 @@ static void _cogl_pipeline_layer_free (CoglPipelineLayer *layer);
 static void _cogl_pipeline_add_layer_difference (CoglPipeline *pipeline,
                                                  CoglPipelineLayer *layer,
                                                  gboolean inc_n_layers);
-static void handle_automatic_blend_enable (CoglPipeline *pipeline,
-                                           CoglPipelineState changes);
 static void recursively_free_layer_caches (CoglPipeline *pipeline);
 static gboolean _cogl_pipeline_is_weak (CoglPipeline *pipeline);
 
@@ -792,19 +784,6 @@ layer_has_alpha_cb (CoglPipelineLayer *layer, void *data)
   return TRUE;
 }
 
-static CoglPipeline *
-_cogl_pipeline_get_user_program (CoglPipeline *pipeline)
-{
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER);
-
-  return authority->big_state->user_program;
-}
-
 static gboolean
 _cogl_pipeline_needs_blending_enabled (CoglPipeline    *pipeline,
                                        unsigned long    changes,
@@ -1084,7 +1063,7 @@ _cogl_pipeline_copy_differences (CoglPipeline *dest,
    */
 check_for_blending_change:
   if (differences & COGL_PIPELINE_STATE_AFFECTS_BLENDING)
-    handle_automatic_blend_enable (dest, differences);
+    _cogl_pipeline_update_blend_enable (dest, differences);
 
   dest->differences |= differences;
 }
@@ -1203,7 +1182,7 @@ reparent_children_cb (CoglPipelineNode *node,
   return TRUE;
 }
 
-static void
+void
 _cogl_pipeline_pre_change_notify (CoglPipeline     *pipeline,
                                   CoglPipelineState change,
                                   const CoglColor  *new_color,
@@ -1514,9 +1493,9 @@ _cogl_pipeline_try_reverting_layers_authority (CoglPipeline *authority,
 }
 
 
-static void
-handle_automatic_blend_enable (CoglPipeline *pipeline,
-                               CoglPipelineState change)
+void
+_cogl_pipeline_update_blend_enable (CoglPipeline *pipeline,
+                                    CoglPipelineState change)
 {
   gboolean blend_enable =
     _cogl_pipeline_needs_blending_enabled (pipeline, change, NULL);
@@ -2288,7 +2267,7 @@ _cogl_pipeline_set_layer_texture_target (CoglPipeline *pipeline,
 
 changed:
 
-  handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
+  _cogl_pipeline_update_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
 }
 
 static void
@@ -2367,7 +2346,7 @@ _cogl_pipeline_set_layer_texture_data (CoglPipeline *pipeline,
 
 changed:
 
-  handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
+  _cogl_pipeline_update_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
 }
 
 /* A convenience for querying the target of a given texture that
@@ -3353,168 +3332,6 @@ _cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
   return TRUE;
 }
 
-static gboolean
-_cogl_pipeline_color_equal (CoglPipeline *authority0,
-                            CoglPipeline *authority1)
-{
-  return cogl_color_equal (&authority0->color, &authority1->color);
-}
-
-static gboolean
-_cogl_pipeline_lighting_state_equal (CoglPipeline *authority0,
-                                     CoglPipeline *authority1)
-{
-  CoglPipelineLightingState *state0 = &authority0->big_state->lighting_state;
-  CoglPipelineLightingState *state1 = &authority1->big_state->lighting_state;
-
-  if (memcmp (state0->ambient, state1->ambient, sizeof (float) * 4) != 0)
-    return FALSE;
-  if (memcmp (state0->diffuse, state1->diffuse, sizeof (float) * 4) != 0)
-    return FALSE;
-  if (memcmp (state0->specular, state1->specular, sizeof (float) * 4) != 0)
-    return FALSE;
-  if (memcmp (state0->emission, state1->emission, sizeof (float) * 4) != 0)
-    return FALSE;
-  if (state0->shininess != state1->shininess)
-    return FALSE;
-
-  return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0,
-                                       CoglPipeline *authority1)
-{
-  CoglPipelineAlphaFuncState *alpha_state0 =
-    &authority0->big_state->alpha_state;
-  CoglPipelineAlphaFuncState *alpha_state1 =
-    &authority1->big_state->alpha_state;
-
-  return alpha_state0->alpha_func == alpha_state1->alpha_func;
-}
-
-static gboolean
-_cogl_pipeline_alpha_func_reference_state_equal (CoglPipeline *authority0,
-                                                 CoglPipeline *authority1)
-{
-  CoglPipelineAlphaFuncState *alpha_state0 =
-    &authority0->big_state->alpha_state;
-  CoglPipelineAlphaFuncState *alpha_state1 =
-    &authority1->big_state->alpha_state;
-
-  return (alpha_state0->alpha_func_reference ==
-          alpha_state1->alpha_func_reference);
-}
-
-static gboolean
-_cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
-                                  CoglPipeline *authority1)
-{
-  CoglPipelineBlendState *blend_state0 = &authority0->big_state->blend_state;
-  CoglPipelineBlendState *blend_state1 = &authority1->big_state->blend_state;
-
-  _COGL_GET_CONTEXT (ctx, FALSE);
-
-#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
-  if (ctx->driver != COGL_DRIVER_GLES1)
-    {
-      if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb)
-        return FALSE;
-      if (blend_state0->blend_equation_alpha !=
-          blend_state1->blend_equation_alpha)
-        return FALSE;
-      if (blend_state0->blend_src_factor_alpha !=
-          blend_state1->blend_src_factor_alpha)
-        return FALSE;
-      if (blend_state0->blend_dst_factor_alpha !=
-          blend_state1->blend_dst_factor_alpha)
-        return FALSE;
-    }
-#endif
-  if (blend_state0->blend_src_factor_rgb !=
-      blend_state1->blend_src_factor_rgb)
-    return FALSE;
-  if (blend_state0->blend_dst_factor_rgb !=
-      blend_state1->blend_dst_factor_rgb)
-    return FALSE;
-#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
-  if (ctx->driver != COGL_DRIVER_GLES1 &&
-      (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-       blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
-       blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-       blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR))
-    {
-      if (!cogl_color_equal (&blend_state0->blend_constant,
-                             &blend_state1->blend_constant))
-        return FALSE;
-    }
-#endif
-
-  return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_depth_state_equal (CoglPipeline *authority0,
-                                  CoglPipeline *authority1)
-{
-  if (authority0->big_state->depth_state.test_enabled == FALSE &&
-      authority1->big_state->depth_state.test_enabled == FALSE)
-    return TRUE;
-  else
-    {
-      CoglDepthState *s0 = &authority0->big_state->depth_state;
-      CoglDepthState *s1 = &authority1->big_state->depth_state;
-      return s0->test_enabled == s1->test_enabled &&
-             s0->test_function == s1->test_function &&
-             s0->write_enabled == s1->write_enabled &&
-             s0->range_near == s1->range_near &&
-             s0->range_far == s1->range_far;
-    }
-}
-
-static gboolean
-_cogl_pipeline_fog_state_equal (CoglPipeline *authority0,
-                                CoglPipeline *authority1)
-{
-  CoglPipelineFogState *fog_state0 = &authority0->big_state->fog_state;
-  CoglPipelineFogState *fog_state1 = &authority1->big_state->fog_state;
-
-  if (fog_state0->enabled == fog_state1->enabled &&
-      cogl_color_equal (&fog_state0->color, &fog_state1->color) &&
-      fog_state0->mode == fog_state1->mode &&
-      fog_state0->density == fog_state1->density &&
-      fog_state0->z_near == fog_state1->z_near &&
-      fog_state0->z_far == fog_state1->z_far)
-    return TRUE;
-  else
-    return FALSE;
-}
-
-static gboolean
-_cogl_pipeline_point_size_equal (CoglPipeline *authority0,
-                                 CoglPipeline *authority1)
-{
-  return authority0->big_state->point_size == authority1->big_state->point_size;
-}
-
-static gboolean
-_cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0,
-                                      CoglPipeline *authority1)
-{
-  CoglPipelineLogicOpsState *logic_ops_state0 = &authority0->big_state->logic_ops_state;
-  CoglPipelineLogicOpsState *logic_ops_state1 = &authority1->big_state->logic_ops_state;
-
-  return logic_ops_state0->color_mask == logic_ops_state1->color_mask;
-}
-
-static gboolean
-_cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
-                                  CoglPipeline *authority1)
-{
-  return (authority0->big_state->user_program ==
-          authority1->big_state->user_program);
-}
-
 static gboolean
 _cogl_pipeline_layers_equal (CoglPipeline *authority0,
                              CoglPipeline *authority1,
@@ -3850,31 +3667,6 @@ done:
 }
 
 void
-cogl_pipeline_get_color (CoglPipeline *pipeline,
-                         CoglColor    *color)
-{
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
-
-  *color = authority->color;
-}
-
-/* This is used heavily by the cogl journal when logging quads */
-void
-_cogl_pipeline_get_colorubv (CoglPipeline *pipeline,
-                             guint8       *color)
-{
-  CoglPipeline *authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
-
-  _cogl_color_get_rgba_4ubv (&authority->color, color);
-}
-
-static void
 _cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline)
 {
   CoglPipeline *new_parent = _cogl_pipeline_get_parent (pipeline);
@@ -3914,7 +3706,7 @@ _cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline)
     }
 }
 
-static void
+void
 _cogl_pipeline_update_authority (CoglPipeline *pipeline,
                                  CoglPipeline *authority,
                                  CoglPipelineState state,
@@ -3943,919 +3735,6 @@ _cogl_pipeline_update_authority (CoglPipeline *pipeline,
     }
 }
 
-void
-cogl_pipeline_set_color (CoglPipeline    *pipeline,
-			 const CoglColor *color)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_COLOR;
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  if (cogl_color_equal (color, &authority->color))
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, color, FALSE);
-
-  pipeline->color = *color;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_color_equal);
-
-  handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_set_color4ub (CoglPipeline *pipeline,
-			    guint8 red,
-                            guint8 green,
-                            guint8 blue,
-                            guint8 alpha)
-{
-  CoglColor color;
-  cogl_color_init_from_4ub (&color, red, green, blue, alpha);
-  cogl_pipeline_set_color (pipeline, &color);
-}
-
-void
-cogl_pipeline_set_color4f (CoglPipeline *pipeline,
-			   float red,
-                           float green,
-                           float blue,
-                           float alpha)
-{
-  CoglColor color;
-  cogl_color_init_from_4f (&color, red, green, blue, alpha);
-  cogl_pipeline_set_color (pipeline, &color);
-}
-
-CoglPipelineBlendEnable
-_cogl_pipeline_get_blend_enabled (CoglPipeline *pipeline)
-{
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND_ENABLE);
-  return authority->blend_enable;
-}
-
-static gboolean
-_cogl_pipeline_blend_enable_equal (CoglPipeline *authority0,
-                                   CoglPipeline *authority1)
-{
-  return authority0->blend_enable == authority1->blend_enable ? TRUE : FALSE;
-}
-
-void
-_cogl_pipeline_set_blend_enabled (CoglPipeline *pipeline,
-                                  CoglPipelineBlendEnable enable)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_BLEND_ENABLE;
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-  g_return_if_fail (enable > 1 &&
-                    "don't pass TRUE or FALSE to _set_blend_enabled!");
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  if (authority->blend_enable == enable)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  pipeline->blend_enable = enable;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_blend_enable_equal);
-
-  handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_get_ambient (CoglPipeline *pipeline,
-                           CoglColor    *ambient)
-{
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
-  cogl_color_init_from_4fv (ambient,
-                            authority->big_state->lighting_state.ambient);
-}
-
-void
-cogl_pipeline_set_ambient (CoglPipeline *pipeline,
-			   const CoglColor *ambient)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
-  CoglPipeline *authority;
-  CoglPipelineLightingState *lighting_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  lighting_state = &authority->big_state->lighting_state;
-  if (cogl_color_equal (ambient, &lighting_state->ambient))
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  lighting_state = &pipeline->big_state->lighting_state;
-  lighting_state->ambient[0] = cogl_color_get_red_float (ambient);
-  lighting_state->ambient[1] = cogl_color_get_green_float (ambient);
-  lighting_state->ambient[2] = cogl_color_get_blue_float (ambient);
-  lighting_state->ambient[3] = cogl_color_get_alpha_float (ambient);
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_lighting_state_equal);
-
-  handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_get_diffuse (CoglPipeline *pipeline,
-                           CoglColor    *diffuse)
-{
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
-  cogl_color_init_from_4fv (diffuse,
-                            authority->big_state->lighting_state.diffuse);
-}
-
-void
-cogl_pipeline_set_diffuse (CoglPipeline *pipeline,
-			   const CoglColor *diffuse)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
-  CoglPipeline *authority;
-  CoglPipelineLightingState *lighting_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  lighting_state = &authority->big_state->lighting_state;
-  if (cogl_color_equal (diffuse, &lighting_state->diffuse))
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  lighting_state = &pipeline->big_state->lighting_state;
-  lighting_state->diffuse[0] = cogl_color_get_red_float (diffuse);
-  lighting_state->diffuse[1] = cogl_color_get_green_float (diffuse);
-  lighting_state->diffuse[2] = cogl_color_get_blue_float (diffuse);
-  lighting_state->diffuse[3] = cogl_color_get_alpha_float (diffuse);
-
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_lighting_state_equal);
-
-  handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_set_ambient_and_diffuse (CoglPipeline *pipeline,
-				       const CoglColor *color)
-{
-  cogl_pipeline_set_ambient (pipeline, color);
-  cogl_pipeline_set_diffuse (pipeline, color);
-}
-
-void
-cogl_pipeline_get_specular (CoglPipeline *pipeline,
-                            CoglColor    *specular)
-{
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
-  cogl_color_init_from_4fv (specular,
-                            authority->big_state->lighting_state.specular);
-}
-
-void
-cogl_pipeline_set_specular (CoglPipeline *pipeline, const CoglColor *specular)
-{
-  CoglPipeline *authority;
-  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
-  CoglPipelineLightingState *lighting_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  lighting_state = &authority->big_state->lighting_state;
-  if (cogl_color_equal (specular, &lighting_state->specular))
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  lighting_state = &pipeline->big_state->lighting_state;
-  lighting_state->specular[0] = cogl_color_get_red_float (specular);
-  lighting_state->specular[1] = cogl_color_get_green_float (specular);
-  lighting_state->specular[2] = cogl_color_get_blue_float (specular);
-  lighting_state->specular[3] = cogl_color_get_alpha_float (specular);
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_lighting_state_equal);
-
-  handle_automatic_blend_enable (pipeline, state);
-}
-
-float
-cogl_pipeline_get_shininess (CoglPipeline *pipeline)
-{
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
-  return authority->big_state->lighting_state.shininess;
-}
-
-void
-cogl_pipeline_set_shininess (CoglPipeline *pipeline,
-			     float shininess)
-{
-  CoglPipeline *authority;
-  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
-  CoglPipelineLightingState *lighting_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  if (shininess < 0.0)
-    {
-      g_warning ("Out of range shininess %f supplied for pipeline\n",
-                 shininess);
-      return;
-    }
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  lighting_state = &authority->big_state->lighting_state;
-
-  if (lighting_state->shininess == shininess)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  lighting_state = &pipeline->big_state->lighting_state;
-  lighting_state->shininess = shininess;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_lighting_state_equal);
-}
-
-void
-cogl_pipeline_get_emission (CoglPipeline *pipeline,
-                            CoglColor    *emission)
-{
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
-  cogl_color_init_from_4fv (emission,
-                            authority->big_state->lighting_state.emission);
-}
-
-void
-cogl_pipeline_set_emission (CoglPipeline *pipeline, const CoglColor *emission)
-{
-  CoglPipeline *authority;
-  CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
-  CoglPipelineLightingState *lighting_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  lighting_state = &authority->big_state->lighting_state;
-  if (cogl_color_equal (emission, &lighting_state->emission))
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  lighting_state = &pipeline->big_state->lighting_state;
-  lighting_state->emission[0] = cogl_color_get_red_float (emission);
-  lighting_state->emission[1] = cogl_color_get_green_float (emission);
-  lighting_state->emission[2] = cogl_color_get_blue_float (emission);
-  lighting_state->emission[3] = cogl_color_get_alpha_float (emission);
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_lighting_state_equal);
-
-  handle_automatic_blend_enable (pipeline, state);
-}
-
-static void
-_cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
-                                        CoglPipelineAlphaFunc alpha_func)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC;
-  CoglPipeline *authority;
-  CoglPipelineAlphaFuncState *alpha_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  alpha_state = &authority->big_state->alpha_state;
-  if (alpha_state->alpha_func == alpha_func)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  alpha_state = &pipeline->big_state->alpha_state;
-  alpha_state->alpha_func = alpha_func;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_alpha_func_state_equal);
-}
-
-static void
-_cogl_pipeline_set_alpha_test_function_reference (CoglPipeline *pipeline,
-                                                  float alpha_reference)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE;
-  CoglPipeline *authority;
-  CoglPipelineAlphaFuncState *alpha_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  alpha_state = &authority->big_state->alpha_state;
-  if (alpha_state->alpha_func_reference == alpha_reference)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  alpha_state = &pipeline->big_state->alpha_state;
-  alpha_state->alpha_func_reference = alpha_reference;
-
-  _cogl_pipeline_update_authority
-    (pipeline, authority, state,
-     _cogl_pipeline_alpha_func_reference_state_equal);
-}
-
-void
-cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
-				       CoglPipelineAlphaFunc alpha_func,
-				       float alpha_reference)
-{
-  _cogl_pipeline_set_alpha_test_function (pipeline, alpha_func);
-  _cogl_pipeline_set_alpha_test_function_reference (pipeline, alpha_reference);
-}
-
-CoglPipelineAlphaFunc
-cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline)
-{
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC);
-
-  return authority->big_state->alpha_state.alpha_func;
-}
-
-float
-cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline)
-{
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0.0f);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline,
-                                  COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE);
-
-  return authority->big_state->alpha_state.alpha_func_reference;
-}
-
-GLenum
-arg_to_gl_blend_factor (CoglBlendStringArgument *arg)
-{
-  if (arg->source.is_zero)
-    return GL_ZERO;
-  if (arg->factor.is_one)
-    return GL_ONE;
-  else if (arg->factor.is_src_alpha_saturate)
-    return GL_SRC_ALPHA_SATURATE;
-  else if (arg->factor.source.info->type ==
-           COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR)
-    {
-      if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
-        {
-          if (arg->factor.source.one_minus)
-            return GL_ONE_MINUS_SRC_COLOR;
-          else
-            return GL_SRC_COLOR;
-        }
-      else
-        {
-          if (arg->factor.source.one_minus)
-            return GL_ONE_MINUS_SRC_ALPHA;
-          else
-            return GL_SRC_ALPHA;
-        }
-    }
-  else if (arg->factor.source.info->type ==
-           COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR)
-    {
-      if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
-        {
-          if (arg->factor.source.one_minus)
-            return GL_ONE_MINUS_DST_COLOR;
-          else
-            return GL_DST_COLOR;
-        }
-      else
-        {
-          if (arg->factor.source.one_minus)
-            return GL_ONE_MINUS_DST_ALPHA;
-          else
-            return GL_DST_ALPHA;
-        }
-    }
-#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
-  else if (arg->factor.source.info->type ==
-           COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
-    {
-      if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
-        {
-          if (arg->factor.source.one_minus)
-            return GL_ONE_MINUS_CONSTANT_COLOR;
-          else
-            return GL_CONSTANT_COLOR;
-        }
-      else
-        {
-          if (arg->factor.source.one_minus)
-            return GL_ONE_MINUS_CONSTANT_ALPHA;
-          else
-            return GL_CONSTANT_ALPHA;
-        }
-    }
-#endif
-
-  g_warning ("Unable to determine valid blend factor from blend string\n");
-  return GL_ONE;
-}
-
-void
-setup_blend_state (CoglBlendStringStatement *statement,
-                   GLenum *blend_equation,
-                   GLint *blend_src_factor,
-                   GLint *blend_dst_factor)
-{
-  switch (statement->function->type)
-    {
-    case COGL_BLEND_STRING_FUNCTION_ADD:
-      *blend_equation = GL_FUNC_ADD;
-      break;
-    /* TODO - add more */
-    default:
-      g_warning ("Unsupported blend function given");
-      *blend_equation = GL_FUNC_ADD;
-    }
-
-  *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]);
-  *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]);
-}
-
-gboolean
-cogl_pipeline_set_blend (CoglPipeline *pipeline,
-                         const char *blend_description,
-                         GError **error)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
-  CoglPipeline *authority;
-  CoglBlendStringStatement statements[2];
-  CoglBlendStringStatement *rgb;
-  CoglBlendStringStatement *a;
-  GError *internal_error = NULL;
-  int count;
-  CoglPipelineBlendState *blend_state;
-
-  _COGL_GET_CONTEXT (ctx, FALSE);
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
-  count =
-    _cogl_blend_string_compile (blend_description,
-                                COGL_BLEND_STRING_CONTEXT_BLENDING,
-                                statements,
-                                &internal_error);
-  if (!count)
-    {
-      if (error)
-	g_propagate_error (error, internal_error);
-      else
-	{
-	  g_warning ("Cannot compile blend description: %s\n",
-		     internal_error->message);
-	  g_error_free (internal_error);
-	}
-      return FALSE;
-    }
-
-  if (count == 1)
-    rgb = a = statements;
-  else
-    {
-      rgb = &statements[0];
-      a = &statements[1];
-    }
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, state);
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  blend_state = &pipeline->big_state->blend_state;
-#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
-  if (ctx->driver != COGL_DRIVER_GLES1)
-    {
-      setup_blend_state (rgb,
-                         &blend_state->blend_equation_rgb,
-                         &blend_state->blend_src_factor_rgb,
-                         &blend_state->blend_dst_factor_rgb);
-      setup_blend_state (a,
-                         &blend_state->blend_equation_alpha,
-                         &blend_state->blend_src_factor_alpha,
-                         &blend_state->blend_dst_factor_alpha);
-    }
-  else
-#endif
-    {
-      setup_blend_state (rgb,
-                         NULL,
-                         &blend_state->blend_src_factor_rgb,
-                         &blend_state->blend_dst_factor_rgb);
-    }
-
-  /* If we are the current authority see if we can revert to one of our
-   * ancestors being the authority */
-  if (pipeline == authority &&
-      _cogl_pipeline_get_parent (authority) != NULL)
-    {
-      CoglPipeline *parent = _cogl_pipeline_get_parent (authority);
-      CoglPipeline *old_authority =
-        _cogl_pipeline_get_authority (parent, state);
-
-      if (_cogl_pipeline_blend_state_equal (authority, old_authority))
-        pipeline->differences &= ~state;
-    }
-
-  /* If we weren't previously the authority on this state then we need
-   * to extended our differences mask and so it's possible that some
-   * of our ancestry will now become redundant, so we aim to reparent
-   * ourselves if that's true... */
-  if (pipeline != authority)
-    {
-      pipeline->differences |= state;
-      _cogl_pipeline_prune_redundant_ancestry (pipeline);
-    }
-
-  handle_automatic_blend_enable (pipeline, state);
-
-  return TRUE;
-}
-
-void
-cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
-                                  const CoglColor *constant_color)
-{
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  if (ctx->driver == COGL_DRIVER_GLES1)
-    return;
-
-#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
-  {
-    CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
-    CoglPipeline *authority;
-    CoglPipelineBlendState *blend_state;
-
-    authority = _cogl_pipeline_get_authority (pipeline, state);
-
-    blend_state = &authority->big_state->blend_state;
-    if (cogl_color_equal (constant_color, &blend_state->blend_constant))
-      return;
-
-    /* - Flush journal primitives referencing the current state.
-     * - Make sure the pipeline has no dependants so it may be modified.
-     * - If the pipeline isn't currently an authority for the state being
-     *   changed, then initialize that state from the current authority.
-     */
-    _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-    blend_state = &pipeline->big_state->blend_state;
-    blend_state->blend_constant = *constant_color;
-
-    _cogl_pipeline_update_authority (pipeline, authority, state,
-                                     _cogl_pipeline_blend_state_equal);
-
-    handle_automatic_blend_enable (pipeline, state);
-  }
-#endif
-}
-
-CoglHandle
-cogl_pipeline_get_user_program (CoglPipeline *pipeline)
-{
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), COGL_INVALID_HANDLE);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER);
-
-  return authority->big_state->user_program;
-}
-
-/* XXX: for now we don't mind if the program has vertex shaders
- * attached but if we ever make a similar API public we should only
- * allow attaching of programs containing fragment shaders. Eventually
- * we will have a CoglPipeline abstraction to also cover vertex
- * processing.
- */
-void
-cogl_pipeline_set_user_program (CoglPipeline *pipeline,
-                                CoglHandle program)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_USER_SHADER;
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  if (authority->big_state->user_program == program)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  if (program != COGL_INVALID_HANDLE)
-    {
-      _cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_DEFAULT);
-      _cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_DEFAULT);
-    }
-
-  /* If we are the current authority see if we can revert to one of our
-   * ancestors being the authority */
-  if (pipeline == authority &&
-      _cogl_pipeline_get_parent (authority) != NULL)
-    {
-      CoglPipeline *parent = _cogl_pipeline_get_parent (authority);
-      CoglPipeline *old_authority =
-        _cogl_pipeline_get_authority (parent, state);
-
-      if (old_authority->big_state->user_program == program)
-        pipeline->differences &= ~state;
-    }
-  else if (pipeline != authority)
-    {
-      /* If we weren't previously the authority on this state then we
-       * need to extended our differences mask and so it's possible
-       * that some of our ancestry will now become redundant, so we
-       * aim to reparent ourselves if that's true... */
-      pipeline->differences |= state;
-      _cogl_pipeline_prune_redundant_ancestry (pipeline);
-    }
-
-  if (program != COGL_INVALID_HANDLE)
-    cogl_handle_ref (program);
-  if (authority == pipeline &&
-      pipeline->big_state->user_program != COGL_INVALID_HANDLE)
-    cogl_handle_unref (pipeline->big_state->user_program);
-  pipeline->big_state->user_program = program;
-
-  handle_automatic_blend_enable (pipeline, state);
-}
-
-gboolean
-cogl_pipeline_set_depth_state (CoglPipeline *pipeline,
-                               const CoglDepthState *depth_state,
-                               GError **error)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_DEPTH;
-  CoglPipeline *authority;
-  CoglDepthState *orig_state;
-
-  _COGL_GET_CONTEXT (ctx, FALSE);
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-  g_return_val_if_fail (depth_state->magic == COGL_DEPTH_STATE_MAGIC, FALSE);
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  orig_state = &authority->big_state->depth_state;
-  if (orig_state->test_enabled == depth_state->test_enabled &&
-      orig_state->write_enabled == depth_state->write_enabled &&
-      orig_state->test_function == depth_state->test_function &&
-      orig_state->range_near == depth_state->range_near &&
-      orig_state->range_far == depth_state->range_far)
-    return TRUE;
-
-  if (ctx->driver == COGL_DRIVER_GLES1 &&
-      (depth_state->range_near != 0 ||
-       depth_state->range_far != 1))
-    {
-      g_set_error (error,
-                   COGL_ERROR,
-                   COGL_ERROR_UNSUPPORTED,
-                   "glDepthRange not available on GLES 1");
-      return FALSE;
-    }
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  pipeline->big_state->depth_state = *depth_state;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_depth_state_equal);
-
-  return TRUE;
-}
-
-void
-cogl_pipeline_get_depth_state (CoglPipeline *pipeline,
-                               CoglDepthState *state)
-{
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
-  *state = authority->big_state->depth_state;
-}
-
-CoglColorMask
-cogl_pipeline_get_color_mask (CoglPipeline *pipeline)
-{
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LOGIC_OPS);
-
-  return authority->big_state->logic_ops_state.color_mask;
-}
-
-void
-cogl_pipeline_set_color_mask (CoglPipeline *pipeline,
-                              CoglColorMask color_mask)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_LOGIC_OPS;
-  CoglPipeline *authority;
-  CoglPipelineLogicOpsState *logic_ops_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  logic_ops_state = &authority->big_state->logic_ops_state;
-  if (logic_ops_state->color_mask == color_mask)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  logic_ops_state = &pipeline->big_state->logic_ops_state;
-  logic_ops_state->color_mask = color_mask;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_logic_ops_state_equal);
-}
-
-static void
-_cogl_pipeline_set_fog_state (CoglPipeline *pipeline,
-                              const CoglPipelineFogState *fog_state)
-{
-  CoglPipelineState state = COGL_PIPELINE_STATE_FOG;
-  CoglPipeline *authority;
-  CoglPipelineFogState *current_fog_state;
-
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  current_fog_state = &authority->big_state->fog_state;
-
-  if (current_fog_state->enabled == fog_state->enabled &&
-      cogl_color_equal (&current_fog_state->color, &fog_state->color) &&
-      current_fog_state->mode == fog_state->mode &&
-      current_fog_state->density == fog_state->density &&
-      current_fog_state->z_near == fog_state->z_near &&
-      current_fog_state->z_far == fog_state->z_far)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  pipeline->big_state->fog_state = *fog_state;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_fog_state_equal);
-}
-
 unsigned long
 _cogl_pipeline_get_age (CoglPipeline *pipeline)
 {
@@ -4887,8 +3766,8 @@ _cogl_pipeline_layer_free (CoglPipelineLayer *layer)
   _cogl_pipeline_layer_unparent (COGL_PIPELINE_NODE (layer));
 
   if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA &&
-      layer->texture != COGL_INVALID_HANDLE)
-    cogl_handle_unref (layer->texture);
+      layer->texture != NULL)
+    cogl_object_unref (layer->texture);
 
   if (layer->differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE)
     g_slice_free (CoglPipelineLayerBigState, layer->big_state);
@@ -4942,7 +3821,7 @@ _cogl_pipeline_init_default_layers (void)
 
   layer->unit_index = 0;
 
-  layer->texture = COGL_INVALID_HANDLE;
+  layer->texture = NULL;
   layer->target = 0;
 
   layer->mag_filter = COGL_PIPELINE_FILTER_LINEAR;
@@ -5209,7 +4088,7 @@ cogl_pipeline_set_layer_combine (CoglPipeline *pipeline,
 
 changed:
 
-  handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
+  _cogl_pipeline_update_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
   return TRUE;
 }
 
@@ -5294,7 +4173,7 @@ cogl_pipeline_set_layer_combine_constant (CoglPipeline *pipeline,
 
 changed:
 
-  handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
+  _cogl_pipeline_update_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
 }
 
 void
@@ -5460,7 +4339,7 @@ cogl_pipeline_remove_layer (CoglPipeline *pipeline, int layer_index)
   _cogl_pipeline_remove_layer_difference (pipeline, layer_info.layer, TRUE);
   _cogl_pipeline_try_reverting_layers_authority (pipeline, NULL);
 
-  handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
+  _cogl_pipeline_update_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
 }
 
 static gboolean
@@ -5734,48 +4613,6 @@ cogl_pipeline_set_layer_filters (CoglPipeline      *pipeline,
     }
 }
 
-float
-cogl_pipeline_get_point_size (CoglHandle  handle)
-{
-  CoglPipeline *pipeline = COGL_PIPELINE (handle);
-  CoglPipeline *authority;
-
-  g_return_val_if_fail (cogl_is_pipeline (handle), FALSE);
-
-  authority =
-    _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);
-
-  return authority->big_state->point_size;
-}
-
-void
-cogl_pipeline_set_point_size (CoglHandle handle,
-                              float      point_size)
-{
-  CoglPipeline *pipeline = COGL_PIPELINE (handle);
-  CoglPipelineState state = COGL_PIPELINE_STATE_POINT_SIZE;
-  CoglPipeline *authority;
-
-  g_return_if_fail (cogl_is_pipeline (handle));
-
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  if (authority->big_state->point_size == point_size)
-    return;
-
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
-  pipeline->big_state->point_size = point_size;
-
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_point_size_equal);
-}
-
 /* While a pipeline is referenced by the Cogl journal we can not allow
  * modifications, so this gives us a mechanism to track journal
  * references separately */
@@ -5831,17 +4668,10 @@ _cogl_pipeline_set_static_breadcrumb (CoglPipeline *pipeline,
   pipeline->static_breadcrumb = breadcrumb;
 }
 
-typedef struct _HashState
-{
-  unsigned long layer_differences;
-  CoglPipelineEvalFlags flags;
-  unsigned int hash;
-} HashState;
-
 static void
 _cogl_pipeline_layer_hash_unit_state (CoglPipelineLayer *authority,
                                       CoglPipelineLayer **authorities,
-                                      HashState *state)
+                                      CoglPipelineHashState *state)
 {
   int unit = authority->unit_index;
   state->hash =
@@ -5851,7 +4681,7 @@ _cogl_pipeline_layer_hash_unit_state (CoglPipelineLayer *authority,
 static void
 _cogl_pipeline_layer_hash_texture_target_state (CoglPipelineLayer *authority,
                                                 CoglPipelineLayer **authorities,
-                                                HashState *state)
+                                                CoglPipelineHashState *state)
 {
   GLenum gl_target = authority->target;
 
@@ -5862,7 +4692,7 @@ _cogl_pipeline_layer_hash_texture_target_state (CoglPipelineLayer *authority,
 static void
 _cogl_pipeline_layer_hash_texture_data_state (CoglPipelineLayer *authority,
                                               CoglPipelineLayer **authorities,
-                                              HashState *state)
+                                              CoglPipelineHashState *state)
 {
   GLuint gl_handle;
 
@@ -5875,7 +4705,7 @@ _cogl_pipeline_layer_hash_texture_data_state (CoglPipelineLayer *authority,
 static void
 _cogl_pipeline_layer_hash_filters_state (CoglPipelineLayer *authority,
                                          CoglPipelineLayer **authorities,
-                                         HashState *state)
+                                         CoglPipelineHashState *state)
 {
   unsigned int hash = state->hash;
   hash = _cogl_util_one_at_a_time_hash (hash, &authority->mag_filter,
@@ -5888,7 +4718,7 @@ _cogl_pipeline_layer_hash_filters_state (CoglPipelineLayer *authority,
 static void
 _cogl_pipeline_layer_hash_wrap_modes_state (CoglPipelineLayer *authority,
                                             CoglPipelineLayer **authorities,
-                                            HashState *state)
+                                            CoglPipelineHashState *state)
 {
   unsigned int hash = state->hash;
   hash = _cogl_util_one_at_a_time_hash (hash, &authority->wrap_mode_s,
@@ -5903,7 +4733,7 @@ _cogl_pipeline_layer_hash_wrap_modes_state (CoglPipelineLayer *authority,
 static void
 _cogl_pipeline_layer_hash_combine_state (CoglPipelineLayer *authority,
                                          CoglPipelineLayer **authorities,
-                                         HashState *state)
+                                         CoglPipelineHashState *state)
 {
   unsigned int hash = state->hash;
   CoglPipelineLayerBigState *b = authority->big_state;
@@ -5942,7 +4772,7 @@ _cogl_pipeline_layer_hash_combine_state (CoglPipelineLayer *authority,
 static void
 _cogl_pipeline_layer_hash_combine_constant_state (CoglPipelineLayer *authority,
                                                   CoglPipelineLayer **authorities,
-                                                  HashState *state)
+                                                  CoglPipelineHashState *state)
 {
   CoglPipelineLayerBigState *b = authority->big_state;
   gboolean need_hash = FALSE;
@@ -5992,7 +4822,7 @@ done:
 static void
 _cogl_pipeline_layer_hash_user_matrix_state (CoglPipelineLayer *authority,
                                              CoglPipelineLayer **authorities,
-                                             HashState *state)
+                                             CoglPipelineHashState *state)
 {
   CoglPipelineLayerBigState *big_state = authority->big_state;
   state->hash = _cogl_util_one_at_a_time_hash (state->hash, &big_state->matrix,
@@ -6002,7 +4832,7 @@ _cogl_pipeline_layer_hash_user_matrix_state (CoglPipelineLayer *authority,
 static void
 _cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority,
                                               CoglPipelineLayer **authorities,
-                                              HashState *state)
+                                              CoglPipelineHashState *state)
 {
   CoglPipelineLayerBigState *big_state = authority->big_state;
   state->hash =
@@ -6012,7 +4842,7 @@ _cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority,
 
 typedef void (*LayerStateHashFunction) (CoglPipelineLayer *authority,
                                         CoglPipelineLayer **authorities,
-                                        HashState *state);
+                                        CoglPipelineHashState *state);
 
 static LayerStateHashFunction
 layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
@@ -6052,7 +4882,7 @@ static gboolean
 _cogl_pipeline_hash_layer_cb (CoglPipelineLayer *layer,
                               void *user_data)
 {
-  HashState *state = user_data;
+  CoglPipelineHashState *state = user_data;
   unsigned long differences = state->layer_differences;
   CoglPipelineLayer *authorities[COGL_PIPELINE_LAYER_STATE_COUNT];
   unsigned long mask;
@@ -6095,25 +4925,9 @@ _cogl_pipeline_hash_layer_cb (CoglPipelineLayer *layer,
   return TRUE;
 }
 
-static void
-_cogl_pipeline_hash_color_state (CoglPipeline *authority,
-                                 HashState *state)
-{
-  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &authority->color,
-                                               _COGL_COLOR_DATA_SIZE);
-}
-
-static void
-_cogl_pipeline_hash_blend_enable_state (CoglPipeline *authority,
-                                        HashState *state)
-{
-  guint8 blend_enable = authority->blend_enable;
-  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &blend_enable, 1);
-}
-
-static void
+void
 _cogl_pipeline_hash_layers_state (CoglPipeline *authority,
-                                  HashState *state)
+                                  CoglPipelineHashState *state)
 {
   state->hash =
     _cogl_util_one_at_a_time_hash (state->hash, &authority->n_layers,
@@ -6123,162 +4937,7 @@ _cogl_pipeline_hash_layers_state (CoglPipeline *authority,
                                          state);
 }
 
-static void
-_cogl_pipeline_hash_lighting_state (CoglPipeline *authority,
-                                    HashState *state)
-{
-  CoglPipelineLightingState *lighting_state =
-    &authority->big_state->lighting_state;
-  state->hash =
-    _cogl_util_one_at_a_time_hash (state->hash, lighting_state,
-                                   sizeof (CoglPipelineLightingState));
-}
-
-static void
-_cogl_pipeline_hash_alpha_func_state (CoglPipeline *authority,
-                                      HashState *state)
-{
-  CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state;
-  state->hash =
-    _cogl_util_one_at_a_time_hash (state->hash, &alpha_state->alpha_func,
-                                   sizeof (alpha_state->alpha_func));
-}
-
-static void
-_cogl_pipeline_hash_alpha_func_reference_state (CoglPipeline *authority,
-                                                HashState *state)
-{
-  CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state;
-  float ref = alpha_state->alpha_func_reference;
-  state->hash =
-    _cogl_util_one_at_a_time_hash (state->hash, &ref, sizeof (float));
-}
-
-static void
-_cogl_pipeline_hash_blend_state (CoglPipeline *authority,
-                                 HashState *state)
-{
-  CoglPipelineBlendState *blend_state = &authority->big_state->blend_state;
-  unsigned int hash;
-
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  if (!authority->real_blend_enable)
-    return;
-
-  hash = state->hash;
-
-#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
-  if (ctx->driver != COGL_DRIVER_GLES1)
-    {
-      hash =
-        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb,
-                                       sizeof (blend_state->blend_equation_rgb));
-      hash =
-        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha,
-                                       sizeof (blend_state->blend_equation_alpha));
-      hash =
-        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha,
-                                       sizeof (blend_state->blend_src_factor_alpha));
-      hash =
-        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha,
-                                       sizeof (blend_state->blend_dst_factor_alpha));
-
-      if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-          blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
-          blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-          blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
-        {
-          hash =
-            _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant,
-                                           sizeof (blend_state->blend_constant));
-        }
-    }
-#endif
-
-  hash =
-    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_rgb,
-                                   sizeof (blend_state->blend_src_factor_rgb));
-  hash =
-    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_rgb,
-                                   sizeof (blend_state->blend_dst_factor_rgb));
-
-  state->hash = hash;
-}
-
-static void
-_cogl_pipeline_hash_user_shader_state (CoglPipeline *authority,
-                                       HashState *state)
-{
-  CoglHandle user_program = authority->big_state->user_program;
-  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &user_program,
-                                               sizeof (user_program));
-}
-
-static void
-_cogl_pipeline_hash_depth_state (CoglPipeline *authority,
-                                 HashState *state)
-{
-  CoglDepthState *depth_state = &authority->big_state->depth_state;
-  unsigned int hash = state->hash;
-
-  if (depth_state->test_enabled)
-    {
-      guint8 enabled = depth_state->test_enabled;
-      CoglDepthTestFunction function = depth_state->test_function;
-      hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled));
-      hash = _cogl_util_one_at_a_time_hash (hash, &function, sizeof (function));
-    }
-
-  if (depth_state->write_enabled)
-    {
-      guint8 enabled = depth_state->write_enabled;
-      float near_val = depth_state->range_near;
-      float far_val = depth_state->range_far;
-      hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled));
-      hash = _cogl_util_one_at_a_time_hash (hash, &near_val, sizeof (near_val));
-      hash = _cogl_util_one_at_a_time_hash (hash, &far_val, sizeof (far_val));
-    }
-
-  state->hash = hash;
-}
-
-static void
-_cogl_pipeline_hash_fog_state (CoglPipeline *authority,
-                               HashState *state)
-{
-  CoglPipelineFogState *fog_state = &authority->big_state->fog_state;
-  unsigned long hash = state->hash;
-
-  if (!fog_state->enabled)
-    hash = _cogl_util_one_at_a_time_hash (hash, &fog_state->enabled,
-                                          sizeof (fog_state->enabled));
-  else
-    hash = _cogl_util_one_at_a_time_hash (hash, &fog_state,
-                                          sizeof (CoglPipelineFogState));
-
-  state->hash = hash;
-}
-
-static void
-_cogl_pipeline_hash_point_size_state (CoglPipeline *authority,
-                                      HashState *state)
-{
-  float point_size = authority->big_state->point_size;
-  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &point_size,
-                                               sizeof (point_size));
-}
-
-static void
-_cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority,
-                                     HashState *state)
-{
-  CoglPipelineLogicOpsState *logic_ops_state = &authority->big_state->logic_ops_state;
-  state->hash = _cogl_util_one_at_a_time_hash (state->hash, &logic_ops_state->color_mask,
-                                               sizeof (CoglColorMask));
-}
-
-typedef void (*StateHashFunction) (CoglPipeline *authority, HashState *state);
+typedef void (*StateHashFunction) (CoglPipeline *authority, CoglPipelineHashState *state);
 
 static StateHashFunction
 state_hash_functions[COGL_PIPELINE_STATE_SPARSE_COUNT];
@@ -6327,7 +4986,7 @@ _cogl_pipeline_hash (CoglPipeline *pipeline,
   CoglPipeline *authorities[COGL_PIPELINE_STATE_SPARSE_COUNT];
   unsigned long mask;
   int i;
-  HashState state;
+  CoglPipelineHashState state;
   unsigned int final_hash = 0;
 
   state.hash = 0;
diff --git a/cogl/cogl-pipeline.h b/cogl/cogl-pipeline.h
index 15b100cd3..0bcbb35f1 100644
--- a/cogl/cogl-pipeline.h
+++ b/cogl/cogl-pipeline.h
@@ -172,562 +172,6 @@ cogl_pipeline_copy (CoglPipeline *source);
 gboolean
 cogl_is_pipeline (CoglHandle handle);
 
-/**
- * cogl_pipeline_set_color:
- * @pipeline: A #CoglPipeline object
- * @color: The components of the color
- *
- * Sets the basic color of the pipeline, used when no lighting is enabled.
- *
- * Note that if you don't add any layers to the pipeline then the color
- * will be blended unmodified with the destination; the default blend
- * expects premultiplied colors: for example, use (0.5, 0.0, 0.0, 0.5) for
- * semi-transparent red. See cogl_color_premultiply().
- *
- * The default value is (1.0, 1.0, 1.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_color (CoglPipeline    *pipeline,
-                         const CoglColor *color);
-
-/**
- * cogl_pipeline_set_color4ub:
- * @pipeline: A #CoglPipeline object
- * @red: The red component
- * @green: The green component
- * @blue: The blue component
- * @alpha: The alpha component
- *
- * Sets the basic color of the pipeline, used when no lighting is enabled.
- *
- * The default value is (0xff, 0xff, 0xff, 0xff)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_color4ub (CoglPipeline *pipeline,
-			    guint8        red,
-                            guint8        green,
-                            guint8        blue,
-                            guint8        alpha);
-
-/**
- * cogl_pipeline_set_color4f:
- * @pipeline: A #CoglPipeline object
- * @red: The red component
- * @green: The green component
- * @blue: The blue component
- * @alpha: The alpha component
- *
- * Sets the basic color of the pipeline, used when no lighting is enabled.
- *
- * The default value is (1.0, 1.0, 1.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_color4f (CoglPipeline *pipeline,
-                           float         red,
-                           float         green,
-                           float         blue,
-                           float         alpha);
-
-/**
- * cogl_pipeline_get_color:
- * @pipeline: A #CoglPipeline object
- * @color: (out): The location to store the color
- *
- * Retrieves the current pipeline color.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_color (CoglPipeline *pipeline,
-                         CoglColor    *color);
-
-/**
- * cogl_pipeline_set_ambient:
- * @pipeline: A #CoglPipeline object
- * @ambient: The components of the desired ambient color
- *
- * Sets the pipeline's ambient color, in the standard OpenGL lighting
- * model. The ambient color affects the overall color of the object.
- *
- * Since the diffuse color will be intense when the light hits the surface
- * directly, the ambient will be most apparent where the light hits at a
- * slant.
- *
- * The default value is (0.2, 0.2, 0.2, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_ambient (CoglPipeline    *pipeline,
-			   const CoglColor *ambient);
-
-/**
- * cogl_pipeline_get_ambient:
- * @pipeline: A #CoglPipeline object
- * @ambient: The location to store the ambient color
- *
- * Retrieves the current ambient color for @pipeline
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_ambient (CoglPipeline *pipeline,
-                           CoglColor    *ambient);
-
-/**
- * cogl_pipeline_set_diffuse:
- * @pipeline: A #CoglPipeline object
- * @diffuse: The components of the desired diffuse color
- *
- * Sets the pipeline's diffuse color, in the standard OpenGL lighting
- * model. The diffuse color is most intense where the light hits the
- * surface directly - perpendicular to the surface.
- *
- * The default value is (0.8, 0.8, 0.8, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_diffuse (CoglPipeline    *pipeline,
-			   const CoglColor *diffuse);
-
-/**
- * cogl_pipeline_get_diffuse:
- * @pipeline: A #CoglPipeline object
- * @diffuse: The location to store the diffuse color
- *
- * Retrieves the current diffuse color for @pipeline
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_diffuse (CoglPipeline *pipeline,
-                           CoglColor    *diffuse);
-
-/**
- * cogl_pipeline_set_ambient_and_diffuse:
- * @pipeline: A #CoglPipeline object
- * @color: The components of the desired ambient and diffuse colors
- *
- * Conveniently sets the diffuse and ambient color of @pipeline at the same
- * time. See cogl_pipeline_set_ambient() and cogl_pipeline_set_diffuse().
- *
- * The default ambient color is (0.2, 0.2, 0.2, 1.0)
- *
- * The default diffuse color is (0.8, 0.8, 0.8, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_ambient_and_diffuse (CoglPipeline    *pipeline,
-				       const CoglColor *color);
-
-/**
- * cogl_pipeline_set_specular:
- * @pipeline: A #CoglPipeline object
- * @specular: The components of the desired specular color
- *
- * Sets the pipeline's specular color, in the standard OpenGL lighting
- * model. The intensity of the specular color depends on the viewport
- * position, and is brightest along the lines of reflection.
- *
- * The default value is (0.0, 0.0, 0.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_specular (CoglPipeline    *pipeline,
-			    const CoglColor *specular);
-
-/**
- * cogl_pipeline_get_specular:
- * @pipeline: A #CoglPipeline object
- * @specular: The location to store the specular color
- *
- * Retrieves the pipelines current specular color.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_specular (CoglPipeline *pipeline,
-                            CoglColor    *specular);
-
-/**
- * cogl_pipeline_set_shininess:
- * @pipeline: A #CoglPipeline object
- * @shininess: The desired shininess; must be >= 0.0
- *
- * Sets the shininess of the pipeline, in the standard OpenGL lighting
- * model, which determines the size of the specular highlights. A
- * higher @shininess will produce smaller highlights which makes the
- * object appear more shiny.
- *
- * The default value is 0.0
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_shininess (CoglPipeline *pipeline,
-			     float         shininess);
-
-/**
- * cogl_pipeline_get_shininess:
- * @pipeline: A #CoglPipeline object
- *
- * Retrieves the pipelines current emission color.
- *
- * Return value: The pipelines current shininess value
- *
- * Since: 2.0
- */
-float
-cogl_pipeline_get_shininess (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_emission:
- * @pipeline: A #CoglPipeline object
- * @emission: The components of the desired emissive color
- *
- * Sets the pipeline's emissive color, in the standard OpenGL lighting
- * model. It will look like the surface is a light source emitting this
- * color.
- *
- * The default value is (0.0, 0.0, 0.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_emission (CoglPipeline    *pipeline,
-			    const CoglColor *emission);
-
-/**
- * cogl_pipeline_get_emission:
- * @pipeline: A #CoglPipeline object
- * @emission: The location to store the emission color
- *
- * Retrieves the pipelines current emission color.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_emission (CoglPipeline *pipeline,
-                            CoglColor    *emission);
-
-/**
- * CoglPipelineAlphaFunc:
- * @COGL_PIPELINE_ALPHA_FUNC_NEVER: Never let the fragment through.
- * @COGL_PIPELINE_ALPHA_FUNC_LESS: Let the fragment through if the incoming
- *   alpha value is less than the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_EQUAL: Let the fragment through if the incoming
- *   alpha value equals the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_LEQUAL: Let the fragment through if the incoming
- *   alpha value is less than or equal to the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_GREATER: Let the fragment through if the incoming
- *   alpha value is greater than the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL: Let the fragment through if the incoming
- *   alpha value does not equal the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_GEQUAL: Let the fragment through if the incoming
- *   alpha value is greater than or equal to the reference alpha value.
- * @COGL_PIPELINE_ALPHA_FUNC_ALWAYS: Always let the fragment through.
- *
- * Alpha testing happens before blending primitives with the framebuffer and
- * gives an opportunity to discard fragments based on a comparison with the
- * incoming alpha value and a reference alpha value. The #CoglPipelineAlphaFunc
- * determines how the comparison is done.
- */
-typedef enum {
-  COGL_PIPELINE_ALPHA_FUNC_NEVER    = 0x0200,
-  COGL_PIPELINE_ALPHA_FUNC_LESS	    = 0x0201,
-  COGL_PIPELINE_ALPHA_FUNC_EQUAL    = 0x0202,
-  COGL_PIPELINE_ALPHA_FUNC_LEQUAL   = 0x0203,
-  COGL_PIPELINE_ALPHA_FUNC_GREATER  = 0x0204,
-  COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL = 0x0205,
-  COGL_PIPELINE_ALPHA_FUNC_GEQUAL   = 0x0206,
-  COGL_PIPELINE_ALPHA_FUNC_ALWAYS   = 0x0207
-} CoglPipelineAlphaFunc;
-/* NB: these values come from the equivalents in gl.h */
-
-/**
- * cogl_pipeline_set_alpha_test_function:
- * @pipeline: A #CoglPipeline object
- * @alpha_func: A @CoglPipelineAlphaFunc constant
- * @alpha_reference: A reference point that the chosen alpha function uses
- *   to compare incoming fragments to.
- *
- * Before a primitive is blended with the framebuffer, it goes through an
- * alpha test stage which lets you discard fragments based on the current
- * alpha value. This function lets you change the function used to evaluate
- * the alpha channel, and thus determine which fragments are discarded
- * and which continue on to the blending stage.
- *
- * The default is %COGL_PIPELINE_ALPHA_FUNC_ALWAYS
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_alpha_test_function (CoglPipeline         *pipeline,
-				       CoglPipelineAlphaFunc alpha_func,
-				       float                 alpha_reference);
-
-/**
- * cogl_pipeline_get_alpha_test_function:
- * @pipeline: A #CoglPipeline object
- *
- * Return value: The alpha test function of @pipeline.
- *
- * Since: 2.0
- */
-CoglPipelineAlphaFunc
-cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_get_alpha_test_reference:
- * @pipeline: A #CoglPipeline object
- *
- * Return value: The alpha test reference value of @pipeline.
- *
- * Since: 2.0
- */
-float
-cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_blend:
- * @pipeline: A #CoglPipeline object
- * @blend_string: A <link linkend="cogl-Blend-Strings">Cogl blend string</link>
- *   describing the desired blend function.
- * @error: return location for a #GError that may report lack of driver
- *   support if you give separate blend string statements for the alpha
- *   channel and RGB channels since some drivers, or backends such as
- *   GLES 1.1, don't support this feature. May be %NULL, in which case a
- *   warning will be printed out using GLib's logging facilities if an
- *   error is encountered.
- *
- * If not already familiar; please refer <link linkend="cogl-Blend-Strings">here</link>
- * for an overview of what blend strings are, and their syntax.
- *
- * Blending occurs after the alpha test function, and combines fragments with
- * the framebuffer.
-
- * Currently the only blend function Cogl exposes is ADD(). So any valid
- * blend statements will be of the form:
- *
- * |[
- *   &lt;channel-mask&gt;=ADD(SRC_COLOR*(&lt;factor&gt;), DST_COLOR*(&lt;factor&gt;))
- * ]|
- *
- * This is the list of source-names usable as blend factors:
- * <itemizedlist>
- *   <listitem><para>SRC_COLOR: The color of the in comming fragment</para></listitem>
- *   <listitem><para>DST_COLOR: The color of the framebuffer</para></listitem>
- *   <listitem><para>CONSTANT: The constant set via cogl_pipeline_set_blend_constant()</para></listitem>
- * </itemizedlist>
- *
- * The source names can be used according to the
- * <link linkend="cogl-Blend-String-syntax">color-source and factor syntax</link>,
- * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would
- * "(CONSTANT[RGB])"
- *
- * These can also be used as factors:
- * <itemizedlist>
- *   <listitem>0: (0, 0, 0, 0)</listitem>
- *   <listitem>1: (1, 1, 1, 1)</listitem>
- *   <listitem>SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1) where f = MIN(SRC_COLOR[A],1-DST_COLOR[A])</listitem>
- * </itemizedlist>
- *
- * <note>Remember; all color components are normalized to the range [0, 1]
- * before computing the result of blending.</note>
- *
- * <example id="cogl-Blend-Strings-blend-unpremul">
- *   <title>Blend Strings/1</title>
- *   <para>Blend a non-premultiplied source over a destination with
- *   premultiplied alpha:</para>
- *   <programlisting>
- * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))"
- * "A   = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
- *   </programlisting>
- * </example>
- *
- * <example id="cogl-Blend-Strings-blend-premul">
- *   <title>Blend Strings/2</title>
- *   <para>Blend a premultiplied source over a destination with
- *   premultiplied alpha</para>
- *   <programlisting>
- * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
- *   </programlisting>
- * </example>
- *
- * The default blend string is:
- * |[
- *    RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))
- * ]|
- *
- * That gives normal alpha-blending when the calculated color for the pipeline
- * is in premultiplied form.
- *
- * Return value: %TRUE if the blend string was successfully parsed, and the
- *   described blending is supported by the underlying driver/hardware. If
- *   there was an error, %FALSE is returned and @error is set accordingly (if
- *   present).
- *
- * Since: 2.0
- */
-gboolean
-cogl_pipeline_set_blend (CoglPipeline *pipeline,
-                         const char   *blend_string,
-                         GError      **error);
-
-/**
- * cogl_pipeline_set_blend_constant:
- * @pipeline: A #CoglPipeline object
- * @constant_color: The constant color you want
- *
- * When blending is setup to reference a CONSTANT blend factor then
- * blending will depend on the constant set with this function.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
-                                  const CoglColor *constant_color);
-
-/**
- * cogl_pipeline_set_point_size:
- * @pipeline: a #CoglHandle to a pipeline.
- * @point_size: the new point size.
- *
- * Changes the size of points drawn when %COGL_VERTICES_MODE_POINTS is
- * used with the vertex buffer API. Note that typically the GPU will
- * only support a limited minimum and maximum range of point sizes. If
- * the chosen point size is outside that range then the nearest value
- * within that range will be used instead. The size of a point is in
- * screen space so it will be the same regardless of any
- * transformations. The default point size is 1.0.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_point_size (CoglHandle pipeline,
-                              float      point_size);
-
-/**
- * cogl_pipeline_get_point_size:
- * @pipeline: a #CoglHandle to a pipeline.
- *
- * Get the size of points drawn when %COGL_VERTICES_MODE_POINTS is
- * used with the vertex buffer API.
- *
- * Return value: the point size of the pipeline.
- *
- * Since: 2.0
- */
-float
-cogl_pipeline_get_point_size (CoglHandle  pipeline);
-
-#define cogl_pipeline_get_color_mask cogl_pipeline_get_color_mask_EXP
-/**
- * cogl_pipeline_get_color_mask:
- * @pipeline: a #CoglPipeline object.
- *
- * Gets the current #CoglColorMask of which channels would be written to the
- * current framebuffer. Each bit set in the mask means that the
- * corresponding color would be written.
- *
- * Returns: A #CoglColorMask
- * Since: 1.8
- * Stability: unstable
- */
-CoglColorMask
-cogl_pipeline_get_color_mask (CoglPipeline *pipeline);
-
-#define cogl_pipeline_set_color_mask cogl_pipeline_set_color_mask_EXP
-/**
- * cogl_pipeline_set_color_mask:
- * @pipeline: a #CoglPipeline object.
- * @color_mask: A #CoglColorMask of which color channels to write to
- *              the current framebuffer.
- *
- * Defines a bit mask of which color channels should be written to the
- * current framebuffer. If a bit is set in @color_mask that means that
- * color will be written.
- *
- * Since: 1.8
- * Stability: unstable
- */
-void
-cogl_pipeline_set_color_mask (CoglPipeline *pipeline,
-                              CoglColorMask color_mask);
-
-/**
- * cogl_pipeline_get_user_program:
- * @pipeline: a #CoglPipeline object.
- *
- * Queries what user program has been associated with the given
- * @pipeline using cogl_pipeline_set_user_program().
- *
- * Return value: The current user program or %COGL_INVALID_HANDLE.
- *
- * Since: 2.0
- */
-CoglHandle
-cogl_pipeline_get_user_program (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_user_program:
- * @pipeline: a #CoglPipeline object.
- * @program: A #CoglHandle to a linked CoglProgram
- *
- * Associates a linked CoglProgram with the given pipeline so that the
- * program can take full control of vertex and/or fragment processing.
- *
- * This is an example of how it can be used to associate an ARBfp
- * program with a #CoglPipeline:
- * |[
- * CoglHandle shader;
- * CoglHandle program;
- * CoglPipeline *pipeline;
- *
- * shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
- * cogl_shader_source (shader,
- *                     "!!ARBfp1.0\n"
- *                     "MOV result.color,fragment.color;\n"
- *                     "END\n");
- * cogl_shader_compile (shader);
- *
- * program = cogl_create_program ();
- * cogl_program_attach_shader (program, shader);
- * cogl_program_link (program);
- *
- * pipeline = cogl_pipeline_new ();
- * cogl_pipeline_set_user_program (pipeline, program);
- *
- * cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
- * cogl_rectangle (0, 0, 100, 100);
- * ]|
- *
- * It is possibly worth keeping in mind that this API is not part of
- * the long term design for how we want to expose shaders to Cogl
- * developers (We are planning on deprecating the cogl_program and
- * cogl_shader APIs in favour of a "snippet" framework) but in the
- * meantime we hope this will handle most practical GLSL and ARBfp
- * requirements.
- *
- * Also remember you need to check for either the
- * %COGL_FEATURE_SHADERS_GLSL or %COGL_FEATURE_SHADERS_ARBFP before
- * using the cogl_program or cogl_shader API.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_user_program (CoglPipeline *pipeline,
-                                CoglHandle program);
-
 /**
  * cogl_pipeline_set_layer:
  * @pipeline: A #CoglPipeline object
@@ -1084,46 +528,6 @@ cogl_pipeline_set_layer_wrap_mode (CoglPipeline        *pipeline,
 
 #ifdef COGL_ENABLE_EXPERIMENTAL_API
 
-/**
- * cogl_pipeline_set_depth_state:
- * @pipeline: A #CoglPipeline object
- * @state: A #CoglDepthState struct
- * @error: A #GError to report failures to setup the given @state.
- *
- * This commits all the depth state configured in @state struct to the
- * given @pipeline. The configuration values are copied into the
- * pipeline so there is no requirement to keep the #CoglDepthState
- * struct around if you don't need it any more.
- *
- * Note: Since some platforms do not support the depth range feature
- * it is possible for this function to fail and report an @error.
- *
- * Returns: TRUE if the GPU supports all the given @state else %FALSE
- *          and returns an @error.
- *
- * Since: 2.0
- * Stability: Unstable
- */
-gboolean
-cogl_pipeline_set_depth_state (CoglPipeline *pipeline,
-                               const CoglDepthState *state,
-                               GError **error);
-
-/**
- * cogl_pipeline_get_depth_state
- * @pipeline: A #CoglPipeline object
- * @state: A destination #CoglDepthState struct
- *
- * Retrieves the current depth state configuration for the given
- * @pipeline as previously set using cogl_pipeline_set_depth_state().
- *
- * Since: 2.0
- * Stability: Unstable
- */
-void
-cogl_pipeline_get_depth_state (CoglPipeline *pipeline,
-                               CoglDepthState *state_out);
-
 /**
  * CoglPipelineLayerCallback:
  * @pipeline: The #CoglPipeline whos layers are being iterated
diff --git a/cogl/cogl.h b/cogl/cogl.h
index ff7f8f46b..6d433c293 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -88,6 +88,7 @@ typedef struct _CoglFramebuffer CoglFramebuffer;
 #include <cogl/cogl-primitive.h>
 #include <cogl/cogl-depth-state.h>
 #include <cogl/cogl-pipeline.h>
+#include <cogl/cogl-pipeline-state.h>
 #include <cogl/cogl-framebuffer.h>
 #ifdef COGL_HAS_XLIB
 #include <cogl/cogl-xlib.h>
diff --git a/doc/reference/cogl-2.0-experimental/Makefile.am b/doc/reference/cogl-2.0-experimental/Makefile.am
index 051714935..b2b9b2f4e 100644
--- a/doc/reference/cogl-2.0-experimental/Makefile.am
+++ b/doc/reference/cogl-2.0-experimental/Makefile.am
@@ -74,6 +74,7 @@ IGNORE_HFILES=\
 	cogl-pipeline-fragend-glsl-private.h	\
 	cogl-pipeline-opengl-private.h		\
 	cogl-pipeline-private.h			\
+	cogl-pipeline-state-private.h		\
 	cogl-pipeline-progend-glsl-private.h	\
 	cogl-pipeline-vertend-fixed-private.h	\
 	cogl-pipeline-vertend-glsl-private.h	\
diff --git a/doc/reference/cogl/Makefile.am b/doc/reference/cogl/Makefile.am
index ef416e496..e4cd24b99 100644
--- a/doc/reference/cogl/Makefile.am
+++ b/doc/reference/cogl/Makefile.am
@@ -72,6 +72,7 @@ IGNORE_HFILES=\
 	cogl-pipeline-fragend-glsl-private.h	\
 	cogl-pipeline-opengl-private.h		\
 	cogl-pipeline-private.h			\
+	cogl-pipeline-state-private.h		\
 	cogl-pipeline-progend-glsl-private.h	\
 	cogl-pipeline-vertend-fixed-private.h	\
 	cogl-pipeline-vertend-glsl-private.h	\