| /* | |
| * Copyright 2014 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/SkCanvas.h" | |
| #include "include/core/SkColorSpace.h" | |
| #include "include/core/SkPaint.h" | |
| #include "include/core/SkString.h" | |
| #include "include/core/SkVertices.h" | |
| #include "include/effects/SkGradient.h" | |
| #include "src/utils/SkPatchUtils.h" | |
| /** | |
| * This bench measures the rendering time of the call SkCanvas::drawPatch with different types of | |
| * input patches (regular case, with loops, a square, with a big difference between "parallel" | |
| * sides). This bench also tests the different combination of optional parameters for the function | |
| * (passing texture coordinates and colors, only textures coordinates, only colors or none). | |
| * Finally, it applies a scale to test if the size affects the rendering time. | |
| */ | |
| class PatchBench : public Benchmark { | |
| public: | |
| enum VertexMode { | |
| kNone_VertexMode, | |
| kColors_VertexMode, | |
| kTexCoords_VertexMode, | |
| kBoth_VertexMode | |
| }; | |
| PatchBench(SkPoint scale, VertexMode vertexMode) | |
| : fScale(scale) | |
| , fVertexMode(vertexMode) { } | |
| // to add name of specific class override this method | |
| virtual void appendName(SkString* name) { | |
| name->append("normal"); | |
| } | |
| // to make other type of patches override this method | |
| virtual void setCubics() { | |
| const SkPoint points[SkPatchUtils::kNumCtrlPts] = { | |
| //top points | |
| {100,100},{150,50},{250,150}, {300,100}, | |
| //right points | |
| {350, 150},{250,200}, | |
| //bottom points | |
| {300,300},{250,250},{150,350},{100,300}, | |
| //left points | |
| {50,250},{150,50} | |
| }; | |
| memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); | |
| } | |
| virtual void setColors() { | |
| const SkColor colors[SkPatchUtils::kNumCorners] = { | |
| SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN | |
| }; | |
| memcpy(fColors, colors, SkPatchUtils::kNumCorners * sizeof(SkColor)); | |
| } | |
| virtual void setTexCoords() { | |
| const SkPoint texCoords[SkPatchUtils::kNumCorners] = { | |
| {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f,1.0f}, {0.0f, 1.0f} | |
| }; | |
| memcpy(fTexCoords, texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint)); | |
| } | |
| // override this method to change the shader | |
| virtual sk_sp<SkShader> createShader() { | |
| const SkColor4f colors[] = { | |
| SkColors::kRed, SkColors::kCyan, SkColors::kGreen, SkColors::kWhite, | |
| SkColors::kMagenta, SkColors::kBlue, SkColors::kYellow, | |
| }; | |
| const SkPoint pts[] = { { 200.f / 4.f, 0.f }, { 3.f * 200.f / 4, 200.f } }; | |
| return SkShaders::LinearGradient(pts, {{colors, {}, SkTileMode::kMirror}, {}}); | |
| } | |
| protected: | |
| const char* onGetName() override { | |
| SkString vertexMode; | |
| switch (fVertexMode) { | |
| case kNone_VertexMode: | |
| vertexMode.set("meshlines"); | |
| break; | |
| case kColors_VertexMode: | |
| vertexMode.set("colors"); | |
| break; | |
| case kTexCoords_VertexMode: | |
| vertexMode.set("texs"); | |
| break; | |
| case kBoth_VertexMode: | |
| vertexMode.set("colors_texs"); | |
| break; | |
| default: | |
| break; | |
| } | |
| SkString type; | |
| this->appendName(&type); | |
| fName.printf("patch_%s_%s_%fx%f", type.c_str(), vertexMode.c_str(), | |
| fScale.x(), fScale.y()); | |
| return fName.c_str(); | |
| } | |
| void onDelayedSetup() override { | |
| this->setCubics(); | |
| this->setColors(); | |
| this->setTexCoords(); | |
| this->setupPaint(&fPaint); | |
| switch (fVertexMode) { | |
| case kTexCoords_VertexMode: | |
| case kBoth_VertexMode: | |
| fPaint.setShader(this->createShader()); | |
| break; | |
| default: | |
| fPaint.setShader(nullptr); | |
| break; | |
| } | |
| } | |
| void onDraw(int loops, SkCanvas* canvas) override { | |
| canvas->scale(fScale.x(), fScale.y()); | |
| for (int i = 0; i < loops; i++) { | |
| switch (fVertexMode) { | |
| case kNone_VertexMode: | |
| canvas->drawPatch(fCubics, nullptr, nullptr, SkBlendMode::kModulate, fPaint); | |
| break; | |
| case kColors_VertexMode: | |
| canvas->drawPatch(fCubics, fColors, nullptr, SkBlendMode::kModulate, fPaint); | |
| break; | |
| case kTexCoords_VertexMode: | |
| canvas->drawPatch(fCubics, nullptr, fTexCoords, SkBlendMode::kModulate, fPaint); | |
| break; | |
| case kBoth_VertexMode: | |
| canvas->drawPatch(fCubics, fColors, fTexCoords, SkBlendMode::kModulate, fPaint); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| } | |
| SkPaint fPaint; | |
| SkString fName; | |
| SkVector fScale; | |
| SkPoint fCubics[12]; | |
| SkPoint fTexCoords[4]; | |
| SkColor fColors[4]; | |
| VertexMode fVertexMode; | |
| using INHERITED = Benchmark; | |
| }; | |
| class SquarePatchBench : public PatchBench { | |
| public: | |
| SquarePatchBench(SkPoint scale, VertexMode vertexMode) | |
| : INHERITED(scale, vertexMode) { } | |
| void appendName(SkString* name) override { | |
| name->append("square"); | |
| } | |
| void setCubics() override { | |
| const SkPoint points[SkPatchUtils::kNumCtrlPts] = { | |
| //top points | |
| {100,100},{150,100},{250,100}, {300,100}, | |
| //right points | |
| {300, 150},{300,250}, | |
| //bottom points | |
| {300,300},{250,300},{150,300},{100,300}, | |
| //left points | |
| {100,250},{100,150} | |
| }; | |
| memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); | |
| } | |
| private: | |
| using INHERITED = PatchBench; | |
| }; | |
| class LODDiffPatchBench : public PatchBench { | |
| public: | |
| LODDiffPatchBench(SkPoint scale, VertexMode vertexMode) | |
| : INHERITED(scale, vertexMode) { } | |
| void appendName(SkString* name) override { | |
| name->append("LOD_Diff"); | |
| } | |
| void setCubics() override { | |
| const SkPoint points[SkPatchUtils::kNumCtrlPts] = { | |
| //top points | |
| {100,175},{150,100},{250,100}, {300,0}, | |
| //right points | |
| {300, 150},{300,250}, | |
| //bottom points | |
| {300,400},{250,300},{150,300},{100,225}, | |
| //left points | |
| {100,215},{100,185} | |
| }; | |
| memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); | |
| } | |
| private: | |
| using INHERITED = PatchBench; | |
| }; | |
| class LoopPatchBench : public PatchBench { | |
| public: | |
| LoopPatchBench(SkPoint scale, VertexMode vertexMode) | |
| : INHERITED(scale, vertexMode) { } | |
| void appendName(SkString* name) override { | |
| name->append("loop"); | |
| } | |
| void setCubics() override { | |
| const SkPoint points[SkPatchUtils::kNumCtrlPts] = { | |
| //top points | |
| {100,100},{300,200},{100,200}, {300,100}, | |
| //right points | |
| {380, 400},{380,0}, | |
| //bottom points | |
| {300,300},{250,250},{30,200},{100,300}, | |
| //left points | |
| {140,325},{150,150} | |
| }; | |
| memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); | |
| } | |
| private: | |
| using INHERITED = PatchBench; | |
| }; | |
| /////////////////////////////////////////////////////////////////////////////// | |
| DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(1.f, 1.0f), PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.f, 1.0f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.f, 1.0f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.f, 1.0f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f), | |
| PatchBench::kBoth_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kNone_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kColors_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kTexCoords_VertexMode); ) | |
| DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f), | |
| PatchBench::kBoth_VertexMode); ) | |
| ////////////////////////////////////////////// | |
| #include "src/utils/SkPatchUtils.h" | |
| class PatchUtilsBench : public Benchmark { | |
| SkString fName; | |
| const bool fLinearInterp; | |
| public: | |
| PatchUtilsBench(bool linearInterp) : fLinearInterp(linearInterp) { | |
| fName.printf("patchutils_%s", linearInterp ? "linear" : "legacy"); | |
| } | |
| const char* onGetName() override { return fName.c_str(); } | |
| bool isSuitableFor(Backend backend) override { | |
| return backend == Backend::kNonRendering; | |
| } | |
| void onDraw(int loops, SkCanvas*) override { | |
| const SkColor colors[] = { 0xFF000000, 0xFF00FF00, 0xFF0000FF, 0xFFFF0000 }; | |
| const SkPoint pts[] = { | |
| { 0, 0 }, { 10, 0 }, { 20, 0 }, { 30, 0 }, | |
| { 30,10}, { 30,20 }, { 30,30 }, { 20,30 }, | |
| { 10,30}, { 0, 30 }, { 0, 20 }, { 0, 10 }, | |
| }; | |
| const SkPoint tex[] = { | |
| { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 }, | |
| }; | |
| auto cs = fLinearInterp ? SkColorSpace::MakeSRGBLinear() : nullptr; | |
| for (int i = 0; i < 100*loops; ++i) { | |
| SkPatchUtils::MakeVertices(pts, colors, tex, 20, 20, cs.get()); | |
| } | |
| } | |
| }; | |
| DEF_BENCH( return new PatchUtilsBench(false); ) | |
| DEF_BENCH( return new PatchUtilsBench(true); ) |