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 25 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder( 26 const SkSurfaceCharacterization& characterization) 27 : fCharacterization(characterization) { 28 } 29 30 SkDeferredDisplayListRecorder::~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 41 bool SkDeferredDisplayListRecorder::init() { 42 SkASSERT(!fSurface); 43 44 if (!fCharacterization.isValid()) { 45 return false; 46 } 47 48 #ifdef SK_RASTER_RECORDER_IMPLEMENTATION 49 // Use raster right now to allow threading 50 const SkImageInfo ii = SkImageInfo::Make(fCharacterization.width(), fCharacterization.height(), 51 kN32_SkColorType, kOpaque_SkAlphaType, 52 fCharacterization.refColorSpace()); 53 54 fSurface = SkSurface::MakeRaster(ii, &fCharacterization.surfaceProps()); 55 return SkToBool(fSurface.get()); 56 #else 57 SkASSERT(!fLazyProxyData); 58 59 #if SK_SUPPORT_GPU 60 if (!fContext) { 61 fContext = GrContextPriv::MakeDDL(fCharacterization.refContextInfo()); 62 if (!fContext) { 63 return false; 64 } 65 } 66 67 fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>( 68 new SkDeferredDisplayList::LazyProxyData); 69 70 auto proxyProvider = fContext->contextPriv().proxyProvider(); 71 72 GrSurfaceDesc desc; 73 desc.fFlags = kRenderTarget_GrSurfaceFlag; 74 desc.fOrigin = fCharacterization.origin(); 75 desc.fWidth = fCharacterization.width(); 76 desc.fHeight = fCharacterization.height(); 77 desc.fConfig = fCharacterization.config(); 78 desc.fSampleCnt = fCharacterization.stencilCount(); 79 80 sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData; 81 82 // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy 83 // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the 84 // DDL is being replayed into. 85 86 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy( 87 [ lazyProxyData ] (GrResourceProvider* resourceProvider) { 88 if (!resourceProvider) { 89 return sk_sp<GrSurface>(); 90 } 91 92 // The proxy backing the destination surface had better have been instantiated 93 // prior to the proxy backing the DLL's surface. Steal its GrRenderTarget. 94 SkASSERT(lazyProxyData->fReplayDest->priv().peekSurface()); 95 return sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->priv().peekSurface()); 96 }, 97 desc, 98 GrRenderTargetFlags::kNone, 99 GrProxyProvider::Textureable(fCharacterization.isTextureable()), 100 GrMipMapped::kNo, 101 SkBackingFit::kExact, 102 SkBudgeted::kYes); 103 104 sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext( 105 std::move(proxy), 106 fCharacterization.refColorSpace(), 107 &fCharacterization.surfaceProps()); 108 fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(), 109 sk_ref_sp(c->asRenderTargetContext())); 110 return SkToBool(fSurface.get()); 111 #else 112 return false; 113 #endif 114 115 #endif 116 } 117 118 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { 119 if (!fSurface) { 120 if (!this->init()) { 121 return nullptr; 122 } 123 } 124 125 return fSurface->getCanvas(); 126 } 127 128 std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { 129 #ifdef SK_RASTER_RECORDER_IMPLEMENTATION 130 sk_sp<SkImage> img = fSurface->makeImageSnapshot(); 131 fSurface.reset(); 132 133 // TODO: need to wrap the opLists associated with the deferred draws 134 // in the SkDeferredDisplayList. 135 return std::unique_ptr<SkDeferredDisplayList>( 136 new SkDeferredDisplayList(fCharacterization, std::move(img))); 137 #else 138 139 #if SK_SUPPORT_GPU 140 auto ddl = std::unique_ptr<SkDeferredDisplayList>( 141 new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData))); 142 143 fContext->contextPriv().moveOpListsToDDL(ddl.get()); 144 return ddl; 145 #else 146 return nullptr; 147 #endif 148 149 #endif // SK_RASTER_RECORDER_IMPLEMENTATION 150 151 } 152 153