cogl: remove _cogl_material_flush_gl_state flush options

Since cogl_material_copy should now be cheap to use we can simplify
how we handle fallbacks and wrap mode overrides etc by simply copying
the original material and making our override changes on the new
material. This avoids the need for a sideband state structure that has
been growing in size and makes flushing material state more complex.

Note the plan is to eventually use weak materials for these override
materials and attach these as private data to the original materials so
we aren't making so many one-shot materials.
This commit is contained in:
Robert Bragg 2010-05-18 22:42:49 +01:00
parent 365605cf42
commit 02b7f51e80
9 changed files with 153 additions and 95 deletions

View File

@ -176,7 +176,7 @@ cogl_create_context (void)
default_texture_data);
cogl_set_source (_context->simple_material);
_cogl_material_flush_gl_state (_context->source_material, NULL);
_cogl_material_flush_gl_state (_context->source_material, FALSE);
_cogl_enable (enable_flags);
_cogl_flush_face_winding ();

View File

@ -33,7 +33,6 @@ typedef struct _CoglJournalEntry
{
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

View File

@ -262,7 +262,7 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
(ctxt->journal_rectangles_color & 4) ?
color_intensity : 0,
0xff);
_cogl_material_flush_gl_state (outline, NULL);
_cogl_material_flush_gl_state (outline, FALSE);
_cogl_enable (COGL_ENABLE_VERTEX_ARRAY);
for (i = 0; i < batch_len; i++)
GE( glDrawArrays (GL_LINE_LOOP, 4 * i + state->vertex_offset, 4) );
@ -315,8 +315,7 @@ _cogl_journal_flush_material_and_entries (CoglJournalEntry *batch_start,
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_BATCHING))
g_print ("BATCHING: material batch len = %d\n", batch_len);
_cogl_material_flush_gl_state (batch_start->material,
&batch_start->flush_options);
_cogl_material_flush_gl_state (batch_start->material, TRUE);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
@ -350,9 +349,9 @@ compare_entry_materials (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
* 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,
NULL,
entry1->material,
&entry1->flush_options,
NULL,
TRUE))
return TRUE;
else
@ -670,6 +669,8 @@ _cogl_journal_log_quad (const float *position,
int next_entry;
guint32 disable_layers;
CoglJournalEntry *entry;
CoglHandle source;
CoglMaterialFlushOptions flush_options;
COGL_STATIC_TIMER (log_timer,
"Mainloop", /* parent */
"Journal Log",
@ -786,36 +787,53 @@ _cogl_journal_log_quad (const float *position,
g_array_set_size (ctx->journal, next_entry + 1);
entry = &g_array_index (ctx->journal, CoglJournalEntry, next_entry);
disable_layers = (1 << n_layers) - 1;
disable_layers = ~disable_layers;
entry->n_layers = n_layers;
source = material;
if (G_UNLIKELY (ctx->legacy_state_set))
{
material = cogl_material_copy (material);
_cogl_material_apply_legacy_state (material);
entry->material = _cogl_material_journal_ref (material);
cogl_handle_unref (material);
source = cogl_material_copy (material);
_cogl_material_apply_legacy_state (source);
}
else
entry->material = _cogl_material_journal_ref (material);
entry->n_layers = n_layers;
entry->flush_options.flags =
COGL_MATERIAL_FLUSH_FALLBACK_MASK |
COGL_MATERIAL_FLUSH_DISABLE_MASK |
COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
entry->flush_options.fallback_layers = fallback_layers;
entry->flush_options.disable_layers = disable_layers;
flush_options.flags = COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
if (G_UNLIKELY (cogl_material_get_n_layers (material) != n_layers))
{
disable_layers = (1 << n_layers) - 1;
disable_layers = ~disable_layers;
flush_options.disable_layers = disable_layers;
flush_options.flags |= COGL_MATERIAL_FLUSH_DISABLE_MASK;
}
if (G_UNLIKELY (fallback_layers))
{
flush_options.fallback_layers = fallback_layers;
flush_options.flags |= COGL_MATERIAL_FLUSH_FALLBACK_MASK;
}
if (G_UNLIKELY (layer0_override_texture))
{
flush_options.flags |= COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE;
flush_options.layer0_override_texture = layer0_override_texture;
}
if (wrap_mode_overrides)
{
entry->flush_options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
entry->flush_options.wrap_mode_overrides = *wrap_mode_overrides;
flush_options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
flush_options.wrap_mode_overrides = *wrap_mode_overrides;
}
if (layer0_override_texture)
if (G_UNLIKELY (flush_options.flags))
{
entry->flush_options.flags |= COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE;
entry->flush_options.layer0_override_texture = layer0_override_texture;
/* If we haven't already created a derived material... */
if (source == material)
source = cogl_material_copy (material);
_cogl_material_apply_overrides (source, &flush_options);
}
entry->material = _cogl_material_journal_ref (source);
if (G_UNLIKELY (source != material))
cogl_handle_unref (source);
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))
cogl_get_modelview_matrix (&entry->model_view);

View File

@ -684,7 +684,7 @@ _cogl_material_get_colorubv (CoglHandle handle,
void
_cogl_material_flush_gl_state (CoglHandle material,
CoglMaterialFlushOptions *options);
gboolean skip_gl_state);
gboolean
_cogl_material_equal (CoglHandle material0_handle,
@ -725,6 +725,10 @@ _cogl_material_apply_legacy_state (CoglHandle handle);
void
_cogl_gl_use_program_wrapper (GLuint program);
void
_cogl_material_apply_overrides (CoglMaterial *material,
CoglMaterialFlushOptions *options);
CoglMaterialBlendEnable
_cogl_material_get_blend_enabled (CoglHandle handle);

View File

@ -2475,7 +2475,7 @@ override_layer_texture_cb (CoglMaterialLayer *layer, void *user_data)
return TRUE;
}
static void
void
_cogl_material_apply_overrides (CoglMaterial *material,
CoglMaterialFlushOptions *options)
{
@ -6401,11 +6401,9 @@ backend_add_layer_cb (CoglMaterialLayer *layer,
*/
void
_cogl_material_flush_gl_state (CoglHandle handle,
CoglMaterialFlushOptions *options)
gboolean skip_gl_color)
{
CoglMaterial *material;
gboolean material_overriden;
gboolean skip_gl_color = FALSE;
CoglMaterial *material = COGL_MATERIAL (handle);
unsigned long materials_difference;
int n_layers;
unsigned long *layer_differences;
@ -6422,33 +6420,6 @@ _cogl_material_flush_gl_state (CoglHandle handle,
COGL_TIMER_START (_cogl_uprof_context, material_flush_timer);
if (G_UNLIKELY (options &&
(options->flags & ~COGL_MATERIAL_FLUSH_SKIP_GL_COLOR)))
{
/* Create a oneshot material to handle the overrides.
*
* XXX: Note this is a stop-gap-solution: We are aiming to
* remove the overrides mechanism and move code like this out
* into the primitives code.
*
* Overrides were originally necessitated by the previously
* large cost of creating derived material, but they made things
* more complex and also introduced a limit of 32 layers.
*
* Although creating derived materials is now much cheaper it
* would be much better for primitives APIs to cache these
* derived materials as private data on the original material.
*/
material = cogl_material_copy (handle);
_cogl_material_apply_overrides (material, options);
material_overriden = TRUE;
}
else
material = COGL_MATERIAL (handle);
if (options && options->flags & COGL_MATERIAL_FLUSH_SKIP_GL_COLOR)
skip_gl_color = TRUE;
if (ctx->current_material == material)
materials_difference = ctx->current_material_changes_since_flush;
else if (ctx->current_material)
@ -6590,9 +6561,6 @@ _cogl_material_flush_gl_state (CoglHandle handle,
unit1->dirty_gl_texture = FALSE;
}
if (material_overriden)
cogl_handle_unref (material);
COGL_TIMER_STOP (_cogl_uprof_context, material_flush_timer);
}

View File

@ -131,7 +131,6 @@ _cogl_path_stroke_nodes (void)
unsigned int path_start = 0;
unsigned long enable_flags = COGL_ENABLE_VERTEX_ARRAY;
CoglPathData *data;
CoglMaterialFlushOptions options;
CoglHandle source;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -147,10 +146,6 @@ _cogl_path_stroke_nodes (void)
_cogl_enable (enable_flags);
options.flags = COGL_MATERIAL_FLUSH_DISABLE_MASK;
/* disable all texture layers */
options.disable_layers = (guint32)~0;
if (G_UNLIKELY (ctx->legacy_state_set))
{
source = cogl_material_copy (ctx->source_material);
@ -159,7 +154,20 @@ _cogl_path_stroke_nodes (void)
else
source = ctx->source_material;
_cogl_material_flush_gl_state (source, &options);
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);
}
_cogl_material_flush_gl_state (source, FALSE);
while (path_start < data->path_nodes->len)
{
@ -231,7 +239,7 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path,
prev_source = cogl_object_ref (ctx->source_material);
cogl_set_source (ctx->stencil_material);
_cogl_material_flush_gl_state (ctx->source_material, NULL);
_cogl_material_flush_gl_state (ctx->source_material, FALSE);
_cogl_enable (enable_flags);
@ -389,7 +397,7 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
else
source = ctx->source_material;
_cogl_material_flush_gl_state (ctx->source_material, NULL);
_cogl_material_flush_gl_state (source, FALSE);
_cogl_enable (COGL_ENABLE_VERTEX_ARRAY);

View File

@ -865,12 +865,18 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
v += state->stride;
}
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;
options.flags =
COGL_MATERIAL_FLUSH_DISABLE_MASK |
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE |
COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
/* disable all except the first layer */
options.disable_layers = (guint32)~1;
options.layer0_override_texture = gl_handle;
/* Override the wrapping mode on all of the slices to use a
@ -887,15 +893,19 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
options.wrap_mode_overrides.values[0].t =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_BORDER;
if (G_UNLIKELY (ctx->legacy_state_set))
if (cogl_material_get_n_layers (source) != 1)
{
source = cogl_material_copy (ctx->source_material);
_cogl_material_apply_legacy_state (source);
/* disable all except the first layer */
options.disable_layers = (guint32)~1;
options.flags |= COGL_MATERIAL_FLUSH_DISABLE_MASK;
}
else
source = ctx->source_material;
_cogl_material_flush_gl_state (source, &options);
/* 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));
@ -1030,16 +1040,6 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
}
}
options.flags = COGL_MATERIAL_FLUSH_FALLBACK_MASK;
if (use_color)
options.flags |= COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
options.fallback_layers = fallback_layers;
if (wrap_mode_overrides)
{
options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
options.wrap_mode_overrides = *wrap_mode_overrides;
}
if (G_UNLIKELY (ctx->legacy_state_set))
{
source = cogl_material_copy (ctx->source_material);
@ -1048,7 +1048,27 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
else
source = ctx->source_material;
_cogl_material_flush_gl_state (source, &options);
options.flags = 0;
if (G_UNLIKELY (fallback_layers))
{
options.flags |= COGL_MATERIAL_FLUSH_FALLBACK_MASK;
options.fallback_layers = fallback_layers;
}
if (wrap_mode_overrides)
{
options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
options.wrap_mode_overrides = *wrap_mode_overrides;
}
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);
}
_cogl_material_flush_gl_state (source, use_color);
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));

View File

@ -1520,6 +1520,7 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
const GList *layers;
guint32 fallback_layers = 0;
int i;
gboolean skip_gl_color = FALSE;
CoglMaterialFlushOptions options;
CoglHandle source;
@ -1588,6 +1589,7 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
COGL_MATERIAL_BLEND_ENABLE_ENABLED;
source = cogl_material_copy (ctx->source_material);
_cogl_material_set_blend_enabled (source, blend_enable);
skip_gl_color = TRUE;
}
break;
case COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY:
@ -1727,6 +1729,47 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
options.fallback_layers = fallback_layers;
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);
/* TODO:
* overrides = cogl_material_get_data (material,
* last_overrides_key);
* if (overrides)
* {
* age = cogl_material_get_age (material);
* XXX: actually we also need to check for legacy_state
* and blending overrides for use of glColorPointer...
* if (overrides->ags != age ||
* memcmp (&overrides->options, &options,
* sizeof (options) != 0)
* {
* cogl_handle_unref (overrides->weak_material);
* g_slice_free (Overrides, overrides);
* overrides = NULL;
* }
* }
* if (!overrides)
* {
* overrides = g_slice_new (Overrides);
* overrides->weak_material =
* cogl_material_weak_copy (ctx->source_material);
* _cogl_material_apply_overrides (overrides->weak_material,
* &options);
*
* cogl_material_set_data (material, last_overrides_key,
* weak_overrides,
* free_overrides_cb,
* NULL);
* }
* source = overrides->weak_material;
*/
}
if (G_UNLIKELY (ctx->legacy_state_set))
{
/* If we haven't already created a derived material... */
@ -1735,7 +1778,7 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
_cogl_material_apply_legacy_state (source);
}
_cogl_material_flush_gl_state (source, &options);
_cogl_material_flush_gl_state (source, skip_gl_color);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;

View File

@ -816,7 +816,6 @@ _cogl_disable_other_texcoord_arrays (const CoglBitmask *mask)
void
cogl_begin_gl (void)
{
CoglMaterialFlushOptions options;
unsigned long enable_flags = 0;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -851,8 +850,7 @@ cogl_begin_gl (void)
* A user should instead call cogl_set_source_color4ub() before
* cogl_begin_gl() to simplify the state flushed.
*/
options.flags = 0;
_cogl_material_flush_gl_state (ctx->source_material, &options);
_cogl_material_flush_gl_state (ctx->source_material, FALSE);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;