• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
SkDeferredDisplayListRecorder(const SkSurfaceCharacterization &)15 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&) {}
16 
~SkDeferredDisplayListRecorder()17 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {}
18 
init()19 bool SkDeferredDisplayListRecorder::init() { return false; }
20 
getCanvas()21 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { return nullptr; }
22 
detach()23 std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { return nullptr; }
24 
makePromiseTexture(const GrBackendFormat & backendFormat,int width,int height,GrMipMapped mipMapped,GrSurfaceOrigin origin,SkColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,PromiseImageTextureFulfillProc textureFulfillProc,PromiseImageTextureReleaseProc textureReleaseProc,PromiseImageTextureDoneProc textureDoneProc,PromiseImageTextureContext textureContext,DelayReleaseCallback delayReleaseCallback)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 
makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,const GrBackendFormat yuvaFormats[],const SkISize yuvaSizes[],const SkYUVAIndex yuvaIndices[4],int imageWidth,int imageHeight,GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace,PromiseImageTextureFulfillProc textureFulfillProc,PromiseImageTextureReleaseProc textureReleaseProc,PromiseImageTextureDoneProc textureDoneProc,PromiseImageTextureContext textureContexts[],DelayReleaseCallback delayReleaseCallback)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 
SkDeferredDisplayListRecorder(const SkSurfaceCharacterization & c)73 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c)
74         : fCharacterization(c) {
75     if (fCharacterization.isValid()) {
76         fContext = GrContextPriv::MakeDDL(fCharacterization.refContextInfo());
77     }
78 }
79 
~SkDeferredDisplayListRecorder()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 
init()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 
getCanvas()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 
detach()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 
makePromiseTexture(const GrBackendFormat & backendFormat,int width,int height,GrMipMapped mipMapped,GrSurfaceOrigin origin,SkColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,PromiseImageTextureFulfillProc textureFulfillProc,PromiseImageTextureReleaseProc textureReleaseProc,PromiseImageTextureDoneProc textureDoneProc,PromiseImageTextureContext textureContext,DelayReleaseCallback delayReleaseCallback)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 
makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,const GrBackendFormat yuvaFormats[],const SkISize yuvaSizes[],const SkYUVAIndex yuvaIndices[4],int imageWidth,int imageHeight,GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace,PromiseImageTextureFulfillProc textureFulfillProc,PromiseImageTextureReleaseProc textureReleaseProc,PromiseImageTextureDoneProc textureDoneProc,PromiseImageTextureContext textureContexts[],DelayReleaseCallback delayReleaseCallback)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