| /* | 
 |  * Copyright 2019 Google LLC | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "bench/Benchmark.h" | 
 |  | 
 | #include "include/core/SkCanvas.h" | 
 | #include "include/core/SkDeferredDisplayListRecorder.h" | 
 | #include "include/core/SkSurfaceCharacterization.h" | 
 | #include "include/gpu/GrDirectContext.h" | 
 |  | 
 | static SkSurfaceCharacterization create_characterization(GrDirectContext* direct) { | 
 |     size_t maxResourceBytes = direct->getResourceCacheLimit(); | 
 |  | 
 |     if (!direct->colorTypeSupportedAsSurface(kRGBA_8888_SkColorType)) { | 
 |         return SkSurfaceCharacterization(); | 
 |     } | 
 |  | 
 |     SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, | 
 |                                        kPremul_SkAlphaType, nullptr); | 
 |  | 
 |     GrBackendFormat backendFormat = direct->defaultBackendFormat(kRGBA_8888_SkColorType, | 
 |                                                                  GrRenderable::kYes); | 
 |     if (!backendFormat.isValid()) { | 
 |         return SkSurfaceCharacterization(); | 
 |     } | 
 |  | 
 |     SkSurfaceProps props(0x0, kUnknown_SkPixelGeometry); | 
 |  | 
 |     SkSurfaceCharacterization c = direct->threadSafeProxy()->createCharacterization( | 
 |                                                         maxResourceBytes, ii, backendFormat, 1, | 
 |                                                         kTopLeft_GrSurfaceOrigin, props, false); | 
 |     return c; | 
 | } | 
 |  | 
 | // This benchmark tries to simulate how Viz is using SkDDLRecorders. | 
 | // For each config it will create a single DDLRecorder which it reuses for all the runs | 
 | // For each run it creates a DDL and stores it for later deletion. | 
 | class DDLRecorderBench : public Benchmark { | 
 | public: | 
 |     DDLRecorderBench() { } | 
 |  | 
 | protected: | 
 |     bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; } | 
 |  | 
 |     const char* onGetName() override { return "DDLRecorder"; } | 
 |  | 
 |     void onDraw(int loops, SkCanvas* origCanvas) override { | 
 |         if (!fRecorder) { | 
 |             return; | 
 |         } | 
 |  | 
 |         SkASSERT(!fDDLs.size()); | 
 |         fDDLs.reserve(loops); | 
 |  | 
 |         for (int i = 0; i < loops; ++i) { | 
 |             SkCanvas* recordingCanvas = fRecorder->getCanvas(); | 
 |  | 
 |             recordingCanvas->drawRect(SkRect::MakeWH(32, 32), SkPaint()); | 
 |  | 
 |             fDDLs.emplace_back(fRecorder->detach()); | 
 |         } | 
 |     } | 
 |  | 
 | private: | 
 |     // We create one DDLRecorder for all the timing runs and just keep reusing it | 
 |     void onPerCanvasPreDraw(SkCanvas* origCanvas) override { | 
 |         auto context = origCanvas->recordingContext()->asDirectContext(); | 
 |         if (!context) { | 
 |             return; | 
 |         } | 
 |  | 
 |         SkSurfaceCharacterization c = create_characterization(context); | 
 |  | 
 |         fRecorder.reset(new SkDeferredDisplayListRecorder(c)); | 
 |     } | 
 |  | 
 |     // We defer the clean up of the DDLs so it is done outside of the timing loop | 
 |     void onPostDraw(SkCanvas*) override { | 
 |         fDDLs.clear(); | 
 |     } | 
 |  | 
 |     std::unique_ptr<SkDeferredDisplayListRecorder>      fRecorder = nullptr; | 
 |     std::vector<sk_sp<SkDeferredDisplayList>>           fDDLs; | 
 |  | 
 |     typedef Benchmark INHERITED; | 
 | }; | 
 |  | 
 | DEF_BENCH(return new DDLRecorderBench();) |