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 "SkPM4f.h" 9 #include "SkRasterPipeline.h" 10 #include "SkSRGB.h" 11 #include "SkTypes.h" 12 #include "Test.h" 13 #include <math.h> 14 15 static uint8_t linear_to_srgb(float l) { 16 return (uint8_t)sk_linear_to_srgb(Sk4f{l})[0]; 17 } 18 19 DEF_TEST(sk_linear_to_srgb, r) { 20 // All bytes should round trip. 21 for (int i = 0; i < 256; i++) { 22 int actual = linear_to_srgb(sk_linear_from_srgb[i]); 23 if (i != actual) { 24 ERRORF(r, "%d -> %d\n", i, actual); 25 } 26 } 27 28 // Should be monotonic between 0 and 1. 29 uint8_t prev = 0; 30 for (float f = FLT_MIN; f <= 1.0f; ) { // We don't bother checking denorm values. 31 uint8_t srgb = linear_to_srgb(f); 32 33 REPORTER_ASSERT(r, srgb >= prev); 34 prev = srgb; 35 36 union { float flt; uint32_t bits; } pun = { f }; 37 pun.bits++; 38 SkDEBUGCODE(pun.bits += 127); 39 f = pun.flt; 40 } 41 } 42 43 DEF_TEST(sk_pipeline_srgb_roundtrip, r) { 44 uint32_t reds[256]; 45 for (int i = 0; i < 256; i++) { 46 reds[i] = i; 47 } 48 49 auto ptr = (void*)reds; 50 51 SkRasterPipeline_<256> p; 52 p.append(SkRasterPipeline::load_8888, &ptr); 53 p.append_from_srgb(kUnpremul_SkAlphaType); 54 p.append(SkRasterPipeline::to_srgb); 55 p.append(SkRasterPipeline::store_8888, &ptr); 56 57 p.run(0,0,256); 58 59 for (int i = 0; i < 256; i++) { 60 if (reds[i] != (uint32_t)i) { 61 ERRORF(r, "%d doesn't round trip, %d", i, reds[i]); 62 } 63 } 64 } 65 66 DEF_TEST(sk_pipeline_srgb_edge_cases, r) { 67 // We need to run at least 4 pixels to make sure we hit all specializations. 68 SkPM4f colors[4] = { {{0,1,1,1}}, {{0,0,0,0}}, {{0,0,0,0}}, {{0,0,0,0}} }; 69 auto& color = colors[0]; 70 void* dst = &color; 71 72 SkRasterPipeline_<256> p; 73 p.append(SkRasterPipeline::uniform_color, &color); 74 p.append(SkRasterPipeline::to_srgb); 75 p.append(SkRasterPipeline::store_f32, &dst); 76 p.run(0,0,4); 77 78 if (color.r() != 0.0f) { 79 ERRORF(r, "expected to_srgb() to map 0.0f to 0.0f, got %f", color.r()); 80 } 81 if (color.g() != 1.0f) { 82 float f = color.g(); 83 uint32_t x; 84 memcpy(&x, &f, 4); 85 ERRORF(r, "expected to_srgb() to map 1.0f to 1.0f, got %f (%08x)", color.g(), x); 86 } 87 } 88