static CoglBool add_layer_declaration_cb (CoglPipelineLayer *layer, void *user_data) { CoglPipelineShaderState *shader_state = user_data; CoglTextureType texture_type = _cogl_pipeline_layer_get_texture_type (layer); const char *target_string; _cogl_gl_util_get_texture_target_string (texture_type, &target_string, NULL); g_string_append_printf (shader_state->header, "attribute vec4 cogl_tex_coord%i_in;\n" "varying vec4 _cogl_tex_coord%i;\n" "#define cogl_tex_coord%i_out _cogl_tex_coord%i\n" "uniform sampler%s cogl_sampler%i;\n", layer->index, layer->index, layer->index, layer->index, target_string, layer->index); return TRUE; }
static CoglBool _cogl_pipeline_fragend_fixed_add_layer (CoglPipeline *pipeline, CoglPipelineLayer *layer, unsigned long layers_difference) { CoglTextureUnit *unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer)); int unit_index = unit->index; int n_rgb_func_args; int n_alpha_func_args; _COGL_GET_CONTEXT (ctx, FALSE); /* XXX: Beware that since we are changing the active texture unit we * must make sure we don't call into other Cogl components that may * temporarily bind texture objects to query/modify parameters since * they will end up binding texture unit 1. See * _cogl_bind_gl_texture_transient for more details. */ _cogl_set_active_texture_unit (unit_index); if (G_UNLIKELY (unit_index >= get_max_texture_units ())) { _cogl_disable_texture_unit (unit_index); /* TODO: although this isn't considered an error that * warrants falling back to a different backend we * should print a warning here. */ return TRUE; } /* Handle enabling or disabling the right texture type */ if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE) { CoglTextureType texture_type = _cogl_pipeline_layer_get_texture_type (layer); GLenum gl_target; switch (texture_type) { case COGL_TEXTURE_TYPE_2D: gl_target = GL_TEXTURE_2D; break; case COGL_TEXTURE_TYPE_3D: gl_target = GL_TEXTURE_3D; break; case COGL_TEXTURE_TYPE_RECTANGLE: gl_target = GL_TEXTURE_RECTANGLE_ARB; break; } _cogl_set_active_texture_unit (unit_index); /* The common GL code handles binding the right texture so we just need to handle enabling and disabling it */ if (unit->enabled_gl_target != gl_target) { /* Disable the previous target if it's still enabled */ if (unit->enabled_gl_target) GE (ctx, glDisable (unit->enabled_gl_target)); /* Enable the new target */ if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) { GE (ctx, glEnable (gl_target)); unit->enabled_gl_target = gl_target; } } } else { /* Even though there may be no difference between the last flushed * texture state and the current layers texture state it may be that the * texture unit has been disabled for some time so we need to assert that * it's enabled now. */ if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)) && unit->enabled_gl_target == 0) { _cogl_set_active_texture_unit (unit_index); GE (ctx, glEnable (unit->gl_target)); unit->enabled_gl_target = unit->gl_target; } } if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE) { CoglPipelineLayer *authority = _cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_COMBINE); CoglPipelineLayerBigState *big_state = authority->big_state; GLenum sources[3]; GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)); /* Set the combiner functions... */ GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, big_state->texture_combine_rgb_func)); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, big_state->texture_combine_alpha_func)); /* * Setup the function arguments... */ /* For the RGB components... */ n_rgb_func_args = _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func); translate_sources (pipeline, n_rgb_func_args, big_state->texture_combine_rgb_src, sources); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, sources[0])); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, big_state->texture_combine_rgb_op[0])); if (n_rgb_func_args > 1) { GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, sources[1])); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, big_state->texture_combine_rgb_op[1])); } if (n_rgb_func_args > 2) { GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_RGB, sources[2])); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB, big_state->texture_combine_rgb_op[2])); } /* For the Alpha component */ n_alpha_func_args = _cogl_get_n_args_for_combine_func (big_state->texture_combine_alpha_func); translate_sources (pipeline, n_alpha_func_args, big_state->texture_combine_alpha_src, sources); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, sources[0])); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, big_state->texture_combine_alpha_op[0])); if (n_alpha_func_args > 1) { GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, sources[1])); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, big_state->texture_combine_alpha_op[1])); } if (n_alpha_func_args > 2) { GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_ALPHA, sources[2])); GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, big_state->texture_combine_alpha_op[2])); } } if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT) { CoglPipelineLayer *authority = _cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT); CoglPipelineLayerBigState *big_state = authority->big_state; GE (ctx, glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, big_state->texture_combine_constant)); } return TRUE; }
/* Note: we are trying to avoid duplicating strings during codegen * which is why we have the slightly awkward * CoglPipelineFragendARBfpArg mechanism. */ static void setup_arg (CoglPipeline *pipeline, CoglPipelineLayer *layer, CoglBlendStringChannelMask mask, int arg_index, CoglPipelineCombineSource src, GLint op, CoglPipelineFragendARBfpArg *arg) { CoglPipelineShaderState *shader_state = get_shader_state (pipeline); static const char *tmp_name[3] = { "tmp0", "tmp1", "tmp2" }; switch (src) { case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE: arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE; arg->name = "texel%d"; arg->texture_unit = _cogl_pipeline_layer_get_unit_index (layer); setup_texture_source (shader_state, arg->texture_unit, _cogl_pipeline_layer_get_texture_type (layer)); break; case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT: { int unit_index = _cogl_pipeline_layer_get_unit_index (layer); UnitState *unit_state = &shader_state->unit_state[unit_index]; unit_state->constant_id = shader_state->next_constant_id++; unit_state->has_combine_constant = TRUE; unit_state->dirty_combine_constant = TRUE; arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT; arg->name = "program.local[%d]"; arg->constant_id = unit_state->constant_id; break; } case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR: arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; arg->name = "fragment.color.primary"; break; case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS: arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; if (_cogl_pipeline_layer_get_unit_index (layer) == 0) arg->name = "fragment.color.primary"; else arg->name = "output"; break; default: /* Sample the texture attached to a specific layer */ { int layer_num = src - COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0; CoglPipelineGetLayerFlags flags = COGL_PIPELINE_GET_LAYER_NO_CREATE; CoglPipelineLayer *other_layer = _cogl_pipeline_get_layer_with_flags (pipeline, layer_num, flags); if (other_layer == NULL) { static CoglBool warning_seen = FALSE; if (!warning_seen) { g_warning ("The application is trying to use a texture " "combine with a layer number that does not exist"); warning_seen = TRUE; } arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; arg->name = "output"; } else { CoglTextureType texture_type; arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE; arg->name = "texture[%d]"; arg->texture_unit = _cogl_pipeline_layer_get_unit_index (other_layer); texture_type = _cogl_pipeline_layer_get_texture_type (other_layer); setup_texture_source (shader_state, arg->texture_unit, texture_type); } } break; } arg->swizzle = ""; switch (op) { case COGL_PIPELINE_COMBINE_OP_SRC_COLOR: break; case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR: g_string_append_printf (shader_state->source, "SUB tmp%d, one, ", arg_index); 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 = ""; break; case COGL_PIPELINE_COMBINE_OP_SRC_ALPHA: /* avoid a swizzle if we know RGB are going to be masked * in the end anyway */ if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) arg->swizzle = ".a"; break; case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA: g_string_append_printf (shader_state->source, "SUB tmp%d, one, ", arg_index); 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 (shader_state->source, ".a;\n"); else g_string_append_printf (shader_state->source, ";\n"); arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; arg->name = tmp_name[arg_index]; break; default: g_error ("Unknown texture combine operator %d", op); break; } }