#define GL_GLEXT_PROTOTYPES 1
-#include <GL/glew.h>
+#include <epoxy/gl.h>
#include <assert.h>
-#include <locale.h>
#include <math.h>
#include <stddef.h>
#include <stdio.h>
node->output_color_space = COLORSPACE_INVALID;
node->output_gamma_curve = GAMMA_INVALID;
node->output_alpha_type = ALPHA_INVALID;
+ node->needs_mipmaps = false;
nodes.push_back(node);
node_map[effect] = node;
void EffectChain::compile_glsl_program(Phase *phase)
{
- string frag_shader = read_file("header.frag");
+ string frag_shader = read_version_dependent_file("header", "frag");
// Create functions for all the texture inputs that we need.
for (unsigned i = 0; i < phase->inputs.size(); ++i) {
frag_shader += string("uniform sampler2D tex_") + effect_id + ";\n";
frag_shader += string("vec4 ") + effect_id + "(vec2 tc) {\n";
- frag_shader += "\treturn texture2D(tex_" + string(effect_id) + ", tc);\n";
+ frag_shader += "\treturn tex2D(tex_" + string(effect_id) + ", tc);\n";
frag_shader += "}\n";
frag_shader += "\n";
}
frag_shader += "\n";
}
frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
- frag_shader.append(read_file("footer.frag"));
+ frag_shader.append(read_version_dependent_file("footer", "frag"));
- phase->glsl_program_num = resource_pool->compile_glsl_program(read_file("vs.vert"), frag_shader);
+ string vert_shader = read_version_dependent_file("vs", "vert");
+ phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader);
}
// Construct GLSL programs, starting at the given effect and following
Node *node = effects_todo_this_phase.top();
effects_todo_this_phase.pop();
+ if (node->effect->needs_mipmaps()) {
+ node->needs_mipmaps = true;
+ }
+
// This should currently only happen for effects that are inputs
// (either true inputs or phase outputs). We special-case inputs,
// and then deduplicate phase outputs below.
start_new_phase = true;
}
+ // Propagate information about needing mipmaps down the chain,
+ // breaking the phase if we notice an incompatibility.
+ //
+ // Note that we cannot do this propagation as a normal pass,
+ // because it needs information about where the phases end
+ // (we should not propagate the flag across phases).
+ if (node->needs_mipmaps) {
+ if (deps[i]->effect->num_inputs() == 0) {
+ Input *input = static_cast<Input *>(deps[i]->effect);
+ start_new_phase |= !input->can_supply_mipmaps();
+ } else {
+ deps[i]->needs_mipmaps = true;
+ }
+ }
+
if (deps[i]->outgoing_links.size() > 1) {
if (!deps[i]->effect->is_single_texture()) {
// More than one effect uses this as the input,
for (unsigned i = 0; i < phase->effects.size(); ++i) {
Node *node = phase->effects[i];
if (node->effect->num_inputs() == 0) {
- CHECK(node->effect->set_int("needs_mipmaps", phase->input_needs_mipmaps));
+ Input *input = static_cast<Input *>(node->effect);
+ assert(!phase->input_needs_mipmaps || input->can_supply_mipmaps());
+ CHECK(input->set_int("needs_mipmaps", phase->input_needs_mipmaps));
}
}
void EffectChain::finalize()
{
- // Save the current locale, and set it to C, so that we can output decimal
- // numbers with printf and be sure to get them in the format mandated by GLSL.
- char *saved_locale = setlocale(LC_NUMERIC, "C");
-
// Output the graph as it is before we do any conversions on it.
output_dot("step0-start.dot");
assert(phases[0]->inputs.empty());
finalized = true;
- setlocale(LC_NUMERIC, saved_locale);
}
void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height)