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;