1/* 2 * Copyright 2017 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#include "SkDeferredDisplayListRecorder.h" 9 10#if SK_SUPPORT_GPU 11#include "GrContextPriv.h" 12#include "GrProxyProvider.h" 13#include "GrTexture.h" 14 15#include "SkGpuDevice.h" 16#include "SkGr.h" 17#include "SkSurface_Gpu.h" 18#endif 19 20#include "SkCanvas.h" // TODO: remove 21#include "SkDeferredDisplayList.h" 22#include "SkSurface.h" 23#include "SkSurfaceCharacterization.h" 24 25SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder( 26 const SkSurfaceCharacterization& characterization) 27 : fCharacterization(characterization) { 28} 29 30SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() { 31#if SK_SUPPORT_GPU && !defined(SK_RASTER_RECORDER_IMPLEMENTATION) 32 auto proxyProvider = fContext->contextPriv().proxyProvider(); 33 34 // DDL TODO: Remove this. DDL contexts should allow for deletion while still having live 35 // uniquely keyed proxies. 36 proxyProvider->removeAllUniqueKeys(); 37#endif 38} 39 40 41bool SkDeferredDisplayListRecorder::init() { 42 SkASSERT(!fSurface); 43 44#ifdef SK_RASTER_RECORDER_IMPLEMENTATION 45 // Use raster right now to allow threading 46 const SkImageInfo ii = SkImageInfo::Make(fCharacterization.width(), fCharacterization.height(), 47 kN32_SkColorType, kOpaque_SkAlphaType, 48 fCharacterization.refColorSpace()); 49 50 fSurface = SkSurface::MakeRaster(ii, &fCharacterization.surfaceProps()); 51 return SkToBool(fSurface.get()); 52#else 53 SkASSERT(!fLazyProxyData); 54 55#if SK_SUPPORT_GPU 56 if (!fContext) { 57 fContext = GrContextPriv::MakeDDL(fCharacterization.contextInfo()); 58 if (!fContext) { 59 return false; 60 } 61 } 62 63 fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>( 64 new SkDeferredDisplayList::LazyProxyData); 65 66 auto proxyProvider = fContext->contextPriv().proxyProvider(); 67 68 GrSurfaceDesc desc; 69 desc.fFlags = kRenderTarget_GrSurfaceFlag; 70 desc.fOrigin = fCharacterization.origin(); 71 desc.fWidth = fCharacterization.width(); 72 desc.fHeight = fCharacterization.height(); 73 desc.fConfig = fCharacterization.config(); 74 desc.fSampleCnt = fCharacterization.stencilCount(); 75 76 sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData; 77 78 // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy 79 // proxy, when instantiated, will use the GrTexture that backs the SkSurface that the 80 // DDL is being replayed into. 81 82 sk_sp<GrSurfaceProxy> proxy = proxyProvider->createLazyProxy( 83 [ lazyProxyData ] (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /* outOrigin */) { 84 if (!resourceProvider) { 85 return sk_sp<GrTexture>(); 86 } 87 88 // The proxy backing the destination surface had better have been instantiated 89 // prior to the proxy backing the DLL's surface. Steal its GrTexture. 90 // DDL TODO: What do we do in the case where the Surface we're replaying into 91 // isn't texturable? 92 SkASSERT(lazyProxyData->fReplayDest->priv().peekTexture()); 93 return sk_ref_sp<GrTexture>(lazyProxyData->fReplayDest->priv().peekTexture()); 94 }, desc, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kYes); 95 96 sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext( 97 std::move(proxy), 98 fCharacterization.refColorSpace(), 99 &fCharacterization.surfaceProps()); 100 fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(), 101 sk_ref_sp(c->asRenderTargetContext())); 102 return SkToBool(fSurface.get()); 103#else 104 return false; 105#endif 106 107#endif 108} 109 110SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { 111 if (!fSurface) { 112 if (!this->init()) { 113 return nullptr; 114 } 115 } 116 117 return fSurface->getCanvas(); 118} 119 120std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { 121#ifdef SK_RASTER_RECORDER_IMPLEMENTATION 122 sk_sp<SkImage> img = fSurface->makeImageSnapshot(); 123 fSurface.reset(); 124 125 // TODO: need to wrap the opLists associated with the deferred draws 126 // in the SkDeferredDisplayList. 127 return std::unique_ptr<SkDeferredDisplayList>( 128 new SkDeferredDisplayList(fCharacterization, std::move(img))); 129#else 130 131#if SK_SUPPORT_GPU 132 auto ddl = std::unique_ptr<SkDeferredDisplayList>( 133 new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData))); 134 135 fContext->contextPriv().moveOpListsToDDL(ddl.get()); 136 return ddl; 137#else 138 return nullptr; 139#endif 140 141#endif // SK_RASTER_RECORDER_IMPLEMENTATION 142 143} 144 145