xref: /aosp_15_r20/external/skia/tests/SRGBTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkColorSpaceXformSteps.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipeline.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipelineOpContexts.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipelineOpList.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
21*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
22*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(srgb_roundtrip,r)23*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(srgb_roundtrip, r) {
24*c8dee2aaSAndroid Build Coastguard Worker     uint32_t reds[256];
25*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < 256; i++) {
26*c8dee2aaSAndroid Build Coastguard Worker         reds[i] = i;
27*c8dee2aaSAndroid Build Coastguard Worker     }
28*c8dee2aaSAndroid Build Coastguard Worker 
29*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline_MemoryCtx ptr = { reds, 0 };
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB(),
32*c8dee2aaSAndroid Build Coastguard Worker                         linear = sRGB->makeLinearGamma();
33*c8dee2aaSAndroid Build Coastguard Worker     const SkAlphaType upm = kUnpremul_SkAlphaType;
34*c8dee2aaSAndroid Build Coastguard Worker 
35*c8dee2aaSAndroid Build Coastguard Worker     SkColorSpaceXformSteps linearize{  sRGB.get(),upm,  linear.get(),upm},
36*c8dee2aaSAndroid Build Coastguard Worker                            reencode {linear.get(),upm,    sRGB.get(),upm};
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline_<256> p;
39*c8dee2aaSAndroid Build Coastguard Worker     p.append(SkRasterPipelineOp::load_8888,  &ptr);
40*c8dee2aaSAndroid Build Coastguard Worker     linearize.apply(&p);
41*c8dee2aaSAndroid Build Coastguard Worker     reencode .apply(&p);
42*c8dee2aaSAndroid Build Coastguard Worker     p.append(SkRasterPipelineOp::store_8888, &ptr);
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker     p.run(0,0,256,1);
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < 256; i++) {
47*c8dee2aaSAndroid Build Coastguard Worker         if (reds[i] != (uint32_t)i) {
48*c8dee2aaSAndroid Build Coastguard Worker             ERRORF(r, "%d doesn't round trip, %u", i, reds[i]);
49*c8dee2aaSAndroid Build Coastguard Worker         }
50*c8dee2aaSAndroid Build Coastguard Worker     }
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(srgb_edge_cases,r)53*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(srgb_edge_cases, r) {
54*c8dee2aaSAndroid Build Coastguard Worker     // We need to run at least 4 pixels to make sure we hit all specializations.
55*c8dee2aaSAndroid Build Coastguard Worker     float colors[4][4] = { {0,1,1,1}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} };
56*c8dee2aaSAndroid Build Coastguard Worker     auto& color = colors[0];
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline_MemoryCtx dst = { &color, 0 };
59*c8dee2aaSAndroid Build Coastguard Worker 
60*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB(),
61*c8dee2aaSAndroid Build Coastguard Worker                         linear = sRGB->makeLinearGamma();
62*c8dee2aaSAndroid Build Coastguard Worker     const SkAlphaType upm = kUnpremul_SkAlphaType;
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker     SkColorSpaceXformSteps steps {linear.get(),upm,    sRGB.get(),upm};
65*c8dee2aaSAndroid Build Coastguard Worker 
66*c8dee2aaSAndroid Build Coastguard Worker     SkSTArenaAlloc<256> alloc;
67*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline p(&alloc);
68*c8dee2aaSAndroid Build Coastguard Worker     p.appendConstantColor(&alloc, color);
69*c8dee2aaSAndroid Build Coastguard Worker     steps.apply(&p);
70*c8dee2aaSAndroid Build Coastguard Worker     p.append(SkRasterPipelineOp::store_f32, &dst);
71*c8dee2aaSAndroid Build Coastguard Worker     p.run(0,0,4,1);
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     if (color[0] != 0.0f) {
74*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "expected to_srgb() to map 0.0f to 0.0f, got %f", color[0]);
75*c8dee2aaSAndroid Build Coastguard Worker     }
76*c8dee2aaSAndroid Build Coastguard Worker     if (color[1] != 1.0f) {
77*c8dee2aaSAndroid Build Coastguard Worker         float f = color[1];
78*c8dee2aaSAndroid Build Coastguard Worker         uint32_t x;
79*c8dee2aaSAndroid Build Coastguard Worker         memcpy(&x, &f, 4);
80*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "expected to_srgb() to map 1.0f to 1.0f, got %f (%08x)", color[1], x);
81*c8dee2aaSAndroid Build Coastguard Worker     }
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker // Linearize and then re-encode pixel values, testing that the output is close to the input.
DEF_TEST(srgb_roundtrip_extended,r)85*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(srgb_roundtrip_extended, r) {
86*c8dee2aaSAndroid Build Coastguard Worker     static const int kSteps = 128;
87*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f rgba[kSteps];
88*c8dee2aaSAndroid Build Coastguard Worker 
89*c8dee2aaSAndroid Build Coastguard Worker     auto expected = [=](int i) {
90*c8dee2aaSAndroid Build Coastguard Worker         float scale = 10000.0f / (3*kSteps);
91*c8dee2aaSAndroid Build Coastguard Worker         return SkColor4f{
92*c8dee2aaSAndroid Build Coastguard Worker             (3*i+0) * scale,
93*c8dee2aaSAndroid Build Coastguard Worker             (3*i+1) * scale,
94*c8dee2aaSAndroid Build Coastguard Worker             (3*i+2) * scale,
95*c8dee2aaSAndroid Build Coastguard Worker             1.0f,
96*c8dee2aaSAndroid Build Coastguard Worker         };
97*c8dee2aaSAndroid Build Coastguard Worker     };
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < kSteps; i++) {
100*c8dee2aaSAndroid Build Coastguard Worker         rgba[i] = expected(i);
101*c8dee2aaSAndroid Build Coastguard Worker     }
102*c8dee2aaSAndroid Build Coastguard Worker 
103*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline_MemoryCtx ptr = { rgba, 0 };
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkColorSpace> cs = SkColorSpace::MakeSRGB();
106*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkColorSpace> linear = cs->makeLinearGamma();
107*c8dee2aaSAndroid Build Coastguard Worker     const SkAlphaType upm = kUnpremul_SkAlphaType;
108*c8dee2aaSAndroid Build Coastguard Worker 
109*c8dee2aaSAndroid Build Coastguard Worker     SkColorSpaceXformSteps linearize{    cs.get(),upm,  linear.get(),upm},
110*c8dee2aaSAndroid Build Coastguard Worker                            reencode {linear.get(),upm,      cs.get(),upm};
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline_<256> p;
113*c8dee2aaSAndroid Build Coastguard Worker     p.append(SkRasterPipelineOp::load_f32,  &ptr);
114*c8dee2aaSAndroid Build Coastguard Worker     linearize.apply(&p);
115*c8dee2aaSAndroid Build Coastguard Worker     reencode .apply(&p);
116*c8dee2aaSAndroid Build Coastguard Worker     p.append(SkRasterPipelineOp::store_f32, &ptr);
117*c8dee2aaSAndroid Build Coastguard Worker     p.run(0,0,kSteps,1);
118*c8dee2aaSAndroid Build Coastguard Worker 
119*c8dee2aaSAndroid Build Coastguard Worker     auto close = [=](float x, float y) {
120*c8dee2aaSAndroid Build Coastguard Worker         return x == y
121*c8dee2aaSAndroid Build Coastguard Worker             || (x/y < 1.001f && y/x < 1.001f);
122*c8dee2aaSAndroid Build Coastguard Worker     };
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < kSteps; i++) {
125*c8dee2aaSAndroid Build Coastguard Worker         SkColor4f want = expected(i);
126*c8dee2aaSAndroid Build Coastguard Worker     #if 0
127*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("got %g %g %g, want %g %g %g\n",
128*c8dee2aaSAndroid Build Coastguard Worker                  rgba[i].fR, rgba[i].fG, rgba[i].fB,
129*c8dee2aaSAndroid Build Coastguard Worker                  want.fR, want.fG, want.fB);
130*c8dee2aaSAndroid Build Coastguard Worker     #endif
131*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, close(rgba[i].fR, want.fR));
132*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, close(rgba[i].fG, want.fG));
133*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, close(rgba[i].fB, want.fB));
134*c8dee2aaSAndroid Build Coastguard Worker     }
135*c8dee2aaSAndroid Build Coastguard Worker }
136