示例#1
0
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;
}