joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #ifndef WrappedBenchmark_DEFINED |
| 9 | #define WrappedBenchmark_DEFINED |
| 10 | |
| 11 | #include "Benchmark.h" |
cdalton | 0f6cca8 | 2015-11-24 08:54:29 -0800 | [diff] [blame] | 12 | #include "SkDevice.h" |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 13 | #include "SkSurface.h" |
cdalton | 0f6cca8 | 2015-11-24 08:54:29 -0800 | [diff] [blame] | 14 | #include "GrContext.h" |
| 15 | #include "GrRenderTarget.h" |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 16 | |
| 17 | // Wrap some other benchmark to allow specialization to either |
| 18 | // cpu or gpu backends. The derived class will override 'setupOffScreen' |
| 19 | // to create an offscreen surface in which the actual rendering will occur. |
| 20 | class WrappedBenchmark : public Benchmark { |
| 21 | public: |
| 22 | // Takes ownership of caller's ref on `bench`. |
cdalton | c70483f | 2015-10-26 13:14:36 -0700 | [diff] [blame] | 23 | explicit WrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench) |
| 24 | : fSurfaceProps(surfaceProps) |
| 25 | , fBench(bench) {} |
| 26 | |
| 27 | const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; } |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 28 | |
| 29 | const char* onGetName() override { return fBench->getName(); } |
| 30 | const char* onGetUniqueName() override { return fBench->getUniqueName(); } |
| 31 | |
| 32 | void onDelayedSetup() override { fBench->delayedSetup(); } |
| 33 | void onPerCanvasPreDraw(SkCanvas* canvas) override { |
cdalton | 0f6cca8 | 2015-11-24 08:54:29 -0800 | [diff] [blame] | 34 | this->setupOffScreen(canvas); |
| 35 | fOffScreen->getCanvas()->clear(SK_ColorWHITE); |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 36 | fBench->perCanvasPreDraw(fOffScreen->getCanvas()); |
| 37 | } |
| 38 | void onPreDraw(SkCanvas* canvas) override { |
| 39 | SkASSERT(fOffScreen.get()); |
| 40 | fBench->preDraw(fOffScreen->getCanvas()); |
| 41 | } |
| 42 | void onPostDraw(SkCanvas* canvas) override { |
| 43 | SkASSERT(fOffScreen.get()); |
| 44 | fBench->postDraw(fOffScreen->getCanvas()); |
| 45 | } |
| 46 | void onPerCanvasPostDraw(SkCanvas* canvas) override { |
| 47 | SkASSERT(fOffScreen.get()); |
| 48 | fBench->perCanvasPostDraw(fOffScreen->getCanvas()); |
| 49 | } |
| 50 | |
| 51 | void onDraw(int loops, SkCanvas* canvas) override { |
| 52 | SkASSERT(fOffScreen.get()); |
| 53 | fBench->draw(loops, fOffScreen->getCanvas()); |
cdalton | 0f6cca8 | 2015-11-24 08:54:29 -0800 | [diff] [blame] | 54 | this->blitToScreen(canvas); |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | virtual SkIPoint onGetSize() override { return fBench->getSize(); } |
| 58 | |
cdalton | 0f6cca8 | 2015-11-24 08:54:29 -0800 | [diff] [blame] | 59 | protected: |
| 60 | virtual void setupOffScreen(SkCanvas*)=0; |
| 61 | |
| 62 | void blitToScreen(SkCanvas* canvas) { |
| 63 | int w = SkTMin(fBench->getSize().fX, fOffScreen->width()); |
| 64 | int h = SkTMin(fBench->getSize().fY, fOffScreen->width()); |
| 65 | this->onBlitToScreen(canvas, w, h); |
| 66 | } |
| 67 | |
| 68 | virtual void onBlitToScreen(SkCanvas* canvas, int w, int h) = 0; |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 69 | |
cdalton | c70483f | 2015-10-26 13:14:36 -0700 | [diff] [blame] | 70 | SkSurfaceProps fSurfaceProps; |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 71 | SkAutoTUnref<SkSurface> fOffScreen; |
| 72 | SkAutoTUnref<Benchmark> fBench; |
| 73 | }; |
| 74 | |
| 75 | // Create a raster surface for off screen rendering |
| 76 | class CpuWrappedBenchmark : public WrappedBenchmark { |
| 77 | public: |
cdalton | c70483f | 2015-10-26 13:14:36 -0700 | [diff] [blame] | 78 | explicit CpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench) |
| 79 | : INHERITED(surfaceProps, bench) {} |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 80 | |
| 81 | private: |
cdalton | 0f6cca8 | 2015-11-24 08:54:29 -0800 | [diff] [blame] | 82 | void setupOffScreen(SkCanvas* canvas) override { |
| 83 | fOffScreen.reset(SkSurface::NewRaster(canvas->imageInfo(), &this->surfaceProps())); |
| 84 | } |
| 85 | |
| 86 | void onBlitToScreen(SkCanvas* canvas, int w, int h) override { |
| 87 | SkAutoTUnref<SkImage> image(fOffScreen->newImageSnapshot()); |
| 88 | SkPaint blitPaint; |
| 89 | blitPaint.setXfermodeMode(SkXfermode::kSrc_Mode); |
| 90 | canvas->drawImageRect(image, SkIRect::MakeWH(w, h), |
| 91 | SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h)), &blitPaint); |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | typedef WrappedBenchmark INHERITED; |
| 95 | }; |
| 96 | |
| 97 | // Create an MSAA & NVPR-enabled GPU backend |
cdalton | baf8fcb | 2015-11-24 09:20:24 -0800 | [diff] [blame] | 98 | class GpuWrappedBenchmark : public WrappedBenchmark { |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 99 | public: |
cdalton | baf8fcb | 2015-11-24 09:20:24 -0800 | [diff] [blame] | 100 | explicit GpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench, |
| 101 | int numSamples) |
cdalton | c70483f | 2015-10-26 13:14:36 -0700 | [diff] [blame] | 102 | : INHERITED(surfaceProps, bench) |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 103 | , fNumSamples(numSamples) {} |
| 104 | |
| 105 | private: |
cdalton | 0f6cca8 | 2015-11-24 08:54:29 -0800 | [diff] [blame] | 106 | void setupOffScreen(SkCanvas* canvas) override { |
| 107 | fOffScreen.reset(SkSurface::NewRenderTarget(canvas->getGrContext(), |
| 108 | SkSurface::kNo_Budgeted, |
| 109 | canvas->imageInfo(), |
| 110 | fNumSamples, |
| 111 | &this->surfaceProps())); |
| 112 | } |
| 113 | |
| 114 | void onBlitToScreen(SkCanvas* canvas, int w, int h) override { |
| 115 | // We call copySurface directly on the underlying GPU surfaces for a more efficient blit. |
| 116 | GrRenderTarget* dst, *src; |
| 117 | |
| 118 | SkCanvas::LayerIter canvasIter(canvas, false); |
| 119 | SkAssertResult((dst = canvasIter.device()->accessRenderTarget())); |
| 120 | |
| 121 | SkCanvas::LayerIter offscreenIter(fOffScreen->getCanvas(), false); |
| 122 | SkAssertResult((src = offscreenIter.device()->accessRenderTarget())); |
| 123 | |
| 124 | SkASSERT(dst->getContext() == src->getContext()); |
| 125 | |
| 126 | dst->getContext()->copySurface(dst, src, SkIRect::MakeWH(w, h), SkIPoint::Make(0, 0)); |
| 127 | |
| 128 | #ifdef SK_DEBUG |
| 129 | // This method should not be called while layers are saved. |
| 130 | canvasIter.next(); |
| 131 | SkASSERT(canvasIter.done()); |
| 132 | |
| 133 | offscreenIter.next(); |
| 134 | SkASSERT(offscreenIter.done()); |
| 135 | #endif |
joshualitt | c9dd93c | 2015-10-15 09:49:31 -0700 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | int fNumSamples; |
| 139 | typedef WrappedBenchmark INHERITED; |
| 140 | }; |
| 141 | |
| 142 | #endif //WrappedBenchmark_DEFINED |