Ejemplo n.º 1
0
CoglPipelineCache *
_cogl_pipeline_cache_new (void)
{
  CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
  unsigned long vertex_state;
  unsigned long layer_vertex_state;
  unsigned int fragment_state;
  unsigned int layer_fragment_state;

  _COGL_GET_CONTEXT (ctx, 0);

  vertex_state =
    _cogl_pipeline_get_state_for_vertex_codegen (ctx);
  layer_vertex_state =
    COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN;
  fragment_state =
    _cogl_pipeline_get_state_for_fragment_codegen (ctx);
  layer_fragment_state =
    _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);

  _cogl_pipeline_hash_table_init (&cache->vertex_hash,
                                  vertex_state,
                                  layer_vertex_state,
                                  "vertex shaders");
  _cogl_pipeline_hash_table_init (&cache->fragment_hash,
                                  fragment_state,
                                  layer_fragment_state,
                                  "fragment shaders");
  _cogl_pipeline_hash_table_init (&cache->combined_hash,
                                  vertex_state | fragment_state,
                                  layer_vertex_state | layer_fragment_state,
                                  "programs");

  return cache;
}
static void
_cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify (
                                                   CoglPipeline *pipeline,
                                                   CoglPipelineState change,
                                                   const CoglColor *new_color)
{
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
    dirty_shader_state (pipeline);
}
Ejemplo n.º 3
0
static gboolean
pipeline_fragment_equal (const void *a, const void *b)
{
    unsigned int fragment_state;
    unsigned int layer_fragment_state;

    _COGL_GET_CONTEXT (ctx, 0);

    fragment_state =
        _cogl_pipeline_get_state_for_fragment_codegen (ctx);
    layer_fragment_state =
        _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);

    return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
                                 fragment_state, layer_fragment_state,
                                 0);
}
Ejemplo n.º 4
0
static unsigned int
pipeline_fragment_hash (const void *data)
{
    unsigned int fragment_state;
    unsigned int layer_fragment_state;

    _COGL_GET_CONTEXT (ctx, 0);

    fragment_state =
        _cogl_pipeline_get_state_for_fragment_codegen (ctx);
    layer_fragment_state =
        _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);

    return _cogl_pipeline_hash ((CoglPipeline *)data,
                                fragment_state, layer_fragment_state,
                                0);
}
static CoglBool
_cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
                                    int n_layers,
                                    unsigned long pipelines_difference,
                                    int n_tex_coord_attribs)
{
  CoglPipelineShaderState *shader_state;
  CoglPipeline *authority;
  CoglPipeline *template_pipeline = NULL;

  _COGL_GET_CONTEXT (ctx, FALSE);

  /* First validate that we can handle the current state using ARBfp
   */

  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
    return FALSE;

  /* TODO: support fog */
  if (_cogl_pipeline_get_fog_enabled (pipeline))
    return FALSE;

  /* Fragment snippets are only supported in the GLSL fragend */
  if (_cogl_pipeline_has_fragment_snippets (pipeline))
    return FALSE;

  /* Now lookup our ARBfp backend private state */
  shader_state = get_shader_state (pipeline);

  /* If we have a valid shader_state then we are all set and don't
   * need to generate a new program. */
  if (shader_state)
    return TRUE;

  /* If we don't have an associated arbfp program yet then find the
   * arbfp-authority (the oldest ancestor whose state will result in
   * the same program being generated as for this pipeline).
   *
   * We always make sure to associate new programs with the
   * arbfp-authority to maximize the chance that other pipelines can
   * share it.
   */
  authority = _cogl_pipeline_find_equivalent_parent
    (pipeline,
     _cogl_pipeline_get_state_for_fragment_codegen (ctx) &
     ~COGL_PIPELINE_STATE_LAYERS,
     _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx));
  shader_state = get_shader_state (authority);
  if (shader_state)
    {
      /* If we are going to share our program state with an arbfp-authority
       * then add a reference to the program state associated with that
       * arbfp-authority... */
      shader_state->ref_count++;
      set_shader_state (pipeline, shader_state);
      return TRUE;
    }

  /* If we haven't yet found an existing program then before we resort to
   * generating a new arbfp program we see if we can find a suitable
   * program in the pipeline_cache. */
  if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
    {
      template_pipeline =
        _cogl_pipeline_cache_get_fragment_template (ctx->pipeline_cache,
                                                    authority);

      shader_state = get_shader_state (template_pipeline);

      if (shader_state)
        shader_state->ref_count++;
    }

  /* If we still haven't got a shader state then we'll have to create
     a new one */
  if (shader_state == NULL)
    {
      shader_state = shader_state_new (n_layers);

      /* We reuse a single grow-only GString for code-gen */
      g_string_set_size (ctx->codegen_source_buffer, 0);
      shader_state->source = ctx->codegen_source_buffer;
      g_string_append (shader_state->source,
                       "!!ARBfp1.0\n"
                       "TEMP output;\n"
                       "TEMP tmp0, tmp1, tmp2, tmp3, tmp4;\n"
                       "PARAM half = {.5, .5, .5, .5};\n"
                       "PARAM one = {1, 1, 1, 1};\n"
                       "PARAM two = {2, 2, 2, 2};\n"
                       "PARAM minus_one = {-1, -1, -1, -1};\n");
    }

  set_shader_state (pipeline, shader_state);

  /* Since we have already resolved the arbfp-authority at this point
   * we might as well also associate any program we find from the cache
   * with the authority too... */
  if (authority != pipeline)
    {
      shader_state->ref_count++;
      set_shader_state (authority, shader_state);
    }

  /* If we found a template then we'll attach it to that too so that
     next time a similar pipeline is used it can use the same state */
  if (template_pipeline)
    {
      shader_state->ref_count++;
      set_shader_state (template_pipeline, shader_state);
    }

  return TRUE;
}
static void
_cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
                                    int n_layers,
                                    unsigned long pipelines_difference)
{
  CoglPipelineShaderState *shader_state;
  CoglPipeline *authority;
  CoglPipelineCacheEntry *cache_entry = NULL;
  CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline);

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  /* Now lookup our ARBfp backend private state */
  shader_state = get_shader_state (pipeline);

  /* If we have a valid shader_state then we are all set and don't
   * need to generate a new program. */
  if (shader_state)
    return;

  /* If we don't have an associated arbfp program yet then find the
   * arbfp-authority (the oldest ancestor whose state will result in
   * the same program being generated as for this pipeline).
   *
   * We always make sure to associate new programs with the
   * arbfp-authority to maximize the chance that other pipelines can
   * share it.
   */
  authority = _cogl_pipeline_find_equivalent_parent
    (pipeline,
     _cogl_pipeline_get_state_for_fragment_codegen (ctx) &
     ~COGL_PIPELINE_STATE_LAYERS,
     _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx));
  shader_state = get_shader_state (authority);
  if (shader_state)
    {
      /* If we are going to share our program state with an arbfp-authority
       * then add a reference to the program state associated with that
       * arbfp-authority... */
      set_shader_state (pipeline, shader_state);
      return;
    }

  /* If we haven't yet found an existing program then before we resort to
   * generating a new arbfp program we see if we can find a suitable
   * program in the pipeline_cache. */
  if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
    {
      cache_entry =
        _cogl_pipeline_cache_get_fragment_template (ctx->pipeline_cache,
                                                    authority);

      shader_state = get_shader_state (cache_entry->pipeline);

      if (shader_state)
        shader_state->ref_count++;
    }

  /* If we still haven't got a shader state then we'll have to create
     a new one */
  if (shader_state == NULL)
    {
      shader_state = shader_state_new (n_layers, cache_entry);

      shader_state->user_program = user_program;
      if (user_program == COGL_INVALID_HANDLE)
        {
          /* We reuse a single grow-only GString for code-gen */
          g_string_set_size (ctx->codegen_source_buffer, 0);
          shader_state->source = ctx->codegen_source_buffer;
          g_string_append (shader_state->source,
                           "!!ARBfp1.0\n"
                           "TEMP output;\n"
                           "TEMP tmp0, tmp1, tmp2, tmp3, tmp4;\n"
                           "PARAM half = {.5, .5, .5, .5};\n"
                           "PARAM one = {1, 1, 1, 1};\n"
                           "PARAM two = {2, 2, 2, 2};\n"
                           "PARAM minus_one = {-1, -1, -1, -1};\n");
        }
    }

  set_shader_state (pipeline, shader_state);

  shader_state->ref_count--;

  /* Since we have already resolved the arbfp-authority at this point
   * we might as well also associate any program we find from the cache
   * with the authority too... */
  if (authority != pipeline)
    set_shader_state (authority, shader_state);

  /* If we found a template then we'll attach it to that too so that
     next time a similar pipeline is used it can use the same state */
  if (cache_entry)
    set_shader_state (cache_entry->pipeline, shader_state);
}