diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index 120793dd7..9f33274bb 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -298,7 +298,6 @@ add_stencil_clip_rectangle (float x_1,
float y_2,
gboolean first)
{
- CoglHandle current_source;
CoglFramebuffer *framebuffer = _cogl_get_framebuffer ();
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -310,8 +309,7 @@ add_stencil_clip_rectangle (float x_1,
_cogl_framebuffer_flush_state (framebuffer, 0);
/* temporarily swap in our special stenciling material */
- current_source = cogl_object_ref (ctx->source_material);
- cogl_set_source (ctx->stencil_material);
+ cogl_push_source (ctx->stencil_material);
if (first)
{
@@ -370,8 +368,7 @@ add_stencil_clip_rectangle (float x_1,
GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
/* restore the original source material */
- cogl_set_source (current_source);
- cogl_object_unref (current_source);
+ cogl_pop_source ();
}
static void
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 5b3418a5a..38954caf6 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -130,8 +130,8 @@ cogl_create_context (void)
_context->legacy_fog_state.enabled = FALSE;
_context->simple_material = cogl_material_new ();
- _context->source_material = NULL;
_context->arbfp_source_buffer = g_string_new ("");
+ _context->source_stack = NULL;
_context->legacy_state_set = 0;
@@ -226,8 +226,8 @@ cogl_create_context (void)
0, /* auto calc row stride */
default_texture_data);
- cogl_set_source (_context->simple_material);
- _cogl_material_flush_gl_state (_context->source_material, FALSE);
+ cogl_push_source (_context->simple_material);
+ _cogl_material_flush_gl_state (_context->simple_material, FALSE);
_cogl_enable (enable_flags);
_cogl_flush_face_winding ();
diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h
index 028b79fa7..50eef3556 100644
--- a/cogl/cogl-context.h
+++ b/cogl/cogl-context.h
@@ -84,8 +84,8 @@ typedef struct
/* Materials */
CoglMaterial *simple_material;
- CoglMaterial *source_material;
GString *arbfp_source_buffer;
+ GList *source_stack;
int legacy_state_set;
diff --git a/cogl/cogl-material-private.h b/cogl/cogl-material-private.h
index 1a3915217..b3820e25d 100644
--- a/cogl/cogl-material-private.h
+++ b/cogl/cogl-material-private.h
@@ -919,5 +919,8 @@ _cogl_material_get_layer_combine_constant (CoglMaterial *material,
int layer_index,
float *constant);
+void
+_cogl_material_prune_to_n_layers (CoglMaterial *material, int n);
+
#endif /* __COGL_MATERIAL_PRIVATE_H */
diff --git a/cogl/cogl-path.c b/cogl/cogl-path.c
index 904b7ef65..2ac194975 100644
--- a/cogl/cogl-path.c
+++ b/cogl/cogl-path.c
@@ -181,7 +181,8 @@ _cogl_path_stroke_nodes (void)
unsigned int path_start = 0;
unsigned long enable_flags = COGL_ENABLE_VERTEX_ARRAY;
CoglPathData *data;
- CoglHandle source;
+ CoglMaterial *copy = NULL;
+ CoglMaterial *source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -198,25 +199,25 @@ _cogl_path_stroke_nodes (void)
if (G_UNLIKELY (ctx->legacy_state_set))
{
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_apply_legacy_state (source);
+ CoglMaterial *users_source = cogl_get_source ();
+ copy = cogl_material_copy (users_source);
+ _cogl_material_apply_legacy_state (copy);
+ source = copy;
}
else
- source = ctx->source_material;
+ source = cogl_get_source ();
if (cogl_material_get_n_layers (source) != 0)
{
- CoglMaterialFlushOptions options;
- options.flags = COGL_MATERIAL_FLUSH_DISABLE_MASK;
- /* disable all texture layers */
- options.disable_layers = (guint32)~0;
-
- /* If we haven't already created a derived material... */
- if (source == ctx->source_material)
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_apply_overrides (source, &options);
+ /* If we haven't already created a derivative material... */
+ if (!copy)
+ copy = cogl_material_copy (source);
+ _cogl_material_prune_to_n_layers (copy, 0);
+ source = copy;
}
+ cogl_push_source (source);
+
_cogl_material_flush_gl_state (source, FALSE);
/* Disable all client texture coordinate arrays */
@@ -234,8 +235,7 @@ _cogl_path_stroke_nodes (void)
path_start += node->path_size;
}
- if (G_UNLIKELY (source != ctx->source_material))
- cogl_handle_unref (source);
+ cogl_pop_source ();
}
void
@@ -308,7 +308,7 @@ _cogl_path_fill_nodes (CoglPath *path)
textures or textures with waste then it won't work to draw the
path directly. Instead we can use draw the texture as a quad
clipped to the stencil buffer. */
- for (l = cogl_material_get_layers (ctx->source_material); l; l = l->next)
+ for (l = cogl_material_get_layers (cogl_get_source ()); l; l = l->next)
{
CoglHandle layer = l->data;
CoglHandle texture = cogl_material_layer_get_texture (layer);
@@ -352,7 +352,6 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path,
{
CoglPathData *data = path->data;
unsigned long enable_flags = COGL_ENABLE_VERTEX_ARRAY;
- CoglHandle prev_source;
CoglFramebuffer *framebuffer = _cogl_get_framebuffer ();
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
@@ -371,10 +370,9 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path,
_cogl_framebuffer_flush_state (framebuffer, 0);
/* Just setup a simple material that doesn't use texturing... */
- prev_source = cogl_object_ref (ctx->source_material);
- cogl_set_source (ctx->stencil_material);
+ cogl_push_source (ctx->stencil_material);
- _cogl_material_flush_gl_state (ctx->source_material, FALSE);
+ _cogl_material_flush_gl_state (ctx->stencil_material, FALSE);
_cogl_enable (enable_flags);
@@ -464,8 +462,7 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path,
GE (glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP));
/* restore the original material */
- cogl_set_source (prev_source);
- cogl_object_unref (prev_source);
+ cogl_pop_source ();
}
void
diff --git a/cogl/cogl-primitives.c b/cogl/cogl-primitives.c
index f380795bf..8f0c41a87 100644
--- a/cogl/cogl-primitives.c
+++ b/cogl/cogl-primitives.c
@@ -495,17 +495,17 @@ _cogl_rectangles_with_multitexture_coords (
struct _CoglMutiTexturedRect *rects,
int n_rects)
{
- CoglHandle material;
- const GList *layers;
- int n_layers;
- const GList *tmp;
- guint32 fallback_layers = 0;
- gboolean all_use_sliced_quad_fallback = FALSE;
- int i;
+ CoglMaterial *material;
+ const GList *layers;
+ int n_layers;
+ const GList *tmp;
+ guint32 fallback_layers = 0;
+ gboolean all_use_sliced_quad_fallback = FALSE;
+ int i;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- material = ctx->source_material;
+ material = cogl_get_source ();
layers = cogl_material_get_layers (material);
n_layers = cogl_material_get_n_layers (material);
@@ -839,7 +839,7 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
float virtual_origin_y;
float v_to_s_scale_x;
float v_to_s_scale_y;
- CoglHandle source;
+ CoglMaterial *source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -868,13 +868,10 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
v += state->stride;
}
+ source = cogl_material_copy (cogl_get_source ());
+
if (G_UNLIKELY (ctx->legacy_state_set))
- {
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_apply_legacy_state (source);
- }
- else
- source = ctx->source_material;
+ _cogl_material_apply_legacy_state (source);
options.flags =
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE |
@@ -904,16 +901,13 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
}
/* If we haven't already created a derived material... */
- if (source == ctx->source_material)
- source = cogl_material_copy (ctx->source_material);
_cogl_material_apply_overrides (source, &options);
_cogl_material_flush_gl_state (source, FALSE);
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, state->n_vertices));
- if (G_UNLIKELY (source != ctx->source_material))
- cogl_handle_unref (source);
+ cogl_handle_unref (source);
}
/* handles 2d-sliced textures with > 1 slice */
@@ -934,7 +928,7 @@ _cogl_texture_polygon_multiple_primitives (const CoglTextureVertex *vertices,
/* We can assume in this case that we have at least one layer in the
* material that corresponds to a sliced cogl texture */
- layers = cogl_material_get_layers (ctx->source_material);
+ layers = cogl_material_get_layers (cogl_get_source ());
layer0 = (CoglHandle)layers->data;
tex_handle = cogl_material_layer_get_texture (layer0);
@@ -986,11 +980,12 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
GList *tmp;
GLfloat *v;
CoglMaterialFlushOptions options;
- CoglHandle source;
+ CoglMaterial *copy = NULL;
+ CoglMaterial *source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- material = ctx->source_material;
+ material = cogl_get_source ();
layers = cogl_material_get_layers (material);
/* Convert the vertices into an array of GLfloats ready to pass to
@@ -1045,11 +1040,12 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
if (G_UNLIKELY (ctx->legacy_state_set))
{
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_apply_legacy_state (source);
+ copy = cogl_material_copy (cogl_get_source ());
+ _cogl_material_apply_legacy_state (copy);
+ source = copy;
}
else
- source = ctx->source_material;
+ source = cogl_get_source ();
options.flags = 0;
@@ -1066,17 +1062,20 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
if (options.flags)
{
/* If we haven't already created a derived material... */
- if (source == ctx->source_material)
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_apply_overrides (source, &options);
+ if (!copy)
+ {
+ copy = cogl_material_copy (source);
+ source = copy;
+ }
+ _cogl_material_apply_overrides (copy, &options);
}
_cogl_material_flush_gl_state (source, use_color);
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
- if (G_UNLIKELY (source != ctx->source_material))
- cogl_handle_unref (source);
+ if (G_UNLIKELY (copy))
+ cogl_handle_unref (copy);
}
void
@@ -1084,7 +1083,8 @@ cogl_polygon (const CoglTextureVertex *vertices,
unsigned int n_vertices,
gboolean use_color)
{
- CoglHandle material;
+ CoglMaterial *material;
+ CoglMaterial *copy = NULL;
const GList *layers, *tmp;
int n_layers;
gboolean use_sliced_polygon_fallback = FALSE;
@@ -1096,8 +1096,6 @@ cogl_polygon (const CoglTextureVertex *vertices,
GLfloat *v;
CoglMaterialWrapModeOverrides wrap_mode_overrides;
CoglMaterialWrapModeOverrides *wrap_mode_overrides_p = NULL;
- CoglHandle original_source_material = NULL;
- gboolean overrode_material = FALSE;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -1108,8 +1106,8 @@ cogl_polygon (const CoglTextureVertex *vertices,
* always be done first when preparing to draw. */
_cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
- material = ctx->source_material;
- layers = cogl_material_get_layers (ctx->source_material);
+ material = cogl_get_source ();
+ layers = cogl_material_get_layers (material);
n_layers = g_list_length ((GList *)layers);
memset (&wrap_mode_overrides, 0, sizeof (wrap_mode_overrides));
@@ -1237,24 +1235,19 @@ cogl_polygon (const CoglTextureVertex *vertices,
if (use_color)
{
- CoglHandle override;
enable_flags |= COGL_ENABLE_COLOR_ARRAY;
GE( glColorPointer (4, GL_UNSIGNED_BYTE,
stride_bytes,
/* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
v + 3 + 2 * n_layers) );
- if (!_cogl_material_get_real_blend_enabled (ctx->source_material))
+ if (!_cogl_material_get_real_blend_enabled (material))
{
CoglMaterialBlendEnable blend_enabled =
COGL_MATERIAL_BLEND_ENABLE_ENABLED;
- original_source_material = ctx->source_material;
- override = cogl_material_copy (original_source_material);
- _cogl_material_set_blend_enabled (override, blend_enabled);
-
- /* XXX: cogl_push_source () */
- overrode_material = TRUE;
- ctx->source_material = override;
+ copy = cogl_material_copy (material);
+ _cogl_material_set_blend_enabled (copy, blend_enabled);
+ material = copy;
}
}
@@ -1277,6 +1270,8 @@ cogl_polygon (const CoglTextureVertex *vertices,
_cogl_bitmask_set_range (&ctx->temp_bitmask, n_layers, TRUE);
_cogl_disable_other_texcoord_arrays (&ctx->temp_bitmask);
+ cogl_push_source (material);
+
if (use_sliced_polygon_fallback)
_cogl_texture_polygon_multiple_primitives (vertices,
n_vertices,
@@ -1291,15 +1286,13 @@ cogl_polygon (const CoglTextureVertex *vertices,
fallback_layers,
wrap_mode_overrides_p);
- /* XXX: cogl_pop_source () */
- if (overrode_material)
- {
- cogl_handle_unref (ctx->source_material);
- ctx->source_material = original_source_material;
- /* XXX: when we have weak materials then any override material
- * should get associated with the original material so we don't
- * create lots of one-shot materials! */
- }
+ cogl_pop_source ();
+
+ if (copy)
+ cogl_object_unref (copy);
+ /* XXX: when we have weak materials then any override material
+ * should get associated with the original material so we don't
+ * create lots of one-shot materials! */
/* Reset the size of the logged vertex array because rendering
rectangles expects it to start at 0 */
diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
index 157d62720..22b0a1fdf 100644
--- a/cogl/cogl-texture.c
+++ b/cogl/cogl-texture.c
@@ -1047,7 +1047,6 @@ _cogl_texture_draw_and_read (CoglHandle handle,
CoglFramebuffer *framebuffer;
int viewport[4];
CoglBitmap *alpha_bmp;
- CoglHandle prev_source;
CoglMatrixStack *projection_stack;
CoglMatrixStack *modelview_stack;
int target_width = _cogl_bitmap_get_width (target_bmp);
@@ -1093,8 +1092,7 @@ _cogl_texture_draw_and_read (CoglHandle handle,
NULL);
}
- prev_source = cogl_handle_ref (ctx->source_material);
- cogl_set_source (ctx->texture_download_material);
+ cogl_push_source (ctx->texture_download_material);
cogl_material_set_layer (ctx->texture_download_material, 0, handle);
@@ -1178,8 +1176,7 @@ _cogl_texture_draw_and_read (CoglHandle handle,
_cogl_matrix_stack_pop (projection_stack);
/* restore the original material */
- cogl_set_source (prev_source);
- cogl_handle_unref (prev_source);
+ cogl_pop_source ();
return TRUE;
}
diff --git a/cogl/cogl-vertex-buffer.c b/cogl/cogl-vertex-buffer.c
index 65f275a65..31522e6d6 100644
--- a/cogl/cogl-vertex-buffer.c
+++ b/cogl/cogl-vertex-buffer.c
@@ -1524,11 +1524,12 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
int i;
gboolean skip_gl_color = FALSE;
CoglMaterialFlushOptions options;
- CoglHandle source;
+ CoglMaterial *source;
+ CoglMaterial *copy = NULL;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
- source = ctx->source_material;
+ source = cogl_get_source ();
if (buffer->new_attributes)
cogl_vertex_buffer_submit_real (buffer);
@@ -1592,12 +1593,13 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
attribute->stride,
pointer));
- if (!_cogl_material_get_real_blend_enabled (ctx->source_material))
+ if (!_cogl_material_get_real_blend_enabled (source))
{
CoglMaterialBlendEnable blend_enable =
COGL_MATERIAL_BLEND_ENABLE_ENABLED;
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_set_blend_enabled (source, blend_enable);
+ copy = cogl_material_copy (source);
+ _cogl_material_set_blend_enabled (copy, blend_enable);
+ source = copy;
skip_gl_color = TRUE;
}
break;
@@ -1745,9 +1747,12 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
if (G_UNLIKELY (options.flags))
{
/* If we haven't already created a derived material... */
- if (source == ctx->source_material)
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_apply_overrides (source, &options);
+ if (!copy)
+ {
+ copy = cogl_material_copy (source);
+ source = copy;
+ }
+ _cogl_material_apply_overrides (copy, &options);
/* TODO:
* overrides = cogl_material_get_data (material,
@@ -1770,7 +1775,7 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
* {
* overrides = g_slice_new (Overrides);
* overrides->weak_material =
- * cogl_material_weak_copy (ctx->source_material);
+ * cogl_material_weak_copy (source);
* _cogl_material_apply_overrides (overrides->weak_material,
* &options);
*
@@ -1786,9 +1791,12 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
if (G_UNLIKELY (ctx->legacy_state_set))
{
/* If we haven't already created a derived material... */
- if (source == ctx->source_material)
- source = cogl_material_copy (ctx->source_material);
- _cogl_material_apply_legacy_state (source);
+ if (!copy)
+ {
+ copy = cogl_material_copy (source);
+ source = copy;
+ }
+ _cogl_material_apply_legacy_state (copy);
}
_cogl_material_flush_gl_state (source, skip_gl_color);
@@ -1804,7 +1812,7 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
static void
disable_state_for_drawing_buffer (CoglVertexBuffer *buffer,
- CoglHandle source)
+ CoglMaterial *source)
{
GList *tmp;
GLenum gl_type;
@@ -1814,8 +1822,8 @@ disable_state_for_drawing_buffer (CoglVertexBuffer *buffer,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- if (G_UNLIKELY (source != ctx->source_material))
- cogl_handle_unref (source);
+ if (G_UNLIKELY (source != cogl_get_source ()))
+ cogl_object_unref (source);
/* Disable all the client state that cogl doesn't currently know
* about:
diff --git a/cogl/cogl.c b/cogl/cogl.c
index 6ec98e07e..8392caf91 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -756,7 +756,7 @@ cogl_begin_gl (void)
* A user should instead call cogl_set_source_color4ub() before
* cogl_begin_gl() to simplify the state flushed.
*/
- _cogl_material_flush_gl_state (ctx->source_material, FALSE);
+ _cogl_material_flush_gl_state (cogl_get_source (), FALSE);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
@@ -946,22 +946,113 @@ _cogl_driver_error_quark (void)
return g_quark_from_static_string ("cogl-driver-error-quark");
}
-void
-cogl_set_source (CoglHandle material_handle)
+typedef struct _CoglSourceState
{
+ CoglMaterial *material;
+ int push_count;
+} CoglSourceState;
+
+static void
+_push_source_real (CoglMaterial *material)
+{
+ CoglSourceState *top = g_slice_new (CoglSourceState);
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- g_return_if_fail (cogl_is_material (material_handle));
+ top->material = cogl_object_ref (material);
+ top->push_count = 1;
- if (ctx->source_material == material_handle)
+ ctx->source_stack = g_list_prepend (ctx->source_stack, top);
+}
+
+/* FIXME: This should take a context pointer for Cogl 2.0 Technically
+ * we could make it so we can retrieve a context reference from the
+ * material, but this would not by symmetric with cogl_pop_source. */
+void
+cogl_push_source (CoglMaterial *material)
+{
+ CoglSourceState *top;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ g_return_if_fail (cogl_is_material (material));
+
+ if (ctx->source_stack)
+ {
+ top = ctx->source_stack->data;
+ if (top->material == material)
+ {
+ top->push_count++;
+ return;
+ }
+ else
+ _push_source_real (material);
+ }
+ else
+ _push_source_real (material);
+}
+
+/* FIXME: This needs to take a context pointer for Cogl 2.0 */
+void
+cogl_pop_source (void)
+{
+ CoglSourceState *top;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ g_return_if_fail (ctx->source_stack);
+
+ top = ctx->source_stack->data;
+ top->push_count--;
+ if (top->push_count == 0)
+ {
+ cogl_object_unref (top->material);
+ g_slice_free (CoglSourceState, top);
+ ctx->source_stack = g_list_delete_link (ctx->source_stack,
+ ctx->source_stack);
+ }
+}
+
+/* FIXME: This needs to take a context pointer for Cogl 2.0 */
+CoglMaterial *
+cogl_get_source (void)
+{
+ CoglSourceState *top;
+
+ _COGL_GET_CONTEXT (ctx, NULL);
+
+ g_return_val_if_fail (ctx->source_stack, NULL);
+
+ top = ctx->source_stack->data;
+ return top->material;
+}
+
+void
+cogl_set_source (CoglMaterial *material)
+{
+ CoglSourceState *top;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ g_return_if_fail (cogl_is_material (material));
+ g_return_if_fail (ctx->source_stack);
+
+ top = ctx->source_stack->data;
+ if (top->material == material)
return;
- cogl_handle_ref (material_handle);
-
- if (ctx->source_material)
- cogl_handle_unref (ctx->source_material);
-
- ctx->source_material = material_handle;
+ if (top->push_count == 1)
+ {
+ /* NB: top->material may be only thing keeping material
+ * alive currently so ref material first... */
+ cogl_object_ref (material);
+ cogl_object_unref (top->material);
+ top->material = material;
+ }
+ else
+ {
+ top->push_count--;
+ cogl_push_source (material);
+ }
}
void
diff --git a/cogl/cogl.h b/cogl/cogl.h
index 8d17880a4..4427aff82 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -574,19 +574,61 @@ cogl_clear (const CoglColor *color,
/**
* cogl_set_source:
- * @material: A #CoglHandle for a material
+ * @material: A #CoglMaterial
*
- * This function sets the source material that will be used to fill subsequent
- * geometry emitted via the cogl API.
- *
- * In the future we may add the ability to set a front facing material,
- * and a back facing material, in which case this function will set both to the
- * same.
+ * This function changes the material at the top of the source stack.
+ * The material at the top of this stack defines the GPU state used to
+ * process subsequent primitives, such as rectangles drawn with
+ * cogl_rectangle() or vertices drawn using cogl_vertex_buffer_draw().
*
* Since: 1.0
*/
void
-cogl_set_source (CoglHandle material);
+cogl_set_source (CoglMaterial *material);
+
+/**
+ * cogl_get_source:
+ *
+ * Returns the current source material as previously set using
+ * cogl_set_source().
+ *
+ * You should typically consider the returned material immutable
+ * and not try to change any of its properties unless you own a
+ * reference to that material. At times you may be able to get a
+ * reference to an internally managed materials and the result of
+ * modifying such materials is undefined.
+ *
+ * Return value: The current source material.
+ *
+ * Since: 1.6
+ */
+CoglMaterial *
+cogl_get_source (void);
+
+/**
+ * cogl_push_source:
+ * @material: A #CoglMaterial
+ *
+ * Pushes the given @material to the top of the source stack. The
+ * material at the top of this stack defines the GPU state used to
+ * process later primitives as defined by cogl_set_source().
+ *
+ * Since: 1.6
+ */
+void
+cogl_push_source (CoglMaterial *material);
+
+/**
+ * cogl_pop_source:
+ *
+ * Removes the material at the top of the source stack. The material
+ * at the top of this stack defines the GPU state used to process
+ * later primitives as defined by cogl_set_source().
+ *
+ * Since: 1.6
+ */
+void
+cogl_pop_source (void);
/**
* cogl_set_source_color:
diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt
index 8acacc786..d6c0cb74f 100644
--- a/doc/reference/cogl/cogl-sections.txt
+++ b/doc/reference/cogl/cogl-sections.txt
@@ -61,6 +61,9 @@ cogl_set_source_color
cogl_set_source_color4ub
cogl_set_source_color4f
cogl_set_source_texture
+cogl_get_source
+cogl_push_source
+cogl_pop_source
CoglReadPixelsFlags