1c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt/*
2c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt * Copyright 2015 Google Inc.
3c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt *
4c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt * Use of this source code is governed by a BSD-style license that can be
5c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt * found in the LICENSE file.
6c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt */
7c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
8c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt#ifndef WrappedBenchmark_DEFINED
9c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt#define WrappedBenchmark_DEFINED
10c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
11c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt#include "Benchmark.h"
120f6cca8a2070b974368652ec04b6003e9205a8a3cdalton#include "SkDevice.h"
13c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt#include "SkSurface.h"
140f6cca8a2070b974368652ec04b6003e9205a8a3cdalton#include "GrContext.h"
150f6cca8a2070b974368652ec04b6003e9205a8a3cdalton#include "GrRenderTarget.h"
16c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
17c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt// Wrap some other benchmark to allow specialization to either
18c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt// cpu or gpu backends. The derived class will override 'setupOffScreen'
19c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt// to create an offscreen surface in which the actual rendering will occur.
20c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualittclass WrappedBenchmark : public Benchmark {
21c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualittpublic:
22c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    // Takes ownership of caller's ref on `bench`.
23c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton    explicit WrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench)
24c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton        : fSurfaceProps(surfaceProps)
25c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton        , fBench(bench) {}
26c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton
27c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton    const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
28c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
29c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    const char* onGetName()       override { return fBench->getName(); }
30c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    const char* onGetUniqueName() override { return fBench->getUniqueName(); }
31c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
32c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    void onDelayedSetup() override { fBench->delayedSetup(); }
33c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    void onPerCanvasPreDraw(SkCanvas* canvas) override {
340f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        this->setupOffScreen(canvas);
350f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        fOffScreen->getCanvas()->clear(SK_ColorWHITE);
36c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        fBench->perCanvasPreDraw(fOffScreen->getCanvas());
37c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    }
38c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    void onPreDraw(SkCanvas* canvas) override {
39c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        SkASSERT(fOffScreen.get());
40c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        fBench->preDraw(fOffScreen->getCanvas());
41c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    }
42c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    void onPostDraw(SkCanvas* canvas) override {
43c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        SkASSERT(fOffScreen.get());
44c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        fBench->postDraw(fOffScreen->getCanvas());
45c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    }
46c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    void onPerCanvasPostDraw(SkCanvas* canvas) override {
47c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        SkASSERT(fOffScreen.get());
48c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        fBench->perCanvasPostDraw(fOffScreen->getCanvas());
49c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    }
50c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
51c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    void onDraw(int loops, SkCanvas* canvas) override {
52c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        SkASSERT(fOffScreen.get());
53c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        fBench->draw(loops, fOffScreen->getCanvas());
540f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        this->blitToScreen(canvas);
55c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    }
56c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
57c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    virtual SkIPoint onGetSize() override { return fBench->getSize(); }
58c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
590f6cca8a2070b974368652ec04b6003e9205a8a3cdaltonprotected:
600f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    virtual void setupOffScreen(SkCanvas*)=0;
610f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
620f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    void blitToScreen(SkCanvas* canvas) {
630f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        int w = SkTMin(fBench->getSize().fX, fOffScreen->width());
640f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        int h = SkTMin(fBench->getSize().fY, fOffScreen->width());
650f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        this->onBlitToScreen(canvas, w, h);
660f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    }
670f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
680f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    virtual void onBlitToScreen(SkCanvas* canvas, int w, int h) = 0;
69c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
70c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton    SkSurfaceProps          fSurfaceProps;
71c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    SkAutoTUnref<SkSurface> fOffScreen;
72c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    SkAutoTUnref<Benchmark> fBench;
73c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt};
74c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
75c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt// Create a raster surface for off screen rendering
76c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualittclass CpuWrappedBenchmark : public WrappedBenchmark {
77c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualittpublic:
78c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton    explicit CpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench)
79c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton        : INHERITED(surfaceProps, bench) {}
80c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
81c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualittprivate:
820f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    void setupOffScreen(SkCanvas* canvas) override {
830f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        fOffScreen.reset(SkSurface::NewRaster(canvas->imageInfo(), &this->surfaceProps()));
840f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    }
850f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
860f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    void onBlitToScreen(SkCanvas* canvas, int w, int h) override {
870f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkAutoTUnref<SkImage> image(fOffScreen->newImageSnapshot());
880f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkPaint blitPaint;
890f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        blitPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
900f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        canvas->drawImageRect(image, SkIRect::MakeWH(w, h),
910f6cca8a2070b974368652ec04b6003e9205a8a3cdalton                              SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h)), &blitPaint);
92c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    }
93c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
94c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    typedef WrappedBenchmark INHERITED;
95c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt};
96c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
97c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt// Create an MSAA & NVPR-enabled GPU backend
98baf8fcbb1b7eb89d5190df804bbda33c2622eb88cdaltonclass GpuWrappedBenchmark : public WrappedBenchmark {
99c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualittpublic:
100baf8fcbb1b7eb89d5190df804bbda33c2622eb88cdalton    explicit GpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench,
101baf8fcbb1b7eb89d5190df804bbda33c2622eb88cdalton                                 int numSamples)
102c70483f5ab83aaa29c0697398aeca3432f3591b6cdalton        : INHERITED(surfaceProps, bench)
103c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt        , fNumSamples(numSamples) {}
104c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
105c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualittprivate:
1060f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    void setupOffScreen(SkCanvas* canvas) override {
1070f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        fOffScreen.reset(SkSurface::NewRenderTarget(canvas->getGrContext(),
1085ec26ae9bfca635ccc98283aad5deda11519d826bsalomon                                                    SkBudgeted::kNo,
1090f6cca8a2070b974368652ec04b6003e9205a8a3cdalton                                                    canvas->imageInfo(),
1100f6cca8a2070b974368652ec04b6003e9205a8a3cdalton                                                    fNumSamples,
1110f6cca8a2070b974368652ec04b6003e9205a8a3cdalton                                                    &this->surfaceProps()));
1120f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    }
1130f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
1140f6cca8a2070b974368652ec04b6003e9205a8a3cdalton    void onBlitToScreen(SkCanvas* canvas, int w, int h) override {
1150f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        // We call copySurface directly on the underlying GPU surfaces for a more efficient blit.
1160f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        GrRenderTarget* dst, *src;
1170f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
1180f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkCanvas::LayerIter canvasIter(canvas, false);
1190f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkAssertResult((dst = canvasIter.device()->accessRenderTarget()));
1200f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
1210f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkCanvas::LayerIter offscreenIter(fOffScreen->getCanvas(), false);
1220f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkAssertResult((src = offscreenIter.device()->accessRenderTarget()));
1230f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
1240f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkASSERT(dst->getContext() == src->getContext());
1250f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
1260f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        dst->getContext()->copySurface(dst, src, SkIRect::MakeWH(w, h), SkIPoint::Make(0, 0));
1270f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
1280f6cca8a2070b974368652ec04b6003e9205a8a3cdalton#ifdef SK_DEBUG
1290f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        // This method should not be called while layers are saved.
1300f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        canvasIter.next();
1310f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkASSERT(canvasIter.done());
1320f6cca8a2070b974368652ec04b6003e9205a8a3cdalton
1330f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        offscreenIter.next();
1340f6cca8a2070b974368652ec04b6003e9205a8a3cdalton        SkASSERT(offscreenIter.done());
1350f6cca8a2070b974368652ec04b6003e9205a8a3cdalton#endif
136c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    }
137c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
138c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    int fNumSamples;
139c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt    typedef WrappedBenchmark INHERITED;
140c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt};
141c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt
142c9dd93cd5bf72a236a14693b04f5e5c983e32ba4joshualitt#endif //WrappedBenchmark_DEFINED
143