| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  * Copyright 2016 Google Inc. |    2  * Copyright 2016 Google Inc. | 
|    3  * |    3  * | 
|    4  * Use of this source code is governed by a BSD-style license that can be |    4  * Use of this source code is governed by a BSD-style license that can be | 
|    5  * found in the LICENSE file. |    5  * found in the LICENSE file. | 
|    6  */ |    6  */ | 
|    7  |    7  | 
|    8 #include <tuple> |    8 #include <tuple> | 
|    9  |    9  | 
|   10 #include "Benchmark.h" |   10 #include "Benchmark.h" | 
|   11 #include "Resources.h" |   11 #include "Resources.h" | 
|   12 #include "SkCpu.h" |   12 #include "SkCpu.h" | 
|   13 #include "SkImage.h" |   13 #include "SkImage.h" | 
|   14 #include "SkImage_Base.h" |   14 #include "SkImage_Base.h" | 
|   15 #include "SkNx.h" |   15 #include "SkNx.h" | 
|   16 #include "SkOpts.h" |   16 #include "SkOpts.h" | 
 |   17 #include "SkPM4fPriv.h" | 
|   17 #include "SkString.h" |   18 #include "SkString.h" | 
|   18  |   19  | 
|   19 #define INNER_LOOPS 10 |   20 #define INNER_LOOPS 10 | 
|   20  |   21  | 
|   21 namespace sk_default { |   22 static void brute_force_srcover_srgb_srgb( | 
|   22 extern void brute_force_srcover_srgb_srgb( |   23     uint32_t* dst, const uint32_t* const src, int ndst, const int nsrc) { | 
|   23     uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); |   24     while (ndst > 0) { | 
 |   25         int n = SkTMin(ndst, nsrc); | 
 |   26  | 
 |   27         for (int i = 0; i < n; i++) { | 
 |   28             srcover_blend_srgb8888_srgb_1(dst++, srgb_to_linear(to_4f(src[i]))); | 
 |   29         } | 
 |   30         ndst -= n; | 
 |   31     } | 
 |   32 } | 
 |   33  | 
 |   34 static void best_non_simd_srcover_srgb_srgb( | 
 |   35     uint32_t* dst, const uint32_t* const src, int ndst, const int nsrc) { | 
 |   36     uint64_t* ddst = reinterpret_cast<uint64_t*>(dst); | 
 |   37  | 
 |   38     auto srcover_srgb_srgb_2 = [](uint32_t* dst, const uint32_t* src) { | 
 |   39         srcover_srgb8888_srgb_1(dst++, *src++); | 
 |   40         srcover_srgb8888_srgb_1(dst, *src); | 
 |   41     }; | 
 |   42  | 
 |   43     while (ndst >0) { | 
 |   44         int count = SkTMin(ndst, nsrc); | 
 |   45         ndst -= count; | 
 |   46         const uint64_t* dsrc = reinterpret_cast<const uint64_t*>(src); | 
 |   47         const uint64_t* end = dsrc + (count >> 1); | 
 |   48         do { | 
 |   49             if ((~*dsrc & 0xFF000000FF000000) == 0) { | 
 |   50                 do { | 
 |   51                     *ddst++ = *dsrc++; | 
 |   52                 } while (dsrc < end && (~*dsrc & 0xFF000000FF000000) == 0); | 
 |   53             } else if ((*dsrc & 0xFF000000FF000000) == 0) { | 
 |   54                 do { | 
 |   55                     dsrc++; | 
 |   56                     ddst++; | 
 |   57                 } while (dsrc < end && (*dsrc & 0xFF000000FF000000) == 0); | 
 |   58             } else { | 
 |   59                 srcover_srgb_srgb_2(reinterpret_cast<uint32_t*>(ddst++), | 
 |   60                                     reinterpret_cast<const uint32_t*>(dsrc++)); | 
 |   61             } | 
 |   62         } while (dsrc < end); | 
 |   63  | 
 |   64         if ((count & 1) != 0) { | 
 |   65             srcover_srgb8888_srgb_1(reinterpret_cast<uint32_t*>(ddst), | 
 |   66                                     *reinterpret_cast<const uint32_t*>(dsrc)); | 
 |   67         } | 
 |   68     } | 
 |   69 } | 
 |   70  | 
 |   71 static void trivial_srcover_srgb_srgb( | 
 |   72     uint32_t* dst, const uint32_t* const src, int ndst, const int nsrc) { | 
 |   73     while (ndst > 0) { | 
 |   74         int n = SkTMin(ndst, nsrc); | 
 |   75  | 
 |   76         for (int i = 0; i < n; i++) { | 
 |   77             srcover_srgb8888_srgb_1(dst++, src[i]); | 
 |   78         } | 
 |   79         ndst -= n; | 
 |   80     } | 
|   24 } |   81 } | 
|   25  |   82  | 
|   26 class SrcOverVSkOptsBruteForce { |   83 class SrcOverVSkOptsBruteForce { | 
|   27 public: |   84 public: | 
|   28     static SkString Name() { return SkString{"VSkOptsBruteForce"}; } |   85     static SkString Name() { return SkString{"VSkOptsBruteForce"}; } | 
|   29     static bool WorksOnCpu() { return true; } |   86     static bool WorksOnCpu() { return true; } | 
|   30     static void BlendN(uint32_t* dst, int count, const uint32_t* src) { |   87     static void BlendN(uint32_t* dst, const uint32_t* src, int count) { | 
|   31         sk_default::brute_force_srcover_srgb_srgb(dst, src, count, count); |   88         brute_force_srcover_srgb_srgb(dst, src, count, count); | 
|   32     } |   89     } | 
|   33 }; |   90 }; | 
|   34  |   91  | 
|   35 namespace sk_default { |  | 
|   36 extern void trivial_srcover_srgb_srgb( |  | 
|   37     uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); |  | 
|   38 } |  | 
|   39  |  | 
|   40 class SrcOverVSkOptsTrivial { |   92 class SrcOverVSkOptsTrivial { | 
|   41 public: |   93 public: | 
|   42     static SkString Name() { return SkString{"VSkOptsTrivial"}; } |   94     static SkString Name() { return SkString{"VSkOptsTrivial"}; } | 
|   43     static bool WorksOnCpu() { return true; } |   95     static bool WorksOnCpu() { return true; } | 
|   44     static void BlendN(uint32_t* dst, int count, const uint32_t* src) { |   96     static void BlendN(uint32_t* dst, const uint32_t* src, int count) { | 
|   45         sk_default::trivial_srcover_srgb_srgb(dst, src, count, count); |   97         trivial_srcover_srgb_srgb(dst, src, count, count); | 
|   46     } |   98     } | 
|   47 }; |   99 }; | 
|   48  |  100  | 
|   49 namespace sk_default { |  | 
|   50 extern void best_non_simd_srcover_srgb_srgb( |  | 
|   51     uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); |  | 
|   52 } |  | 
|   53  |  | 
|   54 class SrcOverVSkOptsNonSimdCore { |  101 class SrcOverVSkOptsNonSimdCore { | 
|   55 public: |  102 public: | 
|   56     static SkString Name() { return SkString{"VSkOptsNonSimdCore"}; } |  103     static SkString Name() { return SkString{"VSkOptsNonSimdCore"}; } | 
|   57     static bool WorksOnCpu() { return true; } |  104     static bool WorksOnCpu() { return true; } | 
|   58     static void BlendN(uint32_t* dst, int count, const uint32_t* src) { |  105     static void BlendN(uint32_t* dst, const uint32_t* src, int count) { | 
|   59         sk_default::best_non_simd_srcover_srgb_srgb(dst, src, count, count); |  106         best_non_simd_srcover_srgb_srgb(dst, src, count, count); | 
|   60     } |  107     } | 
|   61 }; |  108 }; | 
|   62  |  109  | 
|   63 namespace sk_default { |  110 namespace sk_default { | 
|   64 extern void srcover_srgb_srgb( |  111 extern void srcover_srgb_srgb( | 
|   65     uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); |  112     uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); | 
|   66 } |  113 } | 
|   67  |  114  | 
|   68 class SrcOverVSkOptsDefault { |  115 class SrcOverVSkOptsDefault { | 
|   69 public: |  116 public: | 
|   70     static SkString Name() { return SkString{"VSkOptsDefault"}; } |  117     static SkString Name() { return SkString{"VSkOptsDefault"}; } | 
|   71     static bool WorksOnCpu() { return true; } |  118     static bool WorksOnCpu() { return true; } | 
|   72     static void BlendN(uint32_t* dst, int count, const uint32_t* src) { |  119     static void BlendN(uint32_t* dst, const uint32_t* src, int count) { | 
|   73         sk_default::srcover_srgb_srgb(dst, src, count, count); |  120         sk_default::srcover_srgb_srgb(dst, src, count, count); | 
|   74     } |  121     } | 
|   75 }; |  122 }; | 
|   76  |  123  | 
|   77 namespace sk_sse41 { |  124 namespace sk_sse41 { | 
|   78    extern void srcover_srgb_srgb( |  125    extern void srcover_srgb_srgb( | 
|   79        uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); |  126        uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc); | 
|   80 } |  127 } | 
|   81  |  128  | 
|   82 class SrcOverVSkOptsSSE41 { |  129 class SrcOverVSkOptsSSE41 { | 
|   83 public: |  130 public: | 
|   84     static SkString Name() { return SkString{"VSkOptsSSE41"}; } |  131     static SkString Name() { return SkString{"VSkOptsSSE41"}; } | 
|   85     static bool WorksOnCpu() { return SkCpu::Supports(SkCpu::SSE41); } |  132     static bool WorksOnCpu() { return SkCpu::Supports(SkCpu::SSE41); } | 
|   86     static void BlendN(uint32_t* dst, int count, const uint32_t* src) { |  133     static void BlendN(uint32_t* dst, const uint32_t* src, int count) { | 
|   87         sk_sse41::srcover_srgb_srgb(dst, src, count, count); |  134         sk_sse41::srcover_srgb_srgb(dst, src, count, count); | 
|   88     } |  135     } | 
|   89 }; |  136 }; | 
|   90  |  137  | 
|   91 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// |  138 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// | 
|   92  |  139  | 
|   93 template <typename Blender> |  140 template <typename Blender> | 
|   94 class LinearSrcOverBench : public Benchmark { |  141 class LinearSrcOverBench : public Benchmark { | 
|   95 public: |  142 public: | 
|   96     LinearSrcOverBench(const char* fileName) : fFileName(fileName) { |  143     LinearSrcOverBench(const char* fileName) : fFileName(fileName) { | 
|   97         fName = "LinearSrcOver"; |  144         fName = "LinearSrcOver_"; | 
|   98         fName.append(fileName); |  145         fName.append(fileName); | 
|   99         fName.append(Blender::Name()); |  146         fName.append(Blender::Name()); | 
|  100     } |  147     } | 
|  101  |  148  | 
|  102 protected: |  149 protected: | 
|  103     bool isSuitableFor(Backend backend) override { |  150     bool isSuitableFor(Backend backend) override { | 
|  104         return backend == kNonRendering_Backend && Blender::WorksOnCpu(); |  151         return backend == kNonRendering_Backend && Blender::WorksOnCpu(); | 
|  105     } |  152     } | 
|  106     const char* onGetName() override { return fName.c_str(); } |  153     const char* onGetName() override { return fName.c_str(); } | 
|  107  |  154  | 
|  108     void onPreDraw(SkCanvas*) override { |  155     void onPreDraw(SkCanvas*) override { | 
|  109         if (!fPixmap.addr()) { |  156         if (!fPixmap.addr()) { | 
|  110             sk_sp<SkImage> image = GetResourceAsImage(fFileName.c_str()); |  157             sk_sp<SkImage> image = GetResourceAsImage(fFileName.c_str()); | 
|  111             SkBitmap bm; |  158             SkBitmap bm; | 
|  112             if (!as_IB(image)->getROPixels(&bm)) { |  159             if (!as_IB(image)->getROPixels(&bm)) { | 
|  113                 SkFAIL("Could not read resource"); |  160                 SkFAIL("Could not read resource"); | 
|  114             } |  161             } | 
|  115             bm.peekPixels(&fPixmap); |  162             bm.peekPixels(&fPixmap); | 
|  116             fCount = fPixmap.rowBytesAsPixels(); |  163             fCount = fPixmap.rowBytesAsPixels(); | 
|  117             fDst.reset(fCount); |  164             fDst.reset(fCount); | 
|  118             memset(fDst.get(), 0, fPixmap.rowBytes()); |  165             sk_bzero(fDst.get(), fPixmap.rowBytes()); | 
|  119         } |  166         } | 
|  120     } |  167     } | 
|  121  |  168  | 
|  122     void onDraw(int loops, SkCanvas*) override { |  169     void onDraw(int loops, SkCanvas*) override { | 
|  123         SkASSERT(fPixmap.colorType() == kN32_SkColorType); |  170         SkASSERT(fPixmap.colorType() == kN32_SkColorType); | 
|  124  |  171  | 
|  125         const int width = fPixmap.rowBytesAsPixels(); |  172         const int width = fPixmap.rowBytesAsPixels(); | 
|  126  |  173  | 
|  127         for (int i = 0; i < loops * INNER_LOOPS; ++i) { |  174         for (int i = 0; i < loops * INNER_LOOPS; ++i) { | 
|  128             const uint32_t* src = fPixmap.addr32(); |  175             const uint32_t* src = fPixmap.addr32(); | 
|  129             for (int y = 0; y < fPixmap.height(); y++) { |  176             for (int y = 0; y < fPixmap.height(); y++) { | 
|  130                 Blender::BlendN(fDst.get(), width, src); |  177                 Blender::BlendN(fDst.get(), src, width); | 
|  131                 src += width; |  178                 src += width; | 
|  132             } |  179             } | 
|  133         } |  180         } | 
|  134     } |  181     } | 
|  135  |  182  | 
|  136     void onPostDraw(SkCanvas*) override { |  183     void onPostDraw(SkCanvas*) override { | 
|  137         // Make sure the compiler does not optimize away the operation. |  184         // Make sure the compiler does not optimize away the operation. | 
|  138         volatile uint32_t v = 0; |  185         volatile uint32_t v = 0; | 
|  139         for (int i = 0; i < fCount; i++) { |  186         for (int i = 0; i < fCount; i++) { | 
|  140             v ^= fDst[i]; |  187             v ^= fDst[i]; | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
|  164 DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsTrivial>(fileName); )    
      \ |  211 DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsTrivial>(fileName); )    
      \ | 
|  165 DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsNonSimdCore>(fileName); )
      \ |  212 DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsNonSimdCore>(fileName); )
      \ | 
|  166 DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsDefault>(fileName); ) |  213 DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsDefault>(fileName); ) | 
|  167 #endif |  214 #endif | 
|  168  |  215  | 
|  169 BENCHES("yellow_rose.png") |  216 BENCHES("yellow_rose.png") | 
|  170 BENCHES("baby_tux.png") |  217 BENCHES("baby_tux.png") | 
|  171 BENCHES("plane.png") |  218 BENCHES("plane.png") | 
|  172 BENCHES("mandrill_512.png") |  219 BENCHES("mandrill_512.png") | 
|  173 BENCHES("iconstrip.png") |  220 BENCHES("iconstrip.png") | 
| OLD | NEW |