192007583e43115998412ac8b0a06cc2780eb025cmtklein/*
292007583e43115998412ac8b0a06cc2780eb025cmtklein * Copyright 2014 Google Inc.
392007583e43115998412ac8b0a06cc2780eb025cmtklein *
492007583e43115998412ac8b0a06cc2780eb025cmtklein * Use of this source code is governed by a BSD-style license that can be
592007583e43115998412ac8b0a06cc2780eb025cmtklein * found in the LICENSE file.
692007583e43115998412ac8b0a06cc2780eb025cmtklein */
792007583e43115998412ac8b0a06cc2780eb025cmtklein
892007583e43115998412ac8b0a06cc2780eb025cmtklein#include "SKPBench.h"
9c7f7f467df07be73b22dbee38a59762997eb19bcmtklein#include "SkCommandLineFlags.h"
105b69377507478623dcf5b11f3ecb010f87c4794frobertphillips#include "SkMultiPictureDraw.h"
115b69377507478623dcf5b11f3ecb010f87c4794frobertphillips#include "SkSurface.h"
12c7f7f467df07be73b22dbee38a59762997eb19bcmtklein
139a0f629973ee97ea10f5e3c36a802eca4270d7e0egdanielDEFINE_int32(benchTileW, 1600, "Tile width  used for SKP playback.");
149a0f629973ee97ea10f5e3c36a802eca4270d7e0egdanielDEFINE_int32(benchTileH, 512, "Tile height used for SKP playback.");
1592007583e43115998412ac8b0a06cc2780eb025cmtklein
165b69377507478623dcf5b11f3ecb010f87c4794frobertphillipsSKPBench::SKPBench(const char* name, const SkPicture* pic, const SkIRect& clip, SkScalar scale,
175b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                   bool useMultiPictureDraw)
1892007583e43115998412ac8b0a06cc2780eb025cmtklein    : fPic(SkRef(pic))
1992007583e43115998412ac8b0a06cc2780eb025cmtklein    , fClip(clip)
20962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein    , fScale(scale)
215b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    , fName(name)
225b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    , fUseMultiPictureDraw(useMultiPictureDraw) {
230004e7db42713592fa16a0e6481c95fcf8b398c3tfarina    fUniqueName.printf("%s_%.2g", name, scale);  // Scale makes this unqiue for perf.skia.org traces.
245b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    if (useMultiPictureDraw) {
255b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        fUniqueName.append("_mpd");
265b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    }
275b69377507478623dcf5b11f3ecb010f87c4794frobertphillips}
285b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
295b69377507478623dcf5b11f3ecb010f87c4794frobertphillipsSKPBench::~SKPBench() {
305b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    for (int i = 0; i < fSurfaces.count(); ++i) {
315b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        fSurfaces[i]->unref();
325b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    }
3392007583e43115998412ac8b0a06cc2780eb025cmtklein}
3492007583e43115998412ac8b0a06cc2780eb025cmtklein
3592007583e43115998412ac8b0a06cc2780eb025cmtkleinconst char* SKPBench::onGetName() {
3692007583e43115998412ac8b0a06cc2780eb025cmtklein    return fName.c_str();
3792007583e43115998412ac8b0a06cc2780eb025cmtklein}
3892007583e43115998412ac8b0a06cc2780eb025cmtklein
39962890568ddac03d8eb8467a2e81b6f2b7f046f0mtkleinconst char* SKPBench::onGetUniqueName() {
40962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein    return fUniqueName.c_str();
41962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein}
42962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein
435b69377507478623dcf5b11f3ecb010f87c4794frobertphillipsvoid SKPBench::onPerCanvasPreDraw(SkCanvas* canvas) {
445b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    SkIRect bounds;
455b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    SkAssertResult(canvas->getClipDeviceBounds(&bounds));
465b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
47cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon    int tileW = SkTMin(FLAGS_benchTileW, bounds.width());
48cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon    int tileH = SkTMin(FLAGS_benchTileH, bounds.height());
49cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon
50cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon    int xTiles = SkScalarCeilToInt(bounds.width()  / SkIntToScalar(tileW));
51cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon    int yTiles = SkScalarCeilToInt(bounds.height() / SkIntToScalar(tileH));
525b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
535b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    fSurfaces.setReserve(xTiles * yTiles);
545b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    fTileRects.setReserve(xTiles * yTiles);
555b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
56cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon    SkImageInfo ii = canvas->imageInfo().makeWH(tileW, tileH);
575b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
58cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon    for (int y = bounds.fTop; y < bounds.fBottom; y += tileH) {
59cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon        for (int x = bounds.fLeft; x < bounds.fRight; x += tileW) {
60cc4d6673a942db11a678b572cf0dc5fca2b97f8absalomon            const SkIRect tileRect = SkIRect::MakeXYWH(x, y, tileW, tileH);
6163242d7d24917f836eace34ee20faeb49def5e67robertphillips            *fTileRects.append() = tileRect;
625b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            *fSurfaces.push() = canvas->newSurface(ii);
6363242d7d24917f836eace34ee20faeb49def5e67robertphillips
6463242d7d24917f836eace34ee20faeb49def5e67robertphillips            // Never want the contents of a tile to include stuff the parent
6563242d7d24917f836eace34ee20faeb49def5e67robertphillips            // canvas clips out
6663242d7d24917f836eace34ee20faeb49def5e67robertphillips            SkRect clip = SkRect::Make(bounds);
6763242d7d24917f836eace34ee20faeb49def5e67robertphillips            clip.offset(-SkIntToScalar(tileRect.fLeft), -SkIntToScalar(tileRect.fTop));
6863242d7d24917f836eace34ee20faeb49def5e67robertphillips            fSurfaces.top()->getCanvas()->clipRect(clip);
6963242d7d24917f836eace34ee20faeb49def5e67robertphillips
705b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            fSurfaces.top()->getCanvas()->setMatrix(canvas->getTotalMatrix());
715b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            fSurfaces.top()->getCanvas()->scale(fScale, fScale);
725b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        }
735b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    }
745b69377507478623dcf5b11f3ecb010f87c4794frobertphillips}
755b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
765b69377507478623dcf5b11f3ecb010f87c4794frobertphillipsvoid SKPBench::onPerCanvasPostDraw(SkCanvas* canvas) {
775b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    // Draw the last set of tiles into the master canvas in case we're
785b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    // saving the images
795b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    for (int i = 0; i < fTileRects.count(); ++i) {
80186a08ed72749976b533efe7abec062e20c48bdarobertphillips        SkAutoTUnref<SkImage> image(fSurfaces[i]->newImageSnapshot());
81186a08ed72749976b533efe7abec062e20c48bdarobertphillips        canvas->drawImage(image,
825b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                          SkIntToScalar(fTileRects[i].fLeft), SkIntToScalar(fTileRects[i].fTop));
835b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        SkSafeSetNull(fSurfaces[i]);
845b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    }
855b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
865b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    fSurfaces.rewind();
875b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    fTileRects.rewind();
885b69377507478623dcf5b11f3ecb010f87c4794frobertphillips}
895b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
9092007583e43115998412ac8b0a06cc2780eb025cmtkleinbool SKPBench::isSuitableFor(Backend backend) {
9192007583e43115998412ac8b0a06cc2780eb025cmtklein    return backend != kNonRendering_Backend;
9292007583e43115998412ac8b0a06cc2780eb025cmtklein}
9392007583e43115998412ac8b0a06cc2780eb025cmtklein
9492007583e43115998412ac8b0a06cc2780eb025cmtkleinSkIPoint SKPBench::onGetSize() {
9592007583e43115998412ac8b0a06cc2780eb025cmtklein    return SkIPoint::Make(fClip.width(), fClip.height());
9692007583e43115998412ac8b0a06cc2780eb025cmtklein}
9792007583e43115998412ac8b0a06cc2780eb025cmtklein
9892007583e43115998412ac8b0a06cc2780eb025cmtkleinvoid SKPBench::onDraw(const int loops, SkCanvas* canvas) {
995b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    if (fUseMultiPictureDraw) {
1005b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        for (int i = 0; i < loops; i++) {
101261c3ad7fde95748da92550735decc949dc73bf2joshualitt            this->drawMPDPicture();
1020ddad31012dabfc1267effc8071d37f7d606efberobertphillips        }
1035b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    } else {
1045b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        for (int i = 0; i < loops; i++) {
105261c3ad7fde95748da92550735decc949dc73bf2joshualitt            this->drawPicture();
1065b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        }
107c7f7f467df07be73b22dbee38a59762997eb19bcmtklein    }
10892007583e43115998412ac8b0a06cc2780eb025cmtklein}
109261c3ad7fde95748da92550735decc949dc73bf2joshualitt
110261c3ad7fde95748da92550735decc949dc73bf2joshualittvoid SKPBench::drawMPDPicture() {
111261c3ad7fde95748da92550735decc949dc73bf2joshualitt    SkMultiPictureDraw mpd;
112261c3ad7fde95748da92550735decc949dc73bf2joshualitt
113261c3ad7fde95748da92550735decc949dc73bf2joshualitt    for (int j = 0; j < fTileRects.count(); ++j) {
114261c3ad7fde95748da92550735decc949dc73bf2joshualitt        SkMatrix trans;
115261c3ad7fde95748da92550735decc949dc73bf2joshualitt        trans.setTranslate(-fTileRects[j].fLeft/fScale,
116261c3ad7fde95748da92550735decc949dc73bf2joshualitt                           -fTileRects[j].fTop/fScale);
117261c3ad7fde95748da92550735decc949dc73bf2joshualitt        mpd.add(fSurfaces[j]->getCanvas(), fPic, &trans);
118261c3ad7fde95748da92550735decc949dc73bf2joshualitt    }
119261c3ad7fde95748da92550735decc949dc73bf2joshualitt
120261c3ad7fde95748da92550735decc949dc73bf2joshualitt    mpd.draw();
121261c3ad7fde95748da92550735decc949dc73bf2joshualitt
122261c3ad7fde95748da92550735decc949dc73bf2joshualitt    for (int j = 0; j < fTileRects.count(); ++j) {
123261c3ad7fde95748da92550735decc949dc73bf2joshualitt        fSurfaces[j]->getCanvas()->flush();
124261c3ad7fde95748da92550735decc949dc73bf2joshualitt    }
125261c3ad7fde95748da92550735decc949dc73bf2joshualitt}
126261c3ad7fde95748da92550735decc949dc73bf2joshualitt
127261c3ad7fde95748da92550735decc949dc73bf2joshualittvoid SKPBench::drawPicture() {
128261c3ad7fde95748da92550735decc949dc73bf2joshualitt    for (int j = 0; j < fTileRects.count(); ++j) {
129261c3ad7fde95748da92550735decc949dc73bf2joshualitt        const SkMatrix trans = SkMatrix::MakeTrans(-fTileRects[j].fLeft / fScale,
130261c3ad7fde95748da92550735decc949dc73bf2joshualitt                                                   -fTileRects[j].fTop / fScale);
131261c3ad7fde95748da92550735decc949dc73bf2joshualitt        fSurfaces[j]->getCanvas()->drawPicture(fPic, &trans, NULL);
132261c3ad7fde95748da92550735decc949dc73bf2joshualitt    }
133261c3ad7fde95748da92550735decc949dc73bf2joshualitt
134261c3ad7fde95748da92550735decc949dc73bf2joshualitt    for (int j = 0; j < fTileRects.count(); ++j) {
135261c3ad7fde95748da92550735decc949dc73bf2joshualitt        fSurfaces[j]->getCanvas()->flush();
136261c3ad7fde95748da92550735decc949dc73bf2joshualitt    }
137261c3ad7fde95748da92550735decc949dc73bf2joshualitt}
138