int _cogl_blend_string_test (void) { struct _TestString strings[] = { {" A = MODULATE ( TEXTURE[RGB], PREVIOUS[A], PREVIOUS[A] ) ", COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, {" RGB = MODULATE ( TEXTURE[RGB], PREVIOUS[A] ) ", COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, {"A=ADD(TEXTURE[A],PREVIOUS[RGB])", COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, {"A=ADD(TEXTURE[A],PREVIOUS[RGB])", COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, {"RGBA = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))", COGL_BLEND_STRING_CONTEXT_BLENDING }, {"RGB = ADD(SRC_COLOR, DST_COLOR*(0))", COGL_BLEND_STRING_CONTEXT_BLENDING }, {"RGB = ADD(SRC_COLOR, 0)", COGL_BLEND_STRING_CONTEXT_BLENDING }, {"RGB = ADD()", COGL_BLEND_STRING_CONTEXT_BLENDING }, {"RGB = ADD(SRC_COLOR, 0, DST_COLOR)", COGL_BLEND_STRING_CONTEXT_BLENDING }, {NULL} }; int i; CoglError *error = NULL; for (i = 0; strings[i].string; i++) { CoglBlendStringStatement statements[2]; int count = _cogl_blend_string_compile (strings[i].string, strings[i].context, statements, &error); if (!count) { g_print ("Failed to parse string:\n%s\n%s\n", strings[i].string, error->message); cogl_error_free (error); error = NULL; continue; } g_print ("Original:\n"); g_print ("%s\n", strings[i].string); if (count > 0) print_statement (0, &statements[0]); if (count > 1) print_statement (1, &statements[1]); } return 0; }
CoglBool cogl_pipeline_set_blend (CoglPipeline *pipeline, const char *blend_description, CoglError **error) { CoglPipelineState state = COGL_PIPELINE_STATE_BLEND; CoglPipeline *authority; CoglBlendStringStatement statements[2]; CoglBlendStringStatement *rgb; CoglBlendStringStatement *a; int count; CoglPipelineBlendState *blend_state; _COGL_GET_CONTEXT (ctx, FALSE); _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); count = _cogl_blend_string_compile (blend_description, COGL_BLEND_STRING_CONTEXT_BLENDING, statements, error); if (!count) return FALSE; if (count == 1) rgb = a = statements; else { rgb = &statements[0]; a = &statements[1]; } authority = _cogl_pipeline_get_authority (pipeline, state); /* - Flush journal primitives referencing the current state. * - Make sure the pipeline has no dependants so it may be modified. * - If the pipeline isn't currently an authority for the state being * changed, then initialize that state from the current authority. */ _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); blend_state = &pipeline->big_state->blend_state; #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2) if (ctx->driver != COGL_DRIVER_GLES1) { setup_blend_state (rgb, &blend_state->blend_equation_rgb, &blend_state->blend_src_factor_rgb, &blend_state->blend_dst_factor_rgb); setup_blend_state (a, &blend_state->blend_equation_alpha, &blend_state->blend_src_factor_alpha, &blend_state->blend_dst_factor_alpha); } else #endif { setup_blend_state (rgb, NULL, &blend_state->blend_src_factor_rgb, &blend_state->blend_dst_factor_rgb); } /* If we are the current authority see if we can revert to one of our * ancestors being the authority */ if (pipeline == authority && _cogl_pipeline_get_parent (authority) != NULL) { CoglPipeline *parent = _cogl_pipeline_get_parent (authority); CoglPipeline *old_authority = _cogl_pipeline_get_authority (parent, state); if (_cogl_pipeline_blend_state_equal (authority, old_authority)) pipeline->differences &= ~state; } /* If we weren't previously the authority on this state then we need * to extended our differences mask and so it's possible that some * of our ancestry will now become redundant, so we aim to reparent * ourselves if that's true... */ if (pipeline != authority) { pipeline->differences |= state; _cogl_pipeline_prune_redundant_ancestry (pipeline); } _cogl_pipeline_update_blend_enable (pipeline, state); return TRUE; }