|  | /* | 
|  | * Copyright 2015 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "bench/Benchmark.h" | 
|  | #include "include/core/SkMatrix.h" | 
|  | #include "include/core/SkPaint.h" | 
|  | #include "include/core/SkString.h" | 
|  | #include "include/private/SkColorData.h" | 
|  | #include "include/private/SkFixed.h" | 
|  | #include "include/utils/SkRandom.h" | 
|  |  | 
|  | #define TILE(x, width)  (((x) & 0xFFFF) * width >> 16) | 
|  |  | 
|  | class InterpBench : public Benchmark { | 
|  | enum { | 
|  | kBuffer = 128, | 
|  | kLoop   = 20000 | 
|  | }; | 
|  | SkString    fName; | 
|  | int16_t     fDst[kBuffer]; | 
|  | float       fFx, fDx; | 
|  | public: | 
|  | InterpBench(const char name[])  { | 
|  | fName.printf("interp_%s", name); | 
|  | fFx = 3.3f; | 
|  | fDx = 0.1257f; | 
|  | } | 
|  |  | 
|  | bool isSuitableFor(Backend backend) override { | 
|  | return backend == kNonRendering_Backend; | 
|  | } | 
|  |  | 
|  | virtual void performTest(int16_t dst[], float x, float dx, int count) = 0; | 
|  |  | 
|  | protected: | 
|  | virtual int mulLoopCount() const { return 1; } | 
|  |  | 
|  | const char* onGetName() override { | 
|  | return fName.c_str(); | 
|  | } | 
|  |  | 
|  | void onDraw(int loops, SkCanvas*) override { | 
|  | int n = loops * this->mulLoopCount(); | 
|  | for (int i = 0; i < n; i++) { | 
|  | this->performTest(fDst, fFx, fDx, kBuffer); | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | using INHERITED = Benchmark; | 
|  | }; | 
|  |  | 
|  | class Fixed16D16Interp : public InterpBench { | 
|  | public: | 
|  | Fixed16D16Interp() : INHERITED("16.16") {} | 
|  |  | 
|  | protected: | 
|  | void performTest(int16_t dst[], float fx, float dx, int count) override { | 
|  | SkFixed curr = SkFloatToFixed(fx); | 
|  | SkFixed step = SkFloatToFixed(dx); | 
|  | for (int i = 0; i < count; i += 4) { | 
|  | dst[i + 0] = TILE(curr, count); curr += step; | 
|  | dst[i + 1] = TILE(curr, count); curr += step; | 
|  | dst[i + 2] = TILE(curr, count); curr += step; | 
|  | dst[i + 3] = TILE(curr, count); curr += step; | 
|  | } | 
|  | } | 
|  | private: | 
|  | using INHERITED = InterpBench; | 
|  | }; | 
|  |  | 
|  | class Fixed32D32Interp : public InterpBench { | 
|  | public: | 
|  | Fixed32D32Interp() : INHERITED("32.32") {} | 
|  |  | 
|  | protected: | 
|  | void performTest(int16_t dst[], float fx, float dx, int count) override { | 
|  | int64_t curr = (int64_t)(fx * 65536 * 655536); | 
|  | int64_t step = (int64_t)(dx * 65536 * 655536); | 
|  | SkFixed tmp; | 
|  | for (int i = 0; i < count; i += 4) { | 
|  | tmp = (SkFixed)(curr >> 16); | 
|  | dst[i + 0] = TILE(tmp, count); | 
|  | curr += step; | 
|  |  | 
|  | tmp = (SkFixed)(curr >> 16); | 
|  | dst[i + 1] = TILE(tmp, count); | 
|  | curr += step; | 
|  |  | 
|  | tmp = (SkFixed)(curr >> 16); | 
|  | dst[i + 2] = TILE(tmp, count); | 
|  | curr += step; | 
|  |  | 
|  | tmp = (SkFixed)(curr >> 16); | 
|  | dst[i + 3] = TILE(tmp, count); | 
|  | curr += step; | 
|  | } | 
|  | } | 
|  | private: | 
|  | using INHERITED = InterpBench; | 
|  | }; | 
|  |  | 
|  | class Fixed16D48Interp : public InterpBench { | 
|  | public: | 
|  | Fixed16D48Interp() : INHERITED("16.48") {} | 
|  |  | 
|  | protected: | 
|  | void performTest(int16_t dst[], float fx, float dx, int count) override { | 
|  | int64_t curr = (int64_t)(fx * 65536 * 655536 * 65536); | 
|  | int64_t step = (int64_t)(dx * 65536 * 655536 * 65536); | 
|  | SkFixed tmp; | 
|  | for (int i = 0; i < count; i += 4) { | 
|  | tmp = (SkFixed) (curr >> 32); dst[i + 0] = TILE(tmp, count); curr += step; | 
|  | tmp = (SkFixed) (curr >> 32); dst[i + 1] = TILE(tmp, count); curr += step; | 
|  | tmp = (SkFixed) (curr >> 32); dst[i + 2] = TILE(tmp, count); curr += step; | 
|  | tmp = (SkFixed) (curr >> 32); dst[i + 3] = TILE(tmp, count); curr += step; | 
|  | } | 
|  | } | 
|  | private: | 
|  | using INHERITED = InterpBench; | 
|  | }; | 
|  |  | 
|  | class FloatInterp : public InterpBench { | 
|  | public: | 
|  | FloatInterp() : INHERITED("float") {} | 
|  |  | 
|  | protected: | 
|  | void performTest(int16_t dst[], float fx, float dx, int count) override { | 
|  | SkFixed tmp; | 
|  | for (int i = 0; i < count; i += 4) { | 
|  | tmp = SkFloatToFixed(fx); dst[i + 0] = TILE(tmp, count); fx += dx; | 
|  | tmp = SkFloatToFixed(fx); dst[i + 1] = TILE(tmp, count); fx += dx; | 
|  | tmp = SkFloatToFixed(fx); dst[i + 2] = TILE(tmp, count); fx += dx; | 
|  | tmp = SkFloatToFixed(fx); dst[i + 3] = TILE(tmp, count); fx += dx; | 
|  | } | 
|  | } | 
|  | private: | 
|  | using INHERITED = InterpBench; | 
|  | }; | 
|  |  | 
|  | class DoubleInterp : public InterpBench { | 
|  | public: | 
|  | DoubleInterp() : INHERITED("double") {} | 
|  |  | 
|  | protected: | 
|  | void performTest(int16_t dst[], float fx, float dx, int count) override { | 
|  | double ffx = fx; | 
|  | double ddx = dx; | 
|  | SkFixed tmp; | 
|  | for (int i = 0; i < count; i += 4) { | 
|  | tmp = SkDoubleToFixed(ffx); dst[i + 0] = TILE(tmp, count); ffx += ddx; | 
|  | tmp = SkDoubleToFixed(ffx); dst[i + 1] = TILE(tmp, count); ffx += ddx; | 
|  | tmp = SkDoubleToFixed(ffx); dst[i + 2] = TILE(tmp, count); ffx += ddx; | 
|  | tmp = SkDoubleToFixed(ffx); dst[i + 3] = TILE(tmp, count); ffx += ddx; | 
|  | } | 
|  | } | 
|  | private: | 
|  | using INHERITED = InterpBench; | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | DEF_BENCH( return new Fixed16D16Interp(); ) | 
|  | DEF_BENCH( return new Fixed32D32Interp(); ) | 
|  | DEF_BENCH( return new Fixed16D48Interp(); ) | 
|  | DEF_BENCH( return new FloatInterp(); ) | 
|  | DEF_BENCH( return new DoubleInterp(); ) |