|  | /* | 
|  | * 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 <memory> | 
|  |  | 
|  | #include "bench/Benchmark.h" | 
|  |  | 
|  | #include "include/core/SkCanvas.h" | 
|  | #include "include/gpu/ganesh/GrDirectContext.h" | 
|  | #include "include/private/chromium/GrDeferredDisplayListRecorder.h" | 
|  | #include "include/private/chromium/GrSurfaceCharacterization.h" | 
|  |  | 
|  | static GrSurfaceCharacterization create_characterization(GrDirectContext* direct) { | 
|  | size_t maxResourceBytes = direct->getResourceCacheLimit(); | 
|  |  | 
|  | if (!direct->colorTypeSupportedAsSurface(kRGBA_8888_SkColorType)) { | 
|  | return GrSurfaceCharacterization(); | 
|  | } | 
|  |  | 
|  | 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 GrSurfaceCharacterization(); | 
|  | } | 
|  |  | 
|  | SkSurfaceProps props(0x0, kUnknown_SkPixelGeometry); | 
|  |  | 
|  | GrSurfaceCharacterization c = | 
|  | direct->threadSafeProxy()->createCharacterization(maxResourceBytes, | 
|  | ii, | 
|  | backendFormat, | 
|  | 1, | 
|  | kTopLeft_GrSurfaceOrigin, | 
|  | props, | 
|  | skgpu::Mipmapped::kNo); | 
|  | 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 Backend::kGanesh == 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; | 
|  | } | 
|  |  | 
|  | GrSurfaceCharacterization c = create_characterization(context); | 
|  |  | 
|  | fRecorder = std::make_unique<GrDeferredDisplayListRecorder>(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<GrDeferredDisplayListRecorder>      fRecorder = nullptr; | 
|  | std::vector<sk_sp<GrDeferredDisplayList>>           fDDLs; | 
|  |  | 
|  | using INHERITED = Benchmark; | 
|  | }; | 
|  |  | 
|  | DEF_BENCH(return new DDLRecorderBench();) |