]> git.sesse.net Git - movit/blob - effect_chain.cpp
There's no need to #undef PREFIX, since we do the token pasting ourselves.
[movit] / effect_chain.cpp
1 #include <epoxy/gl.h>
2 #include <assert.h>
3 #include <math.h>
4 #include <stddef.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <algorithm>
9 #include <set>
10 #include <stack>
11 #include <utility>
12 #include <vector>
13 #include <Eigen/Core>
14
15 #include "alpha_division_effect.h"
16 #include "alpha_multiplication_effect.h"
17 #include "colorspace_conversion_effect.h"
18 #include "dither_effect.h"
19 #include "effect.h"
20 #include "effect_chain.h"
21 #include "effect_util.h"
22 #include "gamma_compression_effect.h"
23 #include "gamma_expansion_effect.h"
24 #include "init.h"
25 #include "input.h"
26 #include "resource_pool.h"
27 #include "util.h"
28 #include "ycbcr_conversion_effect.h"
29
30 using namespace Eigen;
31 using namespace std;
32
33 namespace movit {
34
35 EffectChain::EffectChain(float aspect_nom, float aspect_denom, ResourcePool *resource_pool)
36         : aspect_nom(aspect_nom),
37           aspect_denom(aspect_denom),
38           output_color_rgba(false),
39           num_output_color_ycbcr(0),
40           dither_effect(NULL),
41           ycbcr_conversion_effect_node(NULL),
42           intermediate_format(GL_RGBA16F),
43           intermediate_transformation(NO_FRAMEBUFFER_TRANSFORMATION),
44           num_dither_bits(0),
45           output_origin(OUTPUT_ORIGIN_BOTTOM_LEFT),
46           finalized(false),
47           resource_pool(resource_pool),
48           do_phase_timing(false) {
49         if (resource_pool == NULL) {
50                 this->resource_pool = new ResourcePool();
51                 owns_resource_pool = true;
52         } else {
53                 owns_resource_pool = false;
54         }
55
56         // Generate a VBO with some data in (shared position and texture coordinate data).
57         float vertices[] = {
58                 0.0f, 2.0f,
59                 0.0f, 0.0f,
60                 2.0f, 0.0f
61         };
62         vbo = generate_vbo(2, GL_FLOAT, sizeof(vertices), vertices);
63 }
64
65 EffectChain::~EffectChain()
66 {
67         for (unsigned i = 0; i < nodes.size(); ++i) {
68                 delete nodes[i]->effect;
69                 delete nodes[i];
70         }
71         for (unsigned i = 0; i < phases.size(); ++i) {
72                 resource_pool->release_glsl_program(phases[i]->glsl_program_num);
73                 delete phases[i];
74         }
75         if (owns_resource_pool) {
76                 delete resource_pool;
77         }
78         glDeleteBuffers(1, &vbo);
79         check_error();
80 }
81
82 Input *EffectChain::add_input(Input *input)
83 {
84         assert(!finalized);
85         inputs.push_back(input);
86         add_node(input);
87         return input;
88 }
89
90 void EffectChain::add_output(const ImageFormat &format, OutputAlphaFormat alpha_format)
91 {
92         assert(!finalized);
93         assert(!output_color_rgba);
94         output_format = format;
95         output_alpha_format = alpha_format;
96         output_color_rgba = true;
97 }
98
99 void EffectChain::add_ycbcr_output(const ImageFormat &format, OutputAlphaFormat alpha_format,
100                                    const YCbCrFormat &ycbcr_format, YCbCrOutputSplitting output_splitting,
101                                    GLenum output_type)
102 {
103         assert(!finalized);
104         assert(num_output_color_ycbcr < 2);
105         output_format = format;
106         output_alpha_format = alpha_format;
107
108         if (num_output_color_ycbcr == 1) {
109                 // Check that the format is the same.
110                 assert(output_ycbcr_format.luma_coefficients == ycbcr_format.luma_coefficients);
111                 assert(output_ycbcr_format.full_range == ycbcr_format.full_range);
112                 assert(output_ycbcr_format.num_levels == ycbcr_format.num_levels);
113                 assert(output_ycbcr_format.chroma_subsampling_x == 1);
114                 assert(output_ycbcr_format.chroma_subsampling_y == 1);
115                 assert(output_ycbcr_type == output_type);
116         } else {
117                 output_ycbcr_format = ycbcr_format;
118                 output_ycbcr_type = output_type;
119         }
120         output_ycbcr_splitting[num_output_color_ycbcr++] = output_splitting;
121
122         assert(ycbcr_format.chroma_subsampling_x == 1);
123         assert(ycbcr_format.chroma_subsampling_y == 1);
124 }
125
126 void EffectChain::change_ycbcr_output_format(const YCbCrFormat &ycbcr_format)
127 {
128         assert(num_output_color_ycbcr > 0);
129         assert(output_ycbcr_format.chroma_subsampling_x == 1);
130         assert(output_ycbcr_format.chroma_subsampling_y == 1);
131
132         output_ycbcr_format = ycbcr_format;
133         if (finalized) {
134                 YCbCrConversionEffect *effect = (YCbCrConversionEffect *)(ycbcr_conversion_effect_node->effect);
135                 effect->change_output_format(ycbcr_format);
136         }
137 }
138
139 Node *EffectChain::add_node(Effect *effect)
140 {
141         for (unsigned i = 0; i < nodes.size(); ++i) {
142                 assert(nodes[i]->effect != effect);
143         }
144
145         Node *node = new Node;
146         node->effect = effect;
147         node->disabled = false;
148         node->output_color_space = COLORSPACE_INVALID;
149         node->output_gamma_curve = GAMMA_INVALID;
150         node->output_alpha_type = ALPHA_INVALID;
151         node->needs_mipmaps = false;
152         node->one_to_one_sampling = false;
153
154         nodes.push_back(node);
155         node_map[effect] = node;
156         effect->inform_added(this);
157         return node;
158 }
159
160 void EffectChain::connect_nodes(Node *sender, Node *receiver)
161 {
162         sender->outgoing_links.push_back(receiver);
163         receiver->incoming_links.push_back(sender);
164 }
165
166 void EffectChain::replace_receiver(Node *old_receiver, Node *new_receiver)
167 {
168         new_receiver->incoming_links = old_receiver->incoming_links;
169         old_receiver->incoming_links.clear();
170         
171         for (unsigned i = 0; i < new_receiver->incoming_links.size(); ++i) {
172                 Node *sender = new_receiver->incoming_links[i];
173                 for (unsigned j = 0; j < sender->outgoing_links.size(); ++j) {
174                         if (sender->outgoing_links[j] == old_receiver) {
175                                 sender->outgoing_links[j] = new_receiver;
176                         }
177                 }
178         }       
179 }
180
181 void EffectChain::replace_sender(Node *old_sender, Node *new_sender)
182 {
183         new_sender->outgoing_links = old_sender->outgoing_links;
184         old_sender->outgoing_links.clear();
185         
186         for (unsigned i = 0; i < new_sender->outgoing_links.size(); ++i) {
187                 Node *receiver = new_sender->outgoing_links[i];
188                 for (unsigned j = 0; j < receiver->incoming_links.size(); ++j) {
189                         if (receiver->incoming_links[j] == old_sender) {
190                                 receiver->incoming_links[j] = new_sender;
191                         }
192                 }
193         }       
194 }
195
196 void EffectChain::insert_node_between(Node *sender, Node *middle, Node *receiver)
197 {
198         for (unsigned i = 0; i < sender->outgoing_links.size(); ++i) {
199                 if (sender->outgoing_links[i] == receiver) {
200                         sender->outgoing_links[i] = middle;
201                         middle->incoming_links.push_back(sender);
202                 }
203         }
204         for (unsigned i = 0; i < receiver->incoming_links.size(); ++i) {
205                 if (receiver->incoming_links[i] == sender) {
206                         receiver->incoming_links[i] = middle;
207                         middle->outgoing_links.push_back(receiver);
208                 }
209         }
210
211         assert(middle->incoming_links.size() == middle->effect->num_inputs());
212 }
213
214 GLenum EffectChain::get_input_sampler(Node *node, unsigned input_num) const
215 {
216         assert(node->effect->needs_texture_bounce());
217         assert(input_num < node->incoming_links.size());
218         assert(node->incoming_links[input_num]->bound_sampler_num >= 0);
219         assert(node->incoming_links[input_num]->bound_sampler_num < 8);
220         return GL_TEXTURE0 + node->incoming_links[input_num]->bound_sampler_num;
221 }
222
223 GLenum EffectChain::has_input_sampler(Node *node, unsigned input_num) const
224 {
225         assert(input_num < node->incoming_links.size());
226         return node->incoming_links[input_num]->bound_sampler_num >= 0 &&
227                 node->incoming_links[input_num]->bound_sampler_num < 8;
228 }
229
230 void EffectChain::find_all_nonlinear_inputs(Node *node, vector<Node *> *nonlinear_inputs)
231 {
232         if (node->output_gamma_curve == GAMMA_LINEAR &&
233             node->effect->effect_type_id() != "GammaCompressionEffect") {
234                 return;
235         }
236         if (node->effect->num_inputs() == 0) {
237                 nonlinear_inputs->push_back(node);
238         } else {
239                 assert(node->effect->num_inputs() == node->incoming_links.size());
240                 for (unsigned i = 0; i < node->incoming_links.size(); ++i) {
241                         find_all_nonlinear_inputs(node->incoming_links[i], nonlinear_inputs);
242                 }
243         }
244 }
245
246 Effect *EffectChain::add_effect(Effect *effect, const vector<Effect *> &inputs)
247 {
248         assert(!finalized);
249         assert(inputs.size() == effect->num_inputs());
250         Node *node = add_node(effect);
251         for (unsigned i = 0; i < inputs.size(); ++i) {
252                 assert(node_map.count(inputs[i]) != 0);
253                 connect_nodes(node_map[inputs[i]], node);
254         }
255         return effect;
256 }
257
258 // ESSL doesn't support token pasting. Replace PREFIX(x) with <effect_id>_x.
259 string replace_prefix(const string &text, const string &prefix)
260 {
261         string output;
262         size_t start = 0;
263
264         while (start < text.size()) {
265                 size_t pos = text.find("PREFIX(", start);
266                 if (pos == string::npos) {
267                         output.append(text.substr(start, string::npos));
268                         break;
269                 }
270
271                 output.append(text.substr(start, pos - start));
272                 output.append(prefix);
273                 output.append("_");
274
275                 pos += strlen("PREFIX(");
276         
277                 // Output stuff until we find the matching ), which we then eat.
278                 int depth = 1;
279                 size_t end_arg_pos = pos;
280                 while (end_arg_pos < text.size()) {
281                         if (text[end_arg_pos] == '(') {
282                                 ++depth;
283                         } else if (text[end_arg_pos] == ')') {
284                                 --depth;
285                                 if (depth == 0) {
286                                         break;
287                                 }
288                         }
289                         ++end_arg_pos;
290                 }
291                 output.append(text.substr(pos, end_arg_pos - pos));
292                 ++end_arg_pos;
293                 assert(depth == 0);
294                 start = end_arg_pos;
295         }
296         return output;
297 }
298
299 namespace {
300
301 template<class T>
302 void extract_uniform_declarations(const vector<Uniform<T> > &effect_uniforms,
303                                   const string &type_specifier,
304                                   const string &effect_id,
305                                   vector<Uniform<T> > *phase_uniforms,
306                                   string *glsl_string)
307 {
308         for (unsigned i = 0; i < effect_uniforms.size(); ++i) {
309                 phase_uniforms->push_back(effect_uniforms[i]);
310                 phase_uniforms->back().prefix = effect_id;
311
312                 *glsl_string += string("uniform ") + type_specifier + " " + effect_id
313                         + "_" + effect_uniforms[i].name + ";\n";
314         }
315 }
316
317 template<class T>
318 void extract_uniform_array_declarations(const vector<Uniform<T> > &effect_uniforms,
319                                         const string &type_specifier,
320                                         const string &effect_id,
321                                         vector<Uniform<T> > *phase_uniforms,
322                                         string *glsl_string)
323 {
324         for (unsigned i = 0; i < effect_uniforms.size(); ++i) {
325                 phase_uniforms->push_back(effect_uniforms[i]);
326                 phase_uniforms->back().prefix = effect_id;
327
328                 char buf[256];
329                 snprintf(buf, sizeof(buf), "uniform %s %s_%s[%d];\n",
330                         type_specifier.c_str(), effect_id.c_str(),
331                         effect_uniforms[i].name.c_str(),
332                         int(effect_uniforms[i].num_values));
333                 *glsl_string += buf;
334         }
335 }
336
337 template<class T>
338 void collect_uniform_locations(GLuint glsl_program_num, vector<Uniform<T> > *phase_uniforms)
339 {
340         for (unsigned i = 0; i < phase_uniforms->size(); ++i) {
341                 Uniform<T> &uniform = (*phase_uniforms)[i];
342                 uniform.location = get_uniform_location(glsl_program_num, uniform.prefix, uniform.name);
343         }
344 }
345
346 }  // namespace
347
348 void EffectChain::compile_glsl_program(Phase *phase)
349 {
350         string frag_shader_header = read_version_dependent_file("header", "frag");
351         string frag_shader = "";
352
353         // Create functions and uniforms for all the texture inputs that we need.
354         for (unsigned i = 0; i < phase->inputs.size(); ++i) {
355                 Node *input = phase->inputs[i]->output_node;
356                 char effect_id[256];
357                 sprintf(effect_id, "in%u", i);
358                 phase->effect_ids.insert(make_pair(input, effect_id));
359         
360                 frag_shader += string("uniform sampler2D tex_") + effect_id + ";\n";
361                 frag_shader += string("vec4 ") + effect_id + "(vec2 tc) {\n";
362                 frag_shader += "\tvec4 tmp = tex2D(tex_" + string(effect_id) + ", tc);\n";
363
364                 if (intermediate_transformation == SQUARE_ROOT_FRAMEBUFFER_TRANSFORMATION &&
365                     phase->inputs[i]->output_node->output_gamma_curve == GAMMA_LINEAR) {
366                         frag_shader += "\ttmp.rgb *= tmp.rgb;\n";
367                 }
368
369                 frag_shader += "\treturn tmp;\n";
370                 frag_shader += "}\n";
371                 frag_shader += "\n";
372
373                 Uniform<int> uniform;
374                 uniform.name = effect_id;
375                 uniform.value = &phase->input_samplers[i];
376                 uniform.prefix = "tex";
377                 uniform.num_values = 1;
378                 uniform.location = -1;
379                 phase->uniforms_sampler2d.push_back(uniform);
380         }
381
382         // Give each effect in the phase its own ID.
383         for (unsigned i = 0; i < phase->effects.size(); ++i) {
384                 Node *node = phase->effects[i];
385                 char effect_id[256];
386                 sprintf(effect_id, "eff%u", i);
387                 phase->effect_ids.insert(make_pair(node, effect_id));
388         }
389
390         for (unsigned i = 0; i < phase->effects.size(); ++i) {
391                 Node *node = phase->effects[i];
392                 const string effect_id = phase->effect_ids[node];
393                 if (node->incoming_links.size() == 1) {
394                         frag_shader += string("#define INPUT ") + phase->effect_ids[node->incoming_links[0]] + "\n";
395                 } else {
396                         for (unsigned j = 0; j < node->incoming_links.size(); ++j) {
397                                 char buf[256];
398                                 sprintf(buf, "#define INPUT%d %s\n", j + 1, phase->effect_ids[node->incoming_links[j]].c_str());
399                                 frag_shader += buf;
400                         }
401                 }
402         
403                 frag_shader += "\n";
404                 frag_shader += string("#define FUNCNAME ") + effect_id + "\n";
405                 frag_shader += replace_prefix(node->effect->output_fragment_shader(), effect_id);
406                 frag_shader += "#undef FUNCNAME\n";
407                 if (node->incoming_links.size() == 1) {
408                         frag_shader += "#undef INPUT\n";
409                 } else {
410                         for (unsigned j = 0; j < node->incoming_links.size(); ++j) {
411                                 char buf[256];
412                                 sprintf(buf, "#undef INPUT%d\n", j + 1);
413                                 frag_shader += buf;
414                         }
415                 }
416                 frag_shader += "\n";
417         }
418         frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
419
420         // If we're the last phase, add the right #defines for Y'CbCr multi-output as needed.
421         vector<string> frag_shader_outputs;  // In order.
422         if (phase->output_node->outgoing_links.empty() && num_output_color_ycbcr > 0) {
423                 switch (output_ycbcr_splitting[0]) {
424                 case YCBCR_OUTPUT_INTERLEAVED:
425                         // No #defines set.
426                         frag_shader_outputs.push_back("FragColor");
427                         break;
428                 case YCBCR_OUTPUT_SPLIT_Y_AND_CBCR:
429                         frag_shader += "#define YCBCR_OUTPUT_SPLIT_Y_AND_CBCR 1\n";
430                         frag_shader_outputs.push_back("Y");
431                         frag_shader_outputs.push_back("Chroma");
432                         break;
433                 case YCBCR_OUTPUT_PLANAR:
434                         frag_shader += "#define YCBCR_OUTPUT_PLANAR 1\n";
435                         frag_shader_outputs.push_back("Y");
436                         frag_shader_outputs.push_back("Cb");
437                         frag_shader_outputs.push_back("Cr");
438                         break;
439                 default:
440                         assert(false);
441                 }
442
443                 if (num_output_color_ycbcr > 1) {
444                         switch (output_ycbcr_splitting[1]) {
445                         case YCBCR_OUTPUT_INTERLEAVED:
446                                 frag_shader += "#define SECOND_YCBCR_OUTPUT_INTERLEAVED 1\n";
447                                 frag_shader_outputs.push_back("YCbCr2");
448                                 break;
449                         case YCBCR_OUTPUT_SPLIT_Y_AND_CBCR:
450                                 frag_shader += "#define SECOND_YCBCR_OUTPUT_SPLIT_Y_AND_CBCR 1\n";
451                                 frag_shader_outputs.push_back("Y2");
452                                 frag_shader_outputs.push_back("Chroma2");
453                                 break;
454                         case YCBCR_OUTPUT_PLANAR:
455                                 frag_shader += "#define SECOND_YCBCR_OUTPUT_PLANAR 1\n";
456                                 frag_shader_outputs.push_back("Y2");
457                                 frag_shader_outputs.push_back("Cb2");
458                                 frag_shader_outputs.push_back("Cr2");
459                                 break;
460                         default:
461                                 assert(false);
462                         }
463                 }
464
465                 if (output_color_rgba) {
466                         // Note: Needs to come in the header, because not only the
467                         // output needs to see it (YCbCrConversionEffect and DitherEffect
468                         // do, too).
469                         frag_shader_header += "#define YCBCR_ALSO_OUTPUT_RGBA 1\n";
470                         frag_shader_outputs.push_back("RGBA");
471                 }
472         }
473
474         // If we're bouncing to a temporary texture, signal transformation if desired.
475         if (!phase->output_node->outgoing_links.empty()) {
476                 if (intermediate_transformation == SQUARE_ROOT_FRAMEBUFFER_TRANSFORMATION &&
477                     phase->output_node->output_gamma_curve == GAMMA_LINEAR) {
478                         frag_shader += "#define SQUARE_ROOT_TRANSFORMATION 1\n";
479                 }
480         }
481
482         frag_shader.append(read_file("footer.frag"));
483
484         // Collect uniforms from all effects and output them. Note that this needs
485         // to happen after output_fragment_shader(), even though the uniforms come
486         // before in the output source, since output_fragment_shader() is allowed
487         // to register new uniforms (e.g. arrays that are of unknown length until
488         // finalization time).
489         // TODO: Make a uniform block for platforms that support it.
490         string frag_shader_uniforms = "";
491         for (unsigned i = 0; i < phase->effects.size(); ++i) {
492                 Node *node = phase->effects[i];
493                 Effect *effect = node->effect;
494                 const string effect_id = phase->effect_ids[node];
495                 extract_uniform_declarations(effect->uniforms_sampler2d, "sampler2D", effect_id, &phase->uniforms_sampler2d, &frag_shader_uniforms);
496                 extract_uniform_declarations(effect->uniforms_bool, "bool", effect_id, &phase->uniforms_bool, &frag_shader_uniforms);
497                 extract_uniform_declarations(effect->uniforms_int, "int", effect_id, &phase->uniforms_int, &frag_shader_uniforms);
498                 extract_uniform_declarations(effect->uniforms_float, "float", effect_id, &phase->uniforms_float, &frag_shader_uniforms);
499                 extract_uniform_declarations(effect->uniforms_vec2, "vec2", effect_id, &phase->uniforms_vec2, &frag_shader_uniforms);
500                 extract_uniform_declarations(effect->uniforms_vec3, "vec3", effect_id, &phase->uniforms_vec3, &frag_shader_uniforms);
501                 extract_uniform_declarations(effect->uniforms_vec4, "vec4", effect_id, &phase->uniforms_vec4, &frag_shader_uniforms);
502                 extract_uniform_array_declarations(effect->uniforms_float_array, "float", effect_id, &phase->uniforms_float, &frag_shader_uniforms);
503                 extract_uniform_array_declarations(effect->uniforms_vec2_array, "vec2", effect_id, &phase->uniforms_vec2, &frag_shader_uniforms);
504                 extract_uniform_array_declarations(effect->uniforms_vec3_array, "vec3", effect_id, &phase->uniforms_vec3, &frag_shader_uniforms);
505                 extract_uniform_array_declarations(effect->uniforms_vec4_array, "vec4", effect_id, &phase->uniforms_vec4, &frag_shader_uniforms);
506                 extract_uniform_declarations(effect->uniforms_mat3, "mat3", effect_id, &phase->uniforms_mat3, &frag_shader_uniforms);
507         }
508
509         frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader;
510
511         string vert_shader = read_version_dependent_file("vs", "vert");
512
513         // If we're the last phase and need to flip the picture to compensate for
514         // the origin, tell the vertex shader so.
515         if (phase->output_node->outgoing_links.empty() && output_origin == OUTPUT_ORIGIN_TOP_LEFT) {
516                 const string needle = "#define FLIP_ORIGIN 0";
517                 size_t pos = vert_shader.find(needle);
518                 assert(pos != string::npos);
519
520                 vert_shader[pos + needle.size() - 1] = '1';
521         }
522
523         phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader, frag_shader_outputs);
524         GLint position_attribute_index = glGetAttribLocation(phase->glsl_program_num, "position");
525         GLint texcoord_attribute_index = glGetAttribLocation(phase->glsl_program_num, "texcoord");
526         if (position_attribute_index != -1) {
527                 phase->attribute_indexes.insert(position_attribute_index);
528         }
529         if (texcoord_attribute_index != -1) {
530                 phase->attribute_indexes.insert(texcoord_attribute_index);
531         }
532
533         // Collect the resulting location numbers for each uniform.
534         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_sampler2d);
535         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_bool);
536         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_int);
537         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_float);
538         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec2);
539         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec3);
540         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_vec4);
541         collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_mat3);
542 }
543
544 // Construct GLSL programs, starting at the given effect and following
545 // the chain from there. We end a program every time we come to an effect
546 // marked as "needs texture bounce", one that is used by multiple other
547 // effects, every time we need to bounce due to output size change
548 // (not all size changes require ending), and of course at the end.
549 //
550 // We follow a quite simple depth-first search from the output, although
551 // without recursing explicitly within each phase.
552 Phase *EffectChain::construct_phase(Node *output, map<Node *, Phase *> *completed_effects)
553 {
554         if (completed_effects->count(output)) {
555                 return (*completed_effects)[output];
556         }
557
558         Phase *phase = new Phase;
559         phase->output_node = output;
560
561         // If the output effect has one-to-one sampling, we try to trace this
562         // status down through the dependency chain. This is important in case
563         // we hit an effect that changes output size (and not sets a virtual
564         // output size); if we have one-to-one sampling, we don't have to break
565         // the phase.
566         output->one_to_one_sampling = output->effect->one_to_one_sampling();
567
568         // Effects that we have yet to calculate, but that we know should
569         // be in the current phase.
570         stack<Node *> effects_todo_this_phase;
571         effects_todo_this_phase.push(output);
572
573         while (!effects_todo_this_phase.empty()) {
574                 Node *node = effects_todo_this_phase.top();
575                 effects_todo_this_phase.pop();
576
577                 if (node->effect->needs_mipmaps()) {
578                         node->needs_mipmaps = true;
579                 }
580
581                 // This should currently only happen for effects that are inputs
582                 // (either true inputs or phase outputs). We special-case inputs,
583                 // and then deduplicate phase outputs below.
584                 if (node->effect->num_inputs() == 0) {
585                         if (find(phase->effects.begin(), phase->effects.end(), node) != phase->effects.end()) {
586                                 continue;
587                         }
588                 } else {
589                         assert(completed_effects->count(node) == 0);
590                 }
591
592                 phase->effects.push_back(node);
593
594                 // Find all the dependencies of this effect, and add them to the stack.
595                 vector<Node *> deps = node->incoming_links;
596                 assert(node->effect->num_inputs() == deps.size());
597                 for (unsigned i = 0; i < deps.size(); ++i) {
598                         bool start_new_phase = false;
599
600                         if (node->effect->needs_texture_bounce() &&
601                             !deps[i]->effect->is_single_texture() &&
602                             !deps[i]->effect->override_disable_bounce()) {
603                                 start_new_phase = true;
604                         }
605
606                         // Propagate information about needing mipmaps down the chain,
607                         // breaking the phase if we notice an incompatibility.
608                         //
609                         // Note that we cannot do this propagation as a normal pass,
610                         // because it needs information about where the phases end
611                         // (we should not propagate the flag across phases).
612                         if (node->needs_mipmaps) {
613                                 if (deps[i]->effect->num_inputs() == 0) {
614                                         Input *input = static_cast<Input *>(deps[i]->effect);
615                                         start_new_phase |= !input->can_supply_mipmaps();
616                                 } else {
617                                         deps[i]->needs_mipmaps = true;
618                                 }
619                         }
620
621                         if (deps[i]->outgoing_links.size() > 1) {
622                                 if (!deps[i]->effect->is_single_texture()) {
623                                         // More than one effect uses this as the input,
624                                         // and it is not a texture itself.
625                                         // The easiest thing to do (and probably also the safest
626                                         // performance-wise in most cases) is to bounce it to a texture
627                                         // and then let the next passes read from that.
628                                         start_new_phase = true;
629                                 } else {
630                                         assert(deps[i]->effect->num_inputs() == 0);
631
632                                         // For textures, we try to be slightly more clever;
633                                         // if none of our outputs need a bounce, we don't bounce
634                                         // but instead simply use the effect many times.
635                                         //
636                                         // Strictly speaking, we could bounce it for some outputs
637                                         // and use it directly for others, but the processing becomes
638                                         // somewhat simpler if the effect is only used in one such way.
639                                         for (unsigned j = 0; j < deps[i]->outgoing_links.size(); ++j) {
640                                                 Node *rdep = deps[i]->outgoing_links[j];
641                                                 start_new_phase |= rdep->effect->needs_texture_bounce();
642                                         }
643                                 }
644                         }
645
646                         if (deps[i]->effect->sets_virtual_output_size()) {
647                                 assert(deps[i]->effect->changes_output_size());
648                                 // If the next effect sets a virtual size to rely on OpenGL's
649                                 // bilinear sampling, we'll really need to break the phase here.
650                                 start_new_phase = true;
651                         } else if (deps[i]->effect->changes_output_size() && !node->one_to_one_sampling) {
652                                 // If the next effect changes size and we don't have one-to-one sampling,
653                                 // we also need to break here.
654                                 start_new_phase = true;
655                         }
656
657                         if (start_new_phase) {
658                                 phase->inputs.push_back(construct_phase(deps[i], completed_effects));
659                         } else {
660                                 effects_todo_this_phase.push(deps[i]);
661
662                                 // Propagate the one-to-one status down through the dependency.
663                                 deps[i]->one_to_one_sampling = node->one_to_one_sampling &&
664                                         deps[i]->effect->one_to_one_sampling();
665                         }
666                 }
667         }
668
669         // No more effects to do this phase. Take all the ones we have,
670         // and create a GLSL program for it.
671         assert(!phase->effects.empty());
672
673         // Deduplicate the inputs, but don't change the ordering e.g. by sorting;
674         // that would be nondeterministic and thus reduce cacheability.
675         // TODO: Make this even more deterministic.
676         vector<Phase *> dedup_inputs;
677         set<Phase *> seen_inputs;
678         for (size_t i = 0; i < phase->inputs.size(); ++i) {
679                 if (seen_inputs.insert(phase->inputs[i]).second) {
680                         dedup_inputs.push_back(phase->inputs[i]);
681                 }
682         }
683         swap(phase->inputs, dedup_inputs);
684
685         // Allocate samplers for each input.
686         phase->input_samplers.resize(phase->inputs.size());
687
688         // We added the effects from the output and back, but we need to output
689         // them in topological sort order in the shader.
690         phase->effects = topological_sort(phase->effects);
691
692         // Figure out if we need mipmaps or not, and if so, tell the inputs that.
693         phase->input_needs_mipmaps = false;
694         for (unsigned i = 0; i < phase->effects.size(); ++i) {
695                 Node *node = phase->effects[i];
696                 phase->input_needs_mipmaps |= node->effect->needs_mipmaps();
697         }
698         for (unsigned i = 0; i < phase->effects.size(); ++i) {
699                 Node *node = phase->effects[i];
700                 if (node->effect->num_inputs() == 0) {
701                         Input *input = static_cast<Input *>(node->effect);
702                         assert(!phase->input_needs_mipmaps || input->can_supply_mipmaps());
703                         CHECK(input->set_int("needs_mipmaps", phase->input_needs_mipmaps));
704                 }
705         }
706
707         // Tell each node which phase it ended up in, so that the unit test
708         // can check that the phases were split in the right place.
709         // Note that this ignores that effects may be part of multiple phases;
710         // if the unit tests need to test such cases, we'll reconsider.
711         for (unsigned i = 0; i < phase->effects.size(); ++i) {
712                 phase->effects[i]->containing_phase = phase;
713         }
714
715         // Actually make the shader for this phase.
716         compile_glsl_program(phase);
717
718         // Initialize timers.
719         if (movit_timer_queries_supported) {
720                 phase->time_elapsed_ns = 0;
721                 phase->num_measured_iterations = 0;
722         }
723
724         assert(completed_effects->count(output) == 0);
725         completed_effects->insert(make_pair(output, phase));
726         phases.push_back(phase);
727         return phase;
728 }
729
730 void EffectChain::output_dot(const char *filename)
731 {
732         if (movit_debug_level != MOVIT_DEBUG_ON) {
733                 return;
734         }
735
736         FILE *fp = fopen(filename, "w");
737         if (fp == NULL) {
738                 perror(filename);
739                 exit(1);
740         }
741
742         fprintf(fp, "digraph G {\n");
743         fprintf(fp, "  output [shape=box label=\"(output)\"];\n");
744         for (unsigned i = 0; i < nodes.size(); ++i) {
745                 // Find out which phase this event belongs to.
746                 vector<int> in_phases;
747                 for (unsigned j = 0; j < phases.size(); ++j) {
748                         const Phase* p = phases[j];
749                         if (find(p->effects.begin(), p->effects.end(), nodes[i]) != p->effects.end()) {
750                                 in_phases.push_back(j);
751                         }
752                 }
753
754                 if (in_phases.empty()) {
755                         fprintf(fp, "  n%ld [label=\"%s\"];\n", (long)nodes[i], nodes[i]->effect->effect_type_id().c_str());
756                 } else if (in_phases.size() == 1) {
757                         fprintf(fp, "  n%ld [label=\"%s\" style=\"filled\" fillcolor=\"/accent8/%d\"];\n",
758                                 (long)nodes[i], nodes[i]->effect->effect_type_id().c_str(),
759                                 (in_phases[0] % 8) + 1);
760                 } else {
761                         // If we had new enough Graphviz, style="wedged" would probably be ideal here.
762                         // But alas.
763                         fprintf(fp, "  n%ld [label=\"%s [in multiple phases]\" style=\"filled\" fillcolor=\"/accent8/%d\"];\n",
764                                 (long)nodes[i], nodes[i]->effect->effect_type_id().c_str(),
765                                 (in_phases[0] % 8) + 1);
766                 }
767
768                 char from_node_id[256];
769                 snprintf(from_node_id, 256, "n%ld", (long)nodes[i]);
770
771                 for (unsigned j = 0; j < nodes[i]->outgoing_links.size(); ++j) {
772                         char to_node_id[256];
773                         snprintf(to_node_id, 256, "n%ld", (long)nodes[i]->outgoing_links[j]);
774
775                         vector<string> labels = get_labels_for_edge(nodes[i], nodes[i]->outgoing_links[j]);
776                         output_dot_edge(fp, from_node_id, to_node_id, labels);
777                 }
778
779                 if (nodes[i]->outgoing_links.empty() && !nodes[i]->disabled) {
780                         // Output node.
781                         vector<string> labels = get_labels_for_edge(nodes[i], NULL);
782                         output_dot_edge(fp, from_node_id, "output", labels);
783                 }
784         }
785         fprintf(fp, "}\n");
786
787         fclose(fp);
788 }
789
790 vector<string> EffectChain::get_labels_for_edge(const Node *from, const Node *to)
791 {
792         vector<string> labels;
793
794         if (to != NULL && to->effect->needs_texture_bounce()) {
795                 labels.push_back("needs_bounce");
796         }
797         if (from->effect->changes_output_size()) {
798                 labels.push_back("resize");
799         }
800
801         switch (from->output_color_space) {
802         case COLORSPACE_INVALID:
803                 labels.push_back("spc[invalid]");
804                 break;
805         case COLORSPACE_REC_601_525:
806                 labels.push_back("spc[rec601-525]");
807                 break;
808         case COLORSPACE_REC_601_625:
809                 labels.push_back("spc[rec601-625]");
810                 break;
811         default:
812                 break;
813         }
814
815         switch (from->output_gamma_curve) {
816         case GAMMA_INVALID:
817                 labels.push_back("gamma[invalid]");
818                 break;
819         case GAMMA_sRGB:
820                 labels.push_back("gamma[sRGB]");
821                 break;
822         case GAMMA_REC_601:  // and GAMMA_REC_709
823                 labels.push_back("gamma[rec601/709]");
824                 break;
825         default:
826                 break;
827         }
828
829         switch (from->output_alpha_type) {
830         case ALPHA_INVALID:
831                 labels.push_back("alpha[invalid]");
832                 break;
833         case ALPHA_BLANK:
834                 labels.push_back("alpha[blank]");
835                 break;
836         case ALPHA_POSTMULTIPLIED:
837                 labels.push_back("alpha[postmult]");
838                 break;
839         default:
840                 break;
841         }
842
843         return labels;
844 }
845
846 void EffectChain::output_dot_edge(FILE *fp,
847                                   const string &from_node_id,
848                                   const string &to_node_id,
849                                   const vector<string> &labels)
850 {
851         if (labels.empty()) {
852                 fprintf(fp, "  %s -> %s;\n", from_node_id.c_str(), to_node_id.c_str());
853         } else {
854                 string label = labels[0];
855                 for (unsigned k = 1; k < labels.size(); ++k) {
856                         label += ", " + labels[k];
857                 }
858                 fprintf(fp, "  %s -> %s [label=\"%s\"];\n", from_node_id.c_str(), to_node_id.c_str(), label.c_str());
859         }
860 }
861
862 void EffectChain::size_rectangle_to_fit(unsigned width, unsigned height, unsigned *output_width, unsigned *output_height)
863 {
864         unsigned scaled_width, scaled_height;
865
866         if (float(width) * aspect_denom >= float(height) * aspect_nom) {
867                 // Same aspect, or W/H > aspect (image is wider than the frame).
868                 // In either case, keep width, and adjust height.
869                 scaled_width = width;
870                 scaled_height = lrintf(width * aspect_denom / aspect_nom);
871         } else {
872                 // W/H < aspect (image is taller than the frame), so keep height,
873                 // and adjust width.
874                 scaled_width = lrintf(height * aspect_nom / aspect_denom);
875                 scaled_height = height;
876         }
877
878         // We should be consistently larger or smaller then the existing choice,
879         // since we have the same aspect.
880         assert(!(scaled_width < *output_width && scaled_height > *output_height));
881         assert(!(scaled_height < *output_height && scaled_width > *output_width));
882
883         if (scaled_width >= *output_width && scaled_height >= *output_height) {
884                 *output_width = scaled_width;
885                 *output_height = scaled_height;
886         }
887 }
888
889 // Propagate input texture sizes throughout, and inform effects downstream.
890 // (Like a lot of other code, we depend on effects being in topological order.)
891 void EffectChain::inform_input_sizes(Phase *phase)
892 {
893         // All effects that have a defined size (inputs and RTT inputs)
894         // get that. Reset all others.
895         for (unsigned i = 0; i < phase->effects.size(); ++i) {
896                 Node *node = phase->effects[i];
897                 if (node->effect->num_inputs() == 0) {
898                         Input *input = static_cast<Input *>(node->effect);
899                         node->output_width = input->get_width();
900                         node->output_height = input->get_height();
901                         assert(node->output_width != 0);
902                         assert(node->output_height != 0);
903                 } else {
904                         node->output_width = node->output_height = 0;
905                 }
906         }
907         for (unsigned i = 0; i < phase->inputs.size(); ++i) {
908                 Phase *input = phase->inputs[i];
909                 input->output_node->output_width = input->virtual_output_width;
910                 input->output_node->output_height = input->virtual_output_height;
911                 assert(input->output_node->output_width != 0);
912                 assert(input->output_node->output_height != 0);
913         }
914
915         // Now propagate from the inputs towards the end, and inform as we go.
916         // The rules are simple:
917         //
918         //   1. Don't touch effects that already have given sizes (ie., inputs
919         //      or effects that change the output size).
920         //   2. If all of your inputs have the same size, that will be your output size.
921         //   3. Otherwise, your output size is 0x0.
922         for (unsigned i = 0; i < phase->effects.size(); ++i) {
923                 Node *node = phase->effects[i];
924                 if (node->effect->num_inputs() == 0) {
925                         continue;
926                 }
927                 unsigned this_output_width = 0;
928                 unsigned this_output_height = 0;
929                 for (unsigned j = 0; j < node->incoming_links.size(); ++j) {
930                         Node *input = node->incoming_links[j];
931                         node->effect->inform_input_size(j, input->output_width, input->output_height);
932                         if (j == 0) {
933                                 this_output_width = input->output_width;
934                                 this_output_height = input->output_height;
935                         } else if (input->output_width != this_output_width || input->output_height != this_output_height) {
936                                 // Inputs disagree.
937                                 this_output_width = 0;
938                                 this_output_height = 0;
939                         }
940                 }
941                 if (node->effect->changes_output_size()) {
942                         // We cannot call get_output_size() before we've done inform_input_size()
943                         // on all inputs.
944                         unsigned real_width, real_height;
945                         node->effect->get_output_size(&real_width, &real_height,
946                                                       &node->output_width, &node->output_height);
947                         assert(node->effect->sets_virtual_output_size() ||
948                                (real_width == node->output_width &&
949                                 real_height == node->output_height));
950                 } else {
951                         node->output_width = this_output_width;
952                         node->output_height = this_output_height;
953                 }
954         }
955 }
956
957 // Note: You should call inform_input_sizes() before this, as the last effect's
958 // desired output size might change based on the inputs.
959 void EffectChain::find_output_size(Phase *phase)
960 {
961         Node *output_node = phase->effects.back();
962
963         // If the last effect explicitly sets an output size, use that.
964         if (output_node->effect->changes_output_size()) {
965                 output_node->effect->get_output_size(&phase->output_width, &phase->output_height,
966                                                      &phase->virtual_output_width, &phase->virtual_output_height);
967                 assert(output_node->effect->sets_virtual_output_size() ||
968                        (phase->output_width == phase->virtual_output_width &&
969                         phase->output_height == phase->virtual_output_height));
970                 return;
971         }
972
973         // If all effects have the same size, use that.
974         unsigned output_width = 0, output_height = 0;
975         bool all_inputs_same_size = true;
976
977         for (unsigned i = 0; i < phase->inputs.size(); ++i) {
978                 Phase *input = phase->inputs[i];
979                 assert(input->output_width != 0);
980                 assert(input->output_height != 0);
981                 if (output_width == 0 && output_height == 0) {
982                         output_width = input->virtual_output_width;
983                         output_height = input->virtual_output_height;
984                 } else if (output_width != input->virtual_output_width ||
985                            output_height != input->virtual_output_height) {
986                         all_inputs_same_size = false;
987                 }
988         }
989         for (unsigned i = 0; i < phase->effects.size(); ++i) {
990                 Effect *effect = phase->effects[i]->effect;
991                 if (effect->num_inputs() != 0) {
992                         continue;
993                 }
994
995                 Input *input = static_cast<Input *>(effect);
996                 if (output_width == 0 && output_height == 0) {
997                         output_width = input->get_width();
998                         output_height = input->get_height();
999                 } else if (output_width != input->get_width() ||
1000                            output_height != input->get_height()) {
1001                         all_inputs_same_size = false;
1002                 }
1003         }
1004
1005         if (all_inputs_same_size) {
1006                 assert(output_width != 0);
1007                 assert(output_height != 0);
1008                 phase->virtual_output_width = phase->output_width = output_width;
1009                 phase->virtual_output_height = phase->output_height = output_height;
1010                 return;
1011         }
1012
1013         // If not, fit all the inputs into the current aspect, and select the largest one. 
1014         output_width = 0;
1015         output_height = 0;
1016         for (unsigned i = 0; i < phase->inputs.size(); ++i) {
1017                 Phase *input = phase->inputs[i];
1018                 assert(input->output_width != 0);
1019                 assert(input->output_height != 0);
1020                 size_rectangle_to_fit(input->output_width, input->output_height, &output_width, &output_height);
1021         }
1022         for (unsigned i = 0; i < phase->effects.size(); ++i) {
1023                 Effect *effect = phase->effects[i]->effect;
1024                 if (effect->num_inputs() != 0) {
1025                         continue;
1026                 }
1027
1028                 Input *input = static_cast<Input *>(effect);
1029                 size_rectangle_to_fit(input->get_width(), input->get_height(), &output_width, &output_height);
1030         }
1031         assert(output_width != 0);
1032         assert(output_height != 0);
1033         phase->virtual_output_width = phase->output_width = output_width;
1034         phase->virtual_output_height = phase->output_height = output_height;
1035 }
1036
1037 void EffectChain::sort_all_nodes_topologically()
1038 {
1039         nodes = topological_sort(nodes);
1040 }
1041
1042 vector<Node *> EffectChain::topological_sort(const vector<Node *> &nodes)
1043 {
1044         set<Node *> nodes_left_to_visit(nodes.begin(), nodes.end());
1045         vector<Node *> sorted_list;
1046         for (unsigned i = 0; i < nodes.size(); ++i) {
1047                 topological_sort_visit_node(nodes[i], &nodes_left_to_visit, &sorted_list);
1048         }
1049         reverse(sorted_list.begin(), sorted_list.end());
1050         return sorted_list;
1051 }
1052
1053 void EffectChain::topological_sort_visit_node(Node *node, set<Node *> *nodes_left_to_visit, vector<Node *> *sorted_list)
1054 {
1055         if (nodes_left_to_visit->count(node) == 0) {
1056                 return;
1057         }
1058         nodes_left_to_visit->erase(node);
1059         for (unsigned i = 0; i < node->outgoing_links.size(); ++i) {
1060                 topological_sort_visit_node(node->outgoing_links[i], nodes_left_to_visit, sorted_list);
1061         }
1062         sorted_list->push_back(node);
1063 }
1064
1065 void EffectChain::find_color_spaces_for_inputs()
1066 {
1067         for (unsigned i = 0; i < nodes.size(); ++i) {
1068                 Node *node = nodes[i];
1069                 if (node->disabled) {
1070                         continue;
1071                 }
1072                 if (node->incoming_links.size() == 0) {
1073                         Input *input = static_cast<Input *>(node->effect);
1074                         node->output_color_space = input->get_color_space();
1075                         node->output_gamma_curve = input->get_gamma_curve();
1076
1077                         Effect::AlphaHandling alpha_handling = input->alpha_handling();
1078                         switch (alpha_handling) {
1079                         case Effect::OUTPUT_BLANK_ALPHA:
1080                                 node->output_alpha_type = ALPHA_BLANK;
1081                                 break;
1082                         case Effect::INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA:
1083                                 node->output_alpha_type = ALPHA_PREMULTIPLIED;
1084                                 break;
1085                         case Effect::OUTPUT_POSTMULTIPLIED_ALPHA:
1086                                 node->output_alpha_type = ALPHA_POSTMULTIPLIED;
1087                                 break;
1088                         case Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK:
1089                         case Effect::DONT_CARE_ALPHA_TYPE:
1090                         default:
1091                                 assert(false);
1092                         }
1093
1094                         if (node->output_alpha_type == ALPHA_PREMULTIPLIED) {
1095                                 assert(node->output_gamma_curve == GAMMA_LINEAR);
1096                         }
1097                 }
1098         }
1099 }
1100
1101 // Propagate gamma and color space information as far as we can in the graph.
1102 // The rules are simple: Anything where all the inputs agree, get that as
1103 // output as well. Anything else keeps having *_INVALID.
1104 void EffectChain::propagate_gamma_and_color_space()
1105 {
1106         // We depend on going through the nodes in order.
1107         sort_all_nodes_topologically();
1108
1109         for (unsigned i = 0; i < nodes.size(); ++i) {
1110                 Node *node = nodes[i];
1111                 if (node->disabled) {
1112                         continue;
1113                 }
1114                 assert(node->incoming_links.size() == node->effect->num_inputs());
1115                 if (node->incoming_links.size() == 0) {
1116                         assert(node->output_color_space != COLORSPACE_INVALID);
1117                         assert(node->output_gamma_curve != GAMMA_INVALID);
1118                         continue;
1119                 }
1120
1121                 Colorspace color_space = node->incoming_links[0]->output_color_space;
1122                 GammaCurve gamma_curve = node->incoming_links[0]->output_gamma_curve;
1123                 for (unsigned j = 1; j < node->incoming_links.size(); ++j) {
1124                         if (node->incoming_links[j]->output_color_space != color_space) {
1125                                 color_space = COLORSPACE_INVALID;
1126                         }
1127                         if (node->incoming_links[j]->output_gamma_curve != gamma_curve) {
1128                                 gamma_curve = GAMMA_INVALID;
1129                         }
1130                 }
1131
1132                 // The conversion effects already have their outputs set correctly,
1133                 // so leave them alone.
1134                 if (node->effect->effect_type_id() != "ColorspaceConversionEffect") {
1135                         node->output_color_space = color_space;
1136                 }               
1137                 if (node->effect->effect_type_id() != "GammaCompressionEffect" &&
1138                     node->effect->effect_type_id() != "GammaExpansionEffect") {
1139                         node->output_gamma_curve = gamma_curve;
1140                 }               
1141         }
1142 }
1143
1144 // Propagate alpha information as far as we can in the graph.
1145 // Similar to propagate_gamma_and_color_space().
1146 void EffectChain::propagate_alpha()
1147 {
1148         // We depend on going through the nodes in order.
1149         sort_all_nodes_topologically();
1150
1151         for (unsigned i = 0; i < nodes.size(); ++i) {
1152                 Node *node = nodes[i];
1153                 if (node->disabled) {
1154                         continue;
1155                 }
1156                 assert(node->incoming_links.size() == node->effect->num_inputs());
1157                 if (node->incoming_links.size() == 0) {
1158                         assert(node->output_alpha_type != ALPHA_INVALID);
1159                         continue;
1160                 }
1161
1162                 // The alpha multiplication/division effects are special cases.
1163                 if (node->effect->effect_type_id() == "AlphaMultiplicationEffect") {
1164                         assert(node->incoming_links.size() == 1);
1165                         assert(node->incoming_links[0]->output_alpha_type == ALPHA_POSTMULTIPLIED);
1166                         node->output_alpha_type = ALPHA_PREMULTIPLIED;
1167                         continue;
1168                 }
1169                 if (node->effect->effect_type_id() == "AlphaDivisionEffect") {
1170                         assert(node->incoming_links.size() == 1);
1171                         assert(node->incoming_links[0]->output_alpha_type == ALPHA_PREMULTIPLIED);
1172                         node->output_alpha_type = ALPHA_POSTMULTIPLIED;
1173                         continue;
1174                 }
1175
1176                 // GammaCompressionEffect and GammaExpansionEffect are also a special case,
1177                 // because they are the only one that _need_ postmultiplied alpha.
1178                 if (node->effect->effect_type_id() == "GammaCompressionEffect" ||
1179                     node->effect->effect_type_id() == "GammaExpansionEffect") {
1180                         assert(node->incoming_links.size() == 1);
1181                         if (node->incoming_links[0]->output_alpha_type == ALPHA_BLANK) {
1182                                 node->output_alpha_type = ALPHA_BLANK;
1183                         } else if (node->incoming_links[0]->output_alpha_type == ALPHA_POSTMULTIPLIED) {
1184                                 node->output_alpha_type = ALPHA_POSTMULTIPLIED;
1185                         } else {
1186                                 node->output_alpha_type = ALPHA_INVALID;
1187                         }
1188                         continue;
1189                 }
1190
1191                 // Only inputs can have unconditional alpha output (OUTPUT_BLANK_ALPHA
1192                 // or OUTPUT_POSTMULTIPLIED_ALPHA), and they have already been
1193                 // taken care of above. Rationale: Even if you could imagine
1194                 // e.g. an effect that took in an image and set alpha=1.0
1195                 // unconditionally, it wouldn't make any sense to have it as
1196                 // e.g. OUTPUT_BLANK_ALPHA, since it wouldn't know whether it
1197                 // got its input pre- or postmultiplied, so it wouldn't know
1198                 // whether to divide away the old alpha or not.
1199                 Effect::AlphaHandling alpha_handling = node->effect->alpha_handling();
1200                 assert(alpha_handling == Effect::INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA ||
1201                        alpha_handling == Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK ||
1202                        alpha_handling == Effect::DONT_CARE_ALPHA_TYPE);
1203
1204                 // If the node has multiple inputs, check that they are all valid and
1205                 // the same.
1206                 bool any_invalid = false;
1207                 bool any_premultiplied = false;
1208                 bool any_postmultiplied = false;
1209
1210                 for (unsigned j = 0; j < node->incoming_links.size(); ++j) {
1211                         switch (node->incoming_links[j]->output_alpha_type) {
1212                         case ALPHA_INVALID:
1213                                 any_invalid = true;
1214                                 break;
1215                         case ALPHA_BLANK:
1216                                 // Blank is good as both pre- and postmultiplied alpha,
1217                                 // so just ignore it.
1218                                 break;
1219                         case ALPHA_PREMULTIPLIED:
1220                                 any_premultiplied = true;
1221                                 break;
1222                         case ALPHA_POSTMULTIPLIED:
1223                                 any_postmultiplied = true;
1224                                 break;
1225                         default:
1226                                 assert(false);
1227                         }
1228                 }
1229
1230                 if (any_invalid) {
1231                         node->output_alpha_type = ALPHA_INVALID;
1232                         continue;
1233                 }
1234
1235                 // Inputs must be of the same type.
1236                 if (any_premultiplied && any_postmultiplied) {
1237                         node->output_alpha_type = ALPHA_INVALID;
1238                         continue;
1239                 }
1240
1241                 if (alpha_handling == Effect::INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA ||
1242                     alpha_handling == Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK) {
1243                         // This combination (requiring premultiplied alpha, but _not_ requiring
1244                         // linear light) is illegal, since the combination of premultiplied alpha
1245                         // and nonlinear inputs is meaningless.
1246                         assert(node->effect->needs_linear_light());
1247
1248                         // If the effect has asked for premultiplied alpha, check that it has got it.
1249                         if (any_postmultiplied) {
1250                                 node->output_alpha_type = ALPHA_INVALID;
1251                         } else if (!any_premultiplied &&
1252                                    alpha_handling == Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK) {
1253                                 // Blank input alpha, and the effect preserves blank alpha.
1254                                 node->output_alpha_type = ALPHA_BLANK;
1255                         } else {
1256                                 node->output_alpha_type = ALPHA_PREMULTIPLIED;
1257                         }
1258                 } else {
1259                         // OK, all inputs are the same, and this effect is not going
1260                         // to change it.
1261                         assert(alpha_handling == Effect::DONT_CARE_ALPHA_TYPE);
1262                         if (any_premultiplied) {
1263                                 node->output_alpha_type = ALPHA_PREMULTIPLIED;
1264                         } else if (any_postmultiplied) {
1265                                 node->output_alpha_type = ALPHA_POSTMULTIPLIED;
1266                         } else {
1267                                 node->output_alpha_type = ALPHA_BLANK;
1268                         }
1269                 }
1270         }
1271 }
1272
1273 bool EffectChain::node_needs_colorspace_fix(Node *node)
1274 {
1275         if (node->disabled) {
1276                 return false;
1277         }
1278         if (node->effect->num_inputs() == 0) {
1279                 return false;
1280         }
1281
1282         // propagate_gamma_and_color_space() has already set our output
1283         // to COLORSPACE_INVALID if the inputs differ, so we can rely on that.
1284         if (node->output_color_space == COLORSPACE_INVALID) {
1285                 return true;
1286         }
1287         return (node->effect->needs_srgb_primaries() && node->output_color_space != COLORSPACE_sRGB);
1288 }
1289
1290 // Fix up color spaces so that there are no COLORSPACE_INVALID nodes left in
1291 // the graph. Our strategy is not always optimal, but quite simple:
1292 // Find an effect that's as early as possible where the inputs are of
1293 // unacceptable colorspaces (that is, either different, or, if the effect only
1294 // wants sRGB, not sRGB.) Add appropriate conversions on all its inputs,
1295 // propagate the information anew, and repeat until there are no more such
1296 // effects.
1297 void EffectChain::fix_internal_color_spaces()
1298 {
1299         unsigned colorspace_propagation_pass = 0;
1300         bool found_any;
1301         do {
1302                 found_any = false;
1303                 for (unsigned i = 0; i < nodes.size(); ++i) {
1304                         Node *node = nodes[i];
1305                         if (!node_needs_colorspace_fix(node)) {
1306                                 continue;
1307                         }
1308
1309                         // Go through each input that is not sRGB, and insert
1310                         // a colorspace conversion after it.
1311                         for (unsigned j = 0; j < node->incoming_links.size(); ++j) {
1312                                 Node *input = node->incoming_links[j];
1313                                 assert(input->output_color_space != COLORSPACE_INVALID);
1314                                 if (input->output_color_space == COLORSPACE_sRGB) {
1315                                         continue;
1316                                 }
1317                                 Node *conversion = add_node(new ColorspaceConversionEffect());
1318                                 CHECK(conversion->effect->set_int("source_space", input->output_color_space));
1319                                 CHECK(conversion->effect->set_int("destination_space", COLORSPACE_sRGB));
1320                                 conversion->output_color_space = COLORSPACE_sRGB;
1321                                 replace_sender(input, conversion);
1322                                 connect_nodes(input, conversion);
1323                         }
1324
1325                         // Re-sort topologically, and propagate the new information.
1326                         propagate_gamma_and_color_space();
1327                         
1328                         found_any = true;
1329                         break;
1330                 }
1331         
1332                 char filename[256];
1333                 sprintf(filename, "step5-colorspacefix-iter%u.dot", ++colorspace_propagation_pass);
1334                 output_dot(filename);
1335                 assert(colorspace_propagation_pass < 100);
1336         } while (found_any);
1337
1338         for (unsigned i = 0; i < nodes.size(); ++i) {
1339                 Node *node = nodes[i];
1340                 if (node->disabled) {
1341                         continue;
1342                 }
1343                 assert(node->output_color_space != COLORSPACE_INVALID);
1344         }
1345 }
1346
1347 bool EffectChain::node_needs_alpha_fix(Node *node)
1348 {
1349         if (node->disabled) {
1350                 return false;
1351         }
1352
1353         // propagate_alpha() has already set our output to ALPHA_INVALID if the
1354         // inputs differ or we are otherwise in mismatch, so we can rely on that.
1355         return (node->output_alpha_type == ALPHA_INVALID);
1356 }
1357
1358 // Fix up alpha so that there are no ALPHA_INVALID nodes left in
1359 // the graph. Similar to fix_internal_color_spaces().
1360 void EffectChain::fix_internal_alpha(unsigned step)
1361 {
1362         unsigned alpha_propagation_pass = 0;
1363         bool found_any;
1364         do {
1365                 found_any = false;
1366                 for (unsigned i = 0; i < nodes.size(); ++i) {
1367                         Node *node = nodes[i];
1368                         if (!node_needs_alpha_fix(node)) {
1369                                 continue;
1370                         }
1371
1372                         // If we need to fix up GammaExpansionEffect, then clearly something
1373                         // is wrong, since the combination of premultiplied alpha and nonlinear inputs
1374                         // is meaningless.
1375                         assert(node->effect->effect_type_id() != "GammaExpansionEffect");
1376
1377                         AlphaType desired_type = ALPHA_PREMULTIPLIED;
1378
1379                         // GammaCompressionEffect is special; it needs postmultiplied alpha.
1380                         if (node->effect->effect_type_id() == "GammaCompressionEffect") {
1381                                 assert(node->incoming_links.size() == 1);
1382                                 assert(node->incoming_links[0]->output_alpha_type == ALPHA_PREMULTIPLIED);
1383                                 desired_type = ALPHA_POSTMULTIPLIED;
1384                         }
1385
1386                         // Go through each input that is not premultiplied alpha, and insert
1387                         // a conversion before it.
1388                         for (unsigned j = 0; j < node->incoming_links.size(); ++j) {
1389                                 Node *input = node->incoming_links[j];
1390                                 assert(input->output_alpha_type != ALPHA_INVALID);
1391                                 if (input->output_alpha_type == desired_type ||
1392                                     input->output_alpha_type == ALPHA_BLANK) {
1393                                         continue;
1394                                 }
1395                                 Node *conversion;
1396                                 if (desired_type == ALPHA_PREMULTIPLIED) {
1397                                         conversion = add_node(new AlphaMultiplicationEffect());
1398                                 } else {
1399                                         conversion = add_node(new AlphaDivisionEffect());
1400                                 }
1401                                 conversion->output_alpha_type = desired_type;
1402                                 replace_sender(input, conversion);
1403                                 connect_nodes(input, conversion);
1404                         }
1405
1406                         // Re-sort topologically, and propagate the new information.
1407                         propagate_gamma_and_color_space();
1408                         propagate_alpha();
1409                         
1410                         found_any = true;
1411                         break;
1412                 }
1413         
1414                 char filename[256];
1415                 sprintf(filename, "step%u-alphafix-iter%u.dot", step, ++alpha_propagation_pass);
1416                 output_dot(filename);
1417                 assert(alpha_propagation_pass < 100);
1418         } while (found_any);
1419
1420         for (unsigned i = 0; i < nodes.size(); ++i) {
1421                 Node *node = nodes[i];
1422                 if (node->disabled) {
1423                         continue;
1424                 }
1425                 assert(node->output_alpha_type != ALPHA_INVALID);
1426         }
1427 }
1428
1429 // Make so that the output is in the desired color space.
1430 void EffectChain::fix_output_color_space()
1431 {
1432         Node *output = find_output_node();
1433         if (output->output_color_space != output_format.color_space) {
1434                 Node *conversion = add_node(new ColorspaceConversionEffect());
1435                 CHECK(conversion->effect->set_int("source_space", output->output_color_space));
1436                 CHECK(conversion->effect->set_int("destination_space", output_format.color_space));
1437                 conversion->output_color_space = output_format.color_space;
1438                 connect_nodes(output, conversion);
1439                 propagate_alpha();
1440                 propagate_gamma_and_color_space();
1441         }
1442 }
1443
1444 // Make so that the output is in the desired pre-/postmultiplication alpha state.
1445 void EffectChain::fix_output_alpha()
1446 {
1447         Node *output = find_output_node();
1448         assert(output->output_alpha_type != ALPHA_INVALID);
1449         if (output->output_alpha_type == ALPHA_BLANK) {
1450                 // No alpha output, so we don't care.
1451                 return;
1452         }
1453         if (output->output_alpha_type == ALPHA_PREMULTIPLIED &&
1454             output_alpha_format == OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED) {
1455                 Node *conversion = add_node(new AlphaDivisionEffect());
1456                 connect_nodes(output, conversion);
1457                 propagate_alpha();
1458                 propagate_gamma_and_color_space();
1459         }
1460         if (output->output_alpha_type == ALPHA_POSTMULTIPLIED &&
1461             output_alpha_format == OUTPUT_ALPHA_FORMAT_PREMULTIPLIED) {
1462                 Node *conversion = add_node(new AlphaMultiplicationEffect());
1463                 connect_nodes(output, conversion);
1464                 propagate_alpha();
1465                 propagate_gamma_and_color_space();
1466         }
1467 }
1468
1469 bool EffectChain::node_needs_gamma_fix(Node *node)
1470 {
1471         if (node->disabled) {
1472                 return false;
1473         }
1474
1475         // Small hack since the output is not an explicit node:
1476         // If we are the last node and our output is in the wrong
1477         // space compared to EffectChain's output, we need to fix it.
1478         // This will only take us to linear, but fix_output_gamma()
1479         // will come and take us to the desired output gamma
1480         // if it is needed.
1481         //
1482         // This needs to be before everything else, since it could
1483         // even apply to inputs (if they are the only effect).
1484         if (node->outgoing_links.empty() &&
1485             node->output_gamma_curve != output_format.gamma_curve &&
1486             node->output_gamma_curve != GAMMA_LINEAR) {
1487                 return true;
1488         }
1489
1490         if (node->effect->num_inputs() == 0) {
1491                 return false;
1492         }
1493
1494         // propagate_gamma_and_color_space() has already set our output
1495         // to GAMMA_INVALID if the inputs differ, so we can rely on that,
1496         // except for GammaCompressionEffect.
1497         if (node->output_gamma_curve == GAMMA_INVALID) {
1498                 return true;
1499         }
1500         if (node->effect->effect_type_id() == "GammaCompressionEffect") {
1501                 assert(node->incoming_links.size() == 1);
1502                 return node->incoming_links[0]->output_gamma_curve != GAMMA_LINEAR;
1503         }
1504
1505         return (node->effect->needs_linear_light() && node->output_gamma_curve != GAMMA_LINEAR);
1506 }
1507
1508 // Very similar to fix_internal_color_spaces(), but for gamma.
1509 // There is one difference, though; before we start adding conversion nodes,
1510 // we see if we can get anything out of asking the sources to deliver
1511 // linear gamma directly. fix_internal_gamma_by_asking_inputs()
1512 // does that part, while fix_internal_gamma_by_inserting_nodes()
1513 // inserts nodes as needed afterwards.
1514 void EffectChain::fix_internal_gamma_by_asking_inputs(unsigned step)
1515 {
1516         unsigned gamma_propagation_pass = 0;
1517         bool found_any;
1518         do {
1519                 found_any = false;
1520                 for (unsigned i = 0; i < nodes.size(); ++i) {
1521                         Node *node = nodes[i];
1522                         if (!node_needs_gamma_fix(node)) {
1523                                 continue;
1524                         }
1525
1526                         // See if all inputs can give us linear gamma. If not, leave it.
1527                         vector<Node *> nonlinear_inputs;
1528                         find_all_nonlinear_inputs(node, &nonlinear_inputs);
1529                         assert(!nonlinear_inputs.empty());
1530
1531                         bool all_ok = true;
1532                         for (unsigned i = 0; i < nonlinear_inputs.size(); ++i) {
1533                                 Input *input = static_cast<Input *>(nonlinear_inputs[i]->effect);
1534                                 all_ok &= input->can_output_linear_gamma();
1535                         }
1536
1537                         if (!all_ok) {
1538                                 continue;
1539                         }
1540
1541                         for (unsigned i = 0; i < nonlinear_inputs.size(); ++i) {
1542                                 CHECK(nonlinear_inputs[i]->effect->set_int("output_linear_gamma", 1));
1543                                 nonlinear_inputs[i]->output_gamma_curve = GAMMA_LINEAR;
1544                         }
1545
1546                         // Re-sort topologically, and propagate the new information.
1547                         propagate_gamma_and_color_space();
1548                         
1549                         found_any = true;
1550                         break;
1551                 }
1552         
1553                 char filename[256];
1554                 sprintf(filename, "step%u-gammafix-iter%u.dot", step, ++gamma_propagation_pass);
1555                 output_dot(filename);
1556                 assert(gamma_propagation_pass < 100);
1557         } while (found_any);
1558 }
1559
1560 void EffectChain::fix_internal_gamma_by_inserting_nodes(unsigned step)
1561 {
1562         unsigned gamma_propagation_pass = 0;
1563         bool found_any;
1564         do {
1565                 found_any = false;
1566                 for (unsigned i = 0; i < nodes.size(); ++i) {
1567                         Node *node = nodes[i];
1568                         if (!node_needs_gamma_fix(node)) {
1569                                 continue;
1570                         }
1571
1572                         // Special case: We could be an input and still be asked to
1573                         // fix our gamma; if so, we should be the only node
1574                         // (as node_needs_gamma_fix() would only return true in
1575                         // for an input in that case). That means we should insert
1576                         // a conversion node _after_ ourselves.
1577                         if (node->incoming_links.empty()) {
1578                                 assert(node->outgoing_links.empty());
1579                                 Node *conversion = add_node(new GammaExpansionEffect());
1580                                 CHECK(conversion->effect->set_int("source_curve", node->output_gamma_curve));
1581                                 conversion->output_gamma_curve = GAMMA_LINEAR;
1582                                 connect_nodes(node, conversion);
1583                         }
1584
1585                         // If not, go through each input that is not linear gamma,
1586                         // and insert a gamma conversion after it.
1587                         for (unsigned j = 0; j < node->incoming_links.size(); ++j) {
1588                                 Node *input = node->incoming_links[j];
1589                                 assert(input->output_gamma_curve != GAMMA_INVALID);
1590                                 if (input->output_gamma_curve == GAMMA_LINEAR) {
1591                                         continue;
1592                                 }
1593                                 Node *conversion = add_node(new GammaExpansionEffect());
1594                                 CHECK(conversion->effect->set_int("source_curve", input->output_gamma_curve));
1595                                 conversion->output_gamma_curve = GAMMA_LINEAR;
1596                                 replace_sender(input, conversion);
1597                                 connect_nodes(input, conversion);
1598                         }
1599
1600                         // Re-sort topologically, and propagate the new information.
1601                         propagate_alpha();
1602                         propagate_gamma_and_color_space();
1603                         
1604                         found_any = true;
1605                         break;
1606                 }
1607         
1608                 char filename[256];
1609                 sprintf(filename, "step%u-gammafix-iter%u.dot", step, ++gamma_propagation_pass);
1610                 output_dot(filename);
1611                 assert(gamma_propagation_pass < 100);
1612         } while (found_any);
1613
1614         for (unsigned i = 0; i < nodes.size(); ++i) {
1615                 Node *node = nodes[i];
1616                 if (node->disabled) {
1617                         continue;
1618                 }
1619                 assert(node->output_gamma_curve != GAMMA_INVALID);
1620         }
1621 }
1622
1623 // Make so that the output is in the desired gamma.
1624 // Note that this assumes linear input gamma, so it might create the need
1625 // for another pass of fix_internal_gamma().
1626 void EffectChain::fix_output_gamma()
1627 {
1628         Node *output = find_output_node();
1629         if (output->output_gamma_curve != output_format.gamma_curve) {
1630                 Node *conversion = add_node(new GammaCompressionEffect());
1631                 CHECK(conversion->effect->set_int("destination_curve", output_format.gamma_curve));
1632                 conversion->output_gamma_curve = output_format.gamma_curve;
1633                 connect_nodes(output, conversion);
1634         }
1635 }
1636
1637 // If the user has requested Y'CbCr output, we need to do this conversion
1638 // _after_ GammaCompressionEffect etc., but before dither (see below).
1639 // This is because Y'CbCr, with the exception of a special optional mode
1640 // in Rec. 2020 (which we currently don't support), is defined to work on
1641 // gamma-encoded data.
1642 void EffectChain::add_ycbcr_conversion_if_needed()
1643 {
1644         assert(output_color_rgba || num_output_color_ycbcr > 0);
1645         if (num_output_color_ycbcr == 0) {
1646                 return;
1647         }
1648         Node *output = find_output_node();
1649         ycbcr_conversion_effect_node = add_node(new YCbCrConversionEffect(output_ycbcr_format, output_ycbcr_type));
1650         connect_nodes(output, ycbcr_conversion_effect_node);
1651 }
1652         
1653 // If the user has requested dither, add a DitherEffect right at the end
1654 // (after GammaCompressionEffect etc.). This needs to be done after everything else,
1655 // since dither is about the only effect that can _not_ be done in linear space.
1656 void EffectChain::add_dither_if_needed()
1657 {
1658         if (num_dither_bits == 0) {
1659                 return;
1660         }
1661         Node *output = find_output_node();
1662         Node *dither = add_node(new DitherEffect());
1663         CHECK(dither->effect->set_int("num_bits", num_dither_bits));
1664         connect_nodes(output, dither);
1665
1666         dither_effect = dither->effect;
1667 }
1668
1669 // Find the output node. This is, simply, one that has no outgoing links.
1670 // If there are multiple ones, the graph is malformed (we do not support
1671 // multiple outputs right now).
1672 Node *EffectChain::find_output_node()
1673 {
1674         vector<Node *> output_nodes;
1675         for (unsigned i = 0; i < nodes.size(); ++i) {
1676                 Node *node = nodes[i];
1677                 if (node->disabled) {
1678                         continue;
1679                 }
1680                 if (node->outgoing_links.empty()) {
1681                         output_nodes.push_back(node);
1682                 }
1683         }
1684         assert(output_nodes.size() == 1);
1685         return output_nodes[0];
1686 }
1687
1688 void EffectChain::finalize()
1689 {
1690         // Output the graph as it is before we do any conversions on it.
1691         output_dot("step0-start.dot");
1692
1693         // Give each effect in turn a chance to rewrite its own part of the graph.
1694         // Note that if more effects are added as part of this, they will be
1695         // picked up as part of the same for loop, since they are added at the end.
1696         for (unsigned i = 0; i < nodes.size(); ++i) {
1697                 nodes[i]->effect->rewrite_graph(this, nodes[i]);
1698         }
1699         output_dot("step1-rewritten.dot");
1700
1701         find_color_spaces_for_inputs();
1702         output_dot("step2-input-colorspace.dot");
1703
1704         propagate_alpha();
1705         output_dot("step3-propagated-alpha.dot");
1706
1707         propagate_gamma_and_color_space();
1708         output_dot("step4-propagated-all.dot");
1709
1710         fix_internal_color_spaces();
1711         fix_internal_alpha(6);
1712         fix_output_color_space();
1713         output_dot("step7-output-colorspacefix.dot");
1714         fix_output_alpha();
1715         output_dot("step8-output-alphafix.dot");
1716
1717         // Note that we need to fix gamma after colorspace conversion,
1718         // because colorspace conversions might create needs for gamma conversions.
1719         // Also, we need to run an extra pass of fix_internal_gamma() after 
1720         // fixing the output gamma, as we only have conversions to/from linear,
1721         // and fix_internal_alpha() since GammaCompressionEffect needs
1722         // postmultiplied input.
1723         fix_internal_gamma_by_asking_inputs(9);
1724         fix_internal_gamma_by_inserting_nodes(10);
1725         fix_output_gamma();
1726         output_dot("step11-output-gammafix.dot");
1727         propagate_alpha();
1728         output_dot("step12-output-alpha-propagated.dot");
1729         fix_internal_alpha(13);
1730         output_dot("step14-output-alpha-fixed.dot");
1731         fix_internal_gamma_by_asking_inputs(15);
1732         fix_internal_gamma_by_inserting_nodes(16);
1733
1734         output_dot("step17-before-ycbcr.dot");
1735         add_ycbcr_conversion_if_needed();
1736
1737         output_dot("step18-before-dither.dot");
1738         add_dither_if_needed();
1739
1740         output_dot("step19-final.dot");
1741         
1742         // Construct all needed GLSL programs, starting at the output.
1743         // We need to keep track of which effects have already been computed,
1744         // as an effect with multiple users could otherwise be calculated
1745         // multiple times.
1746         map<Node *, Phase *> completed_effects;
1747         construct_phase(find_output_node(), &completed_effects);
1748
1749         output_dot("step20-split-to-phases.dot");
1750
1751         assert(phases[0]->inputs.empty());
1752         
1753         finalized = true;
1754 }
1755
1756 void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height)
1757 {
1758         assert(finalized);
1759
1760         // This needs to be set anew, in case we are coming from a different context
1761         // from when we initialized.
1762         check_error();
1763         glDisable(GL_DITHER);
1764         check_error();
1765
1766         const bool final_srgb = glIsEnabled(GL_FRAMEBUFFER_SRGB);
1767         check_error();
1768         bool current_srgb = final_srgb;
1769
1770         // Save original viewport.
1771         GLuint x = 0, y = 0;
1772
1773         if (width == 0 && height == 0) {
1774                 GLint viewport[4];
1775                 glGetIntegerv(GL_VIEWPORT, viewport);
1776                 x = viewport[0];
1777                 y = viewport[1];
1778                 width = viewport[2];
1779                 height = viewport[3];
1780         }
1781
1782         // Basic state.
1783         check_error();
1784         glDisable(GL_BLEND);
1785         check_error();
1786         glDisable(GL_DEPTH_TEST);
1787         check_error();
1788         glDepthMask(GL_FALSE);
1789         check_error();
1790
1791         set<Phase *> generated_mipmaps;
1792
1793         // We choose the simplest option of having one texture per output,
1794         // since otherwise this turns into an (albeit simple) register allocation problem.
1795         map<Phase *, GLuint> output_textures;
1796
1797         for (unsigned phase_num = 0; phase_num < phases.size(); ++phase_num) {
1798                 Phase *phase = phases[phase_num];
1799
1800                 if (do_phase_timing) {
1801                         GLuint timer_query_object;
1802                         if (phase->timer_query_objects_free.empty()) {
1803                                 glGenQueries(1, &timer_query_object);
1804                         } else {
1805                                 timer_query_object = phase->timer_query_objects_free.front();
1806                                 phase->timer_query_objects_free.pop_front();
1807                         }
1808                         glBeginQuery(GL_TIME_ELAPSED, timer_query_object);
1809                         phase->timer_query_objects_running.push_back(timer_query_object);
1810                 }
1811                 if (phase_num == phases.size() - 1) {
1812                         // Last phase goes to the output the user specified.
1813                         glBindFramebuffer(GL_FRAMEBUFFER, dest_fbo);
1814                         check_error();
1815                         GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1816                         assert(status == GL_FRAMEBUFFER_COMPLETE);
1817                         glViewport(x, y, width, height);
1818                         if (dither_effect != NULL) {
1819                                 CHECK(dither_effect->set_int("output_width", width));
1820                                 CHECK(dither_effect->set_int("output_height", height));
1821                         }
1822                 }
1823                 bool last_phase = (phase_num == phases.size() - 1);
1824
1825                 // Enable sRGB rendering for intermediates in case we are
1826                 // rendering to an sRGB format.
1827                 bool needs_srgb = last_phase ? final_srgb : true;
1828                 if (needs_srgb && !current_srgb) {
1829                         glEnable(GL_FRAMEBUFFER_SRGB);
1830                         check_error();
1831                         current_srgb = true;
1832                 } else if (!needs_srgb && current_srgb) {
1833                         glDisable(GL_FRAMEBUFFER_SRGB);
1834                         check_error();
1835                         current_srgb = true;
1836                 }
1837
1838                 execute_phase(phase, last_phase, &output_textures, &generated_mipmaps);
1839                 if (do_phase_timing) {
1840                         glEndQuery(GL_TIME_ELAPSED);
1841                 }
1842         }
1843
1844         for (map<Phase *, GLuint>::const_iterator texture_it = output_textures.begin();
1845              texture_it != output_textures.end();
1846              ++texture_it) {
1847                 resource_pool->release_2d_texture(texture_it->second);
1848         }
1849
1850         glBindFramebuffer(GL_FRAMEBUFFER, 0);
1851         check_error();
1852         glUseProgram(0);
1853         check_error();
1854
1855         glBindBuffer(GL_ARRAY_BUFFER, 0);
1856         check_error();
1857         glBindVertexArray(0);
1858         check_error();
1859
1860         if (do_phase_timing) {
1861                 // Get back the timer queries.
1862                 for (unsigned phase_num = 0; phase_num < phases.size(); ++phase_num) {
1863                         Phase *phase = phases[phase_num];
1864                         for (std::list<GLuint>::iterator timer_it = phase->timer_query_objects_running.begin();
1865                              timer_it != phase->timer_query_objects_running.end(); ) {
1866                                 GLint timer_query_object = *timer_it;
1867                                 GLint available;
1868                                 glGetQueryObjectiv(timer_query_object, GL_QUERY_RESULT_AVAILABLE, &available);
1869                                 if (available) {
1870                                         GLuint64 time_elapsed;
1871                                         glGetQueryObjectui64v(timer_query_object, GL_QUERY_RESULT, &time_elapsed);
1872                                         phase->time_elapsed_ns += time_elapsed;
1873                                         ++phase->num_measured_iterations;
1874                                         phase->timer_query_objects_free.push_back(timer_query_object);
1875                                         phase->timer_query_objects_running.erase(timer_it++);
1876                                 } else {
1877                                         ++timer_it;
1878                                 }
1879                         }
1880                 }
1881         }
1882 }
1883
1884 void EffectChain::enable_phase_timing(bool enable)
1885 {
1886         if (enable) {
1887                 assert(movit_timer_queries_supported);
1888         }
1889         this->do_phase_timing = enable;
1890 }
1891
1892 void EffectChain::reset_phase_timing()
1893 {
1894         for (unsigned phase_num = 0; phase_num < phases.size(); ++phase_num) {
1895                 Phase *phase = phases[phase_num];
1896                 phase->time_elapsed_ns = 0;
1897                 phase->num_measured_iterations = 0;
1898         }
1899 }
1900
1901 void EffectChain::print_phase_timing()
1902 {
1903         double total_time_ms = 0.0;
1904         for (unsigned phase_num = 0; phase_num < phases.size(); ++phase_num) {
1905                 Phase *phase = phases[phase_num];
1906                 double avg_time_ms = phase->time_elapsed_ns * 1e-6 / phase->num_measured_iterations;
1907                 printf("Phase %d: %5.1f ms  [", phase_num, avg_time_ms);
1908                 for (unsigned effect_num = 0; effect_num < phase->effects.size(); ++effect_num) {
1909                         if (effect_num != 0) {
1910                                 printf(", ");
1911                         }
1912                         printf("%s", phase->effects[effect_num]->effect->effect_type_id().c_str());
1913                 }
1914                 printf("]\n");
1915                 total_time_ms += avg_time_ms;
1916         }
1917         printf("Total:   %5.1f ms\n", total_time_ms);
1918 }
1919
1920 void EffectChain::execute_phase(Phase *phase, bool last_phase,
1921                                 map<Phase *, GLuint> *output_textures,
1922                                 set<Phase *> *generated_mipmaps)
1923 {
1924         GLuint fbo = 0;
1925
1926         // Find a texture for this phase.
1927         inform_input_sizes(phase);
1928         if (!last_phase) {
1929                 find_output_size(phase);
1930
1931                 GLuint tex_num = resource_pool->create_2d_texture(intermediate_format, phase->output_width, phase->output_height);
1932                 output_textures->insert(make_pair(phase, tex_num));
1933         }
1934
1935         // Set up RTT inputs for this phase.
1936         for (unsigned sampler = 0; sampler < phase->inputs.size(); ++sampler) {
1937                 glActiveTexture(GL_TEXTURE0 + sampler);
1938                 Phase *input = phase->inputs[sampler];
1939                 input->output_node->bound_sampler_num = sampler;
1940                 glBindTexture(GL_TEXTURE_2D, (*output_textures)[input]);
1941                 check_error();
1942                 if (phase->input_needs_mipmaps && generated_mipmaps->count(input) == 0) {
1943                         glGenerateMipmap(GL_TEXTURE_2D);
1944                         check_error();
1945                         generated_mipmaps->insert(input);
1946                 }
1947                 setup_rtt_sampler(sampler, phase->input_needs_mipmaps);
1948                 phase->input_samplers[sampler] = sampler;  // Bind the sampler to the right uniform.
1949         }
1950
1951         // And now the output. (Already set up for us if it is the last phase.)
1952         if (!last_phase) {
1953                 fbo = resource_pool->create_fbo((*output_textures)[phase]);
1954                 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1955                 glViewport(0, 0, phase->output_width, phase->output_height);
1956         }
1957
1958         GLuint instance_program_num = resource_pool->use_glsl_program(phase->glsl_program_num);
1959         check_error();
1960
1961         // Give the required parameters to all the effects.
1962         unsigned sampler_num = phase->inputs.size();
1963         for (unsigned i = 0; i < phase->effects.size(); ++i) {
1964                 Node *node = phase->effects[i];
1965                 unsigned old_sampler_num = sampler_num;
1966                 node->effect->set_gl_state(instance_program_num, phase->effect_ids[node], &sampler_num);
1967                 check_error();
1968
1969                 if (node->effect->is_single_texture()) {
1970                         assert(sampler_num - old_sampler_num == 1);
1971                         node->bound_sampler_num = old_sampler_num;
1972                 } else {
1973                         node->bound_sampler_num = -1;
1974                 }
1975         }
1976
1977         // Uniforms need to come after set_gl_state(), since they can be updated
1978         // from there.
1979         setup_uniforms(phase);
1980
1981         // Bind the vertex data.
1982         GLuint vao = resource_pool->create_vec2_vao(phase->attribute_indexes, vbo);
1983         glBindVertexArray(vao);
1984
1985         glDrawArrays(GL_TRIANGLES, 0, 3);
1986         check_error();
1987         
1988         for (unsigned i = 0; i < phase->effects.size(); ++i) {
1989                 Node *node = phase->effects[i];
1990                 node->effect->clear_gl_state();
1991         }
1992
1993         resource_pool->unuse_glsl_program(instance_program_num);
1994         resource_pool->release_vec2_vao(vao);
1995
1996         if (!last_phase) {
1997                 resource_pool->release_fbo(fbo);
1998         }
1999 }
2000
2001 void EffectChain::setup_uniforms(Phase *phase)
2002 {
2003         // TODO: Use UBO blocks.
2004         for (size_t i = 0; i < phase->uniforms_sampler2d.size(); ++i) {
2005                 const Uniform<int> &uniform = phase->uniforms_sampler2d[i];
2006                 if (uniform.location != -1) {
2007                         glUniform1iv(uniform.location, uniform.num_values, uniform.value);
2008                 }
2009         }
2010         for (size_t i = 0; i < phase->uniforms_bool.size(); ++i) {
2011                 const Uniform<bool> &uniform = phase->uniforms_bool[i];
2012                 assert(uniform.num_values == 1);
2013                 if (uniform.location != -1) {
2014                         glUniform1i(uniform.location, *uniform.value);
2015                 }
2016         }
2017         for (size_t i = 0; i < phase->uniforms_int.size(); ++i) {
2018                 const Uniform<int> &uniform = phase->uniforms_int[i];
2019                 if (uniform.location != -1) {
2020                         glUniform1iv(uniform.location, uniform.num_values, uniform.value);
2021                 }
2022         }
2023         for (size_t i = 0; i < phase->uniforms_float.size(); ++i) {
2024                 const Uniform<float> &uniform = phase->uniforms_float[i];
2025                 if (uniform.location != -1) {
2026                         glUniform1fv(uniform.location, uniform.num_values, uniform.value);
2027                 }
2028         }
2029         for (size_t i = 0; i < phase->uniforms_vec2.size(); ++i) {
2030                 const Uniform<float> &uniform = phase->uniforms_vec2[i];
2031                 if (uniform.location != -1) {
2032                         glUniform2fv(uniform.location, uniform.num_values, uniform.value);
2033                 }
2034         }
2035         for (size_t i = 0; i < phase->uniforms_vec3.size(); ++i) {
2036                 const Uniform<float> &uniform = phase->uniforms_vec3[i];
2037                 if (uniform.location != -1) {
2038                         glUniform3fv(uniform.location, uniform.num_values, uniform.value);
2039                 }
2040         }
2041         for (size_t i = 0; i < phase->uniforms_vec4.size(); ++i) {
2042                 const Uniform<float> &uniform = phase->uniforms_vec4[i];
2043                 if (uniform.location != -1) {
2044                         glUniform4fv(uniform.location, uniform.num_values, uniform.value);
2045                 }
2046         }
2047         for (size_t i = 0; i < phase->uniforms_mat3.size(); ++i) {
2048                 const Uniform<Matrix3d> &uniform = phase->uniforms_mat3[i];
2049                 assert(uniform.num_values == 1);
2050                 if (uniform.location != -1) {
2051                         // Convert to float (GLSL has no double matrices).
2052                         float matrixf[9];
2053                         for (unsigned y = 0; y < 3; ++y) {
2054                                 for (unsigned x = 0; x < 3; ++x) {
2055                                         matrixf[y + x * 3] = (*uniform.value)(y, x);
2056                                 }
2057                         }
2058                         glUniformMatrix3fv(uniform.location, 1, GL_FALSE, matrixf);
2059                 }
2060         }
2061 }
2062
2063 void EffectChain::setup_rtt_sampler(int sampler_num, bool use_mipmaps)
2064 {
2065         glActiveTexture(GL_TEXTURE0 + sampler_num);
2066         check_error();
2067         if (use_mipmaps) {
2068                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
2069                 check_error();
2070         } else {
2071                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2072                 check_error();
2073         }
2074         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2075         check_error();
2076         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2077         check_error();
2078 }
2079
2080 }  // namespace movit