ShapesBench.cpp revision 32f1908f4c9a64e4862152bde6482f16d096f95f
14a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
24a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton/*
34a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton * Copyright 2016 Google Inc.
44a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton *
54a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton * Use of this source code is governed by a BSD-style license that can be
64a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton * found in the LICENSE file.
74a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton */
84a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
94a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include "Benchmark.h"
104a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include "SkCanvas.h"
114a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include "SkCommandLineFlags.h"
124a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include "SkPaint.h"
134a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include "SkRandom.h"
144a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include "SkRRect.h"
154a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include "SkString.h"
164a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include <stdio.h>
174a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include <stdlib.h>
184a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#include <functional>
194a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
204a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#define ENABLE_COMMAND_LINE_SHAPES_BENCH 0
214a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
224a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#if ENABLE_COMMAND_LINE_SHAPES_BENCH
234a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEFINE_string(shapesType, "mixed", "Type of shape to use in ShapesBench. Must be one of: "
244a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                   "rect, oval, rrect, mixed.");
254a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEFINE_string(innerShapesType, "none", "Type of inner shape to use in ShapesBench. Must be one of: "
264a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                       "none, rect, oval, rrect, mixed.");
274a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEFINE_int32(numShapes, 10000, "Number of shapes to draw in ShapesBench.");
284a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEFINE_string(shapesSize, "32x32", "Size of shapes to draw in ShapesBench.");
294a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEFINE_bool(shapesPersp, false, "Use slight perspective tilt in ShapesBench?");
304a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#endif
314a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
324a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton/*
334a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton * This class is used for several benchmarks that draw different primitive Skia shapes at various
344a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton * sizes. It is used to test both CPU-bound and GPU-bound rendering situations. It draws large
354a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton * amounts of shapes internally (rather than relying on nanobench selecting lots of loops) in order
364a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton * to take advantage of instanced rendering approaches.
374a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton */
384a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonclass ShapesBench : public Benchmark {
394a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonpublic:
404a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    enum ShapesType {
414a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        kNone_ShapesType,
424a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        kRect_ShapesType,
434a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        kOval_ShapesType,
444a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        kRRect_ShapesType,
454a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        kMixed_ShapesType
464a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    };
474a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
484a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    ShapesBench(ShapesType shapesType, ShapesType innerShapesType,
494a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                int numShapes, const SkISize& shapesSize, bool perspective)
504a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        : fShapesType(shapesType)
514a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        , fInnerShapesType(innerShapesType)
524a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        , fNumShapes(numShapes)
534a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        , fShapesSize(shapesSize)
544a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        , fPerspective(perspective) {
554a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        clampShapeSize();
564a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    }
574a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
584a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#if ENABLE_COMMAND_LINE_SHAPES_BENCH
594a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    ShapesBench() {
604a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        if (!strcmp(FLAGS_shapesType[0], "rect")) {
614a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapesType = kRect_ShapesType;
624a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else if (!strcmp(FLAGS_shapesType[0], "oval")) {
634a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapesType = kOval_ShapesType;
644a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else if (!strcmp(FLAGS_shapesType[0], "rrect")) {
654a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapesType = kRRect_ShapesType;
664a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else if (!strcmp(FLAGS_shapesType[0], "mixed")) {
674a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapesType = kMixed_ShapesType;
684a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else {
694a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            SkDebugf("Invalid shapesType \"%s\". Must be one of: rect, oval, rrect, mixed.",
704a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                     FLAGS_shapesType[0]);
714a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            exit(-1);
724a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
734a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        if (!strcmp(FLAGS_innerShapesType[0], "none")) {
744a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerShapesType = kNone_ShapesType;
754a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else if (!strcmp(FLAGS_innerShapesType[0], "rect")) {
764a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerShapesType = kRect_ShapesType;
774a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else if (!strcmp(FLAGS_innerShapesType[0], "oval")) {
784a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerShapesType = kOval_ShapesType;
794a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else if (!strcmp(FLAGS_innerShapesType[0], "rrect")) {
804a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerShapesType = kRRect_ShapesType;
814a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else if (!strcmp(FLAGS_innerShapesType[0], "mixed")) {
824a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerShapesType = kMixed_ShapesType;
834a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        } else {
844a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            SkDebugf("Invalid innerShapesType \"%s\". Must be one of: "
854a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                     "none, rect, oval, rrect, mixed.", FLAGS_innerShapesType[0]);
864a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            exit(-1);
874a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
884a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        if (2 != sscanf(FLAGS_shapesSize[0], "%ix%i", &fShapesSize.fWidth, &fShapesSize.fHeight)) {
894a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            SkDebugf("Could not parse shapesSize from \"%s\". Expected \"%%ix%%i\"\n",
904a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                     FLAGS_shapesSize[0]);
914a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            exit(-1);
924a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
934a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
944a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fNumShapes = FLAGS_numShapes;
954a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fPerspective = FLAGS_shapesPersp;
964a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
974a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        clampShapeSize();
984a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    }
994a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#endif
1004a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1014a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    bool isVisual() override { return true; }
1024a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1034a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonprivate:
1044a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    void clampShapeSize() {
1054a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        float maxDiagonal = static_cast<float>(SkTMin(kBenchWidth, kBenchHeight));
1064a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        float diagonal = sqrtf(static_cast<float>(fShapesSize.width() * fShapesSize.width()) +
1074a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                               static_cast<float>(fShapesSize.height() * fShapesSize.height()));
1084a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        if (diagonal > maxDiagonal) {
1094a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapesSize.fWidth = static_cast<int>(fShapesSize.width() * maxDiagonal / diagonal);
1104a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapesSize.fHeight = static_cast<int>(fShapesSize.height() * maxDiagonal / diagonal);
1114a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
1124a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    }
1134a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1144a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    const char* onGetName() override {
1154a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        const char* shapeTypeNames[] = {
1164a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            "none", "rect", "oval", "rrect", "mixed"
1174a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        };
1184a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1194a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fName.printf("shapes_%s", shapeTypeNames[fShapesType]);
1204a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1214a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        if (kNone_ShapesType != fInnerShapesType) {
1224a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fName.appendf("_inner_%s", shapeTypeNames[fInnerShapesType]);
1234a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
1244a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1254a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fName.appendf("_%i_%ix%i", fNumShapes, fShapesSize.width(), fShapesSize.height());
1264a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1274a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        if (fPerspective) {
1284a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fName.append("_persp");
1294a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
1304a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1314a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        return fName.c_str();
1324a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    }
1334a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkIPoint onGetSize() override { return SkIPoint::Make(kBenchWidth, kBenchHeight); }
1344a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1354a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    void onDelayedSetup() override {
1364a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        SkScalar w = SkIntToScalar(fShapesSize.width());
1374a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        SkScalar h = SkIntToScalar(fShapesSize.height());
1384a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1394a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fRect.setRect(SkRect::MakeXYWH(-w / 2, -h / 2, w, h));
1404a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fOval.setOval(fRect.rect());
1414a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fRRect.setNinePatch(fRect.rect(), w / 8, h / 13, w / 11, h / 7);
1424a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1434a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        if (kNone_ShapesType != fInnerShapesType) {
1444a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fRect.inset(w / 7, h / 11, &fInnerRect);
1454a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerRect.offset(w / 28, h / 44);
1464a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerOval.setOval(fInnerRect.rect());
1474a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fInnerRRect.setRectXY(fInnerRect.rect(), w / 13, w / 7);
1484a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
1494a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
1504a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        SkRandom rand;
1514a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        fShapes.push_back_n(fNumShapes);
1524a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        for (int i = 0; i < fNumShapes; i++) {
1534a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            float pad = sqrtf(static_cast<float>(fShapesSize.width() * fShapesSize.width()) +
1544a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                              static_cast<float>(fShapesSize.height() * fShapesSize.height()));
1554a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapes[i].fMatrix.setTranslate(0.5f * pad + rand.nextF() * (kBenchWidth - pad),
1564a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                            0.5f * pad + rand.nextF() * (kBenchHeight - pad));
1574a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapes[i].fMatrix.preRotate(rand.nextF() * 360.0f);
1584a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            if (fPerspective) {
1594a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                fShapes[i].fMatrix.setPerspX(0.00015f);
1604a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                fShapes[i].fMatrix.setPerspY(-0.00015f);
1614a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            }
1624a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            fShapes[i].fColor = rand.nextU() | 0xff808080;
1634a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
1644a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        for (int i = 0; i < fNumShapes; i++) {
1654a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            // Do this in a separate loop so mixed shapes get the same random numbers during
1664a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            // placement as non-mixed do.
1674a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            int shapeType = fShapesType;
1684a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            if (kMixed_ShapesType == shapeType) {
1694a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                shapeType = rand.nextRangeU(kRect_ShapesType, kRRect_ShapesType);
1704a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            }
1714a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            int innerShapeType = fInnerShapesType;
1724a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            if (kMixed_ShapesType == innerShapeType) {
1734a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                innerShapeType = rand.nextRangeU(kRect_ShapesType, kRRect_ShapesType);
1744a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            }
1754a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            if (kNone_ShapesType == innerShapeType) {
1764a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                switch (shapeType) {
1774a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    using namespace std;
1784a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    using namespace std::placeholders;
1794a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kRect_ShapesType:
1804a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                        fShapes[i].fDraw = bind(&SkCanvas::drawRect, _1, cref(fRect.rect()), _2);
1814a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                        break;
1824a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kOval_ShapesType:
1834a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                        fShapes[i].fDraw = bind(&SkCanvas::drawOval, _1, cref(fOval.rect()), _2);
1844a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                        break;
1854a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kRRect_ShapesType:
1864a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                        fShapes[i].fDraw = bind(&SkCanvas::drawRRect, _1, cref(fRRect), _2);
1874a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                        break;
1884a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                }
1894a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            } else {
1904a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                const SkRRect* outer;
1914a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                switch (shapeType) {
1924a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kRect_ShapesType: outer = &fRect; break;
1934a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kOval_ShapesType: outer = &fOval; break;
1944a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kRRect_ShapesType: outer = &fRRect; break;
1954a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                }
1964a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                const SkRRect* inner;
1974a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                switch (innerShapeType) {
1984a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kRect_ShapesType: inner = &fInnerRect; break;
1994a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kOval_ShapesType: inner = &fInnerOval; break;
2004a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                    case kRRect_ShapesType: inner = &fInnerRRect; break;
2014a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                }
2024a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                fShapes[i].fDraw = std::bind(&SkCanvas::drawDRRect, std::placeholders::_1,
2034a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                             std::cref(*outer), std::cref(*inner),
2044a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                             std::placeholders::_2);
2054a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            }
2064a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
2074a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    }
2084a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2094a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    void onDraw(int loops, SkCanvas* canvas) override {
2104a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        SkPaint paint;
2114a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        this->setupPaint(&paint);
2124a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        for (int j = 0; j < loops; j++) {
2134a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            for (int i = 0; i < fNumShapes; i++) {
2144a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                canvas->save();
2154a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                canvas->setMatrix(fShapes[i].fMatrix);
2164a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                paint.setColor(fShapes[i].fColor);
2174a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                fShapes[i].fDraw(canvas, paint);
2184a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                canvas->restore();
2194a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton            }
2204a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        }
2214a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    }
2224a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2234a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    enum {
2244a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        kBenchWidth = 1000,
2254a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        kBenchHeight = 1000
2264a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    };
2274a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2284a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    struct ShapeInfo {
2294a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        SkMatrix   fMatrix;
2304a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        SkColor    fColor;
2314a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton        std::function<void(SkCanvas*, const SkPaint&)> fDraw;
2324a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    };
2334a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2344a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    ShapesType            fShapesType;
2354a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    ShapesType            fInnerShapesType;
2364a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    int                   fNumShapes;
2374a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkISize               fShapesSize;
2384a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    bool                  fPerspective;
2394a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkString              fName;
2404a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkRRect               fRect;
2414a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkRRect               fOval;
2424a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkRRect               fRRect;
2434a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkRRect               fInnerRect;
2444a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkRRect               fInnerOval;
2454a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkRRect               fInnerRRect;
2464a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    SkTArray<ShapeInfo>   fShapes;
2474a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2484a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2494a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton    typedef Benchmark INHERITED;
2504a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton};
2514a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2524a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton// Small primitives (CPU bound, in theory):
2534a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRect_ShapesType, ShapesBench::kNone_ShapesType,
2544a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                 10000, SkISize::Make(32, 32), false);)
2554a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kOval_ShapesType, ShapesBench::kNone_ShapesType,
2564a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                 10000, SkISize::Make(32, 32), false);)
2574a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kOval_ShapesType, ShapesBench::kNone_ShapesType,
2584a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                 10000, SkISize::Make(32, 33), false);)
2594a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRRect_ShapesType, ShapesBench::kNone_ShapesType,
2604a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                 10000, SkISize::Make(32, 32), false);)
2614a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kMixed_ShapesType, ShapesBench::kNone_ShapesType,
2624a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton                                 10000, SkISize::Make(32, 33), false);)
2634a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2644a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton// Large primitives (GPU bound, in theory):
2654a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRect_ShapesType, ShapesBench::kNone_ShapesType,
26632f1908f4c9a64e4862152bde6482f16d096f95fbrianosman                                 100, SkISize::Make(500, 500), false);)
2674a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kOval_ShapesType, ShapesBench::kNone_ShapesType,
26832f1908f4c9a64e4862152bde6482f16d096f95fbrianosman                                 100, SkISize::Make(500, 500), false);)
2694a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kOval_ShapesType, ShapesBench::kNone_ShapesType,
27032f1908f4c9a64e4862152bde6482f16d096f95fbrianosman                                 100, SkISize::Make(500, 501), false);)
2714a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRRect_ShapesType, ShapesBench::kNone_ShapesType,
27232f1908f4c9a64e4862152bde6482f16d096f95fbrianosman                                 100, SkISize::Make(500, 500), false);)
2734a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kMixed_ShapesType, ShapesBench::kNone_ShapesType,
27432f1908f4c9a64e4862152bde6482f16d096f95fbrianosman                                 100, SkISize::Make(500, 501), false);)
2754a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2764a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton// Donuts (small and large). These fall-back to path rendering due to non-orthogonal rotation
2774a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton// making them quite slow. Thus, reduce the counts substantially:
2784a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRect_ShapesType, ShapesBench::kRect_ShapesType,
279b8c97ba80be1276b79f18475600cee10c737cfbfbrianosman                                 500, SkISize::Make(32, 32), false);)
2804a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRRect_ShapesType, ShapesBench::kRRect_ShapesType,
281b8c97ba80be1276b79f18475600cee10c737cfbfbrianosman                                 500, SkISize::Make(32, 32), false);)
2824a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRect_ShapesType, ShapesBench::kRect_ShapesType,
283b8c97ba80be1276b79f18475600cee10c737cfbfbrianosman                                 50, SkISize::Make(500, 500), false);)
2844a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench(ShapesBench::kRRect_ShapesType, ShapesBench::kRRect_ShapesType,
285b8c97ba80be1276b79f18475600cee10c737cfbfbrianosman                                 50, SkISize::Make(500, 500), false);)
2864a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton
2874a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#if ENABLE_COMMAND_LINE_SHAPES_BENCH
2884a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdaltonDEF_BENCH(return new ShapesBench;)
2894a6e40d9d2e0eb81e00d8b2bd20532aa28f61afbcdalton#endif
290