1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 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 "tests/Test.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkFixed.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBitmapProcState.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/opts/SkBitmapProcState_opts.h"
14*c8dee2aaSAndroid Build Coastguard Worker
15*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
16*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
17*c8dee2aaSAndroid Build Coastguard Worker #include <string>
18*c8dee2aaSAndroid Build Coastguard Worker
highBits(uint32_t rv)19*c8dee2aaSAndroid Build Coastguard Worker uint32_t highBits(uint32_t rv) {
20*c8dee2aaSAndroid Build Coastguard Worker return (rv >> 18) & ((1 << 14) - 1);
21*c8dee2aaSAndroid Build Coastguard Worker }
22*c8dee2aaSAndroid Build Coastguard Worker
middleBits(uint32_t rv)23*c8dee2aaSAndroid Build Coastguard Worker uint32_t middleBits(uint32_t rv) {
24*c8dee2aaSAndroid Build Coastguard Worker return (rv >> 14) & ((1 << 4) - 1);
25*c8dee2aaSAndroid Build Coastguard Worker }
26*c8dee2aaSAndroid Build Coastguard Worker
lowBits(uint32_t rv)27*c8dee2aaSAndroid Build Coastguard Worker uint32_t lowBits(uint32_t rv) {
28*c8dee2aaSAndroid Build Coastguard Worker return rv & ((1 << 14) - 1);
29*c8dee2aaSAndroid Build Coastguard Worker }
30*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MatrixProcs_pack_clamp,r)31*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MatrixProcs_pack_clamp, r) {
32*c8dee2aaSAndroid Build Coastguard Worker struct TestCase {
33*c8dee2aaSAndroid Build Coastguard Worker std::string name;
34*c8dee2aaSAndroid Build Coastguard Worker SkFixed input;
35*c8dee2aaSAndroid Build Coastguard Worker unsigned max;
36*c8dee2aaSAndroid Build Coastguard Worker uint32_t expectedOutput;
37*c8dee2aaSAndroid Build Coastguard Worker };
38*c8dee2aaSAndroid Build Coastguard Worker // The input values are somewhat arbitrary, inspired by real-world values
39*c8dee2aaSAndroid Build Coastguard Worker // with some edge cases added as well.
40*c8dee2aaSAndroid Build Coastguard Worker TestCase tests[] = {
41*c8dee2aaSAndroid Build Coastguard Worker // Negative values keep the fractional part out of convenience, but it is effectively
42*c8dee2aaSAndroid Build Coastguard Worker // ignored later.
43*c8dee2aaSAndroid Build Coastguard Worker {"-2.100 => {0x00, 0xe, 0x00}", SkFloatToFixed(-2.100f), 63, 0x38000},
44*c8dee2aaSAndroid Build Coastguard Worker {"-1.900 => {0x00, 0x1, 0x00}", SkFloatToFixed(-1.900f), 63, 0x04000},
45*c8dee2aaSAndroid Build Coastguard Worker {"-0.500 => {0x00, 0x8, 0x00}", SkFloatToFixed(-0.500f), 63, 0x20000},
46*c8dee2aaSAndroid Build Coastguard Worker {"0.0000 => {0x00, 0x0, 0x01}", SkFloatToFixed(0.0000f), 63, 0x000001},
47*c8dee2aaSAndroid Build Coastguard Worker {"0.0416 => {0x00, 0x0, 0x01}", SkFloatToFixed(0.0416f), 63, 0x000001},
48*c8dee2aaSAndroid Build Coastguard Worker {"1.8583 => {0x01, 0xd, 0x02}", SkFloatToFixed(1.8583f), 63, 0x074002},
49*c8dee2aaSAndroid Build Coastguard Worker {"3.6749 => {0x03, 0xa, 0x04}", SkFloatToFixed(3.6749f), 63, 0x0e8004},
50*c8dee2aaSAndroid Build Coastguard Worker {"5.4916 => {0x05, 0x7, 0x06}", SkFloatToFixed(5.4916f), 63, 0x15c006},
51*c8dee2aaSAndroid Build Coastguard Worker {"7.3083 => {0x07, 0x4, 0x08}", SkFloatToFixed(7.3083f), 63, 0x1d0008},
52*c8dee2aaSAndroid Build Coastguard Worker {"9.0000 => {0x09, 0x0, 0x0a}", SkFloatToFixed(9.0000f), 63, 0x24000a},
53*c8dee2aaSAndroid Build Coastguard Worker {"50.000 => {0x32, 0x0, 0x33}", SkFloatToFixed(50.000f), 63, 0xc80033},
54*c8dee2aaSAndroid Build Coastguard Worker {"50.875 => {0x32, 0xe, 0x33}", SkFloatToFixed(50.875f), 63, 0xcb8033},
55*c8dee2aaSAndroid Build Coastguard Worker {"62.123 => {0x3e, 0x1, 0x3f}", SkFloatToFixed(62.123f), 63, 0xf8403f},
56*c8dee2aaSAndroid Build Coastguard Worker {"62.999 => {0x3e, 0xf, 0x3f}", SkFloatToFixed(62.999f), 63, 0xfbc03f},
57*c8dee2aaSAndroid Build Coastguard Worker {"63.000 => {0x3f, 0x0, 0x3f}", SkFloatToFixed(63.000f), 63, 0xfc003f},
58*c8dee2aaSAndroid Build Coastguard Worker // Similarly, overflow keeps the fractional part.
59*c8dee2aaSAndroid Build Coastguard Worker {"64.500 => {0x3f, 0x8, 0x3f}", SkFloatToFixed(64.500f), 63, 0xfe003f},
60*c8dee2aaSAndroid Build Coastguard Worker {"127.20 => {0x3f, 0x3, 0x3f}", SkFloatToFixed(127.20f), 63, 0xfcc03f},
61*c8dee2aaSAndroid Build Coastguard Worker // Maximum has changed from 63 to 256
62*c8dee2aaSAndroid Build Coastguard Worker {"64.510 => {0x40, 0x8, 0x41}", SkFloatToFixed(64.510f), 256, 0x1020041},
63*c8dee2aaSAndroid Build Coastguard Worker {"127.21 => {0x7f, 0x3, 0x80}", SkFloatToFixed(127.21f), 256, 0x1fcc080},
64*c8dee2aaSAndroid Build Coastguard Worker {"256.77 => {0x100, 0xc, 0x100}", SkFloatToFixed(256.77f), 256, 0x4030100},
65*c8dee2aaSAndroid Build Coastguard Worker {"10000. => {0x100, 0x0, 0x100}", SkFloatToFixed(10000.f), 256, 0x4000100},
66*c8dee2aaSAndroid Build Coastguard Worker };
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker constexpr size_t NUM_TESTS = sizeof(tests) / sizeof(TestCase);
69*c8dee2aaSAndroid Build Coastguard Worker
70*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < NUM_TESTS; i++) {
71*c8dee2aaSAndroid Build Coastguard Worker TestCase tc = tests[i];
72*c8dee2aaSAndroid Build Coastguard Worker uint32_t rv = sktests::pack_clamp(tc.input, tc.max);
73*c8dee2aaSAndroid Build Coastguard Worker uint32_t exp = tc.expectedOutput;
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, rv == tc.expectedOutput,
76*c8dee2aaSAndroid Build Coastguard Worker "%s | %x != %x | {%x, %x, %x} != {%x, %x, %x}\n",
77*c8dee2aaSAndroid Build Coastguard Worker tc.name.c_str(), rv, exp,
78*c8dee2aaSAndroid Build Coastguard Worker highBits(rv), middleBits(rv), lowBits(rv),
79*c8dee2aaSAndroid Build Coastguard Worker highBits(exp), middleBits(exp), lowBits(exp));
80*c8dee2aaSAndroid Build Coastguard Worker }
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MatrixProcs_pack_clamp_out_of_range,r)83*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MatrixProcs_pack_clamp_out_of_range, r) {
84*c8dee2aaSAndroid Build Coastguard Worker // See https://crbug.com/1357122
85*c8dee2aaSAndroid Build Coastguard Worker struct TestCase {
86*c8dee2aaSAndroid Build Coastguard Worker std::string name;
87*c8dee2aaSAndroid Build Coastguard Worker SkFixed input;
88*c8dee2aaSAndroid Build Coastguard Worker unsigned max;
89*c8dee2aaSAndroid Build Coastguard Worker uint32_t expectedOutput;
90*c8dee2aaSAndroid Build Coastguard Worker };
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker // None of these should crash or cause UBSAN errors, although if they were used in drawing,
93*c8dee2aaSAndroid Build Coastguard Worker // they might be incorrect due to packing 16 bits of SkFixed into 14 bits of space.
94*c8dee2aaSAndroid Build Coastguard Worker static constexpr unsigned MAX_PACKED_VALUE = (1 << 14) - 1;
95*c8dee2aaSAndroid Build Coastguard Worker TestCase tests[] = {
96*c8dee2aaSAndroid Build Coastguard Worker {"16000.42=>{0xff, 6, 0xff}", SkFloatToFixed(16000.42f), 255, 0x3fd80ff},
97*c8dee2aaSAndroid Build Coastguard Worker {"17000.42=>{0xff, 6, 0xff}", SkFloatToFixed(17000.42f), 255, 0x3fd80ff},
98*c8dee2aaSAndroid Build Coastguard Worker {"18000.42=>{0xff, 6, 0xff}", SkFloatToFixed(18000.42f), 255, 0x3fd80ff},
99*c8dee2aaSAndroid Build Coastguard Worker
100*c8dee2aaSAndroid Build Coastguard Worker {"16000.42=>{0x3e80, 6, 0x3e81}", SkFloatToFixed(16000.42f), MAX_PACKED_VALUE, 0xfa01be81},
101*c8dee2aaSAndroid Build Coastguard Worker {"16382.00=>{0x3ffe, 0, 0x3fff}", SkFloatToFixed(16382.00f), MAX_PACKED_VALUE, 0xfff83fff},
102*c8dee2aaSAndroid Build Coastguard Worker {"16382.51=>{0x3ffe, 8, 0x3fff}}", SkFloatToFixed(16382.51f), MAX_PACKED_VALUE, 0xfffa3fff},
103*c8dee2aaSAndroid Build Coastguard Worker {"17000.42=>{0x3fff, 6, 0x3fff}", SkFloatToFixed(17000.42f), MAX_PACKED_VALUE, 0xfffdbfff},
104*c8dee2aaSAndroid Build Coastguard Worker {"18000.42=>{0x3fff, 6, 0x3fff}", SkFloatToFixed(18000.42f), MAX_PACKED_VALUE, 0xfffdbfff},
105*c8dee2aaSAndroid Build Coastguard Worker // Adding 1 to this would overflow and cause an UBSAN issue, if it were not suppressed.
106*c8dee2aaSAndroid Build Coastguard Worker // We suppress the warning and it wraps around.
107*c8dee2aaSAndroid Build Coastguard Worker {"32767.90=>{0x3fff, e, 0x0}", SkFloatToFixed(32767.90f), MAX_PACKED_VALUE, 0xffff8000},
108*c8dee2aaSAndroid Build Coastguard Worker };
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker constexpr size_t NUM_TESTS = sizeof(tests) / sizeof(TestCase);
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < NUM_TESTS; i++) {
113*c8dee2aaSAndroid Build Coastguard Worker TestCase tc = tests[i];
114*c8dee2aaSAndroid Build Coastguard Worker uint32_t rv = sktests::pack_clamp(tc.input, tc.max);
115*c8dee2aaSAndroid Build Coastguard Worker uint32_t exp = tc.expectedOutput;
116*c8dee2aaSAndroid Build Coastguard Worker
117*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, rv == tc.expectedOutput,
118*c8dee2aaSAndroid Build Coastguard Worker "%s | %x != %x | {%x, %x, %x} != {%x, %x, %x}\n",
119*c8dee2aaSAndroid Build Coastguard Worker tc.name.c_str(), rv, exp,
120*c8dee2aaSAndroid Build Coastguard Worker highBits(rv), middleBits(rv), lowBits(rv),
121*c8dee2aaSAndroid Build Coastguard Worker highBits(exp), middleBits(exp), lowBits(exp));
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MatrixProcs_pack_repeat,r)125*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MatrixProcs_pack_repeat, r) {
126*c8dee2aaSAndroid Build Coastguard Worker struct TestCase {
127*c8dee2aaSAndroid Build Coastguard Worker std::string name;
128*c8dee2aaSAndroid Build Coastguard Worker SkFixed input;
129*c8dee2aaSAndroid Build Coastguard Worker unsigned max;
130*c8dee2aaSAndroid Build Coastguard Worker uint32_t expectedOutput;
131*c8dee2aaSAndroid Build Coastguard Worker size_t width;
132*c8dee2aaSAndroid Build Coastguard Worker };
133*c8dee2aaSAndroid Build Coastguard Worker TestCase tests[] = {
134*c8dee2aaSAndroid Build Coastguard Worker // negative values wrap back around
135*c8dee2aaSAndroid Build Coastguard Worker {"-0.300 => {0x2c, 0xc, 0x2d}", SkFloatToFixed(-0.300f), 63, 0xb3002d, 63},
136*c8dee2aaSAndroid Build Coastguard Worker {"-0.200 => {0x33, 0x3, 0x34}", SkFloatToFixed(-0.200f), 63, 0xccc034, 63},
137*c8dee2aaSAndroid Build Coastguard Worker {"-0.100 => {0x39, 0x9, 0x3a}", SkFloatToFixed(-0.100f), 63, 0xe6403a, 63},
138*c8dee2aaSAndroid Build Coastguard Worker // The domain of the function is primarily [0.0, 1.0)
139*c8dee2aaSAndroid Build Coastguard Worker {"0.0000 => {0x00, 0x0, 0x01}", SkFloatToFixed(0.0000f), 63, 0x000001, 63},
140*c8dee2aaSAndroid Build Coastguard Worker {"0.1000 => {0x06, 0x6, 0x07}", SkFloatToFixed(0.1000f), 63, 0x198007, 63},
141*c8dee2aaSAndroid Build Coastguard Worker {"0.1234 => {0x07, 0xe, 0x08}", SkFloatToFixed(0.1234f), 63, 0x1f8008, 63},
142*c8dee2aaSAndroid Build Coastguard Worker {"0.2000 => {0x0c, 0xc, 0x0d}", SkFloatToFixed(0.2000f), 63, 0x33000d, 63},
143*c8dee2aaSAndroid Build Coastguard Worker {"0.3000 => {0x13, 0x3, 0x14}", SkFloatToFixed(0.3000f), 63, 0x4cc014, 63},
144*c8dee2aaSAndroid Build Coastguard Worker {"0.4000 => {0x19, 0x9, 0x1a}", SkFloatToFixed(0.4000f), 63, 0x66401a, 63},
145*c8dee2aaSAndroid Build Coastguard Worker {"0.5000 => {0x20, 0x0, 0x21}", SkFloatToFixed(0.5000f), 63, 0x800021, 63},
146*c8dee2aaSAndroid Build Coastguard Worker {"0.5678 => {0x24, 0x5, 0x25}", SkFloatToFixed(0.5678f), 63, 0x914025, 63},
147*c8dee2aaSAndroid Build Coastguard Worker {"0.6000 => {0x26, 0x6, 0x27}", SkFloatToFixed(0.6000f), 63, 0x998027, 63},
148*c8dee2aaSAndroid Build Coastguard Worker {"0.7000 => {0x2c, 0xc, 0x2d}", SkFloatToFixed(0.7000f), 63, 0xb3002d, 63},
149*c8dee2aaSAndroid Build Coastguard Worker {"0.8000 => {0x33, 0x3, 0x34}", SkFloatToFixed(0.8000f), 63, 0xccc034, 63},
150*c8dee2aaSAndroid Build Coastguard Worker {"0.9000 => {0x39, 0x9, 0x3a}", SkFloatToFixed(0.9000f), 63, 0xe6403a, 63},
151*c8dee2aaSAndroid Build Coastguard Worker {"0.9500 => {0x3c, 0xc, 0x3d}", SkFloatToFixed(0.9500f), 63, 0xf3003d, 63},
152*c8dee2aaSAndroid Build Coastguard Worker {"0.9990 => {0x3f, 0xe, 0x00}", SkFloatToFixed(0.9990f), 63, 0xff8000, 63},
153*c8dee2aaSAndroid Build Coastguard Worker // As we go past 1.0, we wrap around, conceptually similar to modular arithmetic.
154*c8dee2aaSAndroid Build Coastguard Worker {"1.0000 => {0x00, 0x0, 0x01}", SkFloatToFixed(1.0000f), 63, 0x000001, 63},
155*c8dee2aaSAndroid Build Coastguard Worker {"1.1000 => {0x06, 0x6, 0x07}", SkFloatToFixed(1.1000f), 63, 0x198007, 63},
156*c8dee2aaSAndroid Build Coastguard Worker {"1.1234 => {0x07, 0xe, 0x08}", SkFloatToFixed(1.1234f), 63, 0x1f8008, 63},
157*c8dee2aaSAndroid Build Coastguard Worker {"1.9500 => {0x3c, 0xc, 0x3d}", SkFloatToFixed(1.9500f), 63, 0xf3003d, 63},
158*c8dee2aaSAndroid Build Coastguard Worker // Maximum has changed from 63 to 256
159*c8dee2aaSAndroid Build Coastguard Worker {"0.4567 => {0x75, 0x5, 0x76}", SkFloatToFixed(0.4567f), 256, 0x1d54076, 256},
160*c8dee2aaSAndroid Build Coastguard Worker {"1.0000 => {0x00, 0x0, 0x01}", SkFloatToFixed(1.0000f), 256, 0x0000001, 256},
161*c8dee2aaSAndroid Build Coastguard Worker {"1.2345 => {0x3c, 0x4, 0x3d}", SkFloatToFixed(1.2345f), 256, 0x0f1003d, 256},
162*c8dee2aaSAndroid Build Coastguard Worker // width does not have to match the maximum value (e.g. rescaling)
163*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64,128] => {0x07, 0x3, 0x07}", SkFloatToFixed(0.1111f), 64, 0x1cc007, 128},
164*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64,256] => {0x07, 0x3, 0x07}", SkFloatToFixed(0.1111f), 64, 0x1cc007, 256},
165*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64,512] => {0x07, 0x3, 0x07}", SkFloatToFixed(0.1111f), 64, 0x1cc007, 512},
166*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64, 32] => {0x07, 0x3, 0x09}", SkFloatToFixed(0.1111f), 64, 0x1cc009, 32},
167*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64, 8] => {0x07, 0x3, 0x0f}", SkFloatToFixed(0.1111f), 64, 0x1cc00f, 8},
168*c8dee2aaSAndroid Build Coastguard Worker };
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker constexpr size_t NUM_TESTS = sizeof(tests) / sizeof(TestCase);
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < NUM_TESTS; i++) {
173*c8dee2aaSAndroid Build Coastguard Worker TestCase tc = tests[i];
174*c8dee2aaSAndroid Build Coastguard Worker uint32_t rv = sktests::pack_repeat(tc.input, tc.max, tc.width);
175*c8dee2aaSAndroid Build Coastguard Worker uint32_t exp = tc.expectedOutput;
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, rv == tc.expectedOutput,
178*c8dee2aaSAndroid Build Coastguard Worker "%s | %x != %x | {%x, %x, %x} != {%x, %x, %x}\n",
179*c8dee2aaSAndroid Build Coastguard Worker tc.name.c_str(), rv, exp,
180*c8dee2aaSAndroid Build Coastguard Worker highBits(rv), middleBits(rv), lowBits(rv),
181*c8dee2aaSAndroid Build Coastguard Worker highBits(exp), middleBits(exp), lowBits(exp));
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MatrixProcs_pack_mirror,r)185*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MatrixProcs_pack_mirror, r) {
186*c8dee2aaSAndroid Build Coastguard Worker struct TestCase {
187*c8dee2aaSAndroid Build Coastguard Worker std::string name;
188*c8dee2aaSAndroid Build Coastguard Worker SkFixed input;
189*c8dee2aaSAndroid Build Coastguard Worker unsigned max;
190*c8dee2aaSAndroid Build Coastguard Worker uint32_t expectedOutput;
191*c8dee2aaSAndroid Build Coastguard Worker size_t width;
192*c8dee2aaSAndroid Build Coastguard Worker };
193*c8dee2aaSAndroid Build Coastguard Worker TestCase tests[] = {
194*c8dee2aaSAndroid Build Coastguard Worker // negative values are treated similarly to absolute values, except
195*c8dee2aaSAndroid Build Coastguard Worker // the first integer is bigger than the last integer.
196*c8dee2aaSAndroid Build Coastguard Worker {"-0.300 => {0x13, 0xc, 0x12}", SkFloatToFixed(-0.300f), 63, 0x4f0012, 63},
197*c8dee2aaSAndroid Build Coastguard Worker {"-0.200 => {0x0c, 0x3, 0x0b}", SkFloatToFixed(-0.200f), 63, 0x30c00b, 63},
198*c8dee2aaSAndroid Build Coastguard Worker {"-0.100 => {0x06, 0x9, 0x05}", SkFloatToFixed(-0.100f), 63, 0x1a4005, 63},
199*c8dee2aaSAndroid Build Coastguard Worker // The domain of the function is primarily [0.0, 1.0)
200*c8dee2aaSAndroid Build Coastguard Worker {"0.0000 => {0x00, 0x0, 0x01}", SkFloatToFixed(0.0000f), 63, 0x000001, 63},
201*c8dee2aaSAndroid Build Coastguard Worker {"0.1000 => {0x06, 0x6, 0x07}", SkFloatToFixed(0.1000f), 63, 0x198007, 63},
202*c8dee2aaSAndroid Build Coastguard Worker {"0.1234 => {0x07, 0xe, 0x08}", SkFloatToFixed(0.1234f), 63, 0x1f8008, 63},
203*c8dee2aaSAndroid Build Coastguard Worker {"0.2000 => {0x0c, 0xc, 0x0d}", SkFloatToFixed(0.2000f), 63, 0x33000d, 63},
204*c8dee2aaSAndroid Build Coastguard Worker {"0.3000 => {0x13, 0x3, 0x14}", SkFloatToFixed(0.3000f), 63, 0x4cc014, 63},
205*c8dee2aaSAndroid Build Coastguard Worker {"0.4000 => {0x19, 0x9, 0x1a}", SkFloatToFixed(0.4000f), 63, 0x66401a, 63},
206*c8dee2aaSAndroid Build Coastguard Worker {"0.5000 => {0x20, 0x0, 0x21}", SkFloatToFixed(0.5000f), 63, 0x800021, 63},
207*c8dee2aaSAndroid Build Coastguard Worker {"0.5678 => {0x24, 0x5, 0x25}", SkFloatToFixed(0.5678f), 63, 0x914025, 63},
208*c8dee2aaSAndroid Build Coastguard Worker {"0.6000 => {0x26, 0x6, 0x27}", SkFloatToFixed(0.6000f), 63, 0x998027, 63},
209*c8dee2aaSAndroid Build Coastguard Worker {"0.7000 => {0x2c, 0xc, 0x2d}", SkFloatToFixed(0.7000f), 63, 0xb3002d, 63},
210*c8dee2aaSAndroid Build Coastguard Worker {"0.8000 => {0x33, 0x3, 0x34}", SkFloatToFixed(0.8000f), 63, 0xccc034, 63},
211*c8dee2aaSAndroid Build Coastguard Worker {"0.9000 => {0x39, 0x9, 0x3a}", SkFloatToFixed(0.9000f), 63, 0xe6403a, 63},
212*c8dee2aaSAndroid Build Coastguard Worker {"0.9500 => {0x3c, 0xc, 0x3d}", SkFloatToFixed(0.9500f), 63, 0xf3003d, 63},
213*c8dee2aaSAndroid Build Coastguard Worker {"0.9990 => {0x3f, 0xe, 0x3f}", SkFloatToFixed(0.9990f), 63, 0xff803f, 63},
214*c8dee2aaSAndroid Build Coastguard Worker // As we go past 1.0, we bounce back, as off a wall or reflecting off a mirror.
215*c8dee2aaSAndroid Build Coastguard Worker {"1.0000 => {0x3f, 0x0, 0x3e}", SkFloatToFixed(1.0000f), 63, 0xfc003e, 63},
216*c8dee2aaSAndroid Build Coastguard Worker {"1.1000 => {0x39, 0x6, 0x38}", SkFloatToFixed(1.1000f), 63, 0xe58038, 63},
217*c8dee2aaSAndroid Build Coastguard Worker {"1.1234 => {0x38, 0xe, 0x37}", SkFloatToFixed(1.1234f), 63, 0xe38037, 63},
218*c8dee2aaSAndroid Build Coastguard Worker {"1.9500 => {0x03, 0xc, 0x02}", SkFloatToFixed(1.9500f), 63, 0xf0002, 63},
219*c8dee2aaSAndroid Build Coastguard Worker // Maximum has changed from 63 to 256
220*c8dee2aaSAndroid Build Coastguard Worker {"0.4567 => {0x75, 0x5, 0x76}", SkFloatToFixed(0.4567f), 256, 0x1d54076, 256},
221*c8dee2aaSAndroid Build Coastguard Worker {"1.0000 => {0x100,0x0, 0xff}", SkFloatToFixed(1.0000f), 256, 0x40000ff, 256},
222*c8dee2aaSAndroid Build Coastguard Worker {"1.2345 => {0xc4, 0x4, 0xc3}", SkFloatToFixed(1.2345f), 256, 0x31100c3, 256},
223*c8dee2aaSAndroid Build Coastguard Worker // width does not have to match the maximum value (e.g. rescaling)
224*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64,128] => {0x07, 0x3, 0x07}", SkFloatToFixed(0.1111f), 64, 0x1cc007, 128},
225*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64,256] => {0x07, 0x3, 0x07}", SkFloatToFixed(0.1111f), 64, 0x1cc007, 256},
226*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64,512] => {0x07, 0x3, 0x07}", SkFloatToFixed(0.1111f), 64, 0x1cc007, 512},
227*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64, 32] => {0x07, 0x3, 0x09}", SkFloatToFixed(0.1111f), 64, 0x1cc009, 32},
228*c8dee2aaSAndroid Build Coastguard Worker {"0.1111 [64, 8] => {0x07, 0x3, 0x0f}", SkFloatToFixed(0.1111f), 64, 0x1cc00f, 8},
229*c8dee2aaSAndroid Build Coastguard Worker };
230*c8dee2aaSAndroid Build Coastguard Worker
231*c8dee2aaSAndroid Build Coastguard Worker constexpr size_t NUM_TESTS = sizeof(tests) / sizeof(TestCase);
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < NUM_TESTS; i++) {
234*c8dee2aaSAndroid Build Coastguard Worker TestCase tc = tests[i];
235*c8dee2aaSAndroid Build Coastguard Worker uint32_t rv = sktests::pack_mirror(tc.input, tc.max, tc.width);
236*c8dee2aaSAndroid Build Coastguard Worker uint32_t exp = tc.expectedOutput;
237*c8dee2aaSAndroid Build Coastguard Worker
238*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, rv == tc.expectedOutput,
239*c8dee2aaSAndroid Build Coastguard Worker "%s | %x != %x | {%x, %x, %x} != {%x, %x, %x}\n",
240*c8dee2aaSAndroid Build Coastguard Worker tc.name.c_str(), rv, exp,
241*c8dee2aaSAndroid Build Coastguard Worker highBits(rv), middleBits(rv), lowBits(rv),
242*c8dee2aaSAndroid Build Coastguard Worker highBits(exp), middleBits(exp), lowBits(exp));
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker }
245*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MatrixProcs_unpack_int,r)246*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MatrixProcs_unpack_int, r) {
247*c8dee2aaSAndroid Build Coastguard Worker struct TestCase {
248*c8dee2aaSAndroid Build Coastguard Worker std::string name;
249*c8dee2aaSAndroid Build Coastguard Worker uint32_t input;
250*c8dee2aaSAndroid Build Coastguard Worker uint32_t expectedLowerBound;
251*c8dee2aaSAndroid Build Coastguard Worker uint32_t expectedLerp;
252*c8dee2aaSAndroid Build Coastguard Worker uint32_t expectedUpperBound;
253*c8dee2aaSAndroid Build Coastguard Worker };
254*c8dee2aaSAndroid Build Coastguard Worker // These are selected from earlier tests to make sure the packed values unpack correctly.
255*c8dee2aaSAndroid Build Coastguard Worker TestCase tests[] = {
256*c8dee2aaSAndroid Build Coastguard Worker {"0x000000 => {0x00, 0x0, 0x00}", 0x000000, 0x00, 0x0, 0x00},
257*c8dee2aaSAndroid Build Coastguard Worker {"0x074002 => {0x01, 0xd, 0x02}", 0x074002, 0x01, 0xd, 0x02},
258*c8dee2aaSAndroid Build Coastguard Worker {"0x15c006 => {0x05, 0x7, 0x06}", 0x15c006, 0x05, 0x7, 0x06},
259*c8dee2aaSAndroid Build Coastguard Worker {"0x1d0008 => {0x07, 0x4, 0x08}", 0x1d0008, 0x07, 0x4, 0x08},
260*c8dee2aaSAndroid Build Coastguard Worker {"0x24000a => {0x09, 0x0, 0x0a}", 0x24000a, 0x09, 0x0, 0x0a},
261*c8dee2aaSAndroid Build Coastguard Worker {"0xfc003f => {0x3f, 0x0, 0x3f}", 0xfc003f, 0x3f, 0x0, 0x3f},
262*c8dee2aaSAndroid Build Coastguard Worker {"0x4000100 => {0x100, 0x0, 0x100}", 0x4000100, 0x100, 0x0, 0x100},
263*c8dee2aaSAndroid Build Coastguard Worker };
264*c8dee2aaSAndroid Build Coastguard Worker
265*c8dee2aaSAndroid Build Coastguard Worker constexpr size_t NUM_TESTS = sizeof(tests) / sizeof(TestCase);
266*c8dee2aaSAndroid Build Coastguard Worker
267*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < NUM_TESTS; i++) {
268*c8dee2aaSAndroid Build Coastguard Worker TestCase tc = tests[i];
269*c8dee2aaSAndroid Build Coastguard Worker uint32_t lower, upper, lerp;
270*c8dee2aaSAndroid Build Coastguard Worker sktests::decode_packed_coordinates_and_weight(tc.input, &lower, &upper, &lerp);
271*c8dee2aaSAndroid Build Coastguard Worker
272*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, lower == tc.expectedLowerBound,
273*c8dee2aaSAndroid Build Coastguard Worker "%s lower %x != %x", tc.name.c_str(), lower, tc.expectedLowerBound);
274*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, lerp == tc.expectedLerp,
275*c8dee2aaSAndroid Build Coastguard Worker "%s lerp %x != %x", tc.name.c_str(), lerp, tc.expectedLerp);
276*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, upper == tc.expectedUpperBound,
277*c8dee2aaSAndroid Build Coastguard Worker "%s upper %x != %x", tc.name.c_str(), upper, tc.expectedUpperBound);
278*c8dee2aaSAndroid Build Coastguard Worker // Make sure our helpers work as expected.
279*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(tc.expectedLowerBound == highBits(tc.input));
280*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(tc.expectedLerp == middleBits(tc.input));
281*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(tc.expectedUpperBound == lowBits(tc.input));
282*c8dee2aaSAndroid Build Coastguard Worker }
283*c8dee2aaSAndroid Build Coastguard Worker }
284