1 // Unit tests for EffectChain.
3 // Note that this also contains the tests for some of the simpler effects.
7 #include "effect_chain.h"
8 #include "flat_input.h"
9 #include "gtest/gtest.h"
10 #include "mirror_effect.h"
11 #include "resize_effect.h"
12 #include "test_util.h"
14 TEST(EffectChainTest, EmptyChain) {
20 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
21 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
23 expect_equal(data, out_data, 3, 2);
26 // An effect that does nothing.
27 class IdentityEffect : public Effect {
30 virtual std::string effect_type_id() const { return "IdentityEffect"; }
31 std::string output_fragment_shader() { return read_file("identity.frag"); }
34 TEST(EffectChainTest, Identity) {
40 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
41 tester.get_chain()->add_effect(new IdentityEffect());
42 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
44 expect_equal(data, out_data, 3, 2);
47 // An effect that does nothing, but requests texture bounce.
48 class BouncingIdentityEffect : public Effect {
50 BouncingIdentityEffect() {}
51 virtual std::string effect_type_id() const { return "IdentityEffect"; }
52 std::string output_fragment_shader() { return read_file("identity.frag"); }
53 bool needs_texture_bounce() const { return true; }
54 AlphaHandling alpha_handling() const { return DONT_CARE_ALPHA_TYPE; }
57 TEST(EffectChainTest, TextureBouncePreservesIdentity) {
63 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
64 tester.get_chain()->add_effect(new BouncingIdentityEffect());
65 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
67 expect_equal(data, out_data, 3, 2);
70 TEST(MirrorTest, BasicTest) {
75 float expected_data[6] = {
80 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
81 tester.get_chain()->add_effect(new MirrorEffect());
82 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
84 expect_equal(expected_data, out_data, 3, 2);
87 // A dummy effect that inverts its input.
88 class InvertEffect : public Effect {
91 virtual std::string effect_type_id() const { return "InvertEffect"; }
92 std::string output_fragment_shader() { return read_file("invert_effect.frag"); }
94 // A real invert would actually care about its alpha,
95 // but in this unit test, it only complicates things.
96 virtual AlphaHandling alpha_handling() const { return DONT_CARE_ALPHA_TYPE; }
99 // Like IdentityEffect, but rewrites itself out of the loop,
100 // splicing in a different effect instead. Also stores the new node,
101 // so we later can check whatever properties we'd like about the graph.
103 class RewritingEffect : public Effect {
105 RewritingEffect() : effect(new T()) {}
106 virtual std::string effect_type_id() const { return "RewritingEffect[" + effect->effect_type_id() + "]"; }
107 std::string output_fragment_shader() { EXPECT_TRUE(false); return read_file("identity.frag"); }
108 virtual void rewrite_graph(EffectChain *graph, Node *self) {
109 replaced_node = graph->add_node(effect);
110 graph->replace_receiver(self, replaced_node);
111 graph->replace_sender(self, replaced_node);
112 self->disabled = true;
119 TEST(EffectChainTest, RewritingWorksAndGammaConversionsAreInserted) {
124 float expected_data[6] = {
125 1.0f, 0.9771f, 0.9673f,
129 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
130 RewritingEffect<InvertEffect> *effect = new RewritingEffect<InvertEffect>();
131 tester.get_chain()->add_effect(effect);
132 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
134 Node *node = effect->replaced_node;
135 ASSERT_EQ(1, node->incoming_links.size());
136 ASSERT_EQ(1, node->outgoing_links.size());
137 EXPECT_EQ("GammaExpansionEffect", node->incoming_links[0]->effect->effect_type_id());
138 EXPECT_EQ("GammaCompressionEffect", node->outgoing_links[0]->effect->effect_type_id());
140 expect_equal(expected_data, out_data, 3, 2);
143 TEST(EffectChainTest, RewritingWorksAndTexturesAreAskedForsRGB) {
144 unsigned char data[] = {
148 float expected_data[4] = {
153 EffectChainTester tester(NULL, 2, 2);
154 tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
155 RewritingEffect<InvertEffect> *effect = new RewritingEffect<InvertEffect>();
156 tester.get_chain()->add_effect(effect);
157 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
159 Node *node = effect->replaced_node;
160 ASSERT_EQ(1, node->incoming_links.size());
161 ASSERT_EQ(1, node->outgoing_links.size());
162 EXPECT_EQ("FlatInput", node->incoming_links[0]->effect->effect_type_id());
163 EXPECT_EQ("GammaCompressionEffect", node->outgoing_links[0]->effect->effect_type_id());
165 expect_equal(expected_data, out_data, 2, 2);
168 TEST(EffectChainTest, RewritingWorksAndColorspaceConversionsAreInserted) {
173 float expected_data[6] = {
178 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_REC_601_525, GAMMA_LINEAR);
179 RewritingEffect<InvertEffect> *effect = new RewritingEffect<InvertEffect>();
180 tester.get_chain()->add_effect(effect);
181 tester.run(out_data, GL_RED, COLORSPACE_REC_601_525, GAMMA_LINEAR);
183 Node *node = effect->replaced_node;
184 ASSERT_EQ(1, node->incoming_links.size());
185 ASSERT_EQ(1, node->outgoing_links.size());
186 EXPECT_EQ("ColorspaceConversionEffect", node->incoming_links[0]->effect->effect_type_id());
187 EXPECT_EQ("ColorspaceConversionEffect", node->outgoing_links[0]->effect->effect_type_id());
189 expect_equal(expected_data, out_data, 3, 2);
192 // A fake input that can change its output colorspace and gamma between instantiation
194 class UnknownColorspaceInput : public FlatInput {
196 UnknownColorspaceInput(ImageFormat format, MovitPixelFormat pixel_format, GLenum type, unsigned width, unsigned height)
197 : FlatInput(format, pixel_format, type, width, height),
198 overridden_color_space(format.color_space),
199 overridden_gamma_curve(format.gamma_curve) {}
200 virtual std::string effect_type_id() const { return "UnknownColorspaceInput"; }
202 void set_color_space(Colorspace colorspace) {
203 overridden_color_space = colorspace;
205 void set_gamma_curve(GammaCurve gamma_curve) {
206 overridden_gamma_curve = gamma_curve;
208 Colorspace get_color_space() const { return overridden_color_space; }
209 GammaCurve get_gamma_curve() const { return overridden_gamma_curve; }
212 Colorspace overridden_color_space;
213 GammaCurve overridden_gamma_curve;
216 TEST(EffectChainTester, HandlesInputChangingColorspace) {
225 float out_data[size];
227 EffectChainTester tester(NULL, 4, 1, FORMAT_GRAYSCALE);
229 // First say that we have sRGB, linear input.
231 format.color_space = COLORSPACE_sRGB;
232 format.gamma_curve = GAMMA_LINEAR;
234 UnknownColorspaceInput *input = new UnknownColorspaceInput(format, FORMAT_GRAYSCALE, GL_FLOAT, 4, 1);
235 input->set_pixel_data(data);
236 tester.get_chain()->add_input(input);
238 // Now we change to Rec. 601 input.
239 input->set_color_space(COLORSPACE_REC_601_625);
240 input->set_gamma_curve(GAMMA_REC_601);
242 // Now ask for Rec. 601 output. Thus, our chain should now be a no-op.
243 tester.run(out_data, GL_RED, COLORSPACE_REC_601_625, GAMMA_REC_601);
244 expect_equal(data, out_data, 4, 1);
247 TEST(EffectChainTest, NoGammaConversionsWhenLinearLightNotNeeded) {
252 float expected_data[6] = {
257 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
258 RewritingEffect<MirrorEffect> *effect = new RewritingEffect<MirrorEffect>();
259 tester.get_chain()->add_effect(effect);
260 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
262 Node *node = effect->replaced_node;
263 ASSERT_EQ(1, node->incoming_links.size());
264 EXPECT_EQ(0, node->outgoing_links.size());
265 EXPECT_EQ("FlatInput", node->incoming_links[0]->effect->effect_type_id());
267 expect_equal(expected_data, out_data, 3, 2);
270 TEST(EffectChainTest, NoColorspaceConversionsWhensRGBPrimariesNotNeeded) {
275 float expected_data[6] = {
280 EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_REC_601_525, GAMMA_LINEAR);
281 RewritingEffect<MirrorEffect> *effect = new RewritingEffect<MirrorEffect>();
282 tester.get_chain()->add_effect(effect);
283 tester.run(out_data, GL_RED, COLORSPACE_REC_601_525, GAMMA_LINEAR);
285 Node *node = effect->replaced_node;
286 ASSERT_EQ(1, node->incoming_links.size());
287 EXPECT_EQ(0, node->outgoing_links.size());
288 EXPECT_EQ("FlatInput", node->incoming_links[0]->effect->effect_type_id());
290 expect_equal(expected_data, out_data, 3, 2);
293 // The identity effect needs linear light, and thus will get conversions on both sides.
294 // Verify that sRGB data is properly converted to and from linear light for the entire ramp.
295 TEST(EffectChainTest, IdentityThroughsRGBConversions) {
297 for (unsigned i = 0; i < 256; ++i) {
301 EffectChainTester tester(data, 256, 1, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
302 tester.get_chain()->add_effect(new IdentityEffect());
303 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
305 expect_equal(data, out_data, 256, 1);
308 // Same, but uses the forward sRGB table from the GPU.
309 TEST(EffectChainTest, IdentityThroughGPUsRGBConversions) {
310 unsigned char data[256];
311 float expected_data[256];
312 for (unsigned i = 0; i < 256; ++i) {
314 expected_data[i] = i / 255.0;
317 EffectChainTester tester(NULL, 256, 1);
318 tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
319 tester.get_chain()->add_effect(new IdentityEffect());
320 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
322 expect_equal(expected_data, out_data, 256, 1);
325 // Same, for the Rec. 601/709 gamma curve.
326 TEST(EffectChainTest, IdentityThroughRec709) {
328 for (unsigned i = 0; i < 256; ++i) {
332 EffectChainTester tester(data, 256, 1, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_REC_709);
333 tester.get_chain()->add_effect(new IdentityEffect());
334 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_REC_709);
336 expect_equal(data, out_data, 256, 1);
339 // The identity effect needs premultiplied alpha, and thus will get conversions on both sides.
340 TEST(EffectChainTest, IdentityThroughAlphaConversions) {
342 float data[4 * size] = {
343 0.8f, 0.0f, 0.0f, 0.5f,
344 0.0f, 0.2f, 0.2f, 0.3f,
345 0.1f, 0.0f, 1.0f, 1.0f,
348 EffectChainTester tester(data, size, 1, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
349 tester.get_chain()->add_effect(new IdentityEffect());
350 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
352 expect_equal(data, out_data, 4, size);
355 TEST(EffectChainTest, NoAlphaConversionsWhenPremultipliedAlphaNotNeeded) {
357 float data[4 * size] = {
358 0.8f, 0.0f, 0.0f, 0.5f,
359 0.0f, 0.2f, 0.2f, 0.3f,
360 0.1f, 0.0f, 1.0f, 1.0f,
362 float expected_data[4 * size] = {
363 0.1f, 0.0f, 1.0f, 1.0f,
364 0.0f, 0.2f, 0.2f, 0.3f,
365 0.8f, 0.0f, 0.0f, 0.5f,
367 float out_data[4 * size];
368 EffectChainTester tester(data, size, 1, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
369 RewritingEffect<MirrorEffect> *effect = new RewritingEffect<MirrorEffect>();
370 tester.get_chain()->add_effect(effect);
371 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
373 Node *node = effect->replaced_node;
374 ASSERT_EQ(1, node->incoming_links.size());
375 EXPECT_EQ(0, node->outgoing_links.size());
376 EXPECT_EQ("FlatInput", node->incoming_links[0]->effect->effect_type_id());
378 expect_equal(expected_data, out_data, 4, size);
381 // An input that outputs only blue, which has blank alpha.
382 class BlueInput : public Input {
384 BlueInput() { register_int("needs_mipmaps", &needs_mipmaps); }
385 virtual std::string effect_type_id() const { return "IdentityEffect"; }
386 std::string output_fragment_shader() { return read_file("blue.frag"); }
387 virtual AlphaHandling alpha_handling() const { return OUTPUT_BLANK_ALPHA; }
388 virtual void finalize() {}
389 virtual bool can_output_linear_gamma() const { return true; }
390 virtual unsigned get_width() const { return 1; }
391 virtual unsigned get_height() const { return 1; }
392 virtual Colorspace get_color_space() const { return COLORSPACE_sRGB; }
393 virtual GammaCurve get_gamma_curve() const { return GAMMA_LINEAR; }
399 // Like RewritingEffect<InvertEffect>, but splicing in a BlueInput instead,
400 // which outputs blank alpha.
401 class RewritingToBlueInput : public Input {
403 RewritingToBlueInput() { register_int("needs_mipmaps", &needs_mipmaps); }
404 virtual std::string effect_type_id() const { return "RewritingToBlueInput"; }
405 std::string output_fragment_shader() { EXPECT_TRUE(false); return read_file("identity.frag"); }
406 virtual void rewrite_graph(EffectChain *graph, Node *self) {
407 Node *blue_node = graph->add_node(new BlueInput());
408 graph->replace_receiver(self, blue_node);
409 graph->replace_sender(self, blue_node);
411 self->disabled = true;
412 this->blue_node = blue_node;
415 // Dummy values that we need to implement because we inherit from Input.
416 // Same as BlueInput.
417 virtual AlphaHandling alpha_handling() const { return OUTPUT_BLANK_ALPHA; }
418 virtual void finalize() {}
419 virtual bool can_output_linear_gamma() const { return true; }
420 virtual unsigned get_width() const { return 1; }
421 virtual unsigned get_height() const { return 1; }
422 virtual Colorspace get_color_space() const { return COLORSPACE_sRGB; }
423 virtual GammaCurve get_gamma_curve() const { return GAMMA_LINEAR; }
431 TEST(EffectChainTest, NoAlphaConversionsWithBlankAlpha) {
433 float data[4 * size] = {
434 0.0f, 0.0f, 1.0f, 1.0f,
435 0.0f, 0.0f, 1.0f, 1.0f,
436 0.0f, 0.0f, 1.0f, 1.0f,
438 float out_data[4 * size];
439 EffectChainTester tester(NULL, size, 1);
440 RewritingToBlueInput *input = new RewritingToBlueInput();
441 tester.get_chain()->add_input(input);
442 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_PREMULTIPLIED);
444 Node *node = input->blue_node;
445 EXPECT_EQ(0, node->incoming_links.size());
446 EXPECT_EQ(0, node->outgoing_links.size());
448 expect_equal(data, out_data, 4, size);
451 // Effectively scales down its input linearly by 4x (and repeating it),
452 // which is not attainable without mipmaps.
453 class MipmapNeedingEffect : public Effect {
455 MipmapNeedingEffect() {}
456 virtual bool needs_mipmaps() const { return true; }
457 virtual std::string effect_type_id() const { return "MipmapNeedingEffect"; }
458 std::string output_fragment_shader() { return read_file("mipmap_needing_effect.frag"); }
459 void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
461 glActiveTexture(GL_TEXTURE0);
463 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
465 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
470 TEST(EffectChainTest, MipmapGenerationWorks) {
471 float data[] = { // In 4x4 blocks.
472 1.0f, 0.0f, 0.0f, 0.0f,
473 0.0f, 0.0f, 0.0f, 0.0f,
474 0.0f, 0.0f, 0.0f, 0.0f,
475 0.0f, 0.0f, 0.0f, 1.0f,
477 0.0f, 0.0f, 0.0f, 0.0f,
478 0.0f, 0.5f, 0.0f, 0.0f,
479 0.0f, 0.0f, 1.0f, 0.0f,
480 0.0f, 0.0f, 0.0f, 0.0f,
482 1.0f, 1.0f, 1.0f, 1.0f,
483 1.0f, 1.0f, 1.0f, 1.0f,
484 1.0f, 1.0f, 1.0f, 1.0f,
485 1.0f, 1.0f, 1.0f, 1.0f,
487 0.0f, 0.0f, 0.0f, 0.0f,
488 0.0f, 1.0f, 1.0f, 0.0f,
489 0.0f, 1.0f, 1.0f, 0.0f,
490 0.0f, 0.0f, 0.0f, 0.0f,
492 float expected_data[] = { // Repeated four times each way.
493 0.125f, 0.125f, 0.125f, 0.125f,
494 0.09375f, 0.09375f, 0.09375f, 0.09375f,
495 1.0f, 1.0f, 1.0f, 1.0f,
496 0.25f, 0.25f, 0.25f, 0.25f,
498 0.125f, 0.125f, 0.125f, 0.125f,
499 0.09375f, 0.09375f, 0.09375f, 0.09375f,
500 1.0f, 1.0f, 1.0f, 1.0f,
501 0.25f, 0.25f, 0.25f, 0.25f,
503 0.125f, 0.125f, 0.125f, 0.125f,
504 0.09375f, 0.09375f, 0.09375f, 0.09375f,
505 1.0f, 1.0f, 1.0f, 1.0f,
506 0.25f, 0.25f, 0.25f, 0.25f,
508 0.125f, 0.125f, 0.125f, 0.125f,
509 0.09375f, 0.09375f, 0.09375f, 0.09375f,
510 1.0f, 1.0f, 1.0f, 1.0f,
511 0.25f, 0.25f, 0.25f, 0.25f,
513 float out_data[4 * 16];
514 EffectChainTester tester(data, 4, 16, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
515 tester.get_chain()->add_effect(new MipmapNeedingEffect());
516 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
518 expect_equal(expected_data, out_data, 4, 16);
521 TEST(EffectChainTest, ResizeDownByFourThenUpByFour) {
522 float data[] = { // In 4x4 blocks.
523 1.0f, 0.0f, 0.0f, 0.0f,
524 0.0f, 0.0f, 0.0f, 0.0f,
525 0.0f, 0.0f, 0.0f, 0.0f,
526 0.0f, 0.0f, 0.0f, 1.0f,
528 0.0f, 0.0f, 0.0f, 0.0f,
529 0.0f, 0.5f, 0.0f, 0.0f,
530 0.0f, 0.0f, 1.0f, 0.0f,
531 0.0f, 0.0f, 0.0f, 0.0f,
533 1.0f, 1.0f, 1.0f, 1.0f,
534 1.0f, 1.0f, 1.0f, 1.0f,
535 1.0f, 1.0f, 1.0f, 1.0f,
536 1.0f, 1.0f, 1.0f, 1.0f,
538 0.0f, 0.0f, 0.0f, 0.0f,
539 0.0f, 1.0f, 1.0f, 0.0f,
540 0.0f, 1.0f, 1.0f, 0.0f,
541 0.0f, 0.0f, 0.0f, 0.0f,
543 float expected_data[] = { // Repeated four times horizontaly, interpolated vertically.
544 0.1250f, 0.1250f, 0.1250f, 0.1250f,
545 0.1250f, 0.1250f, 0.1250f, 0.1250f,
546 0.1211f, 0.1211f, 0.1211f, 0.1211f,
547 0.1133f, 0.1133f, 0.1133f, 0.1133f,
548 0.1055f, 0.1055f, 0.1055f, 0.1055f,
549 0.0977f, 0.0977f, 0.0977f, 0.0977f,
550 0.2070f, 0.2070f, 0.2070f, 0.2070f,
551 0.4336f, 0.4336f, 0.4336f, 0.4336f,
552 0.6602f, 0.6602f, 0.6602f, 0.6602f,
553 0.8867f, 0.8867f, 0.8867f, 0.8867f,
554 0.9062f, 0.9062f, 0.9062f, 0.9062f,
555 0.7188f, 0.7188f, 0.7188f, 0.7188f,
556 0.5312f, 0.5312f, 0.5312f, 0.5312f,
557 0.3438f, 0.3438f, 0.3438f, 0.3438f,
558 0.2500f, 0.2500f, 0.2500f, 0.2500f,
559 0.2500f, 0.2500f, 0.2500f, 0.2500f,
561 float out_data[4 * 16];
563 ResizeEffect *downscale = new ResizeEffect();
564 ASSERT_TRUE(downscale->set_int("width", 1));
565 ASSERT_TRUE(downscale->set_int("height", 4));
567 ResizeEffect *upscale = new ResizeEffect();
568 ASSERT_TRUE(upscale->set_int("width", 4));
569 ASSERT_TRUE(upscale->set_int("height", 16));
571 EffectChainTester tester(data, 4, 16, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
572 tester.get_chain()->add_effect(downscale);
573 tester.get_chain()->add_effect(upscale);
574 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
576 expect_equal(expected_data, out_data, 4, 16);
579 // An effect that multiplies with a constant. Used below.
580 class MultiplyEffect : public Effect {
582 MultiplyEffect() { register_float("factor", &factor); }
583 virtual std::string effect_type_id() const { return "MultiplyEffect"; }
584 std::string output_fragment_shader() { return read_file("multiply.frag"); }
585 virtual AlphaHandling alpha_handling() const { return DONT_CARE_ALPHA_TYPE; }
591 // An effect that adds its two inputs together. Used below.
592 class AddEffect : public Effect {
595 virtual std::string effect_type_id() const { return "AddEffect"; }
596 std::string output_fragment_shader() { return read_file("add.frag"); }
597 virtual unsigned num_inputs() const { return 2; }
598 virtual AlphaHandling alpha_handling() const { return DONT_CARE_ALPHA_TYPE; }
601 // Constructs the graph
605 // MultiplyEffect MultiplyEffect |
609 // and verifies that it gives the correct output.
610 TEST(EffectChainTest, DiamondGraph) {
615 float expected_data[] = {
619 float out_data[2 * 2];
621 MultiplyEffect *mul_half = new MultiplyEffect();
622 ASSERT_TRUE(mul_half->set_float("factor", 0.5f));
624 MultiplyEffect *mul_two = new MultiplyEffect();
625 ASSERT_TRUE(mul_two->set_float("factor", 2.0f));
627 EffectChainTester tester(NULL, 2, 2);
630 format.color_space = COLORSPACE_sRGB;
631 format.gamma_curve = GAMMA_LINEAR;
633 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, 2, 2);
634 input->set_pixel_data(data);
636 tester.get_chain()->add_input(input);
637 tester.get_chain()->add_effect(mul_half, input);
638 tester.get_chain()->add_effect(mul_two, input);
639 tester.get_chain()->add_effect(new AddEffect(), mul_half, mul_two);
640 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
642 expect_equal(expected_data, out_data, 2, 2);
645 // Constructs the graph
649 // MultiplyEffect MultiplyEffect |
651 // \ BouncingIdentityEffect |
655 // and verifies that it gives the correct output.
656 TEST(EffectChainTest, DiamondGraphWithOneInputUsedInTwoPhases) {
661 float expected_data[] = {
665 float out_data[2 * 2];
667 MultiplyEffect *mul_half = new MultiplyEffect();
668 ASSERT_TRUE(mul_half->set_float("factor", 0.5f));
670 MultiplyEffect *mul_two = new MultiplyEffect();
671 ASSERT_TRUE(mul_two->set_float("factor", 2.0f));
673 BouncingIdentityEffect *bounce = new BouncingIdentityEffect();
675 EffectChainTester tester(NULL, 2, 2);
678 format.color_space = COLORSPACE_sRGB;
679 format.gamma_curve = GAMMA_LINEAR;
681 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, 2, 2);
682 input->set_pixel_data(data);
684 tester.get_chain()->add_input(input);
685 tester.get_chain()->add_effect(mul_half, input);
686 tester.get_chain()->add_effect(mul_two, input);
687 tester.get_chain()->add_effect(bounce, mul_two);
688 tester.get_chain()->add_effect(new AddEffect(), mul_half, bounce);
689 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
691 expect_equal(expected_data, out_data, 2, 2);