summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
e0811dd)
Evidently ATI drivers use the freedom the standard gives them to assign
these in another order than they are specified in the shader source,
so we need to explicitly bind them, or YCbCrConversionEffectTest will fail
in the multi-output tests.
Originally reported by Iwan Gabovitch.
frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
// If we're the last phase, add the right #defines for Y'CbCr multi-output as needed.
frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
// If we're the last phase, add the right #defines for Y'CbCr multi-output as needed.
+ vector<string> frag_shader_outputs; // In order.
if (phase->output_node->outgoing_links.empty() && output_color_ycbcr) {
switch (output_ycbcr_splitting) {
case YCBCR_OUTPUT_INTERLEAVED:
// No #defines set.
if (phase->output_node->outgoing_links.empty() && output_color_ycbcr) {
switch (output_ycbcr_splitting) {
case YCBCR_OUTPUT_INTERLEAVED:
// No #defines set.
+ frag_shader_outputs.push_back("FragColor");
break;
case YCBCR_OUTPUT_SPLIT_Y_AND_CBCR:
frag_shader += "#define YCBCR_OUTPUT_SPLIT_Y_AND_CBCR 1\n";
break;
case YCBCR_OUTPUT_SPLIT_Y_AND_CBCR:
frag_shader += "#define YCBCR_OUTPUT_SPLIT_Y_AND_CBCR 1\n";
+ frag_shader_outputs.push_back("Y");
+ frag_shader_outputs.push_back("Chroma");
break;
case YCBCR_OUTPUT_PLANAR:
frag_shader += "#define YCBCR_OUTPUT_PLANAR 1\n";
break;
case YCBCR_OUTPUT_PLANAR:
frag_shader += "#define YCBCR_OUTPUT_PLANAR 1\n";
+ frag_shader_outputs.push_back("Y");
+ frag_shader_outputs.push_back("Cb");
+ frag_shader_outputs.push_back("Cr");
break;
default:
assert(false);
break;
default:
assert(false);
// output needs to see it (YCbCrConversionEffect and DitherEffect
// do, too).
frag_shader_header += "#define YCBCR_ALSO_OUTPUT_RGBA 1\n";
// output needs to see it (YCbCrConversionEffect and DitherEffect
// do, too).
frag_shader_header += "#define YCBCR_ALSO_OUTPUT_RGBA 1\n";
+ frag_shader_outputs.push_back("RGBA");
}
}
frag_shader.append(read_file("footer.frag"));
}
}
frag_shader.append(read_file("footer.frag"));
vert_shader[pos + needle.size() - 1] = '1';
}
vert_shader[pos + needle.size() - 1] = '1';
}
- phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader);
+ phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader, frag_shader_outputs);
// Collect the resulting location numbers for each uniform.
collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_sampler2d);
// Collect the resulting location numbers for each uniform.
collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_sampler2d);
glViewport(0, 0, width, 1);
glViewport(0, 0, width, 1);
+ vector<string> frag_shader_outputs;
GLuint glsl_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs", "vert"),
GLuint glsl_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs", "vert"),
- read_version_dependent_file("texture1d", "frag"));
+ read_version_dependent_file("texture1d", "frag"),
+ frag_shader_outputs);
glUseProgram(glsl_program_num);
check_error();
glUniform1i(glGetUniformLocation(glsl_program_num, "tex"), 0); // Bind the 2D sampler.
glUseProgram(glsl_program_num);
check_error();
glUniform1i(glGetUniformLocation(glsl_program_num, "tex"), 0); // Bind the 2D sampler.
glViewport(0, 0, 512, 1);
glViewport(0, 0, 512, 1);
+ vector<string> frag_shader_outputs;
GLuint glsl_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs", "vert"),
GLuint glsl_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs", "vert"),
- read_version_dependent_file("texture1d", "frag"));
+ read_version_dependent_file("texture1d", "frag"),
+ frag_shader_outputs);
glUseProgram(glsl_program_num);
check_error();
glUniform1i(glGetUniformLocation(glsl_program_num, "tex"), 0); // Bind the 2D sampler.
glUseProgram(glsl_program_num);
check_error();
glUniform1i(glGetUniformLocation(glsl_program_num, "tex"), 0); // Bind the 2D sampler.
program_shaders.erase(shader_it);
}
program_shaders.erase(shader_it);
}
-GLuint ResourcePool::compile_glsl_program(const string& vertex_shader, const string& fragment_shader)
+GLuint ResourcePool::compile_glsl_program(const string& vertex_shader,
+ const string& fragment_shader,
+ const vector<string>& fragment_shader_outputs)
{
GLuint glsl_program_num;
pthread_mutex_lock(&lock);
{
GLuint glsl_program_num;
pthread_mutex_lock(&lock);
- const pair<string, string> key(vertex_shader, fragment_shader);
+
+ // Augment the fragment shader program text with the outputs, so that they become
+ // part of the key. Also potentially useful for debugging.
+ string fragment_shader_processed = fragment_shader;
+ for (unsigned output_index = 0; output_index < fragment_shader_outputs.size(); ++output_index) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "// Bound output: %s\n", fragment_shader_outputs[output_index].c_str());
+ fragment_shader_processed += buf;
+ }
+
+ const pair<string, string> key(vertex_shader, fragment_shader_processed);
if (programs.count(key)) {
// Already in the cache. Increment the refcount, or take it off the freelist
// if it's zero.
if (programs.count(key)) {
// Already in the cache. Increment the refcount, or take it off the freelist
// if it's zero.
check_error();
GLuint vs_obj = compile_shader(vertex_shader, GL_VERTEX_SHADER);
check_error();
check_error();
GLuint vs_obj = compile_shader(vertex_shader, GL_VERTEX_SHADER);
check_error();
- GLuint fs_obj = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
+ GLuint fs_obj = compile_shader(fragment_shader_processed, GL_FRAGMENT_SHADER);
check_error();
glAttachShader(glsl_program_num, vs_obj);
check_error();
glAttachShader(glsl_program_num, fs_obj);
check_error();
check_error();
glAttachShader(glsl_program_num, vs_obj);
check_error();
glAttachShader(glsl_program_num, fs_obj);
check_error();
+
+ // Bind the outputs, if we have multiple ones.
+ if (fragment_shader_outputs.size() > 1) {
+ for (unsigned output_index = 0; output_index < fragment_shader_outputs.size(); ++output_index) {
+ glBindFragDataLocation(glsl_program_num, output_index,
+ fragment_shader_outputs[output_index].c_str());
+ }
+ }
+
glLinkProgram(glsl_program_num);
check_error();
glLinkProgram(glsl_program_num);
check_error();
perror(filename);
exit(1);
}
perror(filename);
exit(1);
}
- fprintf(fp, "%s\n", fragment_shader.c_str());
+ fprintf(fp, "%s\n", fragment_shader_processed.c_str());
#include <map>
#include <string>
#include <utility>
#include <map>
#include <string>
#include <utility>
// compiled program from the cache if possible. Keeps ownership of the
// program; you must call release_glsl_program() instead of deleting it
// when you no longer want it.
// compiled program from the cache if possible. Keeps ownership of the
// program; you must call release_glsl_program() instead of deleting it
// when you no longer want it.
- GLuint compile_glsl_program(const std::string& vertex_shader, const std::string& fragment_shader);
+ //
+ // If <fragment_shader_outputs> contains more than one value, the given
+ // outputs will be bound to fragment shader output colors in the order
+ // they appear in the vector. Otherwise, output order is undefined and
+ // determined by the OpenGL driver.
+ GLuint compile_glsl_program(const std::string& vertex_shader,
+ const std::string& fragment_shader,
+ const std::vector<std::string>& frag_shader_outputs);
void release_glsl_program(GLuint glsl_program_num);
// Allocate a 2D texture of the given internal format and dimensions,
void release_glsl_program(GLuint glsl_program_num);
// Allocate a 2D texture of the given internal format and dimensions,
// changes, even within git versions. There is no specific version
// documentation outside the regular changelogs, though.
// changes, even within git versions. There is no specific version
// documentation outside the regular changelogs, though.
-#define MOVIT_VERSION 14
+#define MOVIT_VERSION 15
#endif // !defined(_MOVIT_VERSION_H)
#endif // !defined(_MOVIT_VERSION_H)
#include <epoxy/gl.h>
#include <math.h>
#include <epoxy/gl.h>
#include <math.h>
+#include <string>
+#include <vector>
+
#include "resource_pool.h"
#include "widgets.h"
#include "util.h"
#define HSV_WHEEL_SIZE 128
#include "resource_pool.h"
#include "widgets.h"
#include "util.h"
#define HSV_WHEEL_SIZE 128
namespace movit {
GLuint hsv_wheel_texnum = 0;
namespace movit {
GLuint hsv_wheel_texnum = 0;
void init_hsv_resources()
{
void init_hsv_resources()
{
+ vector<string> frag_shader_outputs;
textured_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs", "vert"),
textured_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs", "vert"),
- read_version_dependent_file("texture1d", "frag"));
+ read_version_dependent_file("texture1d", "frag"),
+ frag_shader_outputs);
colored_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs-color", "vert"),
colored_program_num = resource_pool.compile_glsl_program(
read_version_dependent_file("vs-color", "vert"),
- read_version_dependent_file("color", "frag"));
+ read_version_dependent_file("color", "frag"),
+ frag_shader_outputs);
make_hsv_wheel_texture();
}
make_hsv_wheel_texture();
}