expect_equal(expected_data, out_data, 3, 2);
}
+// A dummy effect that inverts its input.
+class InvertEffect : public Effect {
+public:
+ InvertEffect() {}
+ virtual std::string effect_type_id() const { return "InvertEffect"; }
+ std::string output_fragment_shader() { return read_file("invert_effect.frag"); }
+};
+
+// Like IdentityEffect, but rewrites itself out of the loop,
+// splicing in a InvertEffect instead. Also stores the new node,
+// so we later can check that there are gamma conversion effects
+// on both sides.
+class RewritingToInvertEffect : public Effect {
+public:
+ RewritingToInvertEffect() {}
+ virtual std::string effect_type_id() const { return "RewritingToInvertEffect"; }
+ std::string output_fragment_shader() { EXPECT_TRUE(false); return read_file("identity.frag"); }
+ virtual void rewrite_graph(EffectChain *graph, Node *self) {
+ Node *invert_node = graph->add_node(new InvertEffect());
+ graph->replace_receiver(self, invert_node);
+ graph->replace_sender(self, invert_node);
+
+ self->disabled = true;
+ this->invert_node = invert_node;
+ }
+
+ Node *invert_node;
+};
+
+TEST(EffectChainTest, RewritingWorksAndGammaConversionsAreInserted) {
+ float data[] = {
+ 0.0f, 0.25f, 0.3f,
+ 0.75f, 1.0f, 1.0f,
+ };
+ float expected_data[6] = {
+ 1.0f, 0.9771f, 0.9673f,
+ 0.7192f, 0.0f, 0.0f,
+ };
+ float out_data[6];
+ EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
+ RewritingToInvertEffect *effect = new RewritingToInvertEffect();
+ tester.get_chain()->add_effect(effect);
+ tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
+
+ Node *node = effect->invert_node;
+ ASSERT_EQ(1, node->incoming_links.size());
+ ASSERT_EQ(1, node->outgoing_links.size());
+ EXPECT_EQ("GammaExpansionEffect", node->incoming_links[0]->effect->effect_type_id());
+ EXPECT_EQ("GammaCompressionEffect", node->outgoing_links[0]->effect->effect_type_id());
+
+ expect_equal(expected_data, out_data, 3, 2);
+}
+
+// Like RewritingToInvertEffect, but splicing in a MirrorEffect instead,
+// which does not need linear light.
+class RewritingToMirrorEffect : public Effect {
+public:
+ RewritingToMirrorEffect() {}
+ virtual std::string effect_type_id() const { return "RewritingToMirrorEffect"; }
+ std::string output_fragment_shader() { EXPECT_TRUE(false); return read_file("identity.frag"); }
+ virtual void rewrite_graph(EffectChain *graph, Node *self) {
+ Node *mirror_node = graph->add_node(new MirrorEffect());
+ graph->replace_receiver(self, mirror_node);
+ graph->replace_sender(self, mirror_node);
+
+ self->disabled = true;
+ this->mirror_node = mirror_node;
+ }
+
+ Node *mirror_node;
+};
+
+TEST(EffectChainTest, NoGammaConversionsWhenLinearLightNotNeeded) {
+ float data[] = {
+ 0.0f, 0.25f, 0.3f,
+ 0.75f, 1.0f, 1.0f,
+ };
+ float expected_data[6] = {
+ 0.3f, 0.25f, 0.0f,
+ 1.0f, 1.0f, 0.75f,
+ };
+ float out_data[6];
+ EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
+ RewritingToMirrorEffect *effect = new RewritingToMirrorEffect();
+ tester.get_chain()->add_effect(effect);
+ tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
+
+ Node *node = effect->mirror_node;
+ ASSERT_EQ(1, node->incoming_links.size());
+ EXPECT_EQ(0, node->outgoing_links.size());
+ EXPECT_EQ("FlatInput", node->incoming_links[0]->effect->effect_type_id());
+
+ expect_equal(expected_data, out_data, 3, 2);
+}
+
// The identity effect needs linear light, and thus will get conversions on both sides.
// Verify that sRGB data is properly converted to and from linear light for the entire ramp.
TEST(EffectChainTest, IdentityThroughsRGBConversions) {