/* Calls should work under both GL and GLES, note GLES needs RGBA */
glGetIntegerv(GL_VIEWPORT, viewport);
+ /* Make sure Cogl flushes any batched geometry to the GPU driver */
+ _cogl_flush ();
+
/* Read the color of the screen co-ords pixel */
glReadPixels (x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
G_BEGIN_DECLS
typedef enum {
- COGL_DEBUG_MISC = 1 << 0,
- COGL_DEBUG_TEXTURE = 1 << 1,
- COGL_DEBUG_MATERIAL = 1 << 2,
- COGL_DEBUG_SHADER = 1 << 3,
- COGL_DEBUG_OFFSCREEN = 1 << 4,
- COGL_DEBUG_DRAW = 1 << 5,
- COGL_DEBUG_PANGO = 1 << 6,
- COGL_DEBUG_RECTANGLES = 1 << 7,
- COGL_DEBUG_HANDLE = 1 << 8,
- COGL_DEBUG_BLEND_STRINGS = 1 << 9
+ COGL_DEBUG_MISC = 1 << 0,
+ COGL_DEBUG_TEXTURE = 1 << 1,
+ COGL_DEBUG_MATERIAL = 1 << 2,
+ COGL_DEBUG_SHADER = 1 << 3,
+ COGL_DEBUG_OFFSCREEN = 1 << 4,
+ COGL_DEBUG_DRAW = 1 << 5,
+ COGL_DEBUG_PANGO = 1 << 6,
+ COGL_DEBUG_RECTANGLES = 1 << 7,
+ COGL_DEBUG_HANDLE = 1 << 8,
+ COGL_DEBUG_BLEND_STRINGS = 1 << 9,
+ COGL_DEBUG_DISABLE_BATCHING = 1 << 10
} CoglDebugFlags;
#ifdef COGL_ENABLE_DEBUG
const GList *cogl_material_get_layers (CoglHandle material);
/**
+ * cogl_material_get_n_layers:
+ * @material: A CoglMaterial object
+ *
+ * Returns: The number of layers defined for the given material
+ *
+ * Since: 1.0
+ */
+int cogl_material_get_n_layers (CoglHandle material);
+
+/**
* CoglMaterialLayerType:
* @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a
* <link linkend="cogl-Textures">Cogl texture</link>
* likely return COGL_INVALID_HANDLE if you try to get the texture.
* Considering this, you can call cogl_material_layer_get_type first,
* to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE.
- *
- * Note: It is possible for a layer object of type
- * COGL_MATERIAL_LAYER_TYPE_TEXTURE to be realized before a texture
- * object has been associated with the layer. For example this happens
- * if you setup layer combining for a given layer index before calling
- * cogl_material_set_layer for that index.
- *
- * Returns: A CoglHandle to the layers texture object or COGL_INVALID_HANDLE
- * if a texture has not been set yet.
*/
CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle);
/* private */
void _cogl_set_indirect_context (gboolean indirect);
+/* private
+ *
+ * cogl_flush:
+ *
+ * As an optimization Cogl drawing functions may batch up primitives
+ * internally, so you need to call _cogl_flush to ensure that the
+ * drawing operations you have submitted for the current frame get
+ * flushed through to the driver and GPU.
+ *
+ * This must be called before issuing a swap buffers.
+ */
+void _cogl_flush (void);
+
+
G_END_DECLS
#undef __COGL_H_INSIDE__
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* The current primitive journal does not support tracking changes to the
+ * clip stack... */
+ _cogl_journal_flush ();
+
stack = (CoglClipStack *) ctx->clip.stacks->data;
ctx->clip.stack_dirty = FALSE;
{ "pango", COGL_DEBUG_PANGO },
{ "rectangles", COGL_DEBUG_RECTANGLES },
{ "handle", COGL_DEBUG_HANDLE },
- { "blend-strings", COGL_DEBUG_BLEND_STRINGS }
+ { "blend-strings", COGL_DEBUG_BLEND_STRINGS },
+ { "disable-batching", COGL_DEBUG_DISABLE_BATCHING }
};
static const gint n_cogl_debug_keys = G_N_ELEMENTS (cogl_debug_keys);
typedef struct _CoglMaterial CoglMaterial;
typedef struct _CoglMaterialLayer CoglMaterialLayer;
+typedef enum _CoglMaterialEqualFlags
+{
+ /* Return FALSE if any component of either material isn't set to its
+ * default value. (Note: if the materials have corresponding flush
+ * options indicating that e.g. the material color won't be flushed then
+ * this will not assert a default color value.) */
+ COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS = 1L<<0,
+
+} CoglMaterialEqualFlags;
+
/* XXX: I don't think gtk-doc supports having private enums so these aren't
* bundled in with CoglMaterialLayerFlags */
typedef enum _CoglMaterialLayerPrivFlags
typedef enum _CoglMaterialFlags
{
- COGL_MATERIAL_FLAG_ENABLE_BLEND = 1L<<0,
- COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING = 1L<<1,
- COGL_MATERIAL_FLAG_DEFAULT_COLOR = 1L<<2,
- COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL = 1L<<3,
- COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC = 1L<<4,
- COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC = 1L<<5
+ COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING = 1L<<0,
+
+ COGL_MATERIAL_FLAG_DEFAULT_COLOR = 1L<<1,
+ COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL = 1L<<2,
+ COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC = 1L<<3,
+ COGL_MATERIAL_FLAG_ENABLE_BLEND = 1L<<4,
+ COGL_MATERIAL_FLAG_DEFAULT_BLEND = 1L<<5
} CoglMaterialFlags;
struct _CoglMaterial
{
CoglHandleObject _parent;
+ gulong journal_ref_count;
gulong flags;
GLint blend_dst_factor_rgb;
GList *layers;
+ guint n_layers;
};
/*
gulong _cogl_material_layer_get_flags (CoglHandle layer_handle);
/*
- * CoglMaterialFlushOption:
- * @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 mask
- * of the layers that can't be supported with the user supplied texture
- * and need to be replaced with fallback textures. (1 = fallback, and the
- * least significant bit = layer 0)
- * @COGL_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask
- * of the layers that you want to completly disable texturing for
- * (1 = fallback, and the least significant bit = layer 0)
- * @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture
- * name to override the texture used for layer 0 of the material. This is
- * intended for dealing with sliced textures where you will need to point
- * to each of the texture slices in turn when drawing your geometry.
- * Passing a value of 0 is the same as not passing the option at all.
+ * CoglMaterialFlushFlag:
+ * @COGL_MATERIAL_FLUSH_FALLBACK_MASK: The fallback_layers member is set to
+ * a guint32 mask of the layers that can't be supported with the user
+ * supplied texture and need to be replaced with fallback textures. (1 =
+ * fallback, and the least significant bit = layer 0)
+ * @COGL_MATERIAL_FLUSH_DISABLE_MASK: The disable_layers member is set to
+ * a guint32 mask of the layers that you want to completly disable
+ * texturing for (1 = fallback, and the least significant bit = layer 0)
+ * @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: The layer0_override_texture member is
+ * set to a GLuint OpenGL texture name to override the texture used for
+ * layer 0 of the material. This is intended for dealing with sliced
+ * textures where you will need to point to each of the texture slices in
+ * turn when drawing your geometry. Passing a value of 0 is the same as
+ * not passing the option at all.
+ * @COGL_MATERIAL_FLUSH_SKIP_GL_COLOR: When flushing the GL state for the
+ * material don't call glColor.
+ */
+typedef enum _CoglMaterialFlushFlag
+{
+ COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1L<<0,
+ COGL_MATERIAL_FLUSH_DISABLE_MASK = 1L<<1,
+ COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE = 1L<<2,
+ COGL_MATERIAL_FLUSH_SKIP_GL_COLOR = 1L<<3
+} CoglMaterialFlushFlag;
+
+/*
+ * CoglMaterialFlushOptions:
+ *
*/
-typedef enum _CoglMaterialFlushOption
+typedef struct _CoglMaterialFlushOptions
{
- COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
-} CoglMaterialFlushOption;
+ CoglMaterialFlushFlag flags;
+
+ guint32 fallback_layers;
+ guint32 disable_layers;
+ GLuint layer0_override_texture;
+} CoglMaterialFlushOptions;
/*
* cogl_material_flush_gl_state:
* @material: A CoglMaterial object
* @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs
*
- * This function commits the state of the specified CoglMaterial - including
- * the texture state for all the layers - to the OpenGL[ES] driver.
+ * Note: It is possible for a layer object of type
+ * COGL_MATERIAL_LAYER_TYPE_TEXTURE to be realized before a texture
+ * object has been associated with the layer. For example this happens
+ * if you setup layer combining for a given layer index before calling
+ * cogl_material_set_layer for that index.
*
- * Since 1.0
+ * Returns: A CoglHandle to the layers texture object or COGL_INVALID_HANDLE
+ * if a texture has not been set yet.
*/
void _cogl_material_flush_gl_state (CoglHandle material,
- ...) G_GNUC_NULL_TERMINATED;
+ CoglMaterialFlushOptions *options);
+
+gboolean _cogl_material_equal (CoglHandle material0_handle,
+ CoglMaterialFlushOptions *material0_flush_options,
+ CoglHandle material1_handle,
+ CoglMaterialFlushOptions *material1_flush_options,
+ CoglMaterialEqualFlags flags);
+
+CoglHandle _cogl_material_journal_ref (CoglHandle material_handle);
+void _cogl_material_journal_unref (CoglHandle material_handle);
#endif /* __COGL_MATERIAL_PRIVATE_H */
#endif
material->blend_src_factor_rgb = GL_ONE;
material->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA;
- material->flags |= COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
+ material->flags |= COGL_MATERIAL_FLAG_DEFAULT_BLEND;
material->layers = NULL;
+ material->n_layers = 0;
return _cogl_material_handle_new (material);
}
g_free (material);
}
+
static void
handle_automatic_blend_enable (CoglMaterial *material)
{
* a flag to know when it's user configured, so we don't trash it */
material->flags &= ~COGL_MATERIAL_FLAG_ENABLE_BLEND;
+
+ /* XXX: Uncomment this to disable all blending */
+#if 0
+ return;
+#endif
+
for (tmp = material->layers; tmp != NULL; tmp = tmp->next)
{
CoglMaterialLayer *layer = tmp->data;
material->flags |= COGL_MATERIAL_FLAG_ENABLE_BLEND;
}
+/* If primitives have been logged in the journal referencing the current
+ * state of this material we need to flush the journal before we can
+ * modify it... */
+static void
+_cogl_material_pre_change_notify (CoglMaterial *material)
+{
+ if (material->journal_ref_count)
+ _cogl_journal_flush ();
+}
+
void
cogl_material_get_color (CoglHandle handle,
CoglColor *color)
if (memcmp (unlit, material->unlit, sizeof (unlit)) == 0)
return;
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
memcpy (material->unlit, unlit, sizeof (unlit));
material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_COLOR;
material = _cogl_material_pointer_from_handle (handle);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
ambient = material->ambient;
ambient[0] = cogl_color_get_red_float (ambient_color);
ambient[1] = cogl_color_get_green_float (ambient_color);
material = _cogl_material_pointer_from_handle (handle);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
diffuse = material->diffuse;
diffuse[0] = cogl_color_get_red_float (diffuse_color);
diffuse[1] = cogl_color_get_green_float (diffuse_color);
material = _cogl_material_pointer_from_handle (handle);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
specular = material->specular;
specular[0] = cogl_color_get_red_float (specular_color);
specular[1] = cogl_color_get_green_float (specular_color);
material = _cogl_material_pointer_from_handle (handle);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
material->shininess = (GLfloat)shininess * 128.0;
material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL;
material = _cogl_material_pointer_from_handle (handle);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
emission = material->emission;
emission[0] = cogl_color_get_red_float (emission_color);
emission[1] = cogl_color_get_green_float (emission_color);
g_return_if_fail (cogl_is_material (handle));
material = _cogl_material_pointer_from_handle (handle);
+
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
material->alpha_func = alpha_func;
material->alpha_func_reference = (GLfloat)alpha_reference;
a = &statements[1];
}
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
#ifndef HAVE_COGL_GLES
setup_blend_state (rgb,
&material->blend_equation_rgb,
&material->blend_dst_factor_rgb);
#endif
- material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
+ material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND;
return TRUE;
}
material = _cogl_material_pointer_from_handle (handle);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
constant = material->blend_constant;
constant[0] = cogl_color_get_red_float (constant_color);
constant[1] = cogl_color_get_green_float (constant_color);
constant[2] = cogl_color_get_blue_float (constant_color);
constant[3] = cogl_color_get_alpha_float (constant_color);
- material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
+ material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND;
#endif
}
{
CoglMaterial *material;
CoglMaterialLayer *layer;
- int n_layers;
g_return_if_fail (cogl_is_material (material_handle));
g_return_if_fail (texture_handle == COGL_INVALID_HANDLE
|| cogl_is_texture (texture_handle));
material = _cogl_material_pointer_from_handle (material_handle);
+
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
layer = _cogl_material_get_layer (material_handle, layer_index, TRUE);
if (texture_handle == layer->texture)
return;
- n_layers = g_list_length (material->layers);
- if (n_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
+ material->n_layers = g_list_length (material->layers);
+ if (material->n_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
{
if (!(material->flags & COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING))
{
a = &statements[1];
}
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
setup_texture_combine_state (rgb,
&layer->texture_combine_rgb_func,
layer->texture_combine_rgb_src,
material = _cogl_material_pointer_from_handle (handle);
layer = _cogl_material_get_layer (material, layer_index, TRUE);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
constant = layer->texture_combine_constant;
constant[0] = cogl_color_get_red_float (constant_color);
constant[1] = cogl_color_get_green_float (constant_color);
material = _cogl_material_pointer_from_handle (material_handle);
layer = _cogl_material_get_layer (material, layer_index, TRUE);
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
layer->matrix = *matrix;
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
g_return_if_fail (cogl_is_material (material_handle));
material = _cogl_material_pointer_from_handle (material_handle);
+
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
for (tmp = material->layers; tmp != NULL; tmp = tmp->next)
{
layer = tmp->data;
CoglHandle handle = (CoglHandle) layer;
cogl_handle_unref (handle);
material->layers = g_list_remove (material->layers, layer);
+ material->n_layers--;
break;
}
}
return material->layers;
}
+int
+cogl_material_get_n_layers (CoglHandle material_handle)
+{
+ CoglMaterial *material;
+
+ g_return_val_if_fail (cogl_is_material (material_handle), 0);
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+
+ return material->n_layers;
+}
+
CoglMaterialLayerType
cogl_material_layer_get_type (CoglHandle layer_handle)
{
!gl_layer_info->disabled))
#endif
{
+ /* XXX: Debug: Comment this out to disable all texturing: */
+#if 1
GE (glEnable (gl_target));
+#endif
}
}
else
}
static void
-_cogl_material_flush_base_gl_state (CoglMaterial *material)
+_cogl_material_flush_base_gl_state (CoglMaterial *material,
+ gboolean skip_gl_color)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR
- && material->flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR))
+ /* XXX:
+ * Currently we only don't update state when the flags indicate that the
+ * current material uses the defaults, and the new material also uses the
+ * defaults, but we could do deeper comparisons of state. */
+
+ if (!skip_gl_color)
{
- /* GLES doesn't have glColor4fv... */
- GE (glColor4f (material->unlit[0],
- material->unlit[1],
- material->unlit[2],
- material->unlit[3]));
+ if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR
+ && material->flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR) ||
+ /* Assume if we were previously told to skip the color, then
+ * the current color needs updating... */
+ ctx->current_material_flush_options.flags &
+ COGL_MATERIAL_FLUSH_SKIP_GL_COLOR)
+ {
+ GE (glColor4f (material->unlit[0],
+ material->unlit[1],
+ material->unlit[2],
+ material->unlit[3]));
+ }
}
if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL
GE (glAlphaFunc (material->alpha_func, material->alpha_func_reference));
}
- if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC
- && material->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC))
+ if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND
+ && material->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND))
{
#if defined (HAVE_COGL_GLES2)
gboolean have_blend_equation_seperate = TRUE;
}
void
-_cogl_material_flush_gl_state (CoglHandle handle, ...)
+_cogl_material_flush_gl_state (CoglHandle handle,
+ CoglMaterialFlushOptions *options)
{
- CoglMaterial *material;
- va_list ap;
- CoglMaterialFlushOption option;
- guint32 fallback_layers = 0;
- guint32 disable_layers = 0;
- GLuint layer0_override_texture = 0;
+ CoglMaterial *material;
+ guint32 fallback_layers = 0;
+ guint32 disable_layers = 0;
+ GLuint layer0_override_texture = 0;
+ gboolean skip_gl_color = FALSE;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
material = _cogl_material_pointer_from_handle (handle);
- _cogl_material_flush_base_gl_state (material);
-
- va_start (ap, handle);
- while ((option = va_arg (ap, CoglMaterialFlushOption)))
+ if (options)
{
- if (option == COGL_MATERIAL_FLUSH_FALLBACK_MASK)
- fallback_layers = va_arg (ap, guint32);
- else if (option == COGL_MATERIAL_FLUSH_DISABLE_MASK)
- disable_layers = va_arg (ap, guint32);
- else if (option == COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE)
- layer0_override_texture = va_arg (ap, GLuint);
+ if (options->flags & COGL_MATERIAL_FLUSH_FALLBACK_MASK)
+ fallback_layers = options->fallback_layers;
+ if (options->flags & COGL_MATERIAL_FLUSH_DISABLE_MASK)
+ disable_layers = options->disable_layers;
+ if (options->flags & COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE)
+ layer0_override_texture = options->layer0_override_texture;
+ if (options->flags & COGL_MATERIAL_FLUSH_SKIP_GL_COLOR)
+ skip_gl_color = TRUE;
}
- va_end (ap);
+
+ _cogl_material_flush_base_gl_state (material,
+ skip_gl_color);
_cogl_material_flush_layers_gl_state (material,
fallback_layers,
ctx->current_material = handle;
ctx->current_material_flags = material->flags;
+ if (options)
+ ctx->current_material_flush_options = *options;
+ else
+ memset (&ctx->current_material_flush_options,
+ 0, sizeof (CoglMaterialFlushOptions));
+}
+
+gboolean
+_cogl_material_equal (CoglHandle material0_handle,
+ CoglMaterialFlushOptions *material0_flush_options,
+ CoglHandle material1_handle,
+ CoglMaterialFlushOptions *material1_flush_options,
+ CoglMaterialEqualFlags flags)
+{
+ CoglMaterial *material0;
+ CoglMaterial *material1;
+ GList *l0, *l1;
+
+ if (!(flags & COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS))
+ {
+ g_critical ("FIXME: _cogl_material_equal doesn't yet support "
+ "deep comparisons of materials");
+ return FALSE;
+ }
+ /* Note: the following code is written with the assumption this
+ * constraint will go away*/
+
+ material0 = _cogl_material_pointer_from_handle (material0_handle);
+ material1 = _cogl_material_pointer_from_handle (material1_handle);
+
+ if (!((material0_flush_options->flags & COGL_MATERIAL_FLUSH_SKIP_GL_COLOR &&
+ material1_flush_options->flags & COGL_MATERIAL_FLUSH_SKIP_GL_COLOR)))
+ {
+ if ((material0->flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR) !=
+ (material1->flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR))
+ return FALSE;
+ else if (flags & COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS &&
+ !(material0->flags & COGL_MATERIAL_FLAG_DEFAULT_COLOR))
+ return FALSE;
+ else if (!memcmp (material0->unlit, material1->unlit,
+ sizeof (material0->unlit)))
+ return FALSE;
+ }
+
+ if ((material0->flags & COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL) !=
+ (material1->flags & COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL))
+ return FALSE;
+ else if (flags & COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS &&
+ !(material0->flags & COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL))
+ return FALSE;
+#if 0
+ else if (!_deep_are_gl_materials_equal ())
+ return FALSE;
+#endif
+
+ if ((material0->flags & COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC) !=
+ (material1->flags & COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC))
+ return FALSE;
+ else if (flags & COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS &&
+ !(material0->flags & COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC))
+ return FALSE;
+#if 0
+ else if (!_deep_are_alpha_funcs_equal ())
+ return FALSE;
+#endif
+
+ if ((material0->flags & COGL_MATERIAL_FLAG_ENABLE_BLEND) !=
+ (material1->flags & COGL_MATERIAL_FLAG_ENABLE_BLEND))
+ return FALSE;
+ /* XXX: potentially blending could be "enabled" but the blend mode
+ * could be equivalent to being disabled. */
+
+ if (material0->flags & COGL_MATERIAL_FLAG_ENABLE_BLEND)
+ {
+ if ((material0->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND) !=
+ (material1->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND))
+ return FALSE;
+ else if (flags & COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS &&
+ !(material0->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND))
+ return FALSE;
+#if 0
+ else if (!_deep_is_blend_equal ())
+ return FALSE;
+#endif
+ }
+
+ if (material0_flush_options->fallback_layers !=
+ material1_flush_options->fallback_layers ||
+ material0_flush_options->disable_layers !=
+ material1_flush_options->disable_layers)
+ return FALSE;
+
+ l0 = material0->layers;
+ l1 = material1->layers;
+
+ while (l0 && l1)
+ {
+ CoglMaterialLayer *layer0;
+ CoglMaterialLayer *layer1;
+
+ if ((l0 == NULL && l1 != NULL) ||
+ (l1 == NULL && l0 != NULL))
+ return FALSE;
+
+ layer0 = l0->data;
+ layer1 = l1->data;
+
+ if (layer0->texture != layer1->texture)
+ return FALSE;
+
+ if ((layer0->flags & COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE) !=
+ (layer1->flags & COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE))
+ return FALSE;
+ else if (flags & COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS &&
+ !(layer0->flags & COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE))
+ return FALSE;
+#if 0
+ else if (!_deep_are_layer_combines_equal ())
+ return FALSE;
+#endif
+
+ l0 = l0->next;
+ l1 = l1->next;
+ }
+
+ if ((l0 == NULL && l1 != NULL) ||
+ (l1 == NULL && l0 != NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* While a material is referenced by the Cogl journal we can not allow
+ * modifications, so this gives us a mechanism to track journal
+ * references separately */
+CoglHandle
+_cogl_material_journal_ref (CoglHandle material_handle)
+{
+ CoglMaterial *material =
+ material = _cogl_material_pointer_from_handle (material_handle);
+ material->journal_ref_count++;
+ cogl_handle_ref (material_handle);
+ return material_handle;
+}
+
+void
+_cogl_material_journal_unref (CoglHandle material_handle)
+{
+ CoglMaterial *material =
+ material = _cogl_material_pointer_from_handle (material_handle);
+ material->journal_ref_count--;
+ cogl_handle_unref (material_handle);
}
/* TODO: Should go in cogl.c, but that implies duplication which is also
g_return_if_fail (cogl_is_material (handle));
material = _cogl_material_pointer_from_handle (handle);
+
+ /* possibly flush primitives referencing the current state... */
+ _cogl_material_pre_change_notify (material);
+
layer = _cogl_material_get_layer (material, layer_index, TRUE);
layer->min_filter = min_filter;
#ifdef HAVE_COGL_GL
+#define glGenBuffers ctx->pf_glGenBuffersARB
+#define glBindBuffer ctx->pf_glBindBufferARB
+#define glBufferData ctx->pf_glBufferDataARB
+#define glBufferSubData ctx->pf_glBufferSubDataARB
+#define glDeleteBuffers ctx->pf_glDeleteBuffersARB
#define glClientActiveTexture ctx->pf_glClientActiveTexture
+#elif defined (HAVE_COGL_GLES2)
+
+#include "../gles/cogl-gles2-wrapper.h"
+
+#endif
+
+
+/* XXX NB:
+ * Our journal's vertex data is arranged as follows:
+ * 4 vertices per quad:
+ * 2 or GLfloats per position
+ * 4 RGBA GLubytes,
+ * 2 GLfloats per tex coord * n_layers
+ *
+ * So for a given number of layers this gets the stride in
+ * 32bit words:
+ */
+#define GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS(N_LAYERS) \
+ (2 + 1 + 2 * (N_LAYERS))
+
+
+typedef void (*CoglJournalBatchCallback) (CoglJournalEntry *start,
+ int n_entries,
+ void *data);
+typedef gboolean (*CoglJournalBatchTest) (CoglJournalEntry *entry0,
+ CoglJournalEntry *entry1);
+
+typedef struct _CoglJournalFlushState
+{
+ /* Note: this is a pointer to handle fallbacks. It normally holds a VBO
+ * offset, but when the driver doesn't support VBOs then this points into
+ * our GArray of logged vertices. */
+ char * vbo_offset;
+ GLuint vertex_offset;
+#ifndef HAVE_COGL_GL
+ CoglJournalIndices *indices;
+ size_t indices_type_size;
#endif
+} CoglJournalFlushState;
/* these are defined in the particular backend */
void _cogl_path_add_node (gboolean new_sub_path,
void _cogl_path_fill_nodes ();
void _cogl_path_stroke_nodes ();
-static void
-_cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
- gint batch_len,
- GLfloat *vertex_pointer)
+void
+_cogl_journal_dump_quad_vertices (guint8 *data, int n_layers)
{
- gsize stride;
- int i;
- gulong enable_flags = 0;
- guint32 disable_mask;
- int prev_n_texcoord_arrays_enabled;
+ size_t stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers);
+ int i;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- /* XXX NB:
- * Our vertex data is arranged as follows:
- * 4 vertices per quad: 2 GLfloats per position,
- * 2 GLfloats per tex coord * n_layers
- */
- stride = 2 + 2 * batch_start->n_layers;
- stride *= sizeof (GLfloat);
-
- disable_mask = (1 << batch_start->n_layers) - 1;
- disable_mask = ~disable_mask;
+ g_print ("stride = %d (%d bytes)\n", (int)stride, (int)stride * 4);
- _cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_FALLBACK_MASK,
- batch_start->fallback_mask,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- disable_mask,
- /* Redundant when dealing with unsliced
- * textures but does no harm... */
- COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
- batch_start->layer0_override_texture,
- NULL);
-
- for (i = 0; i < batch_start->n_layers; i++)
+ for (i = 0; i < 4; i++)
{
- GE (glClientActiveTexture (GL_TEXTURE0 + i));
- GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY));
- GE (glTexCoordPointer (2, GL_FLOAT, stride, vertex_pointer + 2 + 2 * i));
+ float *v = (float *)data + (i * stride);
+ guint8 *c = data + 8 + (i * stride * 4);
+ int j;
+
+ g_print ("v%d: x = %f, y = %f, rgba=0x%02X%02X%02X%02X",
+ i, v[0], v[1], c[0], c[1], c[2], c[3]);
+ for (j = 0; j < n_layers; j++)
+ {
+ float *t = v + 3 + 2 * j;
+ g_print (", tx%d = %f, ty%d = %f", j, t[0], j, t[1]);
+ }
+ g_print ("\n");
}
- prev_n_texcoord_arrays_enabled =
- ctx->n_texcoord_arrays_enabled;
- ctx->n_texcoord_arrays_enabled = batch_start->n_layers;
- for (; i < prev_n_texcoord_arrays_enabled; i++)
+}
+
+void
+_cogl_journal_dump_quad_batch (guint8 *data, int n_layers, int n_quads)
+{
+ size_t byte_stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers) * 4;
+ int i;
+
+ g_print ("_cogl_journal_dump_quad_batch: n_layers = %d, n_quads = %d\n",
+ n_layers, n_quads);
+ for (i = 0; i < n_quads; i++)
+ _cogl_journal_dump_quad_vertices (data + byte_stride * 4 * i, n_layers);
+}
+
+static void
+batch_and_call (CoglJournalEntry *entries,
+ int n_entries,
+ CoglJournalBatchTest can_batch_callback,
+ CoglJournalBatchCallback batch_callback,
+ void *data)
+{
+ int i;
+ int batch_len = 1;
+ CoglJournalEntry *batch_start = entries;
+
+ for (i = 1; i < n_entries; i++)
{
- GE (glClientActiveTexture (GL_TEXTURE0 + i));
- GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
- }
+ CoglJournalEntry *entry0 = &entries[i - 1];
+ CoglJournalEntry *entry1 = entry0 + 1;
- /* FIXME: This api is a bit yukky, ideally it will be removed if we
- * re-work the cogl_enable mechanism */
- enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
+ if (can_batch_callback (entry0, entry1))
+ {
+ batch_len++;
+ continue;
+ }
- if (ctx->enable_backface_culling)
- enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
+ batch_callback (batch_start, batch_len, data);
- enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
- cogl_enable (enable_flags);
+ batch_start = entry1;
+ batch_len = 1;
+ }
- GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer));
- _cogl_current_matrix_state_flush ();
+ /* The last batch... */
+ batch_callback (batch_start, batch_len, data);
+}
+
+static void
+_cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
+ int batch_len,
+ void *data)
+{
+ CoglJournalFlushState *state = data;
+
+ GE (glLoadMatrixf ((GLfloat *)&batch_start->model_view));
#ifdef HAVE_COGL_GL
- GE( glDrawArrays (GL_QUADS, 0, batch_len * 4) );
+ GE (glDrawArrays (GL_QUADS, state->vertex_offset, batch_len * 4));
#else /* HAVE_COGL_GL */
- /* GLES doesn't support GL_QUADS so we will use GL_TRIANGLES and
- indices */
- {
- int needed_indices = batch_len * 6;
- CoglHandle indices_handle
- = cogl_vertex_buffer_indices_get_for_quads (needed_indices);
- CoglVertexBufferIndices *indices
- = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
-
- GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
- GPOINTER_TO_UINT (indices->vbo_name)));
- GE (glDrawElements (GL_TRIANGLES,
- 6 * batch_len,
- indices->type,
- NULL));
- GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
- }
-
-#endif /* HAVE_COGL_GL */
+ if (batch_len > 1)
+ {
+ int indices_offset = (state->vertex_offset / 4) * 6;
+ GE (glDrawElements (GL_TRIANGLES,
+ 6 * batch_len,
+ indices->type,
+ indices_offset * state->indices_type_size));
+ }
+ else
+ {
+ GE (glDrawArrays (GL_TRIANGLE_FAN,
+ state->vertex_offset, /* first */
+ 4)); /* n vertices */
+ }
+#endif
/* DEBUGGING CODE XXX:
* This path will cause all rectangles to be drawn with a red, green
{
static CoglHandle outline = COGL_INVALID_HANDLE;
static int color = 0;
+ int i;
if (outline == COGL_INVALID_HANDLE)
outline = cogl_material_new ();
color == 2 ? 0xff : 0x00,
0xff);
_cogl_material_flush_gl_state (outline, NULL);
- _cogl_current_matrix_state_flush ();
GE( glDrawArrays (GL_LINE_LOOP, 4 * i, 4) );
}
}
+
+ state->vertex_offset += (4 * batch_len);
+}
+
+static gboolean
+compare_entry_modelviews (CoglJournalEntry *entry0,
+ CoglJournalEntry *entry1)
+{
+ /* Batch together quads with the same model view matrix */
+
+ /* FIXME: this is nasty, there are much nicer ways to track this
+ * (at the add_quad_vertices level) without resorting to a memcmp!
+ *
+ * E.g. If the cogl-current-matrix code maintained an "age" for
+ * the modelview matrix we could simply check in add_quad_vertices
+ * if the age has increased, and if so record the change as a
+ * boolean in the journal.
+ */
+ if (memcmp (&entry0->model_view, &entry1->model_view,
+ sizeof (GLfloat) * 16) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* At this point we have a run of quads that we know have compatible
+ * materials, but they may not all have the same modelview matrix */
+static void
+_cogl_journal_flush_material_and_entries (CoglJournalEntry *batch_start,
+ gint batch_len,
+ void *data)
+{
+ gulong enable_flags = 0;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+#if 0
+ if (batch_len != 1)
+ g_debug ("batch len = %d", batch_len);
+#endif
+
+ _cogl_material_flush_gl_state (batch_start->material,
+ &batch_start->flush_options);
+
+ /* FIXME: This api is a bit yukky, ideally it will be removed if we
+ * re-work the cogl_enable mechanism */
+ enable_flags |= _cogl_material_get_cogl_enable_flags (batch_start->material);
+
+ if (ctx->enable_backface_culling)
+ enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
+
+ enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
+ enable_flags |= COGL_ENABLE_COLOR_ARRAY;
+ cogl_enable (enable_flags);
+
+ batch_and_call (batch_start,
+ batch_len,
+ compare_entry_modelviews,
+ _cogl_journal_flush_modelview_and_entries,
+ data);
+
}
+static gboolean
+compare_entry_materials (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
+{
+ /* batch rectangles using compatible materials */
+
+ /* XXX: _cogl_material_equal may give false negatives since it avoids
+ * deep comparisons as an optimization. It aims to compare enough so
+ * that we that we are able to batch the 90% common cases, but may not
+ * look at less common differences. */
+ if (_cogl_material_equal (entry0->material,
+ &entry0->flush_options,
+ entry1->material,
+ &entry1->flush_options,
+ COGL_MATERIAL_EQUAL_FLAGS_ASSERT_ALL_DEFAULTS))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* At this point we know the stride has changed from the previous batch
+ * of journal entries */
+static void
+_cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start,
+ gint batch_len,
+ void *data)
+{
+ CoglJournalFlushState *state = data;
+ size_t stride;
+ int i;
+ int prev_n_texcoord_arrays_enabled;
+#ifndef HAVE_COGL_GL
+ int needed_indices = batch_len * 6;
+ CoglHandle indices_handle;
+ CoglVertexBufferIndices *indices;
+#endif
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ /* XXX NB:
+ * Our vertex data is arranged as follows:
+ * 4 vertices per quad: 2 GLfloats per position,
+ * 4 RGBA GLubytes,
+ * 2 GLfloats per tex coord * n_layers
+ */
+ stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (batch_start->n_layers);
+ stride *= sizeof (GLfloat);
+
+ GE (glVertexPointer (2, GL_FLOAT, stride, (void *)state->vbo_offset));
+ GE (glColorPointer (4, GL_UNSIGNED_BYTE, stride,
+ (void *)(state->vbo_offset + 8)));
+
+ for (i = 0; i < batch_start->n_layers; i++)
+ {
+ GE (glClientActiveTexture (GL_TEXTURE0 + i));
+ GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY));
+ GE (glTexCoordPointer (2, GL_FLOAT, stride,
+ (void *)(state->vbo_offset + 12 + 8 * i)));
+ }
+ prev_n_texcoord_arrays_enabled =
+ ctx->n_texcoord_arrays_enabled;
+ ctx->n_texcoord_arrays_enabled = batch_start->n_layers;
+ for (; i < prev_n_texcoord_arrays_enabled; i++)
+ {
+ GE (glClientActiveTexture (GL_TEXTURE0 + i));
+ GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
+ }
+
+#ifndef HAVE_COGL_GL
+ indices_handle = cogl_vertex_buffer_indices_get_for_quads (needed_indices);
+ indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
+ state->indices = indices;
+
+ if (indices->type == GL_UNSIGNED_BYTE)
+ state->indices_type_size = 1;
+ else if (indices->type == GL_UNSIGNED_SHORT)
+ state->indices_type_size = 2;
+ else
+ g_critical ("unknown indices type %d", indices->type);
+
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
+ GPOINTER_TO_UINT (indices->vbo_name)));
+#endif
+
+ /* We only call gl{Vertex,Color,Texture}Pointer when the stride within
+ * the VBO changes. (due to a change in the number of material layers)
+ * While the stride remains constant we walk forward through the above
+ * VBO use a vertex offset passed to glDraw{Arrays,Elements} */
+ state->vertex_offset = 0;
+
+ /* XXX: Uncomment for debugging */
+#if 0
+ g_assert (cogl_get_features () & COGL_FEATURE_VBOS);
+ _cogl_journal_dump_quad_batch (((guint8 *)ctx->logged_vertices->data) +
+ (size_t)state->vbo_offset,
+ batch_start->n_layers,
+ batch_len);
+#endif
+
+ batch_and_call (batch_start,
+ batch_len,
+ compare_entry_materials,
+ _cogl_journal_flush_material_and_entries,
+ data);
+
+#ifndef HAVE_COGL_GL
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
+#endif
+
+ /* progress forward through the VBO containing all our vertices */
+ state->vbo_offset += (stride * 4 * batch_len);
+}
+
+static gboolean
+compare_entry_strides (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
+{
+ /* Currently the only thing that affects the stride for our vertex arrays
+ * is the number of material layers. We need to update our VBO offsets
+ * whenever the stride changes. */
+ /* TODO: We should be padding the n_layers == 1 case as if it were
+ * n_layers == 2 so we can reduce the need to split batches. */
+ if (entry0->n_layers == entry1->n_layers)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+upload_vertices_to_vbo (GArray *vertices, CoglJournalFlushState *state)
+{
+ size_t needed_vbo_len;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ needed_vbo_len = vertices->len * sizeof (GLfloat);
+ if (ctx->journal_vbo_len < needed_vbo_len)
+ {
+ GE (glDeleteBuffers (1, &ctx->journal_vbo));
+
+ GE (glGenBuffers (1, &ctx->journal_vbo));
+ GE (glBindBuffer (GL_ARRAY_BUFFER, ctx->journal_vbo));
+ GE (glBufferData (GL_ARRAY_BUFFER,
+ needed_vbo_len,
+ vertices->data,
+ GL_STATIC_DRAW));
+ ctx->journal_vbo_len = needed_vbo_len;
+ }
+ else
+ {
+ GE (glBindBuffer (GL_ARRAY_BUFFER, ctx->journal_vbo));
+ GE (glBufferData (GL_ARRAY_BUFFER,
+ needed_vbo_len,
+ NULL,
+ GL_STATIC_DRAW));
+ GE (glBufferSubData (GL_ARRAY_BUFFER,
+ 0,
+ needed_vbo_len,
+ vertices->data));
+ }
+
+ /* As we flush the journal entries in batches we walk forward through the
+ * above VBO starting at offset 0... */
+ state->vbo_offset = 0;
+}
+
+/* XXX NB: When _cogl_journal_flush() returns all state relating
+ * to materials, all glEnable flags and current matrix state
+ * is undefined.
+ */
void
_cogl_journal_flush (void)
{
- GLfloat *current_vertex_pointer;
- GLfloat *batch_vertex_pointer;
- CoglJournalEntry *batch_start;
- guint batch_len;
- int i;
+ CoglJournalFlushState state;
+ int i;
+ gboolean vbo_fallback =
+ (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (ctx->journal->len == 0)
return;
- /* Current non-variables / constraints:
- *
- * - We don't have to worry about much GL state changing between journal
- * entries since currently the journal never out lasts a single call to
- * _cogl_multitexture_multiple_rectangles. So the user doesn't get the
- * chance to fiddle with anything. (XXX: later this will be extended at
- * which point we can start logging certain state changes)
- *
- * - Implied from above: all entries will refer to the same material.
- *
- * - Although _cogl_multitexture_multiple_rectangles can cause the wrap mode
- * of textures to be modified, the journal is flushed if a wrap mode is
- * changed so we don't currently have to log wrap mode changes.
- *
- * - XXX - others?
- */
+ /* Load all the vertex data we have accumulated so far into a single VBO
+ * to minimize memory management costs within the GL driver. */
+ if (!vbo_fallback)
+ upload_vertices_to_vbo (ctx->logged_vertices, &state);
+ else
+ state.vbo_offset = (char *)ctx->logged_vertices->data;
- /* TODO: "compile" the journal to find ways of batching draw calls and vertex
- * data.
- *
- * Simple E.g. given current constraints...
- * pass 0 - load all data into a single CoglVertexBuffer
- * pass 1 - batch gl draw calls according to entries that use the same
- * textures.
+ /* Since the journal deals with emitting the modelview matrices manually
+ * we need to dirty our client side matrix stack cache... */
+ _cogl_current_matrix_state_dirty ();
+
+ /* batch_and_call() batches a list of journal entries according to some
+ * given criteria and calls a callback once for each determined batch.
*
- * We will be able to do cooler stuff here when we extend the life of
- * journals beyond _cogl_multitexture_multiple_rectangles.
+ * The process of flushing the journal is done by splitting the entries
+ * by three broad criteria:
+ * 1) We split the entries according the number of material layers.
+ * Each time the number of material layers changes, then the stride
+ * changes, so we need to call gl{Vertex,Color,Texture}Pointer to
+ * inform GL of new VO offsets.
+ * 2) We then split according to compatible Cogl materials.
+ * This is where we flush material state
+ * 3) Finally we split according to modelview matrix changes.
+ * This is when we finally tell GL to draw something.
*/
+ batch_and_call ((CoglJournalEntry *)ctx->journal->data, /* first entry */
+ ctx->journal->len, /* max number of entries to consider */
+ compare_entry_strides,
+ _cogl_journal_flush_vbo_offsets_and_entries, /* callback */
+ &state); /* data */
- batch_vertex_pointer = (GLfloat *)ctx->logged_vertices->data;
- batch_start = (CoglJournalEntry *)ctx->journal->data;
- batch_len = 1;
-
- current_vertex_pointer = batch_vertex_pointer;
-
- for (i = 1; i < ctx->journal->len; i++)
+ for (i = 0; i < ctx->journal->len; i++)
{
- CoglJournalEntry *prev_entry =
- &g_array_index (ctx->journal, CoglJournalEntry, i - 1);
- CoglJournalEntry *current_entry = prev_entry + 1;
- gsize stride;
-
- /* Progress the vertex pointer to the next quad */
- stride = 2 + current_entry->n_layers * 2;
- current_vertex_pointer += stride * 4;
-
- /* batch rectangles using the same textures */
- if (current_entry->material == prev_entry->material &&
- current_entry->n_layers == prev_entry->n_layers &&
- current_entry->fallback_mask == prev_entry->fallback_mask &&
- current_entry->layer0_override_texture
- == prev_entry->layer0_override_texture)
- {
- batch_len++;
- continue;
- }
-
- _cogl_journal_flush_quad_batch (batch_start,
- batch_len,
- batch_vertex_pointer);
-
- batch_start = current_entry;
- batch_len = 1;
- batch_vertex_pointer = current_vertex_pointer;
+ CoglJournalEntry *entry =
+ &g_array_index (ctx->journal, CoglJournalEntry, i);
+ _cogl_material_journal_unref (entry->material);
}
- /* The last batch... */
- _cogl_journal_flush_quad_batch (batch_start,
- batch_len,
- batch_vertex_pointer);
-
+ if (!vbo_fallback)
+ GE (glBindBuffer (GL_ARRAY_BUFFER, 0));
g_array_set_size (ctx->journal, 0);
g_array_set_size (ctx->logged_vertices, 0);
float x_2,
float y_2,
CoglHandle material,
- gint n_layers,
- guint32 fallback_mask,
+ int n_layers,
+ guint32 fallback_layers,
GLuint layer0_override_texture,
float *tex_coords,
guint tex_coords_len)
{
- int stride;
+ size_t stride;
+ size_t byte_stride;
int next_vert;
GLfloat *v;
+ GLubyte *c;
int i;
int next_entry;
+ guint32 disable_layers;
CoglJournalEntry *entry;
+ CoglColor color;
+ guint8 r, g, b, a;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
* directly passed to OpenGL
*/
- /* We pack the vertex data as 2 (x,y) GLfloats folowed by 2 (tx,ty) GLfloats
- * for each texture being used, E.g.:
- * [X, Y, TX0, TY0, TX1, TY1, X, Y, TX0, TY0, X, Y, ...]
- */
- stride = 2 + n_layers * 2;
+ /* XXX: See definition of GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS for details
+ * about how we pack our vertex data */
+ stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers);
+ /* NB: stride is in 32bit words */
+ byte_stride = stride * 4;
next_vert = ctx->logged_vertices->len;
g_array_set_size (ctx->logged_vertices, next_vert + 4 * stride);
v = &g_array_index (ctx->logged_vertices, GLfloat, next_vert);
+ c = (GLubyte *)(v + 2);
/* XXX: All the jumping around to fill in this strided buffer doesn't
* seem ideal. */
/* XXX: we could defer expanding the vertex data for GL until we come
* to flushing the journal. */
+ cogl_material_get_color (material, &color);
+ r = cogl_color_get_red_byte (&color);
+ g = cogl_color_get_green_byte (&color);
+ b = cogl_color_get_blue_byte (&color);
+ a = cogl_color_get_alpha_byte (&color);
+
v[0] = x_1; v[1] = y_1;
+ c[0] = r; c[1] = g; c[2] = b; c[3] = a;
v += stride;
+ c += byte_stride;
v[0] = x_1; v[1] = y_2;
+ c[0] = r; c[1] = g; c[2] = b; c[3] = a;
v += stride;
+ c += byte_stride;
v[0] = x_2; v[1] = y_2;
+ c[0] = r; c[1] = g; c[2] = b; c[3] = a;
v += stride;
+ c += byte_stride;
v[0] = x_2; v[1] = y_1;
+ c[0] = r; c[1] = g; c[2] = b; c[3] = a;
for (i = 0; i < n_layers; i++)
{
- GLfloat *t =
- &g_array_index (ctx->logged_vertices, GLfloat, next_vert + 2 + 2 * i);
+ /* NB: See note at top about vertex buffer layout: */
+ GLfloat *t = &g_array_index (ctx->logged_vertices,
+ GLfloat, next_vert + 3 + 2 * i);
t[0] = tex_coords[0]; t[1] = tex_coords[1];
t += stride;
t[0] = tex_coords[2]; t[1] = tex_coords[1];
}
+ /* XXX: Uncomment for debugging */
+#if 0
+ v = &g_array_index (ctx->logged_vertices, GLfloat, next_vert);
+ _cogl_journal_dump_quad_vertices ((guint8 *)v, n_layers);
+#endif
+
next_entry = ctx->journal->len;
g_array_set_size (ctx->journal, next_entry + 1);
entry = &g_array_index (ctx->journal, CoglJournalEntry, next_entry);
- entry->material = material;
+ disable_layers = (1 << n_layers) - 1;
+ disable_layers = ~disable_layers;
+
+ entry->material = _cogl_material_journal_ref (material);
entry->n_layers = n_layers;
- entry->fallback_mask = fallback_mask;
- entry->layer0_override_texture = layer0_override_texture;
+ entry->flush_options.flags =
+ COGL_MATERIAL_FLUSH_FALLBACK_MASK |
+ COGL_MATERIAL_FLUSH_DISABLE_MASK |
+ COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE |
+ COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
+ entry->flush_options.fallback_layers = fallback_layers;
+ entry->flush_options.disable_layers = disable_layers;
+ entry->flush_options.layer0_override_texture = layer0_override_texture;
+ cogl_get_modelview_matrix (&entry->model_view);
+
+ if (cogl_debug_flags & COGL_DEBUG_DISABLE_BATCHING
+ || cogl_debug_flags & COGL_DEBUG_RECTANGLES)
+ _cogl_journal_flush ();
}
static void
float x_2,
float y_2,
CoglHandle material,
- gint n_layers,
- guint32 fallback_mask,
+ guint32 fallback_layers,
const float *user_tex_coords,
gint user_tex_coords_len)
{
- float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers);
+ int n_layers = cogl_material_get_n_layers (material);
+ float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers);
const GList *layers;
GList *tmp;
int i;
/* NB: marking for fallback will replace the layer with
* a default transparent texture */
- fallback_mask |= (1 << i);
+ fallback_layers |= (1 << i);
}
}
y_2,
material,
n_layers,
- fallback_mask,
+ fallback_layers,
0, /* don't replace the layer0 texture */
final_tex_coords,
n_layers * 4);
const GList *layers;
int n_layers;
const GList *tmp;
- guint32 fallback_mask = 0;
+ guint32 fallback_layers = 0;
gboolean all_use_sliced_quad_fallback = FALSE;
int i;
material = ctx->source_material;
layers = cogl_material_get_layers (material);
- n_layers = g_list_length ((GList *)layers);
+ n_layers = cogl_material_get_n_layers (material);
/*
* Validate all the layers of the current source material...
{
if (i == 0)
{
- fallback_mask = ~1; /* fallback all except the first layer */
+ fallback_layers = ~1; /* fallback all except the first layer */
all_use_sliced_quad_fallback = TRUE;
if (tmp->next)
{
/* NB: marking for fallback will replace the layer with
* a default transparent texture */
- fallback_mask |= (1 << i);
+ fallback_layers |= (1 << i);
continue;
}
}
/* NB: marking for fallback will replace the layer with
* a default transparent texture */
- fallback_mask |= (1 << i);
+ fallback_layers |= (1 << i);
continue;
}
}
|| !_cogl_multitexture_unsliced_quad (rects[i].x_1, rects[i].y_1,
rects[i].x_2, rects[i].y_2,
material,
- n_layers,
- fallback_mask,
+ fallback_layers,
rects[i].tex_coords,
rects[i].tex_coords_len))
{
}
}
+#if 0
+ /* XXX: The current journal doesn't handle changes to the model view matrix
+ * so for now we force a flush at the end of every primitive. */
_cogl_journal_flush ();
+#endif
}
void
int x, y, tex_num, i;
GLuint gl_handle;
GLfloat *v;
+ CoglMaterialFlushOptions options;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
v += stride;
}
- _cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- (guint32)~1, /* disable all except the
- first layer */
- COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
- gl_handle,
- NULL);
+ options.flags =
+ COGL_MATERIAL_FLUSH_DISABLE_MASK |
+ COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE;
+ /* disable all except the first layer */
+ options.disable_layers = (guint32)~1;
+ options.layer0_override_texture = gl_handle;
+
+ _cogl_material_flush_gl_state (ctx->source_material, &options);
_cogl_current_matrix_state_flush ();
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) );
guint n_layers,
guint stride,
gboolean use_color,
- guint32 fallback_mask)
+ guint32 fallback_layers)
{
CoglHandle material;
const GList *layers;
GList *tmp;
CoglTexSliceSpan *y_span, *x_span;
GLfloat *v;
+ CoglMaterialFlushOptions options;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
}
}
- _cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_FALLBACK_MASK,
- fallback_mask,
- NULL);
+ options.flags = COGL_MATERIAL_FLUSH_FALLBACK_MASK;
+ if (use_color)
+ options.flags |= COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
+ options.fallback_layers = fallback_layers;
+ _cogl_material_flush_gl_state (ctx->source_material, &options);
_cogl_current_matrix_state_flush ();
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
int n_layers;
GList *tmp;
gboolean use_sliced_polygon_fallback = FALSE;
- guint32 fallback_mask = 0;
+ guint32 fallback_layers = 0;
int i;
gulong enable_flags;
guint stride;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _cogl_journal_flush ();
cogl_clip_ensure ();
material = ctx->source_material;
"textures with waste\n", i);
warning_seen = TRUE;
- fallback_mask |= (1 << i);
+ fallback_layers |= (1 << i);
continue;
}
}
n_layers,
stride,
use_color,
- fallback_mask);
+ fallback_layers);
/* Reset the size of the logged vertex array because rendering
rectangles expects it to start at 0 */
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _cogl_journal_flush ();
cogl_clip_ensure ();
if (ctx->path_nodes->len == 0)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_clip_ensure ();
-
if (ctx->path_nodes->len == 0)
return;
+ _cogl_journal_flush ();
+ cogl_clip_ensure ();
+
_cogl_path_stroke_nodes();
}
floatVec2 p4;
};
+void _cogl_journal_flush (void);
+
#endif /* __COGL_PRIMITIVES_H */
#include "cogl-vertex-buffer-private.h"
#include "cogl-texture-private.h"
#include "cogl-material-private.h"
+#include "cogl-primitives.h"
#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
(VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1)))
gulong enable_flags = 0;
guint max_texcoord_attrib_unit = 0;
const GList *layers;
- guint32 fallback_mask = 0;
- guint32 disable_mask = ~0;
+ guint32 fallback_layers = 0;
+ guint32 disable_layers = ~0;
int i;
+ CoglMaterialFlushOptions options;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
pointer));
if (attribute->texture_unit > max_texcoord_attrib_unit)
max_texcoord_attrib_unit = attribute->texture_unit;
- disable_mask &= ~(1 << attribute->texture_unit);
+ disable_layers &= ~(1 << attribute->texture_unit);
break;
case COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY:
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
* vertices once for each layer, each time with a fiddled texture
* matrix.
*/
- fallback_mask |= (1 << i);
+ fallback_layers |= (1 << i);
}
}
- _cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_FALLBACK_MASK,
- fallback_mask,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- disable_mask,
- NULL);
+ options.flags =
+ COGL_MATERIAL_FLUSH_FALLBACK_MASK |
+ COGL_MATERIAL_FLUSH_DISABLE_MASK;
+ options.fallback_layers = fallback_layers;
+ options.disable_layers = disable_layers;
+ _cogl_material_flush_gl_state (ctx->source_material, &options);
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
if (ctx->enable_backface_culling)
if (!cogl_is_vertex_buffer (handle))
return;
+ _cogl_journal_flush ();
+ cogl_clip_ensure ();
+
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
cogl_clip_ensure ();
if (!cogl_is_vertex_buffer (handle))
return;
+ _cogl_journal_flush ();
+ cogl_clip_ensure ();
+
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
if (!cogl_is_vertex_buffer_indices (indices_handle))
void
cogl_set_depth_test_enabled (gboolean setting)
{
+ /* Currently the journal can't track changes to depth state... */
+ _cogl_journal_flush ();
+
if (setting)
{
glEnable (GL_DEPTH_TEST);
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* Currently the journal can't track changes to backface culling state... */
+ _cogl_journal_flush ();
+
ctx->enable_backface_culling = setting;
}
float height,
gboolean first)
{
+ CoglHandle current_source;
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_material_flush_gl_state (ctx->stencil_material, NULL);
+ _cogl_journal_flush ();
+
+ /* temporarily swap in our special stenciling material */
+ current_source = cogl_handle_ref (ctx->source_material);
+ cogl_set_source (ctx->stencil_material);
if (first)
{
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
}
+ /* make sure our rectangles hit the stencil buffer before we restore
+ * the stencil function / operation */
+ _cogl_journal_flush ();
+
/* Restore the stencil mode */
GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
+
+ /* restore the original source material */
+ cogl_set_source (current_source);
+ cogl_handle_unref (current_source);
}
void
GLfloat fogColor[4];
GLenum gl_mode = GL_LINEAR;
+ /* The cogl journal doesn't currently track fog state changes */
+ _cogl_journal_flush ();
+
fogColor[0] = cogl_color_get_red_float (fog_color);
fogColor[1] = cogl_color_get_green_float (fog_color);
fogColor[2] = cogl_color_get_blue_float (fog_color);
void
cogl_disable_fog (void)
{
+ /* Currently the journal can't track changes to fog state... */
+ _cogl_journal_flush ();
+
glDisable (GL_FOG);
}
#endif
void
+_cogl_flush (void)
+{
+ _cogl_journal_flush ();
+}
+
+void
cogl_read_pixels (int x,
int y,
int width,
glPixelStorei (GL_PACK_SKIP_ROWS, 0);
#endif /* HAVE_COGL_GL */
+ /* make sure any batched primitives get emitted to the GL driver before
+ * issuing our read pixels... */
+ _cogl_flush ();
+
glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
/* TODO: consider using the GL_MESA_pack_invert extension in the future
_context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
_context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
+ _context->journal_vbo = 0;
+ _context->journal_vbo_len = 0;
_context->current_material = NULL;
_context->current_material_flags = 0;
+ memset (&_context->current_material_flush_options,
+ 0, sizeof (CoglMaterialFlushOptions));
_context->current_layers = g_array_new (FALSE, FALSE,
sizeof (CoglLayerInfo));
_context->n_texcoord_arrays_enabled = 0;
#include "cogl-clip-stack.h"
#include "cogl-matrix-stack.h"
#include "cogl-current-matrix.h"
+#include "cogl-material-private.h"
typedef struct
{
* can batch things together. */
GArray *journal;
GArray *logged_vertices;
+ GLuint journal_vbo;
+ size_t journal_vbo_len;
/* Some simple caching, to minimize state changes... */
CoglHandle current_material;
gulong current_material_flags;
+ CoglMaterialFlushOptions current_material_flush_options;
GArray *current_layers;
guint n_texcoord_arrays_enabled;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _cogl_journal_flush ();
+
g_assert (ctx->draw_buffer_stack != NULL);
draw_buffer = ctx->draw_buffer_stack->data;
{
guint path_start = 0;
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
+ CoglMaterialFlushOptions options;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
- _cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- (guint32)~0, /* disable all texture layers */
- NULL);
+ options.flags = COGL_MATERIAL_FLUSH_DISABLE_MASK;
+ /* disable all texture layers */
+ options.disable_layers = (guint32)~0;
+
+ _cogl_material_flush_gl_state (ctx->source_material, &options);
_cogl_current_matrix_state_flush ();
while (path_start < ctx->path_nodes->len)
CoglPathNode *path,
gboolean merge)
{
- guint path_start = 0;
- guint sub_path_num = 0;
- float bounds_x;
- float bounds_y;
- float bounds_w;
- float bounds_h;
- gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
+ guint path_start = 0;
+ guint sub_path_num = 0;
+ float bounds_x;
+ float bounds_y;
+ float bounds_w;
+ float bounds_h;
+ gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
+ CoglHandle prev_source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _cogl_journal_flush ();
+
/* Just setup a simple material that doesn't use texturing... */
- _cogl_material_flush_gl_state (ctx->stencil_material, NULL);
+ prev_source = cogl_handle_ref (ctx->source_material);
+ cogl_set_source (ctx->stencil_material);
+
+ _cogl_material_flush_gl_state (ctx->source_material, NULL);
enable_flags |=
_cogl_material_get_cogl_enable_flags (ctx->source_material);
GE( glColorMask (FALSE, FALSE, FALSE, FALSE) );
GE( glDepthMask (FALSE) );
- _cogl_current_matrix_state_flush ();
while (path_start < path_size)
{
+ /* NB: after calling _cogl_journal_flush the current matrix
+ * state is undefined */
+ _cogl_current_matrix_state_flush ();
+
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( glStencilOp (GL_ZERO, GL_REPLACE, GL_REPLACE) );
cogl_rectangle (bounds_x, bounds_y,
bounds_x + bounds_w, bounds_y + bounds_h);
-
+ _cogl_journal_flush ();
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
}
cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
+ _cogl_journal_flush ();
_cogl_current_matrix_pop ();
GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
+
+ /* restore the original material */
+ cogl_set_source (prev_source);
+ cogl_handle_unref (prev_source);
}
void
if (handle != COGL_INVALID_HANDLE && !cogl_is_program (handle))
return;
+ /* The Cogl journal doesn't currently cope with the use of
+ * shaders so we have to flush all priitives whenever the
+ * current shader changes... */
+ _cogl_journal_flush ();
+
if (handle == COGL_INVALID_HANDLE)
gl_handle = 0;
else
#include "cogl-bitmap-private.h"
#include "cogl-handle.h"
+#include "cogl-material-private.h"
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
* later flush the journal we aim to batch data, and gl draw calls. */
typedef struct _CoglJournalEntry
{
- CoglHandle material;
- gint n_layers;
- guint32 fallback_mask;
- GLuint layer0_override_texture;
+ CoglHandle material;
+ int n_layers;
+ CoglMaterialFlushOptions flush_options;
+ CoglMatrix model_view;
+ /* XXX: These entries are pretty big now considering the padding in
+ * CoglMaterialFlushOptions and CoglMatrix, so we might need to optimize this
+ * later. */
} CoglJournalEntry;
CoglTexture*
#include "cogl-material.h"
#include "cogl-context.h"
#include "cogl-handle.h"
+#include "cogl-primitives.h"
#include <string.h>
#include <stdlib.h>
#endif
-extern void _cogl_journal_flush (void);
-
static void _cogl_texture_free (CoglTexture *tex);
COGL_HANDLE_DEFINE (Texture, texture);
eglWaitNative (EGL_CORE_NATIVE_ENGINE);
clutter_actor_paint (CLUTTER_ACTOR (stage));
+ _cogl_flush ();
eglWaitGL();
eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface);
/* this will cause the stage implementation to be painted as well */
clutter_actor_paint (CLUTTER_ACTOR (stage));
+ _cogl_flush ();
/* Why this paint is done in backend as likely GL windowing system
* specific calls, like swapping buffers.
eglWaitNative (EGL_CORE_NATIVE_ENGINE);
clutter_actor_paint (CLUTTER_ACTOR (stage));
+ _cogl_flush ();
eglWaitGL();
eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface);
}
/* this will cause the stage implementation to be painted */
clutter_actor_paint (CLUTTER_ACTOR (stage));
+ _cogl_flush ();
if (stage_x11->xwin != None)
{
- (void) drawRect: (NSRect) bounds
{
clutter_actor_paint (CLUTTER_ACTOR (self->stage_osx->wrapper));
+ _cogl_flush ();
[[self openGLContext] flushBuffer];
}
ClutterStage *stage)
{
clutter_actor_paint (CLUTTER_ACTOR (stage));
-
+ _cogl_flush ();
+
SDL_GL_SwapBuffers();
}
/* this will cause the stage implementation to be painted */
clutter_actor_paint (CLUTTER_ACTOR (stage));
+ _cogl_flush ();
if (stage_win32->client_dc)
SwapBuffers (stage_win32->client_dc);