1 /* 2 * Copyright 2016 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 "Test.h" 9 #include "SkHalf.h" 10 #include "SkRasterPipeline.h" 11 #include "../src/jumper/SkJumper.h" 12 13 DEF_TEST(SkRasterPipeline, r) { 14 // Build and run a simple pipeline to exercise SkRasterPipeline, 15 // drawing 50% transparent blue over opaque red in half-floats. 16 uint64_t red = 0x3c00000000003c00ull, 17 blue = 0x3800380000000000ull, 18 result; 19 20 void* load_s_ctx = &blue; 21 void* load_d_ctx = &red; 22 void* store_ctx = &result; 23 24 SkRasterPipeline_<256> p; 25 p.append(SkRasterPipeline::load_f16, &load_s_ctx); 26 p.append(SkRasterPipeline::load_f16_dst, &load_d_ctx); 27 p.append(SkRasterPipeline::srcover); 28 p.append(SkRasterPipeline::store_f16, &store_ctx); 29 p.run(0,0,1); 30 31 // We should see half-intensity magenta. 32 REPORTER_ASSERT(r, ((result >> 0) & 0xffff) == 0x3800); 33 REPORTER_ASSERT(r, ((result >> 16) & 0xffff) == 0x0000); 34 REPORTER_ASSERT(r, ((result >> 32) & 0xffff) == 0x3800); 35 REPORTER_ASSERT(r, ((result >> 48) & 0xffff) == 0x3c00); 36 } 37 38 DEF_TEST(SkRasterPipeline_empty, r) { 39 // No asserts... just a test that this is safe to run. 40 SkRasterPipeline_<256> p; 41 p.run(0,0,20); 42 } 43 44 DEF_TEST(SkRasterPipeline_nonsense, r) { 45 // No asserts... just a test that this is safe to run and terminates. 46 // srcover() calls st->next(); this makes sure we've always got something there to call. 47 SkRasterPipeline_<256> p; 48 p.append(SkRasterPipeline::srcover); 49 p.run(0,0,20); 50 } 51 52 DEF_TEST(SkRasterPipeline_JIT, r) { 53 // This tests a couple odd corners that a JIT backend can stumble over. 54 55 uint32_t buf[72] = { 56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 58 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62 }; 63 64 const uint32_t* src = buf + 0; 65 uint32_t* dst = buf + 36; 66 67 // Copy buf[x] to buf[x+36] for x in [15,35). 68 SkRasterPipeline_<256> p; 69 p.append(SkRasterPipeline:: load_8888, &src); 70 p.append(SkRasterPipeline::store_8888, &dst); 71 p.run(15,0, 20); 72 73 for (int i = 0; i < 36; i++) { 74 if (i < 15 || i == 35) { 75 REPORTER_ASSERT(r, dst[i] == 0); 76 } else { 77 REPORTER_ASSERT(r, dst[i] == (uint32_t)(i - 11)); 78 } 79 } 80 } 81 82 static uint16_t h(float f) { 83 // Remember, a float is 1-8-23 (sign-exponent-mantissa) with 127 exponent bias. 84 uint32_t sem; 85 memcpy(&sem, &f, sizeof(sem)); 86 uint32_t s = sem & 0x80000000, 87 em = sem ^ s; 88 89 // Convert to 1-5-10 half with 15 bias, flushing denorm halfs (including zero) to zero. 90 auto denorm = (int32_t)em < 0x38800000; // I32 comparison is often quicker, and always safe 91 // here. 92 return denorm ? SkTo<uint16_t>(0) 93 : SkTo<uint16_t>((s>>16) + (em>>13) - ((127-15)<<10)); 94 } 95 96 static uint16_t n(uint16_t x) { 97 return (x<<8) | (x>>8); 98 } 99 100 static float a(uint16_t x) { 101 return (1/65535.0f) * x; 102 } 103 104 DEF_TEST(SkRasterPipeline_tail, r) { 105 { 106 float data[][4] = { 107 {00, 01, 02, 03}, 108 {10, 11, 12, 13}, 109 {20, 21, 22, 23}, 110 {30, 31, 32, 33}, 111 }; 112 113 float buffer[4][4]; 114 float* src = &data[0][0]; 115 float* dst = &buffer[0][0]; 116 117 for (unsigned i = 1; i <= 4; i++) { 118 memset(buffer, 0xff, sizeof(buffer)); 119 SkRasterPipeline_<256> p; 120 p.append(SkRasterPipeline::load_f32, &src); 121 p.append(SkRasterPipeline::store_f32, &dst); 122 p.run(0,0, i); 123 for (unsigned j = 0; j < i; j++) { 124 for (unsigned k = 0; k < 4; k++) { 125 if (buffer[j][k] != data[j][k]) { 126 ERRORF(r, "(%u, %u) - a: %g r: %g\n", j, k, data[j][k], buffer[j][k]); 127 } 128 } 129 } 130 for (int j = i; j < 4; j++) { 131 for (auto f : buffer[j]) { 132 REPORTER_ASSERT(r, SkScalarIsNaN(f)); 133 } 134 } 135 } 136 } 137 138 { 139 uint16_t data[][4] = { 140 {h(00), h(01), h(02), h(03)}, 141 {h(10), h(11), h(12), h(13)}, 142 {h(20), h(21), h(22), h(23)}, 143 {h(30), h(31), h(32), h(33)}, 144 }; 145 uint16_t buffer[4][4]; 146 uint16_t* src = &data[0][0]; 147 uint16_t* dst = &buffer[0][0]; 148 149 for (unsigned i = 1; i <= 4; i++) { 150 memset(buffer, 0xff, sizeof(buffer)); 151 SkRasterPipeline_<256> p; 152 p.append(SkRasterPipeline::load_f16, &src); 153 p.append(SkRasterPipeline::store_f16, &dst); 154 p.run(0,0, i); 155 for (unsigned j = 0; j < i; j++) { 156 REPORTER_ASSERT(r, 157 !memcmp(&data[j][0], &buffer[j][0], sizeof(buffer[j]))); 158 } 159 for (int j = i; j < 4; j++) { 160 for (auto f : buffer[j]) { 161 REPORTER_ASSERT(r, f == 0xffff); 162 } 163 } 164 } 165 } 166 167 { 168 uint16_t data[][3] = { 169 {n(00), n(01), n(02)}, 170 {n(10), n(11), n(12)}, 171 {n(20), n(21), n(22)}, 172 {n(30), n(31), n(32)} 173 }; 174 175 float answer[][4] = { 176 {a(00), a(01), a(02), 1.0f}, 177 {a(10), a(11), a(12), 1.0f}, 178 {a(20), a(21), a(22), 1.0f}, 179 {a(30), a(31), a(32), 1.0f} 180 }; 181 182 float buffer[4][4]; 183 uint16_t* src = &data[0][0]; 184 float* dst = &buffer[0][0]; 185 186 for (unsigned i = 1; i <= 4; i++) { 187 memset(buffer, 0xff, sizeof(buffer)); 188 SkRasterPipeline_<256> p; 189 p.append(SkRasterPipeline::load_rgb_u16_be, &src); 190 p.append(SkRasterPipeline::store_f32, &dst); 191 p.run(0,0, i); 192 for (unsigned j = 0; j < i; j++) { 193 for (unsigned k = 0; k < 4; k++) { 194 if (buffer[j][k] != answer[j][k]) { 195 ERRORF(r, "(%u, %u) - a: %g r: %g\n", j, k, answer[j][k], buffer[j][k]); 196 } 197 } 198 } 199 for (int j = i; j < 4; j++) { 200 for (auto f : buffer[j]) { 201 REPORTER_ASSERT(r, SkScalarIsNaN(f)); 202 } 203 } 204 } 205 } 206 } 207 208 DEF_TEST(SkRasterPipeline_lowp, r) { 209 uint32_t rgba[64]; 210 for (int i = 0; i < 64; i++) { 211 rgba[i] = (4*i+0) << 0 212 | (4*i+1) << 8 213 | (4*i+2) << 16 214 | (4*i+3) << 24; 215 } 216 217 void* ptr = rgba; 218 219 SkRasterPipeline_<256> p; 220 p.append(SkRasterPipeline::load_bgra, &ptr); 221 p.append(SkRasterPipeline::store_8888, &ptr); 222 p.run(0,0,64); 223 224 for (int i = 0; i < 64; i++) { 225 uint32_t want = (4*i+0) << 16 226 | (4*i+1) << 8 227 | (4*i+2) << 0 228 | (4*i+3) << 24; 229 if (rgba[i] != want) { 230 ERRORF(r, "got %08x, want %08x\n", rgba[i], want); 231 } 232 } 233 } 234 235 DEF_TEST(SkRasterPipeline_2d, r) { 236 uint32_t rgba[2*2] = {0,0,0,0}; 237 238 SkSTArenaAlloc<256> alloc; 239 SkRasterPipeline p(&alloc); 240 241 // Splat out the (2d) dst coordinates: (0.5,0.5), (1.5,0.5), (0.5,1.5), (1.5,1.5). 242 p.append(SkRasterPipeline::seed_shader); 243 244 // Scale down to [0,1] range to write out as bytes. 245 p.append_matrix(&alloc, SkMatrix::Concat(SkMatrix::MakeScale(0.5f), 246 SkMatrix::MakeTrans(-0.5f, -0.5f))); 247 248 // Write out to rgba, with row stride = 2 pixels. 249 SkJumper_MemoryCtx ctx = { rgba, 2 }; 250 p.append(SkRasterPipeline::store_8888_2d, &ctx); 251 252 p.run_2d(0,0, 2,2); 253 254 REPORTER_ASSERT(r, ((rgba[0] >> 0) & 0xff) == 0); 255 REPORTER_ASSERT(r, ((rgba[1] >> 0) & 0xff) == 128); 256 REPORTER_ASSERT(r, ((rgba[2] >> 0) & 0xff) == 0); 257 REPORTER_ASSERT(r, ((rgba[3] >> 0) & 0xff) == 128); 258 259 REPORTER_ASSERT(r, ((rgba[0] >> 8) & 0xff) == 0); 260 REPORTER_ASSERT(r, ((rgba[1] >> 8) & 0xff) == 0); 261 REPORTER_ASSERT(r, ((rgba[2] >> 8) & 0xff) == 128); 262 REPORTER_ASSERT(r, ((rgba[3] >> 8) & 0xff) == 128); 263 } 264