#include "mirror_effect.h"
#include "multiply_effect.h"
#include "resize_effect.h"
+#include "resource_pool.h"
#include "test_util.h"
#include "util.h"
template<class T>
class RewritingEffect : public Effect {
public:
- RewritingEffect() : effect(new T()), replaced_node(NULL) {}
+ RewritingEffect() : effect(new T()), replaced_node(nullptr) {}
virtual string effect_type_id() const { return "RewritingEffect[" + effect->effect_type_id() + "]"; }
string output_fragment_shader() { EXPECT_TRUE(false); return read_file("identity.frag"); }
virtual void rewrite_graph(EffectChain *graph, Node *self) {
0.0000f, 0.0000f, 0.0000f, 1.0000f
};
float out_data[4 * 4];
- EffectChainTester tester(NULL, 1, 4);
+ EffectChainTester tester(nullptr, 1, 4);
tester.add_input(data, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_sRGB);
RewritingEffect<InvertEffect> *effect = new RewritingEffect<InvertEffect>();
tester.get_chain()->add_effect(effect);
};
float out_data[size];
- EffectChainTester tester(NULL, 4, 1, FORMAT_GRAYSCALE);
+ EffectChainTester tester(nullptr, 4, 1, FORMAT_GRAYSCALE);
// First say that we have sRGB, linear input.
ImageFormat format;
expected_data[i] = i / 255.0;
};
float out_data[256];
- EffectChainTester tester(NULL, 256, 1);
+ EffectChainTester tester(nullptr, 256, 1);
tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
tester.get_chain()->add_effect(new IdentityEffect());
tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
// which outputs blank alpha.
class RewritingToBlueInput : public Input {
public:
- RewritingToBlueInput() : blue_node(NULL) { register_int("needs_mipmaps", &needs_mipmaps); }
+ RewritingToBlueInput() : blue_node(nullptr) { register_int("needs_mipmaps", &needs_mipmaps); }
virtual string effect_type_id() const { return "RewritingToBlueInput"; }
string output_fragment_shader() { EXPECT_TRUE(false); return read_file("identity.frag"); }
virtual void rewrite_graph(EffectChain *graph, Node *self) {
0.0f, 0.0f, 1.0f, 1.0f,
};
float out_data[4 * size];
- EffectChainTester tester(NULL, size, 1);
+ EffectChainTester tester(nullptr, size, 1);
RewritingToBlueInput *input = new RewritingToBlueInput();
tester.get_chain()->add_input(input);
tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
0.0f, 0.0f, 1.0f, 1.0f,
};
float out_data[4 * size];
- EffectChainTester tester(NULL, size, 1);
+ EffectChainTester tester(nullptr, size, 1);
tester.get_chain()->add_input(new BlueInput());
tester.get_chain()->add_effect(new BlankAlphaPreservingEffect());
RewritingEffect<MirrorEffect> *effect = new RewritingEffect<MirrorEffect>();
0.0f, 0.0f, 1.0f, 1.0f,
};
float out_data[4 * size];
- EffectChainTester tester(NULL, size, 1);
+ EffectChainTester tester(nullptr, size, 1);
tester.get_chain()->add_input(new BlueInput());
tester.get_chain()->add_effect(new IdentityEffect()); // Not BlankAlphaPreservingEffect.
RewritingEffect<MirrorEffect> *effect = new RewritingEffect<MirrorEffect>();
0.25f, 0.25f, 0.25f, 0.25f,
};
float out_data[4 * 16];
- EffectChainTester tester(NULL, 4, 16, FORMAT_GRAYSCALE);
+ EffectChainTester tester(nullptr, 4, 16, FORMAT_GRAYSCALE);
ImageFormat format;
format.color_space = COLORSPACE_sRGB;
MultiplyEffect *mul_two = new MultiplyEffect();
ASSERT_TRUE(mul_two->set_vec4("factor", two));
- EffectChainTester tester(NULL, 2, 2);
+ EffectChainTester tester(nullptr, 2, 2);
ImageFormat format;
format.color_space = COLORSPACE_sRGB;
BouncingIdentityEffect *bounce = new BouncingIdentityEffect();
- EffectChainTester tester(NULL, 2, 2);
+ EffectChainTester tester(nullptr, 2, 2);
ImageFormat format;
format.color_space = COLORSPACE_sRGB;
};
float out_data[2 * 2];
- EffectChainTester tester(NULL, 2, 2);
+ EffectChainTester tester(nullptr, 2, 2);
tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
// MirrorEffect does not get linear light, so the conversions will be
};
float out_data[2 * 2];
- EffectChainTester tester(NULL, 2, 2);
+ EffectChainTester tester(nullptr, 2, 2);
tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_REC_601_625, GAMMA_LINEAR);
// MirrorEffect does not get linear light, so the conversions will be
};
float out_data[4 * 3];
- EffectChainTester tester(NULL, 4, 3); // Note non-square aspect.
+ EffectChainTester tester(nullptr, 4, 3); // Note non-square aspect.
ImageFormat format;
format.color_space = COLORSPACE_sRGB;
// (keep the height, round the width 9.333 to 9).
float out_data[9 * 7];
- EffectChainTester tester(NULL, 4, 3);
+ EffectChainTester tester(nullptr, 4, 3);
ImageFormat format;
format.color_space = COLORSPACE_sRGB;
FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, 1, size);
input->set_pixel_data(data);
- EffectChainTester tester(NULL, 1, size);
+ EffectChainTester tester(nullptr, 1, size);
tester.get_chain()->add_input(new BlueInput());
Effect *phase1_end = tester.get_chain()->add_effect(new BouncingIdentityEffect());
tester.get_chain()->add_input(input);
check_error();
glBindTexture(GL_TEXTURE_2D, texnum);
check_error();
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
check_error();
glGenFramebuffers(1, &fbo);
// setlocale() behind-the-scenes, and that might corrupt the returned
// pointer, so we need to take our own copy of it here.
char *saved_locale = setlocale(LC_ALL, "nb_NO.UTF_8");
- if (saved_locale == NULL) {
+ if (saved_locale == nullptr) {
// The locale wasn't available.
return;
}
<< "Expected sRGB not to be able to represent 0.5 exactly (got " << out_data[1] << ")";
EXPECT_LT(fabs(out_data[1] - data[1]), 0.1f)
<< "Expected sRGB to be able to represent 0.5 approximately (got " << out_data[1] << ")";
+
+ // This state should have been preserved.
+ EXPECT_FALSE(glIsEnabled(GL_FRAMEBUFFER_SRGB));
}
// An effect that is like IdentityEffect, but also does not require linear light.
}
// This maximum error is pretty bad; about 6.5 levels of a 10-bit sRGB
- // framebuffer.
- expect_equal(linear_data, out_data, size, 1, 7e-3, 2e-5);
+ // framebuffer. (Slightly more on NVIDIA cards.)
+ expect_equal(linear_data, out_data, size, 1, 7.5e-3, 2e-5);
}
TEST(EffectChainTest, SquareRoot10bitIntermediateAccuracy) {
// This maximum error is much better; about 0.7 levels of a 10-bit sRGB
// framebuffer (ideal would be 0.5). That is an order of magnitude better
// than in the linear test above. The RMS error is much better, too.
- expect_equal(linear_data, out_data, size, 1, 7e-4, 5e-6);
+ expect_equal(linear_data, out_data, size, 1, 7.5e-4, 5e-6);
}
TEST(EffectChainTest, SquareRootIntermediateIsTurnedOffForNonLinearData) {
expect_equal(data, out_data, size, 1, 1e-6, 1e-6);
}
+// An effect that stores which program number was last run under.
+class RecordingIdentityEffect : public Effect {
+public:
+ RecordingIdentityEffect() {}
+ virtual string effect_type_id() const { return "RecordingIdentityEffect"; }
+ string output_fragment_shader() { return read_file("identity.frag"); }
+
+ GLuint last_glsl_program_num;
+ void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
+ {
+ last_glsl_program_num = glsl_program_num;
+ }
+};
+
+TEST(EffectChainTest, ProgramsAreClonedForMultipleThreads) {
+ float data[] = {
+ 0.0f, 0.25f, 0.3f,
+ 0.75f, 1.0f, 1.0f,
+ };
+ float out_data[6];
+ EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+ RecordingIdentityEffect *effect = new RecordingIdentityEffect();
+ tester.get_chain()->add_effect(effect);
+ tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+
+ expect_equal(data, out_data, 3, 2);
+
+ ASSERT_NE(0, effect->last_glsl_program_num);
+
+ // Now pretend some other effect is using this program number;
+ // ResourcePool will then need to clone it.
+ ResourcePool *resource_pool = tester.get_chain()->get_resource_pool();
+ GLuint master_program_num = resource_pool->use_glsl_program(effect->last_glsl_program_num);
+ EXPECT_EQ(effect->last_glsl_program_num, master_program_num);
+
+ // Re-run should still give the correct data, but it should have run
+ // with a different program.
+ tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+ expect_equal(data, out_data, 3, 2);
+ EXPECT_NE(effect->last_glsl_program_num, master_program_num);
+
+ // Release the program, and check one final time.
+ resource_pool->unuse_glsl_program(master_program_num);
+ tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+ expect_equal(data, out_data, 3, 2);
+}
+
} // namespace movit