diff --git a/cogl/cogl-pipeline-fragend-arbfp.c b/cogl/cogl-pipeline-fragend-arbfp.c index 3f24edb2c..da0907ff2 100644 --- a/cogl/cogl-pipeline-fragend-arbfp.c +++ b/cogl/cogl-pipeline-fragend-arbfp.c @@ -55,6 +55,8 @@ #define GL_TEXTURE_3D 0x806F #endif +const CoglPipelineFragend _cogl_pipeline_arbfp_fragend; + typedef struct _UnitState { int constant_id; /* The program.local[] index */ @@ -63,7 +65,7 @@ typedef struct _UnitState unsigned int sampled:1; } UnitState; -typedef struct _ArbfpProgramState +typedef struct { int ref_count; @@ -84,82 +86,65 @@ typedef struct _ArbfpProgramState /* We need to track the last pipeline that an ARBfp program was used * with so know if we need to update any program.local parameters. */ CoglPipeline *last_used_for_pipeline; -} ArbfpProgramState; +} CoglPipelineShaderState; -typedef struct _CoglPipelineFragendARBfpPrivate +static CoglUserDataKey shader_state_key; + +static CoglPipelineShaderState * +shader_state_new (int n_layers) { - ArbfpProgramState *arbfp_program_state; -} CoglPipelineFragendARBfpPrivate; + CoglPipelineShaderState *shader_state; -const CoglPipelineFragend _cogl_pipeline_arbfp_fragend; + shader_state = g_slice_new0 (CoglPipelineShaderState); + shader_state->ref_count = 1; + shader_state->unit_state = g_new0 (UnitState, n_layers); - -static ArbfpProgramState * -arbfp_program_state_new (int n_layers) -{ - ArbfpProgramState *state = g_slice_new0 (ArbfpProgramState); - state->ref_count = 1; - state->unit_state = g_new0 (UnitState, n_layers); - return state; + return shader_state; } -static ArbfpProgramState * -arbfp_program_state_ref (ArbfpProgramState *state) +static CoglPipelineShaderState * +get_shader_state (CoglPipeline *pipeline) { - state->ref_count++; - return state; -} - -void -arbfp_program_state_unref (ArbfpProgramState *state) -{ - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - g_return_if_fail (state->ref_count > 0); - - state->ref_count--; - if (state->ref_count == 0) - { - if (state->gl_program) - { - GE (ctx, glDeletePrograms (1, &state->gl_program)); - state->gl_program = 0; - } - - g_free (state->unit_state); - - g_slice_free (ArbfpProgramState, state); - } -} - -static CoglPipelineFragendARBfpPrivate * -get_arbfp_priv (CoglPipeline *pipeline) -{ - if (!(pipeline->fragend_priv_set_mask & COGL_PIPELINE_FRAGEND_ARBFP_MASK)) - return NULL; - - return pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_ARBFP]; + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key); } static void -set_arbfp_priv (CoglPipeline *pipeline, CoglPipelineFragendARBfpPrivate *priv) +destroy_shader_state (void *user_data) { - if (priv) + CoglPipelineShaderState *shader_state = user_data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (--shader_state->ref_count == 0) { - pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_ARBFP] = priv; - pipeline->fragend_priv_set_mask |= COGL_PIPELINE_FRAGEND_ARBFP_MASK; + if (shader_state->gl_program) + { + GE (ctx, glDeletePrograms (1, &shader_state->gl_program)); + shader_state->gl_program = 0; + } + + g_free (shader_state->unit_state); + + g_slice_free (CoglPipelineShaderState, shader_state); } - else - pipeline->fragend_priv_set_mask &= ~COGL_PIPELINE_FRAGEND_ARBFP_MASK; } -static ArbfpProgramState * -get_arbfp_program_state (CoglPipeline *pipeline) +static void +set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state) { - CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (pipeline); - if (!priv) - return NULL; - return priv->arbfp_program_state; + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + shader_state, + destroy_shader_state); +} + +static void +dirty_shader_state (CoglPipeline *pipeline) +{ + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + NULL, + NULL); } static gboolean @@ -168,10 +153,8 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, unsigned long pipelines_difference, int n_tex_coord_attribs) { - CoglPipelineFragendARBfpPrivate *priv; + CoglPipelineShaderState *shader_state; CoglPipeline *authority; - CoglPipelineFragendARBfpPrivate *authority_priv; - ArbfpProgramState *arbfp_program_state; CoglHandle user_program; _COGL_GET_CONTEXT (ctx, FALSE); @@ -203,16 +186,11 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, /* Now lookup our ARBfp backend private state (allocating if * necessary) */ - priv = get_arbfp_priv (pipeline); - if (!priv) - { - priv = g_slice_new0 (CoglPipelineFragendARBfpPrivate); - set_arbfp_priv (pipeline, priv); - } + shader_state = get_shader_state (pipeline); - /* If we have a valid arbfp_program_state pointer then we are all - * set and don't need to generate a new program. */ - if (priv->arbfp_program_state) + /* 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 @@ -228,41 +206,36 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, _cogl_pipeline_get_state_for_fragment_codegen (ctx) & ~COGL_PIPELINE_STATE_LAYERS, _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)); - authority_priv = get_arbfp_priv (authority); - if (authority_priv && - authority_priv->arbfp_program_state) + shader_state = get_shader_state (authority); + if (shader_state) { /* If we are going to share our program state with an arbfp-authority - * then steal a reference to the program state associated with that + * then add a reference to the program state associated with that * arbfp-authority... */ - priv->arbfp_program_state = - arbfp_program_state_ref (authority_priv->arbfp_program_state); + shader_state->ref_count++; + set_shader_state (pipeline, shader_state); return TRUE; } - if (!authority_priv) - { - authority_priv = g_slice_new0 (CoglPipelineFragendARBfpPrivate); - set_arbfp_priv (authority, authority_priv); - } - /* 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 arbfp_cache. */ if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES)))) { - arbfp_program_state = g_hash_table_lookup (ctx->arbfp_cache, authority); - if (arbfp_program_state) + shader_state = g_hash_table_lookup (ctx->arbfp_cache, authority); + if (shader_state) { - priv->arbfp_program_state = - arbfp_program_state_ref (arbfp_program_state); + shader_state->ref_count++; + 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_priv != priv) - authority_priv->arbfp_program_state = - arbfp_program_state_ref (arbfp_program_state); + if (authority != pipeline) + { + shader_state->ref_count++; + set_shader_state (authority, shader_state); + } return TRUE; } } @@ -271,26 +244,27 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, * generating code for a new program... */ - arbfp_program_state = arbfp_program_state_new (n_layers); - - priv->arbfp_program_state = arbfp_program_state_ref (arbfp_program_state); + shader_state = shader_state_new (n_layers); + 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 generate with the authority too... */ - if (authority_priv != priv) - authority_priv->arbfp_program_state = - arbfp_program_state_ref (arbfp_program_state); + if (authority != pipeline) + { + shader_state->ref_count++; + set_shader_state (authority, shader_state); + } - arbfp_program_state->user_program = user_program; + shader_state->user_program = user_program; if (user_program == COGL_INVALID_HANDLE) { int i; /* We reuse a single grow-only GString for code-gen */ g_string_set_size (ctx->codegen_source_buffer, 0); - arbfp_program_state->source = ctx->codegen_source_buffer; - g_string_append (arbfp_program_state->source, + 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" @@ -302,14 +276,14 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, /* At the end of code-gen we'll add the program to a cache and * we'll use the authority pipeline as the basis for key into * that cache... */ - arbfp_program_state->arbfp_authority = authority; + shader_state->arbfp_authority = authority; for (i = 0; i < n_layers; i++) { - arbfp_program_state->unit_state[i].sampled = FALSE; - arbfp_program_state->unit_state[i].dirty_combine_constant = FALSE; + shader_state->unit_state[i].sampled = FALSE; + shader_state->unit_state[i].dirty_combine_constant = FALSE; } - arbfp_program_state->next_constant_id = 0; + shader_state->next_constant_id = 0; } return TRUE; @@ -370,20 +344,20 @@ gl_target_to_arbfp_string (GLenum gl_target) } static void -setup_texture_source (ArbfpProgramState *arbfp_program_state, +setup_texture_source (CoglPipelineShaderState *shader_state, int unit_index, GLenum gl_target) { - if (!arbfp_program_state->unit_state[unit_index].sampled) + if (!shader_state->unit_state[unit_index].sampled) { if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) - g_string_append_printf (arbfp_program_state->source, + g_string_append_printf (shader_state->source, "TEMP texel%d;\n" "MOV texel%d, one;\n", unit_index, unit_index); else - g_string_append_printf (arbfp_program_state->source, + g_string_append_printf (shader_state->source, "TEMP texel%d;\n" "TEX texel%d,fragment.texcoord[%d]," "texture[%d],%s;\n", @@ -392,7 +366,7 @@ setup_texture_source (ArbfpProgramState *arbfp_program_state, unit_index, unit_index, gl_target_to_arbfp_string (gl_target)); - arbfp_program_state->unit_state[unit_index].sampled = TRUE; + shader_state->unit_state[unit_index].sampled = TRUE; } } @@ -452,7 +426,7 @@ setup_arg (CoglPipeline *pipeline, GLint op, CoglPipelineFragendARBfpArg *arg) { - ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); static const char *tmp_name[3] = { "tmp0", "tmp1", "tmp2" }; GLenum gl_target; CoglHandle texture; @@ -465,14 +439,14 @@ setup_arg (CoglPipeline *pipeline, arg->texture_unit = _cogl_pipeline_layer_get_unit_index (layer); texture = _cogl_pipeline_layer_get_texture (layer); cogl_texture_get_gl_texture (texture, NULL, &gl_target); - setup_texture_source (arbfp_program_state, arg->texture_unit, gl_target); + setup_texture_source (shader_state, arg->texture_unit, gl_target); break; case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT: { int unit_index = _cogl_pipeline_layer_get_unit_index (layer); - UnitState *unit_state = &arbfp_program_state->unit_state[unit_index]; + UnitState *unit_state = &shader_state->unit_state[unit_index]; - unit_state->constant_id = arbfp_program_state->next_constant_id++; + unit_state->constant_id = shader_state->next_constant_id++; unit_state->dirty_combine_constant = TRUE; arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT; @@ -497,7 +471,7 @@ setup_arg (CoglPipeline *pipeline, arg->texture_unit = src - GL_TEXTURE0; texture = _cogl_pipeline_layer_get_texture (layer); cogl_texture_get_gl_texture (texture, NULL, &gl_target); - setup_texture_source (arbfp_program_state, arg->texture_unit, gl_target); + setup_texture_source (shader_state, arg->texture_unit, gl_target); } arg->swizzle = ""; @@ -507,11 +481,11 @@ setup_arg (CoglPipeline *pipeline, case COGL_PIPELINE_COMBINE_OP_SRC_COLOR: break; case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR: - g_string_append_printf (arbfp_program_state->source, + g_string_append_printf (shader_state->source, "SUB tmp%d, one, ", arg_index); - append_arg (arbfp_program_state->source, arg); - g_string_append_printf (arbfp_program_state->source, ";\n"); + append_arg (shader_state->source, arg); + g_string_append_printf (shader_state->source, ";\n"); arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; arg->name = tmp_name[arg_index]; arg->swizzle = ""; @@ -523,16 +497,16 @@ setup_arg (CoglPipeline *pipeline, arg->swizzle = ".a"; break; case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA: - g_string_append_printf (arbfp_program_state->source, + g_string_append_printf (shader_state->source, "SUB tmp%d, one, ", arg_index); - append_arg (arbfp_program_state->source, arg); + append_arg (shader_state->source, arg); /* avoid a swizzle if we know RGB are going to be masked * in the end anyway */ if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) - g_string_append_printf (arbfp_program_state->source, ".a;\n"); + g_string_append_printf (shader_state->source, ".a;\n"); else - g_string_append_printf (arbfp_program_state->source, ";\n"); + g_string_append_printf (shader_state->source, ";\n"); arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; arg->name = tmp_name[arg_index]; break; @@ -577,7 +551,7 @@ append_function (CoglPipeline *pipeline, CoglPipelineFragendARBfpArg *args, int n_args) { - ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); const char *mask_name; switch (mask) @@ -599,35 +573,35 @@ append_function (CoglPipeline *pipeline, switch (function) { case COGL_PIPELINE_COMBINE_FUNC_ADD: - g_string_append_printf (arbfp_program_state->source, + g_string_append_printf (shader_state->source, "ADD_SAT output%s, ", mask_name); break; case COGL_PIPELINE_COMBINE_FUNC_MODULATE: /* Note: no need to saturate since we can assume operands * have values in the range [0,1] */ - g_string_append_printf (arbfp_program_state->source, "MUL output%s, ", + g_string_append_printf (shader_state->source, "MUL output%s, ", mask_name); break; case COGL_PIPELINE_COMBINE_FUNC_REPLACE: /* Note: no need to saturate since we can assume operand * has a value in the range [0,1] */ - g_string_append_printf (arbfp_program_state->source, "MOV output%s, ", + g_string_append_printf (shader_state->source, "MOV output%s, ", mask_name); break; case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT: - g_string_append_printf (arbfp_program_state->source, + g_string_append_printf (shader_state->source, "SUB_SAT output%s, ", mask_name); break; case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED: - g_string_append_printf (arbfp_program_state->source, "ADD tmp3%s, ", + g_string_append_printf (shader_state->source, "ADD tmp3%s, ", mask_name); - append_arg (arbfp_program_state->source, &args[0]); - g_string_append (arbfp_program_state->source, ", "); - append_arg (arbfp_program_state->source, &args[1]); - g_string_append (arbfp_program_state->source, ";\n"); - g_string_append_printf (arbfp_program_state->source, + append_arg (shader_state->source, &args[0]); + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[1]); + g_string_append (shader_state->source, ";\n"); + g_string_append_printf (shader_state->source, "SUB_SAT output%s, tmp3, half", mask_name); n_args = 0; @@ -656,20 +630,20 @@ append_function (CoglPipeline *pipeline, * output = 4 * DP3 (src0 - 0.5, src1 - 0.5) */ - g_string_append (arbfp_program_state->source, "MAD tmp3, two, "); - append_arg (arbfp_program_state->source, &args[0]); - g_string_append (arbfp_program_state->source, ", minus_one;\n"); + g_string_append (shader_state->source, "MAD tmp3, two, "); + append_arg (shader_state->source, &args[0]); + g_string_append (shader_state->source, ", minus_one;\n"); if (!fragend_arbfp_args_equal (&args[0], &args[1])) { - g_string_append (arbfp_program_state->source, "MAD tmp4, two, "); - append_arg (arbfp_program_state->source, &args[1]); - g_string_append (arbfp_program_state->source, ", minus_one;\n"); + g_string_append (shader_state->source, "MAD tmp4, two, "); + append_arg (shader_state->source, &args[1]); + g_string_append (shader_state->source, ", minus_one;\n"); } else tmp4 = "tmp3"; - g_string_append_printf (arbfp_program_state->source, + g_string_append_printf (shader_state->source, "DP3_SAT output%s, tmp3, %s", mask_name, tmp4); n_args = 0; @@ -681,31 +655,31 @@ append_function (CoglPipeline *pipeline, /* NB: GL_INTERPOLATE = arg0*arg2 + arg1*(1-arg2) * but LRP dst, a, b, c = b*a + c*(1-a) */ - g_string_append_printf (arbfp_program_state->source, "LRP output%s, ", + g_string_append_printf (shader_state->source, "LRP output%s, ", mask_name); - append_arg (arbfp_program_state->source, &args[2]); - g_string_append (arbfp_program_state->source, ", "); - append_arg (arbfp_program_state->source, &args[0]); - g_string_append (arbfp_program_state->source, ", "); - append_arg (arbfp_program_state->source, &args[1]); + append_arg (shader_state->source, &args[2]); + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[0]); + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[1]); n_args = 0; break; default: g_error ("Unknown texture combine function %d", function); - g_string_append_printf (arbfp_program_state->source, "MUL_SAT output%s, ", + g_string_append_printf (shader_state->source, "MUL_SAT output%s, ", mask_name); n_args = 2; break; } if (n_args > 0) - append_arg (arbfp_program_state->source, &args[0]); + append_arg (shader_state->source, &args[0]); if (n_args > 1) { - g_string_append (arbfp_program_state->source, ", "); - append_arg (arbfp_program_state->source, &args[1]); + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[1]); } - g_string_append (arbfp_program_state->source, ";\n"); + g_string_append (shader_state->source, ";\n"); } static void @@ -745,7 +719,7 @@ _cogl_pipeline_fragend_arbfp_add_layer (CoglPipeline *pipeline, CoglPipelineLayer *layer, unsigned long layers_difference) { - ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); CoglPipelineLayer *combine_authority = _cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_COMBINE); @@ -780,7 +754,7 @@ _cogl_pipeline_fragend_arbfp_add_layer (CoglPipeline *pipeline, * We are careful to only saturate when writing to output. */ - if (!arbfp_program_state->source) + if (!shader_state->source) return TRUE; if (!_cogl_pipeline_need_texture_combine_separate (combine_authority)) @@ -827,12 +801,12 @@ _cogl_pipeline_fragend_arbfp_add_layer (CoglPipeline *pipeline, gboolean _cogl_pipeline_fragend_arbfp_passthrough (CoglPipeline *pipeline) { - ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); - if (!arbfp_program_state->source) + if (!shader_state->source) return TRUE; - g_string_append (arbfp_program_state->source, + g_string_append (shader_state->source, "MOV output, fragment.color.primary;\n"); return TRUE; } @@ -841,7 +815,7 @@ typedef struct _UpdateConstantsState { int unit; gboolean update_all; - ArbfpProgramState *arbfp_program_state; + CoglPipelineShaderState *shader_state; } UpdateConstantsState; static gboolean @@ -850,8 +824,8 @@ update_constants_cb (CoglPipeline *pipeline, void *user_data) { UpdateConstantsState *state = user_data; - ArbfpProgramState *arbfp_program_state = state->arbfp_program_state; - UnitState *unit_state = &arbfp_program_state->unit_state[state->unit++]; + CoglPipelineShaderState *shader_state = state->shader_state; + UnitState *unit_state = &shader_state->unit_state[state->unit++]; _COGL_GET_CONTEXT (ctx, FALSE); @@ -873,12 +847,12 @@ static gboolean _cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline, unsigned long pipelines_difference) { - ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); GLuint gl_program; _COGL_GET_CONTEXT (ctx, FALSE); - if (arbfp_program_state->source) + if (shader_state->source) { GLenum gl_error; COGL_STATIC_COUNTER (fragend_arbfp_compile_counter, @@ -889,32 +863,32 @@ _cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline, COGL_COUNTER_INC (_cogl_uprof_context, fragend_arbfp_compile_counter); - g_string_append (arbfp_program_state->source, + g_string_append (shader_state->source, "MOV result.color,output;\n"); - g_string_append (arbfp_program_state->source, "END\n"); + g_string_append (shader_state->source, "END\n"); if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE))) - g_message ("pipeline program:\n%s", arbfp_program_state->source->str); + g_message ("pipeline program:\n%s", shader_state->source->str); - GE (ctx, glGenPrograms (1, &arbfp_program_state->gl_program)); + GE (ctx, glGenPrograms (1, &shader_state->gl_program)); GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, - arbfp_program_state->gl_program)); + shader_state->gl_program)); while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR) ; ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - arbfp_program_state->source->len, - arbfp_program_state->source->str); + shader_state->source->len, + shader_state->source->str); if (ctx->glGetError () != GL_NO_ERROR) { g_warning ("\n%s\n%s", - arbfp_program_state->source->str, + shader_state->source->str, ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB)); } - arbfp_program_state->source = NULL; + shader_state->source = NULL; if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES)))) { @@ -942,9 +916,9 @@ _cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline, * other pipelines) and only takes a copy of the state that * relates to the arbfp program and references small dummy * textures instead of potentially large user textures. */ - key = cogl_pipeline_copy (arbfp_program_state->arbfp_authority); - arbfp_program_state_ref (arbfp_program_state); - g_hash_table_insert (ctx->arbfp_cache, key, arbfp_program_state); + key = cogl_pipeline_copy (shader_state->arbfp_authority); + shader_state->ref_count++; + g_hash_table_insert (ctx->arbfp_cache, key, shader_state); if (G_UNLIKELY (g_hash_table_size (ctx->arbfp_cache) > 50)) { static gboolean seen = FALSE; @@ -959,77 +933,59 @@ _cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline, /* The authority is only valid during codegen since the program * state may have a longer lifetime than the original authority * it is created for. */ - arbfp_program_state->arbfp_authority = NULL; + shader_state->arbfp_authority = NULL; } - if (arbfp_program_state->user_program != COGL_INVALID_HANDLE) + if (shader_state->user_program != COGL_INVALID_HANDLE) { /* An arbfp program should contain exactly one shader which we can use directly */ - CoglProgram *program = arbfp_program_state->user_program; + CoglProgram *program = shader_state->user_program; CoglShader *shader = program->attached_shaders->data; gl_program = shader->gl_handle; } else - gl_program = arbfp_program_state->gl_program; + gl_program = shader_state->gl_program; GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, gl_program)); _cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_ARBFP); - if (arbfp_program_state->user_program == COGL_INVALID_HANDLE) + if (shader_state->user_program == COGL_INVALID_HANDLE) { UpdateConstantsState state; state.unit = 0; - state.arbfp_program_state = arbfp_program_state; + state.shader_state = shader_state; /* If this arbfp program was last used with a different pipeline * then we need to ensure we update all program.local params */ state.update_all = - pipeline != arbfp_program_state->last_used_for_pipeline; + pipeline != shader_state->last_used_for_pipeline; cogl_pipeline_foreach_layer (pipeline, update_constants_cb, &state); } else { - CoglProgram *program = arbfp_program_state->user_program; + CoglProgram *program = shader_state->user_program; gboolean program_changed; /* If the shader has changed since it was last flushed then we need to update all uniforms */ - program_changed = program->age != arbfp_program_state->user_program_age; + program_changed = program->age != shader_state->user_program_age; _cogl_program_flush_uniforms (program, gl_program, program_changed); - arbfp_program_state->user_program_age = program->age; + shader_state->user_program_age = program->age; } /* We need to track what pipeline used this arbfp program last since * we will need to update program.local params when switching * between different pipelines. */ - arbfp_program_state->last_used_for_pipeline = pipeline; + shader_state->last_used_for_pipeline = pipeline; return TRUE; } -static void -dirty_arbfp_program_state (CoglPipeline *pipeline) -{ - CoglPipelineFragendARBfpPrivate *priv; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - priv = get_arbfp_priv (pipeline); - if (!priv) - return; - - if (priv->arbfp_program_state) - { - arbfp_program_state_unref (priv->arbfp_program_state); - priv->arbfp_program_state = NULL; - } -} - static void _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify ( CoglPipeline *pipeline, @@ -1039,7 +995,7 @@ _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify ( _COGL_GET_CONTEXT (ctx, NO_RETVAL); if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) - dirty_arbfp_program_state (pipeline); + dirty_shader_state (pipeline); } /* NB: layers are considered immutable once they have any dependants @@ -1056,29 +1012,23 @@ _cogl_pipeline_fragend_arbfp_layer_pre_change_notify ( CoglPipelineLayer *layer, CoglPipelineLayerState change) { - CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (owner); + CoglPipelineShaderState *shader_state = get_shader_state (owner); _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (!priv) + if (!shader_state) return; if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx))) { - dirty_arbfp_program_state (owner); + dirty_shader_state (owner); return; } if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT) { - ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (owner); - - if (arbfp_program_state) - { - int unit_index = _cogl_pipeline_layer_get_unit_index (layer); - arbfp_program_state->unit_state[unit_index].dirty_combine_constant = - TRUE; - } + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + shader_state->unit_state[unit_index].dirty_combine_constant = TRUE; } /* TODO: we could be saving snippets of texture combine code along @@ -1087,19 +1037,6 @@ _cogl_pipeline_fragend_arbfp_layer_pre_change_notify ( return; } -static void -_cogl_pipeline_fragend_arbfp_free_priv (CoglPipeline *pipeline) -{ - CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (pipeline); - if (priv) - { - if (priv->arbfp_program_state) - arbfp_program_state_unref (priv->arbfp_program_state); - g_slice_free (CoglPipelineFragendARBfpPrivate, priv); - set_arbfp_priv (pipeline, NULL); - } -} - const CoglPipelineFragend _cogl_pipeline_arbfp_fragend = { _cogl_pipeline_fragend_arbfp_start, @@ -1108,8 +1045,7 @@ const CoglPipelineFragend _cogl_pipeline_arbfp_fragend = _cogl_pipeline_fragend_arbfp_end, _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify, NULL, - _cogl_pipeline_fragend_arbfp_layer_pre_change_notify, - _cogl_pipeline_fragend_arbfp_free_priv + _cogl_pipeline_fragend_arbfp_layer_pre_change_notify }; #endif /* COGL_PIPELINE_FRAGEND_ARBFP */ diff --git a/cogl/cogl-pipeline-fragend-fixed.c b/cogl/cogl-pipeline-fragend-fixed.c index 97fe04382..93627e4d3 100644 --- a/cogl/cogl-pipeline-fragend-fixed.c +++ b/cogl/cogl-pipeline-fragend-fixed.c @@ -363,7 +363,6 @@ const CoglPipelineFragend _cogl_pipeline_fixed_fragend = NULL, /* pipeline_change_notify */ NULL, /* pipeline_set_parent_notify */ NULL, /* layer_change_notify */ - NULL /* free_priv */ }; #endif /* COGL_PIPELINE_FRAGEND_FIXED */ diff --git a/cogl/cogl-pipeline-fragend-glsl.c b/cogl/cogl-pipeline-fragend-glsl.c index 32b355d17..35e43e9e1 100644 --- a/cogl/cogl-pipeline-fragend-glsl.c +++ b/cogl/cogl-pipeline-fragend-glsl.c @@ -56,13 +56,15 @@ #define GL_TEXTURE_3D 0x806F #endif +const CoglPipelineFragend _cogl_pipeline_glsl_backend; + typedef struct _UnitState { unsigned int sampled:1; unsigned int combine_constant_used:1; } UnitState; -typedef struct _GlslShaderState +typedef struct { int ref_count; @@ -75,120 +77,83 @@ typedef struct _GlslShaderState program changes then we may need to redecide whether to generate a shader at all */ unsigned int user_program_age; -} GlslShaderState; +} CoglPipelineShaderState; -typedef struct _CoglPipelineFragendGlslPrivate +static CoglUserDataKey shader_state_key; + +static CoglPipelineShaderState * +shader_state_new (int n_layers) { - GlslShaderState *glsl_shader_state; -} CoglPipelineFragendGlslPrivate; + CoglPipelineShaderState *shader_state; -const CoglPipelineFragend _cogl_pipeline_glsl_backend; + shader_state = g_slice_new0 (CoglPipelineShaderState); + shader_state->ref_count = 1; + shader_state->unit_state = g_new0 (UnitState, n_layers); -static GlslShaderState * -glsl_shader_state_new (int n_layers) -{ - GlslShaderState *state = g_slice_new0 (GlslShaderState); - - state->ref_count = 1; - state->unit_state = g_new0 (UnitState, n_layers); - - return state; + return shader_state; } -static GlslShaderState * -glsl_shader_state_ref (GlslShaderState *state) +static CoglPipelineShaderState * +get_shader_state (CoglPipeline *pipeline) { - state->ref_count++; - return state; -} - -void -glsl_shader_state_unref (GlslShaderState *state) -{ - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - g_return_if_fail (state->ref_count > 0); - - state->ref_count--; - if (state->ref_count == 0) - { - if (state->gl_shader) - GE( ctx, glDeleteShader (state->gl_shader) ); - - g_free (state->unit_state); - - g_slice_free (GlslShaderState, state); - } -} - -static CoglPipelineFragendGlslPrivate * -get_glsl_priv (CoglPipeline *pipeline) -{ - if (!(pipeline->fragend_priv_set_mask & COGL_PIPELINE_FRAGEND_GLSL_MASK)) - return NULL; - - return pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_GLSL]; + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key); } static void -set_glsl_priv (CoglPipeline *pipeline, CoglPipelineFragendGlslPrivate *priv) +destroy_shader_state (void *user_data) { - if (priv) + CoglPipelineShaderState *shader_state = user_data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (--shader_state->ref_count == 0) { - pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_GLSL] = priv; - pipeline->fragend_priv_set_mask |= COGL_PIPELINE_FRAGEND_GLSL_MASK; + if (shader_state->gl_shader) + GE( ctx, glDeleteShader (shader_state->gl_shader) ); + + g_free (shader_state->unit_state); + + g_slice_free (CoglPipelineShaderState, shader_state); } - else - pipeline->fragend_priv_set_mask &= ~COGL_PIPELINE_FRAGEND_GLSL_MASK; } -static GlslShaderState * -get_glsl_shader_state (CoglPipeline *pipeline) +static void +set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state) { - CoglPipelineFragendGlslPrivate *priv = get_glsl_priv (pipeline); - if (!priv) - return NULL; - return priv->glsl_shader_state; + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + shader_state, + destroy_shader_state); +} + +static void +dirty_shader_state (CoglPipeline *pipeline) +{ + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + NULL, + NULL); } GLuint _cogl_pipeline_fragend_glsl_get_shader (CoglPipeline *pipeline) { - GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); - if (glsl_shader_state) - return glsl_shader_state->gl_shader; + if (shader_state) + return shader_state->gl_shader; else return 0; } -static void -dirty_glsl_shader_state (CoglPipeline *pipeline) -{ - CoglPipelineFragendGlslPrivate *priv; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - priv = get_glsl_priv (pipeline); - if (!priv) - return; - - if (priv->glsl_shader_state) - { - glsl_shader_state_unref (priv->glsl_shader_state); - priv->glsl_shader_state = NULL; - } -} - static gboolean _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, int n_layers, unsigned long pipelines_difference, int n_tex_coord_attribs) { - CoglPipelineFragendGlslPrivate *priv; + CoglPipelineShaderState *shader_state; CoglPipeline *authority; - CoglPipelineFragendGlslPrivate *authority_priv; CoglProgram *user_program; int i; @@ -206,16 +171,10 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, _cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL) return FALSE; - /* Now lookup our glsl backend private state (allocating if - * necessary) */ - priv = get_glsl_priv (pipeline); - if (!priv) - { - priv = g_slice_new0 (CoglPipelineFragendGlslPrivate); - set_glsl_priv (pipeline, priv); - } + /* Now lookup our glsl backend private state */ + shader_state = get_shader_state (pipeline); - if (!priv->glsl_shader_state) + if (shader_state == NULL) { /* If we don't have an associated glsl shader yet then find the * glsl-authority (the oldest ancestor whose state will result in @@ -231,43 +190,39 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, ~COGL_PIPELINE_STATE_LAYERS, _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)); - authority_priv = get_glsl_priv (authority); - if (!authority_priv) - { - authority_priv = g_slice_new0 (CoglPipelineFragendGlslPrivate); - set_glsl_priv (authority, authority_priv); - } + shader_state = get_shader_state (authority); /* If we don't have an existing program associated with the * glsl-authority then start generating code for a new shader... */ - if (!authority_priv->glsl_shader_state) + if (shader_state == NULL) { - GlslShaderState *glsl_shader_state = - glsl_shader_state_new (n_layers); - authority_priv->glsl_shader_state = glsl_shader_state; + shader_state = shader_state_new (n_layers); + set_shader_state (authority, shader_state); } /* If the pipeline isn't actually its own glsl-authority * then take a reference to the program state associated * with the glsl-authority... */ if (authority != pipeline) - priv->glsl_shader_state = - glsl_shader_state_ref (authority_priv->glsl_shader_state); + { + shader_state->ref_count++; + set_shader_state (pipeline, shader_state); + } } - if (priv->glsl_shader_state->gl_shader) + if (shader_state->gl_shader) { /* If we already have a valid GLSL shader then we don't need to generate a new one. However if there's a user program and it has changed since the last link then we do need a new shader */ if (user_program == NULL || - (priv->glsl_shader_state->user_program_age == user_program->age)) + shader_state->user_program_age == user_program->age) return TRUE; /* We need to recreate the shader so destroy the existing one */ - GE( ctx, glDeleteShader (priv->glsl_shader_state->gl_shader) ); - priv->glsl_shader_state->gl_shader = 0; + GE( ctx, glDeleteShader (shader_state->gl_shader) ); + shader_state->gl_shader = 0; } /* If we make it here then we have a glsl_shader_state struct @@ -275,7 +230,7 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, encountered it or because the user program has changed */ if (user_program) - priv->glsl_shader_state->user_program_age = user_program->age; + shader_state->user_program_age = user_program->age; /* If the user program contains a fragment shader then we don't need to generate one */ @@ -290,25 +245,25 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, add_layer callback is invoked */ g_string_set_size (ctx->codegen_header_buffer, 0); g_string_set_size (ctx->codegen_source_buffer, 0); - priv->glsl_shader_state->header = ctx->codegen_header_buffer; - priv->glsl_shader_state->source = ctx->codegen_source_buffer; + shader_state->header = ctx->codegen_header_buffer; + shader_state->source = ctx->codegen_source_buffer; - g_string_append (priv->glsl_shader_state->source, + g_string_append (shader_state->source, "void\n" "main ()\n" "{\n"); for (i = 0; i < n_layers; i++) { - priv->glsl_shader_state->unit_state[i].sampled = FALSE; - priv->glsl_shader_state->unit_state[i].combine_constant_used = FALSE; + shader_state->unit_state[i].sampled = FALSE; + shader_state->unit_state[i].combine_constant_used = FALSE; } return TRUE; } static void -add_constant_lookup (GlslShaderState *glsl_shader_state, +add_constant_lookup (CoglPipelineShaderState *shader_state, CoglPipeline *pipeline, CoglPipelineLayer *layer, const char *swizzle) @@ -316,21 +271,21 @@ add_constant_lookup (GlslShaderState *glsl_shader_state, int unit_index = _cogl_pipeline_layer_get_unit_index (layer); /* Create a sampler uniform for this layer if we haven't already */ - if (!glsl_shader_state->unit_state[unit_index].combine_constant_used) + if (!shader_state->unit_state[unit_index].combine_constant_used) { - g_string_append_printf (glsl_shader_state->header, + g_string_append_printf (shader_state->header, "uniform vec4 _cogl_layer_constant_%i;\n", unit_index); - glsl_shader_state->unit_state[unit_index].combine_constant_used = TRUE; + shader_state->unit_state[unit_index].combine_constant_used = TRUE; } - g_string_append_printf (glsl_shader_state->source, + g_string_append_printf (shader_state->source, "_cogl_layer_constant_%i.%s", unit_index, swizzle); } static void -add_texture_lookup (GlslShaderState *glsl_shader_state, +add_texture_lookup (CoglPipelineShaderState *shader_state, CoglPipeline *pipeline, CoglPipelineLayer *layer, const char *swizzle) @@ -343,9 +298,9 @@ add_texture_lookup (GlslShaderState *glsl_shader_state, if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) { - g_string_append (glsl_shader_state->source, + g_string_append (shader_state->source, "vec4 (1.0, 1.0, 1.0, 1.0)."); - g_string_append (glsl_shader_state->source, swizzle); + g_string_append (shader_state->source, swizzle); return; } @@ -394,16 +349,16 @@ add_texture_lookup (GlslShaderState *glsl_shader_state, } /* Create a sampler uniform for this layer if we haven't already */ - if (!glsl_shader_state->unit_state[unit_index].sampled) + if (!shader_state->unit_state[unit_index].sampled) { - g_string_append_printf (glsl_shader_state->header, + g_string_append_printf (shader_state->header, "uniform sampler%s _cogl_sampler_%i;\n", target_string, unit_index); - glsl_shader_state->unit_state[unit_index].sampled = TRUE; + shader_state->unit_state[unit_index].sampled = TRUE; } - g_string_append_printf (glsl_shader_state->source, + g_string_append_printf (shader_state->source, "texture%s (_cogl_sampler_%i, ", target_string, unit_index); @@ -418,15 +373,15 @@ add_texture_lookup (GlslShaderState *glsl_shader_state, if (ctx->driver == COGL_DRIVER_GLES2 && cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline, layer->index)) - g_string_append_printf (glsl_shader_state->source, + g_string_append_printf (shader_state->source, "gl_PointCoord.%s", tex_coord_swizzle); else - g_string_append_printf (glsl_shader_state->source, + g_string_append_printf (shader_state->source, "cogl_tex_coord_in[%d].%s", unit_index, tex_coord_swizzle); - g_string_append_printf (glsl_shader_state->source, ").%s", swizzle); + g_string_append_printf (shader_state->source, ").%s", swizzle); } typedef struct @@ -454,14 +409,14 @@ find_pipeline_layer_cb (CoglPipelineLayer *layer, } static void -add_arg (GlslShaderState *glsl_shader_state, +add_arg (CoglPipelineShaderState *shader_state, CoglPipeline *pipeline, CoglPipelineLayer *layer, CoglPipelineCombineSource src, CoglPipelineCombineOp operand, const char *swizzle) { - GString *shader_source = glsl_shader_state->source; + GString *shader_source = shader_state->source; char alpha_swizzle[5] = "aaaa"; g_string_append_c (shader_source, '('); @@ -484,14 +439,14 @@ add_arg (GlslShaderState *glsl_shader_state, switch (src) { case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE: - add_texture_lookup (glsl_shader_state, + add_texture_lookup (shader_state, pipeline, layer, swizzle); break; case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT: - add_constant_lookup (glsl_shader_state, + add_constant_lookup (shader_state, pipeline, layer, swizzle); @@ -521,7 +476,7 @@ add_arg (GlslShaderState *glsl_shader_state, find_pipeline_layer_cb, &data); - add_texture_lookup (glsl_shader_state, + add_texture_lookup (shader_state, pipeline, data.layer, swizzle); @@ -540,40 +495,40 @@ append_masked_combine (CoglPipeline *pipeline, CoglPipelineCombineSource *src, CoglPipelineCombineOp *op) { - GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline); - GString *shader_source = glsl_shader_state->source; + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + GString *shader_source = shader_state->source; - g_string_append_printf (glsl_shader_state->source, + g_string_append_printf (shader_state->source, " cogl_color_out.%s = ", swizzle); switch (function) { case COGL_PIPELINE_COMBINE_FUNC_REPLACE: - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], swizzle); break; case COGL_PIPELINE_COMBINE_FUNC_MODULATE: - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], swizzle); g_string_append (shader_source, " * "); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], swizzle); break; case COGL_PIPELINE_COMBINE_FUNC_ADD: - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], swizzle); g_string_append (shader_source, " + "); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], swizzle); break; case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED: - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], swizzle); g_string_append (shader_source, " + "); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], swizzle); g_string_append_printf (shader_source, " - vec4(0.5, 0.5, 0.5, 0.5).%s", @@ -581,26 +536,26 @@ append_masked_combine (CoglPipeline *pipeline, break; case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT: - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], swizzle); g_string_append (shader_source, " - "); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], swizzle); break; case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE: - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], swizzle); g_string_append (shader_source, " * "); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[2], op[2], swizzle); g_string_append (shader_source, " + "); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], swizzle); g_string_append_printf (shader_source, " * (vec4(1.0, 1.0, 1.0, 1.0).%s - ", swizzle); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[2], op[2], swizzle); g_string_append_c (shader_source, ')'); break; @@ -608,22 +563,22 @@ append_masked_combine (CoglPipeline *pipeline, case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB: case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA: g_string_append (shader_source, "vec4(4.0 * (("); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], "r"); g_string_append (shader_source, " - 0.5) * ("); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], "r"); g_string_append (shader_source, " - 0.5) + ("); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], "g"); g_string_append (shader_source, " - 0.5) * ("); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], "g"); g_string_append (shader_source, " - 0.5) + ("); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[0], op[0], "b"); g_string_append (shader_source, " - 0.5) * ("); - add_arg (glsl_shader_state, pipeline, layer, + add_arg (shader_state, pipeline, layer, src[1], op[1], "b"); g_string_append_printf (shader_source, " - 0.5))).%s", swizzle); break; @@ -637,13 +592,13 @@ _cogl_pipeline_fragend_glsl_add_layer (CoglPipeline *pipeline, CoglPipelineLayer *layer, unsigned long layers_difference) { - GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); CoglPipelineLayer *combine_authority = _cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_COMBINE); CoglPipelineLayerBigState *big_state = combine_authority->big_state; - if (!glsl_shader_state->source) + if (!shader_state->source) return TRUE; if (!_cogl_pipeline_need_texture_combine_separate (combine_authority) || @@ -680,12 +635,12 @@ _cogl_pipeline_fragend_glsl_add_layer (CoglPipeline *pipeline, gboolean _cogl_pipeline_fragend_glsl_passthrough (CoglPipeline *pipeline) { - GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); - if (!glsl_shader_state->source) + if (!shader_state->source) return TRUE; - g_string_append (glsl_shader_state->source, + g_string_append (shader_state->source, " cogl_color_out = cogl_color_in;\n"); return TRUE; @@ -698,7 +653,7 @@ _cogl_pipeline_fragend_glsl_passthrough (CoglPipeline *pipeline) static void add_alpha_test_snippet (CoglPipeline *pipeline, - GlslShaderState *glsl_shader_state) + CoglPipelineShaderState *shader_state) { CoglPipelineAlphaFunc alpha_func; @@ -711,7 +666,7 @@ add_alpha_test_snippet (CoglPipeline *pipeline, if (alpha_func == COGL_PIPELINE_ALPHA_FUNC_NEVER) { /* Always discard the fragment */ - g_string_append (glsl_shader_state->source, + g_string_append (shader_state->source, " discard;\n"); return; } @@ -719,31 +674,31 @@ add_alpha_test_snippet (CoglPipeline *pipeline, /* For all of the other alpha functions we need a uniform for the reference */ - g_string_append (glsl_shader_state->header, + g_string_append (shader_state->header, "uniform float _cogl_alpha_test_ref;\n"); - g_string_append (glsl_shader_state->source, + g_string_append (shader_state->source, " if (cogl_color_out.a "); switch (alpha_func) { case COGL_PIPELINE_ALPHA_FUNC_LESS: - g_string_append (glsl_shader_state->source, ">="); + g_string_append (shader_state->source, ">="); break; case COGL_PIPELINE_ALPHA_FUNC_EQUAL: - g_string_append (glsl_shader_state->source, "!="); + g_string_append (shader_state->source, "!="); break; case COGL_PIPELINE_ALPHA_FUNC_LEQUAL: - g_string_append (glsl_shader_state->source, ">"); + g_string_append (shader_state->source, ">"); break; case COGL_PIPELINE_ALPHA_FUNC_GREATER: - g_string_append (glsl_shader_state->source, "<="); + g_string_append (shader_state->source, "<="); break; case COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL: - g_string_append (glsl_shader_state->source, "=="); + g_string_append (shader_state->source, "=="); break; case COGL_PIPELINE_ALPHA_FUNC_GEQUAL: - g_string_append (glsl_shader_state->source, "< "); + g_string_append (shader_state->source, "< "); break; case COGL_PIPELINE_ALPHA_FUNC_ALWAYS: @@ -752,7 +707,7 @@ add_alpha_test_snippet (CoglPipeline *pipeline, break; } - g_string_append (glsl_shader_state->source, + g_string_append (shader_state->source, " _cogl_alpha_test_ref)\n discard;\n"); } @@ -762,11 +717,11 @@ gboolean _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline, unsigned long pipelines_difference) { - GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); _COGL_GET_CONTEXT (ctx, FALSE); - if (glsl_shader_state->source) + if (shader_state->source) { const char *source_strings[2]; GLint lengths[2]; @@ -784,23 +739,23 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline, #ifdef HAVE_COGL_GLES2 if (ctx->driver == COGL_DRIVER_GLES2) - add_alpha_test_snippet (pipeline, glsl_shader_state); + add_alpha_test_snippet (pipeline, shader_state); #endif - g_string_append (glsl_shader_state->source, "}\n"); + g_string_append (shader_state->source, "}\n"); GE_RET( shader, ctx, glCreateShader (GL_FRAGMENT_SHADER) ); - lengths[0] = glsl_shader_state->header->len; - source_strings[0] = glsl_shader_state->header->str; - lengths[1] = glsl_shader_state->source->len; - source_strings[1] = glsl_shader_state->source->str; + lengths[0] = shader_state->header->len; + source_strings[0] = shader_state->header->str; + lengths[1] = shader_state->source->len; + source_strings[1] = shader_state->source->str; /* Find the highest texture unit that is sampled to pass as the number of texture coordinate attributes */ n_layers = cogl_pipeline_get_n_layers (pipeline); for (i = 0; i < n_layers; i++) - if (glsl_shader_state->unit_state[i].sampled) + if (shader_state->unit_state[i].sampled) n_tex_coord_attribs = i + 1; _cogl_shader_set_source_with_boilerplate (shader, GL_FRAGMENT_SHADER, @@ -822,9 +777,9 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline, g_warning ("Shader compilation failed:\n%s", shader_log); } - glsl_shader_state->header = NULL; - glsl_shader_state->source = NULL; - glsl_shader_state->gl_shader = shader; + shader_state->header = NULL; + shader_state->source = NULL; + shader_state->gl_shader = shader; } return TRUE; @@ -838,7 +793,7 @@ _cogl_pipeline_fragend_glsl_pre_change_notify (CoglPipeline *pipeline, _COGL_GET_CONTEXT (ctx, NO_RETVAL); if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) - dirty_glsl_shader_state (pipeline); + dirty_shader_state (pipeline); } /* NB: layers are considered immutable once they have any dependants @@ -855,17 +810,11 @@ _cogl_pipeline_fragend_glsl_layer_pre_change_notify ( CoglPipelineLayer *layer, CoglPipelineLayerState change) { - CoglPipelineFragendGlslPrivate *priv; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - priv = get_glsl_priv (owner); - if (!priv) - return; - if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx))) { - dirty_glsl_shader_state (owner); + dirty_shader_state (owner); return; } @@ -874,19 +823,6 @@ _cogl_pipeline_fragend_glsl_layer_pre_change_notify ( * the snippet. */ } -static void -_cogl_pipeline_fragend_glsl_free_priv (CoglPipeline *pipeline) -{ - CoglPipelineFragendGlslPrivate *priv = get_glsl_priv (pipeline); - if (priv) - { - if (priv->glsl_shader_state) - glsl_shader_state_unref (priv->glsl_shader_state); - g_slice_free (CoglPipelineFragendGlslPrivate, priv); - set_glsl_priv (pipeline, NULL); - } -} - const CoglPipelineFragend _cogl_pipeline_glsl_fragend = { _cogl_pipeline_fragend_glsl_start, @@ -895,8 +831,7 @@ const CoglPipelineFragend _cogl_pipeline_glsl_fragend = _cogl_pipeline_fragend_glsl_end, _cogl_pipeline_fragend_glsl_pre_change_notify, NULL, /* pipeline_set_parent_notify */ - _cogl_pipeline_fragend_glsl_layer_pre_change_notify, - _cogl_pipeline_fragend_glsl_free_priv, + _cogl_pipeline_fragend_glsl_layer_pre_change_notify }; #endif /* COGL_PIPELINE_FRAGEND_GLSL */ diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h index ba0fabf26..35d05e7dc 100644 --- a/cogl/cogl-pipeline-private.h +++ b/cogl/cogl-pipeline-private.h @@ -649,10 +649,6 @@ struct _CoglPipeline * pipeline in comparison to its parent. */ unsigned long differences; - /* The fragment processing backends can associate private data with a - * pipeline. */ - void *fragend_privs[COGL_PIPELINE_N_FRAGENDS]; - /* Whenever a pipeline is modified we increment the age. There's no * guarantee that it won't wrap but it can nevertheless be a * convenient mechanism to determine when a pipeline has been @@ -704,17 +700,6 @@ struct _CoglPipeline /* bitfields */ - /* A pipeline can have private data associated with it for multiple - * fragment processing backends. Although only one backend is - * associated with a pipeline the backends may want to cache private - * state with the ancestors of other pipelines and those ancestors - * could currently be associated with different backends. - * - * Each set bit indicates if the corresponding ->fragend_privs[] - * entry is valid. - */ - unsigned int fragend_priv_set_mask:COGL_PIPELINE_N_FRAGENDS; - /* Weak pipelines don't count as dependants on their parents which * means that the parent pipeline can be modified without * considering how the modifications may affect the weak pipeline. @@ -771,8 +756,6 @@ typedef struct _CoglPipelineFragend void (*layer_pre_change_notify) (CoglPipeline *owner, CoglPipelineLayer *layer, CoglPipelineLayerState change); - - void (*free_priv) (CoglPipeline *pipeline); } CoglPipelineFragend; typedef struct _CoglPipelineVertend diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c index ae8e0af66..9eb1d7cbe 100644 --- a/cogl/cogl-pipeline-progend-glsl.c +++ b/cogl/cogl-pipeline-progend-glsl.c @@ -138,14 +138,14 @@ typedef struct CoglPipeline *last_used_for_pipeline; UnitState *unit_state; -} CoglPipelineProgendPrivate; +} CoglPipelineProgramState; -static CoglUserDataKey glsl_priv_key; +static CoglUserDataKey program_state_key; -static CoglPipelineProgendPrivate * -get_glsl_priv (CoglPipeline *pipeline) +static CoglPipelineProgramState * +get_program_state (CoglPipeline *pipeline) { - return cogl_object_get_user_data (COGL_OBJECT (pipeline), &glsl_priv_key); + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &program_state_key); } #ifdef HAVE_COGL_GLES2 @@ -162,96 +162,101 @@ get_glsl_priv (CoglPipeline *pipeline) int _cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline); + CoglPipelineProgramState *program_state = get_program_state (pipeline); _COGL_GET_CONTEXT (ctx, -1); - g_return_val_if_fail (priv != NULL, -1); - g_return_val_if_fail (priv->program != 0, -1); + g_return_val_if_fail (program_state != NULL, -1); + g_return_val_if_fail (program_state->program != 0, -1); - if (priv->position_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( priv->position_attribute_location, - ctx, glGetAttribLocation (priv->program, "cogl_position_in") ); + if (program_state->position_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) + GE_RET( program_state->position_attribute_location, + ctx, glGetAttribLocation (program_state->program, + "cogl_position_in") ); - return priv->position_attribute_location; + return program_state->position_attribute_location; } int _cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline); + CoglPipelineProgramState *program_state = get_program_state (pipeline); _COGL_GET_CONTEXT (ctx, -1); - g_return_val_if_fail (priv != NULL, -1); - g_return_val_if_fail (priv->program != 0, -1); + g_return_val_if_fail (program_state != NULL, -1); + g_return_val_if_fail (program_state->program != 0, -1); - if (priv->color_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( priv->color_attribute_location, - ctx, glGetAttribLocation (priv->program, "cogl_color_in") ); + if (program_state->color_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) + GE_RET( program_state->color_attribute_location, + ctx, glGetAttribLocation (program_state->program, + "cogl_color_in") ); - return priv->color_attribute_location; + return program_state->color_attribute_location; } int _cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline); + CoglPipelineProgramState *program_state = get_program_state (pipeline); _COGL_GET_CONTEXT (ctx, -1); - g_return_val_if_fail (priv != NULL, -1); - g_return_val_if_fail (priv->program != 0, -1); + g_return_val_if_fail (program_state != NULL, -1); + g_return_val_if_fail (program_state->program != 0, -1); - if (priv->normal_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( priv->normal_attribute_location, - ctx, glGetAttribLocation (priv->program, "cogl_normal_in") ); + if (program_state->normal_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) + GE_RET( program_state->normal_attribute_location, + ctx, glGetAttribLocation (program_state->program, + "cogl_normal_in") ); - return priv->normal_attribute_location; + return program_state->normal_attribute_location; } int _cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline, int unit) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline); + CoglPipelineProgramState *program_state = get_program_state (pipeline); _COGL_GET_CONTEXT (ctx, -1); - g_return_val_if_fail (priv != NULL, -1); - g_return_val_if_fail (priv->program != 0, -1); + g_return_val_if_fail (program_state != NULL, -1); + g_return_val_if_fail (program_state->program != 0, -1); if (unit == 0) { - if (priv->tex_coord0_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( priv->tex_coord0_attribute_location, - ctx, glGetAttribLocation (priv->program, + if (program_state->tex_coord0_attribute_location == + ATTRIBUTE_LOCATION_UNKNOWN) + GE_RET( program_state->tex_coord0_attribute_location, + ctx, glGetAttribLocation (program_state->program, "cogl_tex_coord0_in") ); - return priv->tex_coord0_attribute_location; + return program_state->tex_coord0_attribute_location; } else { char *name = g_strdup_printf ("cogl_tex_coord%i_in", unit); int *locations; - if (priv->tex_coord_attribute_locations == NULL) - priv->tex_coord_attribute_locations = g_array_new (FALSE, FALSE, - sizeof (int)); - if (priv->tex_coord_attribute_locations->len <= unit - 1) + if (program_state->tex_coord_attribute_locations == NULL) + program_state->tex_coord_attribute_locations = + g_array_new (FALSE, FALSE, sizeof (int)); + if (program_state->tex_coord_attribute_locations->len <= unit - 1) { - int i = priv->tex_coord_attribute_locations->len; - g_array_set_size (priv->tex_coord_attribute_locations, unit); + int i = program_state->tex_coord_attribute_locations->len; + g_array_set_size (program_state->tex_coord_attribute_locations, unit); for (; i < unit; i++) - g_array_index (priv->tex_coord_attribute_locations, int, i) = - ATTRIBUTE_LOCATION_UNKNOWN; + g_array_index (program_state->tex_coord_attribute_locations, int, i) + = ATTRIBUTE_LOCATION_UNKNOWN; } - locations = &g_array_index (priv->tex_coord_attribute_locations, int, 0); + locations = &g_array_index (program_state->tex_coord_attribute_locations, + int, 0); if (locations[unit - 1] == ATTRIBUTE_LOCATION_UNKNOWN) GE_RET( locations[unit - 1], - ctx, glGetAttribLocation (priv->program, name) ); + ctx, glGetAttribLocation (program_state->program, name) ); g_free (name); @@ -260,79 +265,100 @@ _cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline, } static void -clear_attribute_cache (CoglPipelineProgendPrivate *priv) +clear_attribute_cache (CoglPipelineProgramState *program_state) { - priv->position_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - priv->color_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - priv->normal_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - priv->tex_coord0_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - if (priv->tex_coord_attribute_locations) + program_state->position_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; + program_state->color_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; + program_state->normal_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; + program_state->tex_coord0_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; + if (program_state->tex_coord_attribute_locations) { - g_array_free (priv->tex_coord_attribute_locations, TRUE); - priv->tex_coord_attribute_locations = NULL; + g_array_free (program_state->tex_coord_attribute_locations, TRUE); + program_state->tex_coord_attribute_locations = NULL; } } static void -clear_flushed_matrix_stacks (CoglPipelineProgendPrivate *priv) +clear_flushed_matrix_stacks (CoglPipelineProgramState *program_state) { - if (priv->flushed_modelview_stack) + if (program_state->flushed_modelview_stack) { - cogl_object_unref (priv->flushed_modelview_stack); - priv->flushed_modelview_stack = NULL; + cogl_object_unref (program_state->flushed_modelview_stack); + program_state->flushed_modelview_stack = NULL; } - if (priv->flushed_projection_stack) + if (program_state->flushed_projection_stack) { - cogl_object_unref (priv->flushed_projection_stack); - priv->flushed_projection_stack = NULL; + cogl_object_unref (program_state->flushed_projection_stack); + program_state->flushed_projection_stack = NULL; } - priv->flushed_modelview_is_identity = FALSE; + program_state->flushed_modelview_is_identity = FALSE; } #endif /* HAVE_COGL_GLES2 */ -static void -destroy_glsl_priv (void *user_data) +static CoglPipelineProgramState * +program_state_new (int n_layers) { - CoglPipelineProgendPrivate *priv = user_data; + CoglPipelineProgramState *program_state; + + program_state = g_slice_new (CoglPipelineProgramState); + program_state->ref_count = 1; + program_state->program = 0; + program_state->n_tex_coord_attribs = 0; + program_state->unit_state = g_new (UnitState, n_layers); +#ifdef HAVE_COGL_GLES2 + program_state->tex_coord_attribute_locations = NULL; + program_state->flushed_modelview_stack = NULL; + program_state->flushed_modelview_is_identity = FALSE; + program_state->flushed_projection_stack = NULL; +#endif + + return program_state; +} + +static void +destroy_program_state (void *user_data) +{ + CoglPipelineProgramState *program_state = user_data; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (--priv->ref_count == 0) + if (--program_state->ref_count == 0) { #ifdef HAVE_COGL_GLES2 if (ctx->driver == COGL_DRIVER_GLES2) { - clear_attribute_cache (priv); - clear_flushed_matrix_stacks (priv); + clear_attribute_cache (program_state); + clear_flushed_matrix_stacks (program_state); } #endif - if (priv->program) - GE( ctx, glDeleteProgram (priv->program) ); + if (program_state->program) + GE( ctx, glDeleteProgram (program_state->program) ); - g_free (priv->unit_state); + g_free (program_state->unit_state); - g_slice_free (CoglPipelineProgendPrivate, priv); + g_slice_free (CoglPipelineProgramState, program_state); } } static void -set_glsl_priv (CoglPipeline *pipeline, CoglPipelineProgendPrivate *priv) +set_program_state (CoglPipeline *pipeline, + CoglPipelineProgramState *program_state) { cogl_object_set_user_data (COGL_OBJECT (pipeline), - &glsl_priv_key, - priv, - destroy_glsl_priv); + &program_state_key, + program_state, + destroy_program_state); } static void -dirty_glsl_program_state (CoglPipeline *pipeline) +dirty_program_state (CoglPipeline *pipeline) { cogl_object_set_user_data (COGL_OBJECT (pipeline), - &glsl_priv_key, + &program_state_key, NULL, - destroy_glsl_priv); + NULL); } static void @@ -371,7 +397,7 @@ typedef struct int unit; GLuint gl_program; gboolean update_all; - CoglPipelineProgendPrivate *priv; + CoglPipelineProgramState *program_state; } UpdateUniformsState; static gboolean @@ -380,8 +406,8 @@ get_uniform_cb (CoglPipeline *pipeline, void *user_data) { UpdateUniformsState *state = user_data; - CoglPipelineProgendPrivate *priv = state->priv; - UnitState *unit_state = &priv->unit_state[state->unit]; + CoglPipelineProgramState *program_state = state->program_state; + UnitState *unit_state = &program_state->unit_state[state->unit]; GLint uniform_location; _COGL_GET_CONTEXT (ctx, FALSE); @@ -439,8 +465,8 @@ update_constants_cb (CoglPipeline *pipeline, void *user_data) { UpdateUniformsState *state = user_data; - CoglPipelineProgendPrivate *priv = state->priv; - UnitState *unit_state = &priv->unit_state[state->unit++]; + CoglPipelineProgramState *program_state = state->program_state; + UnitState *unit_state = &program_state->unit_state[state->unit++]; _COGL_GET_CONTEXT (ctx, FALSE); @@ -482,21 +508,22 @@ update_constants_cb (CoglPipeline *pipeline, static void update_builtin_uniforms (CoglPipeline *pipeline, GLuint gl_program, - CoglPipelineProgendPrivate *priv) + CoglPipelineProgramState *program_state) { int i; - if (priv->dirty_builtin_uniforms == 0) + if (program_state->dirty_builtin_uniforms == 0) return; for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) - if ((priv->dirty_builtin_uniforms & (1 << i)) && - priv->builtin_uniform_locations[i] != -1) + if ((program_state->dirty_builtin_uniforms & (1 << i)) && + program_state->builtin_uniform_locations[i] != -1) builtin_uniforms[i].update_func (pipeline, - priv->builtin_uniform_locations[i], + program_state + ->builtin_uniform_locations[i], builtin_uniforms[i].getter_func); - priv->dirty_builtin_uniforms = 0; + program_state->dirty_builtin_uniforms = 0; } #endif /* HAVE_COGL_GLES2 */ @@ -506,7 +533,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, unsigned long pipelines_difference, int n_tex_coord_attribs) { - CoglPipelineProgendPrivate *priv; + CoglPipelineProgramState *program_state; GLuint gl_program; gboolean program_changed = FALSE; UpdateUniformsState state; @@ -520,11 +547,11 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, pipeline->vertend != COGL_PIPELINE_VERTEND_GLSL) return; - priv = get_glsl_priv (pipeline); + program_state = get_program_state (pipeline); user_program = cogl_pipeline_get_user_program (pipeline); - if (priv == NULL) + if (program_state == NULL) { CoglPipeline *authority; @@ -539,29 +566,19 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) | COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN); - priv = get_glsl_priv (authority); + program_state = get_program_state (authority); - if (priv == NULL) + if (program_state == NULL) { - priv = g_slice_new (CoglPipelineProgendPrivate); - priv->ref_count = 1; - priv->program = 0; - priv->n_tex_coord_attribs = 0; - priv->unit_state = g_new (UnitState, - cogl_pipeline_get_n_layers (pipeline)); -#ifdef HAVE_COGL_GLES2 - priv->tex_coord_attribute_locations = NULL; - priv->flushed_modelview_stack = NULL; - priv->flushed_modelview_is_identity = FALSE; - priv->flushed_projection_stack = NULL; -#endif - set_glsl_priv (authority, priv); + program_state + = program_state_new (cogl_pipeline_get_n_layers (pipeline)); + set_program_state (authority, program_state); } if (authority != pipeline) { - priv->ref_count++; - set_glsl_priv (pipeline, priv); + program_state->ref_count++; + set_program_state (pipeline, program_state); } } @@ -571,26 +588,26 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, * Also if the number of texture coordinate attributes in use has * increased, then delete the program so we can prepend a new * _cogl_tex_coord[] varying array declaration. */ - if (priv->program && user_program && - (user_program->age != priv->user_program_age || - n_tex_coord_attribs > priv->n_tex_coord_attribs)) + if (program_state->program && user_program && + (user_program->age != program_state->user_program_age || + n_tex_coord_attribs > program_state->n_tex_coord_attribs)) { - GE( ctx, glDeleteProgram (priv->program) ); - priv->program = 0; + GE( ctx, glDeleteProgram (program_state->program) ); + program_state->program = 0; } - if (priv->program == 0) + if (program_state->program == 0) { GLuint backend_shader; GSList *l; - GE_RET( priv->program, ctx, glCreateProgram () ); + GE_RET( program_state->program, ctx, glCreateProgram () ); /* Attach all of the shader from the user program */ if (user_program) { - if (priv->n_tex_coord_attribs > n_tex_coord_attribs) - n_tex_coord_attribs = priv->n_tex_coord_attribs; + if (program_state->n_tex_coord_attribs > n_tex_coord_attribs) + n_tex_coord_attribs = program_state->n_tex_coord_attribs; #ifdef HAVE_COGL_GLES2 /* Find the largest count of texture coordinate attributes @@ -614,29 +631,29 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL); - GE( ctx, glAttachShader (priv->program, + GE( ctx, glAttachShader (program_state->program, shader->gl_handle) ); } - priv->user_program_age = user_program->age; + program_state->user_program_age = user_program->age; } /* Attach any shaders from the GLSL backends */ if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL && (backend_shader = _cogl_pipeline_fragend_glsl_get_shader (pipeline))) - GE( ctx, glAttachShader (priv->program, backend_shader) ); + GE( ctx, glAttachShader (program_state->program, backend_shader) ); if (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL && (backend_shader = _cogl_pipeline_vertend_glsl_get_shader (pipeline))) - GE( ctx, glAttachShader (priv->program, backend_shader) ); + GE( ctx, glAttachShader (program_state->program, backend_shader) ); - link_program (priv->program); + link_program (program_state->program); program_changed = TRUE; - priv->n_tex_coord_attribs = n_tex_coord_attribs; + program_state->n_tex_coord_attribs = n_tex_coord_attribs; } - gl_program = priv->program; + gl_program = program_state->program; if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL) _cogl_use_fragment_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL); @@ -645,7 +662,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, state.unit = 0; state.gl_program = gl_program; - state.priv = priv; + state.program_state = program_state; if (program_changed) cogl_pipeline_foreach_layer (pipeline, @@ -654,7 +671,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, state.unit = 0; state.update_all = (program_changed || - priv->last_used_for_pipeline != pipeline); + program_state->last_used_for_pipeline != pipeline); cogl_pipeline_foreach_layer (pipeline, update_constants_cb, @@ -667,33 +684,31 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, { int i; - clear_attribute_cache (priv); - clear_flushed_matrix_stacks (priv); + clear_attribute_cache (program_state); + clear_flushed_matrix_stacks (program_state); for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) - GE_RET( priv->builtin_uniform_locations[i], - ctx, + GE_RET( program_state->builtin_uniform_locations[i], ctx, glGetUniformLocation (gl_program, builtin_uniforms[i].uniform_name) ); - GE_RET( priv->modelview_uniform, - ctx, glGetUniformLocation (gl_program, - "cogl_modelview_matrix") ); + GE_RET( program_state->modelview_uniform, ctx, + glGetUniformLocation (gl_program, + "cogl_modelview_matrix") ); - GE_RET( priv->projection_uniform, - ctx, glGetUniformLocation (gl_program, - "cogl_projection_matrix") ); + GE_RET( program_state->projection_uniform, ctx, + glGetUniformLocation (gl_program, + "cogl_projection_matrix") ); - GE_RET( priv->mvp_uniform, - ctx, + GE_RET( program_state->mvp_uniform, ctx, glGetUniformLocation (gl_program, "cogl_modelview_projection_matrix") ); } if (program_changed || - priv->last_used_for_pipeline != pipeline) - priv->dirty_builtin_uniforms = ~(unsigned long) 0; + program_state->last_used_for_pipeline != pipeline) + program_state->dirty_builtin_uniforms = ~(unsigned long) 0; - update_builtin_uniforms (pipeline, gl_program, priv); + update_builtin_uniforms (pipeline, gl_program, program_state); } #endif @@ -704,7 +719,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, /* We need to track the last pipeline that the program was used with * so know if we need to update all of the uniforms */ - priv->last_used_for_pipeline = pipeline; + program_state->last_used_for_pipeline = pipeline; } static void @@ -715,7 +730,8 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline, _COGL_GET_CONTEXT (ctx, NO_RETVAL); if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) - dirty_glsl_program_state (pipeline); + dirty_program_state (pipeline); + #ifdef HAVE_COGL_GLES2 else if (ctx->driver == COGL_DRIVER_GLES2) { @@ -724,9 +740,10 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline, for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) if ((change & builtin_uniforms[i].change)) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline); - if (priv) - priv->dirty_builtin_uniforms |= 1 << i; + CoglPipelineProgramState *program_state + = get_program_state (pipeline); + if (program_state) + program_state->dirty_builtin_uniforms |= 1 << i; return; } } @@ -751,27 +768,27 @@ _cogl_pipeline_progend_glsl_layer_pre_change_notify ( if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) { - dirty_glsl_program_state (owner); + dirty_program_state (owner); return; } if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (owner); - if (priv) + CoglPipelineProgramState *program_state = get_program_state (owner); + if (program_state) { int unit_index = _cogl_pipeline_layer_get_unit_index (layer); - priv->unit_state[unit_index].dirty_combine_constant = TRUE; + program_state->unit_state[unit_index].dirty_combine_constant = TRUE; } } if (change & COGL_PIPELINE_LAYER_STATE_USER_MATRIX) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (owner); - if (priv) + CoglPipelineProgramState *program_state = get_program_state (owner); + if (program_state) { int unit_index = _cogl_pipeline_layer_get_unit_index (layer); - priv->unit_state[unit_index].dirty_texture_matrix = TRUE; + program_state->unit_state[unit_index].dirty_texture_matrix = TRUE; } } } @@ -783,11 +800,11 @@ flush_modelview_cb (gboolean is_identity, const CoglMatrix *matrix, void *user_data) { - CoglPipelineProgendPrivate *priv = user_data; + CoglPipelineProgramState *program_state = user_data; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - GE( ctx, glUniformMatrix4fv (priv->modelview_uniform, 1, FALSE, + GE( ctx, glUniformMatrix4fv (program_state->modelview_uniform, 1, FALSE, cogl_matrix_get_array (matrix)) ); } @@ -796,17 +813,17 @@ flush_projection_cb (gboolean is_identity, const CoglMatrix *matrix, void *user_data) { - CoglPipelineProgendPrivate *priv = user_data; + CoglPipelineProgramState *program_state = user_data; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - GE( ctx, glUniformMatrix4fv (priv->projection_uniform, 1, FALSE, + GE( ctx, glUniformMatrix4fv (program_state->projection_uniform, 1, FALSE, cogl_matrix_get_array (matrix)) ); } typedef struct { - CoglPipelineProgendPrivate *priv; + CoglPipelineProgramState *program_state; const CoglMatrix *projection_matrix; } FlushCombinedData; @@ -825,7 +842,8 @@ flush_combined_step_two_cb (gboolean is_identity, if (is_identity) { const float *array = cogl_matrix_get_array (data->projection_matrix); - GE( ctx, glUniformMatrix4fv (data->priv->mvp_uniform, 1, FALSE, array ) ); + GE( ctx, glUniformMatrix4fv (data->program_state->mvp_uniform, + 1, FALSE, array ) ); } else { @@ -833,7 +851,7 @@ flush_combined_step_two_cb (gboolean is_identity, data->projection_matrix, matrix); - GE( ctx, glUniformMatrix4fv (data->priv->mvp_uniform, 1, FALSE, + GE( ctx, glUniformMatrix4fv (data->program_state->mvp_uniform, 1, FALSE, cogl_matrix_get_array (&mvp_matrix)) ); } } @@ -847,7 +865,7 @@ flush_combined_step_one_cb (gboolean is_identity, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - data.priv = user_data; + data.program_state = user_data; data.projection_matrix = matrix; _cogl_matrix_stack_prepare_for_flush (ctx->flushed_modelview_stack, @@ -859,7 +877,7 @@ flush_combined_step_one_cb (gboolean is_identity, static void _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline) { - CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline); + CoglPipelineProgramState *program_state = get_program_state (pipeline); gboolean modelview_changed; gboolean projection_changed; @@ -872,7 +890,7 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline) vertend, but this is a requirement on GLES2 anyway */ g_return_if_fail (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL); - priv = get_glsl_priv (pipeline); + program_state = get_program_state (pipeline); /* An initial pipeline is flushed while creating the context. At this point there are no matrices flushed so we can't do @@ -885,59 +903,62 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline) the identity matrix so it makes sense to optimise this case by specifically checking whether we already have the identity matrix which will catch a lot of common cases of redundant flushing */ - if (priv->flushed_modelview_is_identity && + if (program_state->flushed_modelview_is_identity && _cogl_matrix_stack_has_identity_flag (ctx->flushed_modelview_stack)) modelview_changed = FALSE; else modelview_changed = - priv->flushed_modelview_stack != ctx->flushed_modelview_stack || - priv->flushed_modelview_stack_age != - _cogl_matrix_stack_get_age (priv->flushed_modelview_stack); + program_state->flushed_modelview_stack != ctx->flushed_modelview_stack || + program_state->flushed_modelview_stack_age != + _cogl_matrix_stack_get_age (program_state->flushed_modelview_stack); projection_changed = - priv->flushed_projection_stack != ctx->flushed_projection_stack || - priv->flushed_projection_stack_age != - _cogl_matrix_stack_get_age (priv->flushed_projection_stack); + program_state->flushed_projection_stack != ctx->flushed_projection_stack || + program_state->flushed_projection_stack_age != + _cogl_matrix_stack_get_age (program_state->flushed_projection_stack); if (modelview_changed) { cogl_object_ref (ctx->flushed_modelview_stack); - if (priv->flushed_modelview_stack) - cogl_object_unref (priv->flushed_modelview_stack); - priv->flushed_modelview_stack = ctx->flushed_modelview_stack; - priv->flushed_modelview_stack_age = + if (program_state->flushed_modelview_stack) + cogl_object_unref (program_state->flushed_modelview_stack); + program_state->flushed_modelview_stack = ctx->flushed_modelview_stack; + program_state->flushed_modelview_stack_age = _cogl_matrix_stack_get_age (ctx->flushed_modelview_stack); - priv->flushed_modelview_is_identity = + program_state->flushed_modelview_is_identity = _cogl_matrix_stack_has_identity_flag (ctx->flushed_modelview_stack); - if (priv->modelview_uniform != -1) - _cogl_matrix_stack_prepare_for_flush (priv->flushed_modelview_stack, + if (program_state->modelview_uniform != -1) + _cogl_matrix_stack_prepare_for_flush (program_state + ->flushed_modelview_stack, COGL_MATRIX_MODELVIEW, flush_modelview_cb, - priv); + program_state); } if (projection_changed) { cogl_object_ref (ctx->flushed_projection_stack); - if (priv->flushed_projection_stack) - cogl_object_unref (priv->flushed_projection_stack); - priv->flushed_projection_stack = ctx->flushed_projection_stack; - priv->flushed_projection_stack_age = + if (program_state->flushed_projection_stack) + cogl_object_unref (program_state->flushed_projection_stack); + program_state->flushed_projection_stack = ctx->flushed_projection_stack; + program_state->flushed_projection_stack_age = _cogl_matrix_stack_get_age (ctx->flushed_projection_stack); - if (priv->projection_uniform != -1) - _cogl_matrix_stack_prepare_for_flush (priv->flushed_projection_stack, + if (program_state->projection_uniform != -1) + _cogl_matrix_stack_prepare_for_flush (program_state + ->flushed_projection_stack, COGL_MATRIX_PROJECTION, flush_projection_cb, - priv); + program_state); } - if (priv->mvp_uniform != -1 && (modelview_changed || projection_changed)) + if (program_state->mvp_uniform != -1 && + (modelview_changed || projection_changed)) _cogl_matrix_stack_prepare_for_flush (ctx->flushed_projection_stack, COGL_MATRIX_PROJECTION, flush_combined_step_one_cb, - priv); + program_state); } static void diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c index f13eceb3c..74fc9a8d9 100644 --- a/cogl/cogl-pipeline-vertend-glsl.c +++ b/cogl/cogl-pipeline-vertend-glsl.c @@ -55,57 +55,69 @@ typedef struct program changes then we may need to redecide whether to generate a shader at all */ unsigned int user_program_age; -} CoglPipelineVertendPrivate; +} CoglPipelineShaderState; -static CoglUserDataKey glsl_priv_key; +static CoglUserDataKey shader_state_key; -static CoglPipelineVertendPrivate * -get_glsl_priv (CoglPipeline *pipeline) +static CoglPipelineShaderState * +shader_state_new (void) { - return cogl_object_get_user_data (COGL_OBJECT (pipeline), &glsl_priv_key); + CoglPipelineShaderState *shader_state; + + shader_state = g_slice_new0 (CoglPipelineShaderState); + shader_state->ref_count = 1; + + return shader_state; +} + +static CoglPipelineShaderState * +get_shader_state (CoglPipeline *pipeline) +{ + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key); } static void -destroy_glsl_priv (void *user_data) +destroy_shader_state (void *user_data) { - CoglPipelineVertendPrivate *priv = user_data; + CoglPipelineShaderState *shader_state = user_data; _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (--priv->ref_count == 0) + if (--shader_state->ref_count == 0) { - if (priv->gl_shader) - GE( ctx, glDeleteShader (priv->gl_shader) ); + if (shader_state->gl_shader) + GE( ctx, glDeleteShader (shader_state->gl_shader) ); - g_slice_free (CoglPipelineVertendPrivate, priv); + g_slice_free (CoglPipelineShaderState, shader_state); } } static void -set_glsl_priv (CoglPipeline *pipeline, CoglPipelineVertendPrivate *priv) +set_shader_state (CoglPipeline *pipeline, + CoglPipelineShaderState *shader_state) { cogl_object_set_user_data (COGL_OBJECT (pipeline), - &glsl_priv_key, - priv, - destroy_glsl_priv); + &shader_state_key, + shader_state, + destroy_shader_state); } static void -dirty_glsl_shader_state (CoglPipeline *pipeline) +dirty_shader_state (CoglPipeline *pipeline) { cogl_object_set_user_data (COGL_OBJECT (pipeline), - &glsl_priv_key, + &shader_state_key, NULL, - destroy_glsl_priv); + NULL); } GLuint _cogl_pipeline_vertend_glsl_get_shader (CoglPipeline *pipeline) { - CoglPipelineVertendPrivate *priv = get_glsl_priv (pipeline); + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); - if (priv) - return priv->gl_shader; + if (shader_state) + return shader_state->gl_shader; else return 0; } @@ -115,7 +127,7 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, int n_layers, unsigned long pipelines_difference) { - CoglPipelineVertendPrivate *priv; + CoglPipelineShaderState *shader_state; CoglProgram *user_program; _COGL_GET_CONTEXT (ctx, FALSE); @@ -134,9 +146,9 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, /* Now lookup our glsl backend private state (allocating if * necessary) */ - priv = get_glsl_priv (pipeline); + shader_state = get_shader_state (pipeline); - if (priv == NULL) + if (shader_state == NULL) { CoglPipeline *authority; @@ -148,42 +160,41 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, ~COGL_PIPELINE_STATE_LAYERS, COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN); - priv = get_glsl_priv (authority); + shader_state = get_shader_state (authority); - if (priv == NULL) + if (shader_state == NULL) { - priv = g_slice_new0 (CoglPipelineVertendPrivate); - priv->ref_count = 1; - set_glsl_priv (authority, priv); + shader_state = shader_state_new (); + set_shader_state (authority, shader_state); } if (authority != pipeline) { - priv->ref_count++; - set_glsl_priv (pipeline, priv); + shader_state->ref_count++; + set_shader_state (pipeline, shader_state); } } - if (priv->gl_shader) + if (shader_state->gl_shader) { /* If we already have a valid GLSL shader then we don't need to generate a new one. However if there's a user program and it has changed since the last link then we do need a new shader */ if (user_program == NULL || - priv->user_program_age == user_program->age) + shader_state->user_program_age == user_program->age) return TRUE; /* We need to recreate the shader so destroy the existing one */ - GE( ctx, glDeleteShader (priv->gl_shader) ); - priv->gl_shader = 0; + GE( ctx, glDeleteShader (shader_state->gl_shader) ); + shader_state->gl_shader = 0; } - /* If we make it here then we have a priv struct without a gl_shader + /* If we make it here then we have a shader_state struct without a gl_shader either because this is the first time we've encountered it or because the user program has changed */ if (user_program) - priv->user_program_age = user_program->age; + shader_state->user_program_age = user_program->age; /* If the user program contains a vertex shader then we don't need to generate one */ @@ -198,10 +209,10 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, add_layer callback is invoked */ g_string_set_size (ctx->codegen_header_buffer, 0); g_string_set_size (ctx->codegen_source_buffer, 0); - priv->header = ctx->codegen_header_buffer; - priv->source = ctx->codegen_source_buffer; + shader_state->header = ctx->codegen_header_buffer; + shader_state->source = ctx->codegen_source_buffer; - g_string_append (priv->source, + g_string_append (shader_state->source, "void\n" "main ()\n" "{\n"); @@ -209,7 +220,7 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, if (ctx->driver == COGL_DRIVER_GLES2) /* There is no builtin uniform for the pointsize on GLES2 so we need to copy it from the custom uniform in the vertex shader */ - g_string_append (priv->source, + g_string_append (shader_state->source, " cogl_point_size_out = cogl_point_size_in;\n"); /* On regular OpenGL we'll just flush the point size builtin */ else if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE) @@ -232,12 +243,12 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline, CoglPipelineLayer *layer, unsigned long layers_difference) { - CoglPipelineVertendPrivate *priv; + CoglPipelineShaderState *shader_state; int unit_index; _COGL_GET_CONTEXT (ctx, FALSE); - priv = get_glsl_priv (pipeline); + shader_state = get_shader_state (pipeline); unit_index = _cogl_pipeline_layer_get_unit_index (layer); @@ -263,7 +274,7 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline, } } - if (priv->source == NULL) + if (shader_state->source == NULL) return TRUE; /* Transform the texture coordinates by the layer's user matrix. @@ -277,7 +288,7 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline, * avoid setting them if not */ - g_string_append_printf (priv->source, + g_string_append_printf (shader_state->source, " cogl_tex_coord_out[%i] = " "cogl_texture_matrix[%i] * cogl_tex_coord%i_in;\n", unit_index, unit_index, unit_index); @@ -289,13 +300,13 @@ static gboolean _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline, unsigned long pipelines_difference) { - CoglPipelineVertendPrivate *priv; + CoglPipelineShaderState *shader_state; _COGL_GET_CONTEXT (ctx, FALSE); - priv = get_glsl_priv (pipeline); + shader_state = get_shader_state (pipeline); - if (priv->source) + if (shader_state->source) { const char *source_strings[2]; GLint lengths[2]; @@ -310,7 +321,7 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline, 0 /* no application private data */); COGL_COUNTER_INC (_cogl_uprof_context, vertend_glsl_compile_counter); - g_string_append (priv->source, + g_string_append (shader_state->source, " cogl_position_out = " "cogl_modelview_projection_matrix * " "cogl_position_in;\n" @@ -319,10 +330,10 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline, GE_RET( shader, ctx, glCreateShader (GL_VERTEX_SHADER) ); - lengths[0] = priv->header->len; - source_strings[0] = priv->header->str; - lengths[1] = priv->source->len; - source_strings[1] = priv->source->str; + lengths[0] = shader_state->header->len; + source_strings[0] = shader_state->header->str; + lengths[1] = shader_state->source->len; + source_strings[1] = shader_state->source->str; n_layers = cogl_pipeline_get_n_layers (pipeline); @@ -345,9 +356,9 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline, g_warning ("Shader compilation failed:\n%s", shader_log); } - priv->header = NULL; - priv->source = NULL; - priv->gl_shader = shader; + shader_state->header = NULL; + shader_state->source = NULL; + shader_state->gl_shader = shader; } return TRUE; @@ -359,7 +370,7 @@ _cogl_pipeline_vertend_glsl_pre_change_notify (CoglPipeline *pipeline, const CoglColor *new_color) { if ((change & COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN)) - dirty_glsl_shader_state (pipeline); + dirty_shader_state (pipeline); } /* NB: layers are considered immutable once they have any dependants @@ -376,15 +387,15 @@ _cogl_pipeline_vertend_glsl_layer_pre_change_notify ( CoglPipelineLayer *layer, CoglPipelineLayerState change) { - CoglPipelineVertendPrivate *priv; + CoglPipelineShaderState *shader_state; - priv = get_glsl_priv (owner); - if (!priv) + shader_state = get_shader_state (owner); + if (!shader_state) return; if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN)) { - dirty_glsl_shader_state (owner); + dirty_shader_state (owner); return; } diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c index 64ae858dd..4d70a6f9a 100644 --- a/cogl/cogl-pipeline.c +++ b/cogl/cogl-pipeline.c @@ -448,7 +448,6 @@ _cogl_pipeline_copy (CoglPipeline *src, gboolean is_weak) pipeline->deprecated_get_layers_list_dirty = TRUE; pipeline->fragend = src->fragend; - pipeline->fragend_priv_set_mask = 0; pipeline->vertend = src->vertend; @@ -501,18 +500,6 @@ cogl_pipeline_new (void) return new; } -static void -_cogl_pipeline_fragend_free_priv (CoglPipeline *pipeline) -{ - if (pipeline->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED && - _cogl_pipeline_fragends[pipeline->fragend]->free_priv) - { - const CoglPipelineFragend *fragend = - _cogl_pipeline_fragends[pipeline->fragend]; - fragend->free_priv (pipeline); - } -} - static gboolean destroy_weak_children_cb (CoglPipelineNode *node, void *user_data) @@ -545,8 +532,6 @@ _cogl_pipeline_free (CoglPipeline *pipeline) g_assert (COGL_LIST_EMPTY (&COGL_PIPELINE_NODE (pipeline)->children)); - _cogl_pipeline_fragend_free_priv (pipeline); - _cogl_pipeline_unparent (COGL_PIPELINE_NODE (pipeline)); if (pipeline->differences & COGL_PIPELINE_STATE_USER_SHADER && @@ -970,7 +955,6 @@ _cogl_pipeline_needs_blending_enabled (CoglPipeline *pipeline, void _cogl_pipeline_set_fragend (CoglPipeline *pipeline, int fragend) { - _cogl_pipeline_fragend_free_priv (pipeline); pipeline->fragend = fragend; }