blob: f0ae414c606ea2cb732f7f91b22c5d7eafa9da88 [file] [log] [blame]
Mike Klein6968f9c2018-05-24 12:33:23 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkColorSpacePriv.h"
9#include "SkColorSpaceXformSteps.h"
10#include "Test.h"
11
Mike Klein6968f9c2018-05-24 12:33:23 -040012DEF_TEST(SkColorSpaceXformSteps, r) {
Mike Klein97918ff2018-05-25 12:55:58 -040013 auto srgb = SkColorSpace::MakeSRGB(),
14 adobe = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut),
15 srgb22 = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace:: kSRGB_Gamut),
16 srgb1 = srgb ->makeLinearGamma(),
17 adobe1 = adobe->makeLinearGamma();
Mike Klein6968f9c2018-05-24 12:33:23 -040018
Mike Klein8f3d36c2018-08-14 10:28:05 -040019 auto premul = kPremul_SkAlphaType,
20 opaque = kOpaque_SkAlphaType,
21 unpremul = kUnpremul_SkAlphaType;
22
Mike Klein6968f9c2018-05-24 12:33:23 -040023 struct {
24 sk_sp<SkColorSpace> src, dst;
Mike Klein8f3d36c2018-08-14 10:28:05 -040025 SkAlphaType srcAT, dstAT;
Mike Klein6968f9c2018-05-24 12:33:23 -040026
Mike Klein97918ff2018-05-25 12:55:58 -040027 bool unpremul;
28 bool linearize;
Mike Klein6968f9c2018-05-24 12:33:23 -040029 bool gamut_transform;
Mike Klein97918ff2018-05-25 12:55:58 -040030 bool encode;
Mike Klein6968f9c2018-05-24 12:33:23 -040031 bool premul;
32
Mike Klein6968f9c2018-05-24 12:33:23 -040033 } tests[] = {
Mike Klein97918ff2018-05-25 12:55:58 -040034 // The general case is converting between two color spaces with different gamuts
35 // and different transfer functions. There's no optimization possible here.
Mike Klein8f3d36c2018-08-14 10:28:05 -040036 { adobe, srgb, premul, premul,
Mike Klein97918ff2018-05-25 12:55:58 -040037 true, // src is encoded as f(s)*a,a, so we unpremul to f(s),a before linearizing.
38 true, // linearize to s,a
39 true, // transform s to dst gamut, s'
40 true, // encode with dst transfer function, g(s'), a
41 true, // premul to g(s')*a, a
Mike Klein6968f9c2018-05-24 12:33:23 -040042 },
Mike Klein97918ff2018-05-25 12:55:58 -040043 // All the same going the other direction.
Mike Klein8f3d36c2018-08-14 10:28:05 -040044 { srgb, adobe, premul, premul, true,true,true,true,true },
Mike Klein6968f9c2018-05-24 12:33:23 -040045
Mike Klein97918ff2018-05-25 12:55:58 -040046 // If the src alpha type is unpremul, we'll not need that initial unpremul step.
Mike Klein8f3d36c2018-08-14 10:28:05 -040047 { adobe, srgb, unpremul, premul, false,true,true,true,true },
48 { srgb, adobe, unpremul, premul, false,true,true,true,true },
Mike Klein6968f9c2018-05-24 12:33:23 -040049
Mike Klein97918ff2018-05-25 12:55:58 -040050 // If opaque, we need neither the initial unpremul, nor the premul later.
Mike Klein8f3d36c2018-08-14 10:28:05 -040051 { adobe, srgb, opaque, premul, false,true,true,true,false },
52 { srgb, adobe, opaque, premul, false,true,true,true,false },
Mike Klein6968f9c2018-05-24 12:33:23 -040053
Mike Klein97918ff2018-05-25 12:55:58 -040054
55 // Now let's go between sRGB and sRGB with a 2.2 gamma, the gamut staying the same.
Mike Klein8f3d36c2018-08-14 10:28:05 -040056 { srgb, srgb22, premul, premul,
Mike Klein97918ff2018-05-25 12:55:58 -040057 true, // we need to linearize, so we need to unpremul
58 true, // we need to encode to 2.2 gamma, so we need to get linear
59 false, // no need to change gamut
60 true, // linear -> gamma 2.2
61 true, // premul going into the blend
Mike Klein6968f9c2018-05-24 12:33:23 -040062 },
Mike Klein97918ff2018-05-25 12:55:58 -040063 // Same sort of logic in the other direction.
Mike Klein8f3d36c2018-08-14 10:28:05 -040064 { srgb22, srgb, premul, premul, true,true,false,true,true },
Mike Klein6968f9c2018-05-24 12:33:23 -040065
Mike Klein97918ff2018-05-25 12:55:58 -040066 // As in the general case, when we change the alpha type unpremul and premul steps drop out.
Mike Klein8f3d36c2018-08-14 10:28:05 -040067 { srgb, srgb22, unpremul, premul, false,true,false,true,true },
68 { srgb22, srgb, unpremul, premul, false,true,false,true,true },
69 { srgb, srgb22, opaque, premul, false,true,false,true,false },
70 { srgb22, srgb, opaque, premul, false,true,false,true,false },
Mike Klein6968f9c2018-05-24 12:33:23 -040071
Mike Klein97918ff2018-05-25 12:55:58 -040072 // Let's look at the special case of completely matching color spaces.
73 // We should be ready to go into the blend without any fuss.
Mike Klein8f3d36c2018-08-14 10:28:05 -040074 { srgb, srgb, premul, premul, false,false,false,false,false },
75 { srgb, srgb, unpremul, premul, false,false,false,false,true },
76 { srgb, srgb, opaque, premul, false,false,false,false,false },
Mike Klein6968f9c2018-05-24 12:33:23 -040077
Mike Klein97918ff2018-05-25 12:55:58 -040078 // We can drop out the linearize step when the source is already linear.
Mike Klein8f3d36c2018-08-14 10:28:05 -040079 { srgb1, adobe, premul, premul, true,false,true,true,true },
80 { srgb1, srgb, premul, premul, true,false,false,true,true },
Mike Klein97918ff2018-05-25 12:55:58 -040081 // And we can drop the encode step when the destination is linear.
Mike Klein8f3d36c2018-08-14 10:28:05 -040082 { adobe, srgb1, premul, premul, true,true,true,false,true },
83 { srgb, srgb1, premul, premul, true,true,false,false,true },
Mike Klein6968f9c2018-05-24 12:33:23 -040084
Mike Klein97918ff2018-05-25 12:55:58 -040085 // Here's an interesting case where only gamut transform is needed.
Mike Klein8f3d36c2018-08-14 10:28:05 -040086 { adobe1, srgb1, premul, premul, false,false,true,false,false },
87 { adobe1, srgb1, opaque, premul, false,false,true,false,false },
88 { adobe1, srgb1, unpremul, premul, false,false,true,false, true },
Mike Klein6968f9c2018-05-24 12:33:23 -040089
Mike Klein97918ff2018-05-25 12:55:58 -040090 // Just finishing up with something to produce each other possible output.
91 // Nothing terribly interesting in these eight.
Mike Klein8f3d36c2018-08-14 10:28:05 -040092 { srgb, srgb1, opaque, premul, false, true,false,false,false },
93 { srgb, srgb1, unpremul, premul, false, true,false,false, true },
94 { srgb, adobe1, opaque, premul, false, true, true,false,false },
95 { srgb, adobe1, unpremul, premul, false, true, true,false, true },
96 { srgb1, srgb, opaque, premul, false,false,false, true,false },
97 { srgb1, srgb, unpremul, premul, false,false,false, true, true },
98 { srgb1, adobe, opaque, premul, false,false, true, true,false },
99 { srgb1, adobe, unpremul, premul, false,false, true, true, true },
100
101 // Now test non-premul outputs.
102 { srgb , srgb , premul, unpremul, true,false,false,false,false },
103 { srgb , srgb1 , premul, unpremul, true, true,false,false,false },
104 { srgb1, adobe1, premul, unpremul, true,false, true,false,false },
105 { srgb , adobe1, premul, unpremul, true, true, true,false,false },
106 { srgb1, srgb , premul, unpremul, true,false,false, true,false },
107 { srgb , srgb22, premul, unpremul, true, true,false, true,false },
108 { srgb1, adobe , premul, unpremul, true,false, true, true,false },
109 { srgb , adobe , premul, unpremul, true, true, true, true,false },
Mike Kleinb85fc3b2018-08-21 12:51:02 -0400110
111 // Opaque outputs are treated as the same alpha type as the source input.
112 // TODO: we'd really like to have a good way of explaining why we think this is useful.
113 { srgb , srgb , premul, opaque, false,false,false,false,false },
114 { srgb , srgb1 , premul, opaque, true, true,false,false, true },
115 { srgb1, adobe1, premul, opaque, false,false, true,false,false },
116 { srgb , adobe1, premul, opaque, true, true, true,false, true },
117 { srgb1, srgb , premul, opaque, true,false,false, true, true },
118 { srgb , srgb22, premul, opaque, true, true,false, true, true },
119 { srgb1, adobe , premul, opaque, true,false, true, true, true },
120 { srgb , adobe , premul, opaque, true, true, true, true, true },
121
122 { srgb , srgb , unpremul, opaque, false,false,false,false,false },
123 { srgb , srgb1 , unpremul, opaque, false, true,false,false,false },
124 { srgb1, adobe1, unpremul, opaque, false,false, true,false,false },
125 { srgb , adobe1, unpremul, opaque, false, true, true,false,false },
126 { srgb1, srgb , unpremul, opaque, false,false,false, true,false },
127 { srgb , srgb22, unpremul, opaque, false, true,false, true,false },
128 { srgb1, adobe , unpremul, opaque, false,false, true, true,false },
129 { srgb , adobe , unpremul, opaque, false, true, true, true,false },
Mike Klein6968f9c2018-05-24 12:33:23 -0400130 };
131
Mike Klein97918ff2018-05-25 12:55:58 -0400132 uint32_t tested = 0x00000000;
Mike Klein6968f9c2018-05-24 12:33:23 -0400133 for (auto t : tests) {
Mike Klein8f3d36c2018-08-14 10:28:05 -0400134 SkColorSpaceXformSteps steps{t.src.get(), t.srcAT,
135 t.dst.get(), t.dstAT};
Brian Osmanf018b7d2018-06-13 17:21:19 -0400136 REPORTER_ASSERT(r, steps.flags.unpremul == t.unpremul);
137 REPORTER_ASSERT(r, steps.flags.linearize == t.linearize);
138 REPORTER_ASSERT(r, steps.flags.gamut_transform == t.gamut_transform);
139 REPORTER_ASSERT(r, steps.flags.encode == t.encode);
140 REPORTER_ASSERT(r, steps.flags.premul == t.premul);
Mike Klein97918ff2018-05-25 12:55:58 -0400141
142 uint32_t bits = (uint32_t)t.unpremul << 0
143 | (uint32_t)t.linearize << 1
144 | (uint32_t)t.gamut_transform << 2
145 | (uint32_t)t.encode << 3
146 | (uint32_t)t.premul << 4;
147 tested |= (1<<bits);
148 }
149
150 // We'll check our test cases cover all 2^5 == 32 possible outputs.
151 for (uint32_t t = 0; t < 32; t++) {
152 if (tested & (1<<t)) {
153 continue;
154 }
155
Mike Klein8f3d36c2018-08-14 10:28:05 -0400156 // There are a couple impossible outputs, so consider those bits tested.
157 //
Mike Klein97918ff2018-05-25 12:55:58 -0400158 // Unpremul then premul should be optimized away to a noop, so 0b10001 isn't possible.
159 // A gamut transform in the middle is fine too, so 0b10101 isn't possible either.
Mike Kleina23436c2018-05-31 10:59:52 -0400160 if (t == 0b10001 || t == 0b10101) {
Mike Klein97918ff2018-05-25 12:55:58 -0400161 continue;
162 }
163
164 ERRORF(r, "{ xxx, yyy, at, %s,%s,%s,%s,%s }, not covered",
165 (t& 1) ? " true" : "false",
166 (t& 2) ? " true" : "false",
167 (t& 4) ? " true" : "false",
168 (t& 8) ? " true" : "false",
169 (t&16) ? " true" : "false");
Mike Klein6968f9c2018-05-24 12:33:23 -0400170 }
171}