/* * 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