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 #include "SkMessageBus.h" 10 #include "SkDeferredDisplayList.h" 11 #include "SkSurface.h" 12 #include "SkSurfaceCharacterization.h" 13 14 #if !SK_SUPPORT_GPU 15 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&) {} 16 17 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {} 18 19 bool SkDeferredDisplayListRecorder::init() { return false; } 20 21 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { return nullptr; } 22 23 std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { return nullptr; } 24 25 sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture( 26 const GrBackendFormat& backendFormat, 27 int width, 28 int height, 29 GrMipMapped mipMapped, 30 GrSurfaceOrigin origin, 31 SkColorType colorType, 32 SkAlphaType alphaType, 33 sk_sp<SkColorSpace> colorSpace, 34 PromiseImageTextureFulfillProc textureFulfillProc, 35 PromiseImageTextureReleaseProc textureReleaseProc, 36 PromiseImageTextureDoneProc textureDoneProc, 37 PromiseImageTextureContext textureContext, 38 DelayReleaseCallback delayReleaseCallback) { 39 return nullptr; 40 } 41 42 sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture( 43 SkYUVColorSpace yuvColorSpace, 44 const GrBackendFormat yuvaFormats[], 45 const SkISize yuvaSizes[], 46 const SkYUVAIndex yuvaIndices[4], 47 int imageWidth, 48 int imageHeight, 49 GrSurfaceOrigin imageOrigin, 50 sk_sp<SkColorSpace> imageColorSpace, 51 PromiseImageTextureFulfillProc textureFulfillProc, 52 PromiseImageTextureReleaseProc textureReleaseProc, 53 PromiseImageTextureDoneProc textureDoneProc, 54 PromiseImageTextureContext textureContexts[], 55 DelayReleaseCallback delayReleaseCallback) { 56 return nullptr; 57 } 58 59 #else 60 61 #include "GrContextPriv.h" 62 #include "GrProxyProvider.h" 63 #include "GrRenderTargetContext.h" 64 #include "GrTexture.h" 65 #include "SkGr.h" 66 #include "SkImage_Gpu.h" 67 #include "SkImage_GpuYUVA.h" 68 #include "SkMakeUnique.h" 69 #include "SkPromiseImageTexture.h" 70 #include "SkSurface_Gpu.h" 71 #include "SkYUVASizeInfo.h" 72 73 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c) 74 : fCharacterization(c) { 75 if (fCharacterization.isValid()) { 76 fContext = GrContextPriv::MakeDDL(fCharacterization.refContextInfo()); 77 } 78 } 79 80 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() { 81 if (fContext) { 82 auto proxyProvider = fContext->contextPriv().proxyProvider(); 83 84 // This allows the uniquely keyed proxies to keep their keys but removes their back 85 // pointer to the about-to-be-deleted proxy provider. The proxies will use their 86 // unique key to reattach to cached versions of themselves or to appropriately tag new 87 // resources (if a cached version was not found). This system operates independent of 88 // the replaying context's proxy provider (i.e., these uniquely keyed proxies will not 89 // appear in the replaying proxy providers uniquely keyed proxy map). This should be fine 90 // since no one else should be trying to reconnect to the orphaned proxies and orphaned 91 // proxies from different DDLs that share the same key should simply reconnect to the 92 // same cached resource. 93 proxyProvider->orphanAllUniqueKeys(); 94 } 95 } 96 97 98 bool SkDeferredDisplayListRecorder::init() { 99 SkASSERT(fContext); 100 SkASSERT(!fLazyProxyData); 101 SkASSERT(!fSurface); 102 103 if (!fCharacterization.isValid()) { 104 return false; 105 } 106 107 fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>( 108 new SkDeferredDisplayList::LazyProxyData); 109 110 auto proxyProvider = fContext->contextPriv().proxyProvider(); 111 112 bool usesGLFBO0 = fCharacterization.usesGLFBO0(); 113 if (usesGLFBO0) { 114 if (GrBackendApi::kOpenGL != fContext->backend() || 115 fCharacterization.isTextureable()) { 116 return false; 117 } 118 } 119 120 GrSurfaceDesc desc; 121 desc.fFlags = kRenderTarget_GrSurfaceFlag; 122 desc.fWidth = fCharacterization.width(); 123 desc.fHeight = fCharacterization.height(); 124 desc.fConfig = fCharacterization.config(); 125 desc.fSampleCnt = fCharacterization.stencilCount(); 126 127 sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData; 128 129 // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy 130 // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the 131 // DDL is being replayed into. 132 133 GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone; 134 if (fContext->contextPriv().caps()->usesMixedSamples() && desc.fSampleCnt > 1 && !usesGLFBO0) { 135 // In GL, FBO 0 never supports mixed samples 136 surfaceFlags |= GrInternalSurfaceFlags::kMixedSampled; 137 } 138 if (usesGLFBO0) { 139 surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0; 140 } 141 static constexpr GrProxyProvider::TextureInfo kTextureInfo{GrMipMapped::kNo, 142 GrTextureType::k2D}; 143 const GrProxyProvider::TextureInfo* optionalTextureInfo = nullptr; 144 if (fCharacterization.isTextureable()) { 145 optionalTextureInfo = &kTextureInfo; 146 } 147 148 const GrBackendFormat format = fContext->contextPriv().caps()->getBackendFormatFromColorType( 149 fCharacterization.colorType()); 150 151 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy( 152 [lazyProxyData](GrResourceProvider* resourceProvider) { 153 if (!resourceProvider) { 154 return sk_sp<GrSurface>(); 155 } 156 157 // The proxy backing the destination surface had better have been instantiated 158 // prior to the proxy backing the DLL's surface. Steal its GrRenderTarget. 159 SkASSERT(lazyProxyData->fReplayDest->peekSurface()); 160 return sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->peekSurface()); 161 }, 162 format, 163 desc, 164 fCharacterization.origin(), 165 surfaceFlags, 166 optionalTextureInfo, 167 SkBackingFit::kExact, 168 SkBudgeted::kYes); 169 170 sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext( 171 std::move(proxy), 172 fCharacterization.refColorSpace(), 173 &fCharacterization.surfaceProps()); 174 fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(), 175 sk_ref_sp(c->asRenderTargetContext())); 176 return SkToBool(fSurface.get()); 177 } 178 179 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { 180 if (!fContext) { 181 return nullptr; 182 } 183 184 if (!fSurface && !this->init()) { 185 return nullptr; 186 } 187 188 return fSurface->getCanvas(); 189 } 190 191 std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { 192 if (!fContext) { 193 return nullptr; 194 } 195 196 if (fSurface) { 197 SkCanvas* canvas = fSurface->getCanvas(); 198 199 canvas->restoreToCount(0); 200 } 201 202 auto ddl = std::unique_ptr<SkDeferredDisplayList>( 203 new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData))); 204 205 fContext->contextPriv().moveOpListsToDDL(ddl.get()); 206 207 // We want a new lazy proxy target for each recorded DDL so force the (lazy proxy-backed) 208 // SkSurface to be regenerated for each DDL. 209 fSurface = nullptr; 210 return ddl; 211 } 212 213 sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture( 214 const GrBackendFormat& backendFormat, 215 int width, 216 int height, 217 GrMipMapped mipMapped, 218 GrSurfaceOrigin origin, 219 SkColorType colorType, 220 SkAlphaType alphaType, 221 sk_sp<SkColorSpace> colorSpace, 222 PromiseImageTextureFulfillProc textureFulfillProc, 223 PromiseImageTextureReleaseProc textureReleaseProc, 224 PromiseImageTextureDoneProc textureDoneProc, 225 PromiseImageTextureContext textureContext, 226 DelayReleaseCallback delayReleaseCallback) { 227 if (!fContext) { 228 return nullptr; 229 } 230 231 return SkImage_Gpu::MakePromiseTexture(fContext.get(), 232 backendFormat, 233 width, 234 height, 235 mipMapped, 236 origin, 237 colorType, 238 alphaType, 239 std::move(colorSpace), 240 textureFulfillProc, 241 textureReleaseProc, 242 textureDoneProc, 243 textureContext, 244 delayReleaseCallback); 245 } 246 247 sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture( 248 SkYUVColorSpace yuvColorSpace, 249 const GrBackendFormat yuvaFormats[], 250 const SkISize yuvaSizes[], 251 const SkYUVAIndex yuvaIndices[4], 252 int imageWidth, 253 int imageHeight, 254 GrSurfaceOrigin imageOrigin, 255 sk_sp<SkColorSpace> imageColorSpace, 256 PromiseImageTextureFulfillProc textureFulfillProc, 257 PromiseImageTextureReleaseProc textureReleaseProc, 258 PromiseImageTextureDoneProc textureDoneProc, 259 PromiseImageTextureContext textureContexts[], 260 DelayReleaseCallback delayReleaseCallback) { 261 if (!fContext) { 262 return nullptr; 263 } 264 265 return SkImage_GpuYUVA::MakePromiseYUVATexture(fContext.get(), 266 yuvColorSpace, 267 yuvaFormats, 268 yuvaSizes, 269 yuvaIndices, 270 imageWidth, 271 imageHeight, 272 imageOrigin, 273 std::move(imageColorSpace), 274 textureFulfillProc, 275 textureReleaseProc, 276 textureDoneProc, 277 textureContexts, 278 delayReleaseCallback); 279 } 280 281 #endif 282