From 3979de69823c487ce9cd9455077ce755011fb0dc Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 18 May 2010 22:42:49 +0100 Subject: [PATCH] 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. --- cogl/cogl-context.c | 2 +- cogl/cogl-journal-private.h | 1 - cogl/cogl-journal.c | 68 +++++++++++++++++++++++------------- cogl/cogl-material-private.h | 6 +++- cogl/cogl-material.c | 38 ++------------------ cogl/cogl-path.c | 24 ++++++++----- cogl/cogl-primitives.c | 60 ++++++++++++++++++++----------- cogl/cogl-vertex-buffer.c | 45 +++++++++++++++++++++++- cogl/cogl.c | 4 +-- 9 files changed, 153 insertions(+), 95 deletions(-) diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index a01d74007..e227594f7 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -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 (); diff --git a/cogl/cogl-journal-private.h b/cogl/cogl-journal-private.h index afe7ea10f..da4f08f16 100644 --- a/cogl/cogl-journal-private.h +++ b/cogl/cogl-journal-private.h @@ -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 diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c index e850a2779..085405f5f 100644 --- a/cogl/cogl-journal.c +++ b/cogl/cogl-journal.c @@ -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); diff --git a/cogl/cogl-material-private.h b/cogl/cogl-material-private.h index a1029fe84..a272034d0 100644 --- a/cogl/cogl-material-private.h +++ b/cogl/cogl-material-private.h @@ -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); diff --git a/cogl/cogl-material.c b/cogl/cogl-material.c index f8f366fca..d1d7cd9ff 100644 --- a/cogl/cogl-material.c +++ b/cogl/cogl-material.c @@ -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); } diff --git a/cogl/cogl-path.c b/cogl/cogl-path.c index e1c3b8f4d..b732a22f1 100644 --- a/cogl/cogl-path.c +++ b/cogl/cogl-path.c @@ -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); diff --git a/cogl/cogl-primitives.c b/cogl/cogl-primitives.c index b24ff3af4..9cd23cd90 100644 --- a/cogl/cogl-primitives.c +++ b/cogl/cogl-primitives.c @@ -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)); diff --git a/cogl/cogl-vertex-buffer.c b/cogl/cogl-vertex-buffer.c index a4af74f89..fbbc2febc 100644 --- a/cogl/cogl-vertex-buffer.c +++ b/cogl/cogl-vertex-buffer.c @@ -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; diff --git a/cogl/cogl.c b/cogl/cogl.c index 41ccad873..81467b74b 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -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;