/* * 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/SkGradientShader.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 createShader() { const SkColor colors[] = { SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE, SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW, }; const SkPoint pts[] = { { 200.f / 4.f, 0.f }, { 3.f * 200.f / 4, 200.f } }; return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(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 == kNonRendering_Backend; } 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); )