Home | History | Annotate | Download | only in VisualBench
      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"
     12 #include "SkDevice.h"
     13 #include "SkSurface.h"
     14 #include "GrContext.h"
     15 #include "GrRenderTarget.h"
     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`.
     23     explicit WrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench)
     24         : fSurfaceProps(surfaceProps)
     25         , fBench(bench) {}
     26 
     27     const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
     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 {
     34         this->setupOffScreen(canvas);
     35         fOffScreen->getCanvas()->clear(SK_ColorWHITE);
     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());
     54         this->blitToScreen(canvas);
     55     }
     56 
     57     virtual SkIPoint onGetSize() override { return fBench->getSize(); }
     58 
     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;
     69 
     70     SkSurfaceProps          fSurfaceProps;
     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:
     78     explicit CpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench)
     79         : INHERITED(surfaceProps, bench) {}
     80 
     81 private:
     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);
     92     }
     93 
     94     typedef WrappedBenchmark INHERITED;
     95 };
     96 
     97 // Create an MSAA & NVPR-enabled GPU backend
     98 class GpuWrappedBenchmark : public WrappedBenchmark {
     99 public:
    100     explicit GpuWrappedBenchmark(const SkSurfaceProps& surfaceProps, Benchmark* bench,
    101                                  int numSamples)
    102         : INHERITED(surfaceProps, bench)
    103         , fNumSamples(numSamples) {}
    104 
    105 private:
    106     void setupOffScreen(SkCanvas* canvas) override {
    107         fOffScreen.reset(SkSurface::NewRenderTarget(canvas->getGrContext(),
    108                                                     SkBudgeted::kNo,
    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
    136     }
    137 
    138     int fNumSamples;
    139     typedef WrappedBenchmark INHERITED;
    140 };
    141 
    142 #endif //WrappedBenchmark_DEFINED
    143