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 <string> 9 #include <tuple> 10 #include <vector> 11 #include "Resources.h" 12 #include "SkCpu.h" 13 #include "SkImage.h" 14 #include "SkImage_Base.h" 15 #include "SkOpts.h" 16 #include "SkPM4fPriv.h" 17 #include "SkNx.h" 18 #include "Test.h" 19 20 typedef void (*Blender)(uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); 21 22 static inline void srcover_srgb_srgb_1(uint32_t* dst, uint32_t src) { 23 auto d = Sk4f_fromS32(*dst), 24 s = Sk4f_fromS32( src); 25 *dst = Sk4f_toS32(s + d * (1.0f - s[3])); 26 } 27 28 static void brute_force_srcover_srgb_srgb( 29 uint32_t* dst, const uint32_t* const src, int ndst, const int nsrc) { 30 while (ndst > 0) { 31 int n = SkTMin(ndst, nsrc); 32 33 for (int i = 0; i < n; i++) { 34 srcover_srgb_srgb_1(dst++, src[i]); 35 } 36 ndst -= n; 37 } 38 } 39 40 static SkString mismatch_message(std::string resourceName, int x, int y, 41 uint32_t src, uint32_t good, uint32_t bad) { 42 return SkStringPrintf( 43 "%s - missmatch at %d, %d src: %08x good: %08x bad: %08x", 44 resourceName.c_str(), x, y, src, good, bad); 45 } 46 47 static void test_blender(std::string resourceName, skiatest::Reporter* reporter) { 48 std::string fileName = resourceName + ".png"; 49 sk_sp<SkImage> image = GetResourceAsImage(fileName.c_str()); 50 if (image == nullptr) { 51 ERRORF(reporter, "image is NULL"); 52 return; 53 } 54 SkBitmap bm; 55 sk_sp<SkColorSpace> srgbColorSpace = SkColorSpace::MakeSRGB(); 56 if (!as_IB(image)->getROPixels(&bm, srgbColorSpace.get())) { 57 ERRORF(reporter, "Could not read resource"); 58 return; 59 } 60 61 SkPixmap pixmap; 62 bm.peekPixels(&pixmap); 63 SkASSERTF(pixmap.colorType() == kN32_SkColorType, "colorType: %d", pixmap.colorType()); 64 SkASSERT(pixmap.alphaType() != kUnpremul_SkAlphaType); 65 const uint32_t* src = pixmap.addr32(); 66 const int width = pixmap.rowBytesAsPixels(); 67 SkASSERT(width > 0); 68 SkASSERT(width < 4000); 69 SkAutoTArray<uint32_t> correctDst(width); 70 SkAutoTArray<uint32_t> testDst(width); 71 72 for (int y = 0; y < pixmap.height(); y++) { 73 // TODO: zero is not the most interesting dst to test srcover... 74 sk_bzero(correctDst.get(), width * sizeof(uint32_t)); 75 sk_bzero(testDst.get(), width * sizeof(uint32_t)); 76 brute_force_srcover_srgb_srgb(correctDst.get(), src, width, width); 77 SkOpts:: srcover_srgb_srgb( testDst.get(), src, width, width); 78 for (int x = 0; x < width; x++) { 79 REPORTER_ASSERT_MESSAGE( 80 reporter, correctDst[x] == testDst[x], 81 mismatch_message(resourceName, x, y, src[x], correctDst[x], testDst[x])); 82 if (correctDst[x] != testDst[x]) break; 83 } 84 src += width; 85 } 86 } 87 88 DEF_TEST(SkBlend_optsCheck, reporter) { 89 std::vector<std::string> testResources = { 90 "yellow_rose", "baby_tux", "plane", "mandrill_512", "iconstrip" 91 }; 92 93 for (auto& resourceName : testResources) { 94 test_blender(resourceName, reporter); 95 } 96 } 97 98 DEF_TEST(SkBlend_optsSqrtCheck, reporter) { 99 for (int c = 0; c < 256; c++) { 100 Sk4f i{(float)c}; 101 Sk4f ii = i * i; 102 Sk4f s = ii.sqrt() + 0.5f; 103 Sk4f sf = s.floor(); 104 REPORTER_ASSERT_MESSAGE( 105 reporter, i[0] == sf[0], SkStringPrintf("i: %f, s: %f", i[0], sf[0])); 106 } 107 } 108