| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef WrappedBenchmark_DEFINED |
| #define WrappedBenchmark_DEFINED |
| |
| #include "Benchmark.h" |
| #include "SkDevice.h" |
| #include "SkSurface.h" |
| #include "GrContext.h" |
| #include "GrRenderTarget.h" |
| |
| // Wrap some other benchmark to allow specialization to either |
| // cpu or gpu backends. The derived class will override 'setupOffScreen' |
| // to create an offscreen surface in which the actual rendering will occur. |
| class WrappedBenchmark : public Benchmark { |
| public: |
| // Takes ownership of caller's ref on `bench`. |
| explicit WrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench) |
| : fSurfaceProps(surfaceProps) |
| , fBench(bench) {} |
| |
| const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; } |
| |
| const char* onGetName() override { return fBench->getName(); } |
| const char* onGetUniqueName() override { return fBench->getUniqueName(); } |
| |
| void onDelayedSetup() override { fBench->delayedSetup(); } |
| void onPerCanvasPreDraw(SkCanvas* canvas) override { |
| this->setupOffScreen(canvas); |
| fOffScreen->getCanvas()->clear(SK_ColorWHITE); |
| fBench->perCanvasPreDraw(fOffScreen->getCanvas()); |
| } |
| void onPreDraw(SkCanvas* canvas) override { |
| SkASSERT(fOffScreen.get()); |
| fBench->preDraw(fOffScreen->getCanvas()); |
| } |
| void onPostDraw(SkCanvas* canvas) override { |
| SkASSERT(fOffScreen.get()); |
| fBench->postDraw(fOffScreen->getCanvas()); |
| } |
| void onPerCanvasPostDraw(SkCanvas* canvas) override { |
| SkASSERT(fOffScreen.get()); |
| fBench->perCanvasPostDraw(fOffScreen->getCanvas()); |
| } |
| |
| void onDraw(int loops, SkCanvas* canvas) override { |
| SkASSERT(fOffScreen.get()); |
| fBench->draw(loops, fOffScreen->getCanvas()); |
| this->blitToScreen(canvas); |
| } |
| |
| virtual SkIPoint onGetSize() override { return fBench->getSize(); } |
| |
| protected: |
| virtual void setupOffScreen(SkCanvas*)=0; |
| |
| void blitToScreen(SkCanvas* canvas) { |
| int w = SkTMin(fBench->getSize().fX, fOffScreen->width()); |
| int h = SkTMin(fBench->getSize().fY, fOffScreen->width()); |
| this->onBlitToScreen(canvas, w, h); |
| } |
| |
| virtual void onBlitToScreen(SkCanvas* canvas, int w, int h) = 0; |
| |
| SkSurfaceProps fSurfaceProps; |
| SkAutoTUnref<SkSurface> fOffScreen; |
| SkAutoTUnref<Benchmark> fBench; |
| }; |
| |
| // Create a raster surface for off screen rendering |
| class CpuWrappedBenchmark : public WrappedBenchmark { |
| public: |
| explicit CpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench) |
| : INHERITED(surfaceProps, bench) {} |
| |
| private: |
| void setupOffScreen(SkCanvas* canvas) override { |
| fOffScreen.reset(SkSurface::NewRaster(canvas->imageInfo(), &this->surfaceProps())); |
| } |
| |
| void onBlitToScreen(SkCanvas* canvas, int w, int h) override { |
| SkAutoTUnref<SkImage> image(fOffScreen->newImageSnapshot()); |
| SkPaint blitPaint; |
| blitPaint.setXfermodeMode(SkXfermode::kSrc_Mode); |
| canvas->drawImageRect(image, SkIRect::MakeWH(w, h), |
| SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h)), &blitPaint); |
| } |
| |
| typedef WrappedBenchmark INHERITED; |
| }; |
| |
| // Create an MSAA & NVPR-enabled GPU backend |
| class GpuWrappedBenchmark : public WrappedBenchmark { |
| public: |
| explicit GpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench, |
| int numSamples) |
| : INHERITED(surfaceProps, bench) |
| , fNumSamples(numSamples) {} |
| |
| private: |
| void setupOffScreen(SkCanvas* canvas) override { |
| fOffScreen.reset(SkSurface::NewRenderTarget(canvas->getGrContext(), |
| SkBudgeted::kNo, |
| canvas->imageInfo(), |
| fNumSamples, |
| &this->surfaceProps())); |
| } |
| |
| void onBlitToScreen(SkCanvas* canvas, int w, int h) override { |
| // We call copySurface directly on the underlying GPU surfaces for a more efficient blit. |
| GrRenderTarget* dst, *src; |
| |
| SkCanvas::LayerIter canvasIter(canvas, false); |
| SkAssertResult((dst = canvasIter.device()->accessRenderTarget())); |
| |
| SkCanvas::LayerIter offscreenIter(fOffScreen->getCanvas(), false); |
| SkAssertResult((src = offscreenIter.device()->accessRenderTarget())); |
| |
| SkASSERT(dst->getContext() == src->getContext()); |
| |
| dst->getContext()->copySurface(dst, src, SkIRect::MakeWH(w, h), SkIPoint::Make(0, 0)); |
| |
| #ifdef SK_DEBUG |
| // This method should not be called while layers are saved. |
| canvasIter.next(); |
| SkASSERT(canvasIter.done()); |
| |
| offscreenIter.next(); |
| SkASSERT(offscreenIter.done()); |
| #endif |
| } |
| |
| int fNumSamples; |
| typedef WrappedBenchmark INHERITED; |
| }; |
| |
| #endif //WrappedBenchmark_DEFINED |