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