output_color_rgba(false),
output_color_ycbcr(false),
dither_effect(NULL),
+ ycbcr_conversion_effect_node(NULL),
intermediate_format(GL_RGBA16F),
intermediate_transformation(NO_FRAMEBUFFER_TRANSFORMATION),
num_dither_bits(0),
assert(ycbcr_format.chroma_subsampling_y == 1);
}
+void EffectChain::change_ycbcr_output_format(const YCbCrFormat &ycbcr_format)
+{
+ assert(output_color_ycbcr);
+ assert(output_ycbcr_format.chroma_subsampling_x == ycbcr_format.chroma_subsampling_x);
+ assert(output_ycbcr_format.chroma_subsampling_y == ycbcr_format.chroma_subsampling_y);
+ assert(fabs(output_ycbcr_format.cb_x_position - ycbcr_format.cb_x_position) < 1e-3);
+ assert(fabs(output_ycbcr_format.cb_y_position - ycbcr_format.cb_y_position) < 1e-3);
+ assert(fabs(output_ycbcr_format.cr_x_position - ycbcr_format.cr_x_position) < 1e-3);
+ assert(fabs(output_ycbcr_format.cr_y_position - ycbcr_format.cr_y_position) < 1e-3);
+
+ output_ycbcr_format = ycbcr_format;
+ if (finalized) {
+ YCbCrConversionEffect *effect = (YCbCrConversionEffect *)(ycbcr_conversion_effect_node->effect);
+ effect->change_output_format(ycbcr_format);
+ }
+}
+
Node *EffectChain::add_node(Effect *effect)
{
for (unsigned i = 0; i < nodes.size(); ++i) {
if (alpha_handling == Effect::INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA ||
alpha_handling == Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK) {
// This combination (requiring premultiplied alpha, but _not_ requiring
- // linear light) is illegal, // since the combination
- // of premultiplied alpha and nonlinear inputs is
- // meaningless.
+ // linear light) is illegal, since the combination of premultiplied alpha
+ // and nonlinear inputs is meaningless.
assert(node->effect->needs_linear_light());
-
+
// If the effect has asked for premultiplied alpha, check that it has got it.
if (any_postmultiplied) {
node->output_alpha_type = ALPHA_INVALID;
return;
}
Node *output = find_output_node();
- Node *ycbcr = add_node(new YCbCrConversionEffect(output_ycbcr_format));
- connect_nodes(output, ycbcr);
+ ycbcr_conversion_effect_node = add_node(new YCbCrConversionEffect(output_ycbcr_format));
+ connect_nodes(output, ycbcr_conversion_effect_node);
}
// If the user has requested dither, add a DitherEffect right at the end
check_error();
glDisable(GL_DITHER);
check_error();
- glEnable(GL_FRAMEBUFFER_SRGB);
+
+ const bool final_srgb = glIsEnabled(GL_FRAMEBUFFER_SRGB);
check_error();
+ bool current_srgb = final_srgb;
// Save original viewport.
GLuint x = 0, y = 0;
CHECK(dither_effect->set_int("output_height", height));
}
}
- execute_phase(phase, phase_num == phases.size() - 1, &bound_attribute_indices, &output_textures, &generated_mipmaps);
+ bool last_phase = (phase_num == phases.size() - 1);
+
+ // Enable sRGB rendering for intermediates in case we are
+ // rendering to an sRGB format.
+ bool needs_srgb = last_phase ? final_srgb : true;
+ if (needs_srgb && !current_srgb) {
+ glEnable(GL_FRAMEBUFFER_SRGB);
+ check_error();
+ current_srgb = true;
+ } else if (!needs_srgb && current_srgb) {
+ glDisable(GL_FRAMEBUFFER_SRGB);
+ check_error();
+ current_srgb = true;
+ }
+
+ execute_phase(phase, last_phase, &bound_attribute_indices, &output_textures, &generated_mipmaps);
if (do_phase_timing) {
glEndQuery(GL_TIME_ELAPSED);
}
output_textures->insert(make_pair(phase, tex_num));
}
- glUseProgram(phase->glsl_program_num);
- check_error();
-
// Set up RTT inputs for this phase.
for (unsigned sampler = 0; sampler < phase->inputs.size(); ++sampler) {
glActiveTexture(GL_TEXTURE0 + sampler);
glViewport(0, 0, phase->output_width, phase->output_height);
}
+ GLuint instance_program_num = resource_pool->use_glsl_program(phase->glsl_program_num);
+ check_error();
+
// Give the required parameters to all the effects.
unsigned sampler_num = phase->inputs.size();
for (unsigned i = 0; i < phase->effects.size(); ++i) {
Node *node = phase->effects[i];
unsigned old_sampler_num = sampler_num;
- node->effect->set_gl_state(phase->glsl_program_num, phase->effect_ids[node], &sampler_num);
+ node->effect->set_gl_state(instance_program_num, phase->effect_ids[node], &sampler_num);
check_error();
if (node->effect->is_single_texture()) {
node->effect->clear_gl_state();
}
+ resource_pool->unuse_glsl_program(instance_program_num);
+
if (!last_phase) {
resource_pool->release_fbo(fbo);
}