• 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 "include/core/SkDeferredDisplayListRecorder.h"
9 
10 #include "include/core/SkDeferredDisplayList.h"
11 #include "include/core/SkSurface.h"
12 #include "include/core/SkSurfaceCharacterization.h"
13 #include "src/core/SkMessageBus.h"
14 
15 #if !SK_SUPPORT_GPU
SkDeferredDisplayListRecorder(const SkSurfaceCharacterization &)16 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&) {}
17 
~SkDeferredDisplayListRecorder()18 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {}
19 
init()20 bool SkDeferredDisplayListRecorder::init() { return false; }
21 
getCanvas()22 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { return nullptr; }
23 
detach()24 sk_sp<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { return nullptr; }
25 
26 #else
27 
28 #include "include/core/SkPromiseImageTexture.h"
29 #include "include/gpu/GrRecordingContext.h"
30 #include "include/gpu/GrYUVABackendTextures.h"
31 #include "src/gpu/GrProxyProvider.h"
32 #include "src/gpu/GrRecordingContextPriv.h"
33 #include "src/gpu/GrTexture.h"
34 #include "src/gpu/SkGr.h"
35 #include "src/image/SkImage_Gpu.h"
36 #include "src/image/SkImage_GpuYUVA.h"
37 #include "src/image/SkSurface_Gpu.h"
38 
SkDeferredDisplayListRecorder(const SkSurfaceCharacterization & c)39 SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c)
40         : fCharacterization(c) {
41     if (fCharacterization.isValid()) {
42         fContext = GrRecordingContextPriv::MakeDDL(fCharacterization.refContextInfo());
43     }
44 }
45 
~SkDeferredDisplayListRecorder()46 SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {
47     if (fContext) {
48         auto proxyProvider = fContext->priv().proxyProvider();
49 
50         // This allows the uniquely keyed proxies to keep their keys but removes their back
51         // pointer to the about-to-be-deleted proxy provider. The proxies will use their
52         // unique key to reattach to cached versions of themselves or to appropriately tag new
53         // resources (if a cached version was not found). This system operates independent of
54         // the replaying context's proxy provider (i.e., these uniquely keyed proxies will not
55         // appear in the replaying proxy providers uniquely keyed proxy map). This should be fine
56         // since no one else should be trying to reconnect to the orphaned proxies and orphaned
57         // proxies from different DDLs that share the same key should simply reconnect to the
58         // same cached resource.
59         proxyProvider->orphanAllUniqueKeys();
60     }
61 }
62 
init()63 bool SkDeferredDisplayListRecorder::init() {
64     SkASSERT(fContext);
65     SkASSERT(!fTargetProxy);
66     SkASSERT(!fLazyProxyData);
67     SkASSERT(!fSurface);
68 
69     if (!fCharacterization.isValid()) {
70         return false;
71     }
72 
73     fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>(
74                                                     new SkDeferredDisplayList::LazyProxyData);
75 
76     auto proxyProvider = fContext->priv().proxyProvider();
77     const GrCaps* caps = fContext->priv().caps();
78 
79     bool usesGLFBO0 = fCharacterization.usesGLFBO0();
80     if (usesGLFBO0) {
81         if (GrBackendApi::kOpenGL != fContext->backend() ||
82             fCharacterization.isTextureable()) {
83             return false;
84         }
85     }
86 
87     bool vkRTSupportsInputAttachment = fCharacterization.vkRTSupportsInputAttachment();
88     if (vkRTSupportsInputAttachment && GrBackendApi::kVulkan != fContext->backend()) {
89         return false;
90     }
91 
92     if (fCharacterization.vulkanSecondaryCBCompatible()) {
93         // Because of the restrictive API allowed for a GrVkSecondaryCBDrawContext, we know ahead
94         // of time that we don't be able to support certain parameter combinations. Specifically we
95         // fail on usesGLFBO0 since we can't mix GL and Vulkan. We can't have a texturable object.
96         // We can't use it as in input attachment since we don't control the render pass this will
97         // be played into and thus can't force it to have an input attachment and the correct
98         // dependencies. And finally the GrVkSecondaryCBDrawContext always assumes a top left
99         // origin.
100         if (usesGLFBO0 ||
101             vkRTSupportsInputAttachment ||
102             fCharacterization.isTextureable() ||
103             fCharacterization.origin() == kBottomLeft_GrSurfaceOrigin) {
104             return false;
105         }
106     }
107 
108     GrColorType grColorType = SkColorTypeToGrColorType(fCharacterization.colorType());
109 
110     // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy
111     // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the
112     // DDL is being replayed into.
113 
114     GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
115     if (usesGLFBO0) {
116         surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
117     } else if (fCharacterization.sampleCount() > 1 && !caps->msaaResolvesAutomatically() &&
118                fCharacterization.isTextureable()) {
119         surfaceFlags |= GrInternalSurfaceFlags::kRequiresManualMSAAResolve;
120     }
121 
122     if (vkRTSupportsInputAttachment) {
123         surfaceFlags |= GrInternalSurfaceFlags::kVkRTSupportsInputAttachment;
124     }
125 
126     // FIXME: Why do we use GrMipmapped::kNo instead of SkSurfaceCharacterization::fIsMipMapped?
127     static constexpr GrProxyProvider::TextureInfo kTextureInfo{GrMipmapped::kNo,
128                                                                GrTextureType::k2D};
129     const GrProxyProvider::TextureInfo* optionalTextureInfo = nullptr;
130     if (fCharacterization.isTextureable()) {
131         optionalTextureInfo = &kTextureInfo;
132     }
133 
134     fTargetProxy = proxyProvider->createLazyRenderTargetProxy(
135             [lazyProxyData = fLazyProxyData](GrResourceProvider* resourceProvider,
136                                              const GrSurfaceProxy::LazySurfaceDesc&) {
137                 // The proxy backing the destination surface had better have been instantiated
138                 // prior to this one (i.e., the proxy backing the DDL's surface).
139                 // Fulfill this lazy proxy with the destination surface's GrRenderTarget.
140                 SkASSERT(lazyProxyData->fReplayDest->peekSurface());
141                 auto surface = sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->peekSurface());
142                 return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
143             },
144             fCharacterization.backendFormat(),
145             fCharacterization.dimensions(),
146             fCharacterization.sampleCount(),
147             surfaceFlags,
148             optionalTextureInfo,
149             GrMipmapStatus::kNotAllocated,
150             SkBackingFit::kExact,
151             SkBudgeted::kYes,
152             fCharacterization.isProtected(),
153             fCharacterization.vulkanSecondaryCBCompatible(),
154             GrSurfaceProxy::UseAllocator::kYes);
155 
156     if (!fTargetProxy) {
157         return false;
158     }
159     fTargetProxy->priv().setIsDDLTarget();
160 
161     auto device = fContext->priv().createDevice(grColorType,
162                                                 fTargetProxy,
163                                                 fCharacterization.refColorSpace(),
164                                                 fCharacterization.origin(),
165                                                 fCharacterization.surfaceProps(),
166                                                 skgpu::BaseDevice::InitContents::kUninit);
167     if (!device) {
168         return false;
169     }
170 
171     fSurface = sk_make_sp<SkSurface_Gpu>(std::move(device));
172     return SkToBool(fSurface.get());
173 }
174 
getCanvas()175 SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
176     if (!fContext) {
177         return nullptr;
178     }
179 
180     if (!fSurface && !this->init()) {
181         return nullptr;
182     }
183 
184     return fSurface->getCanvas();
185 }
186 
detach()187 sk_sp<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
188     if (!fContext || !fTargetProxy) {
189         return nullptr;
190     }
191 
192     if (fSurface) {
193         SkCanvas* canvas = fSurface->getCanvas();
194 
195         canvas->restoreToCount(0);
196     }
197 
198     auto ddl = sk_sp<SkDeferredDisplayList>(new SkDeferredDisplayList(fCharacterization,
199                                                                       std::move(fTargetProxy),
200                                                                       std::move(fLazyProxyData)));
201 
202     fContext->priv().moveRenderTasksToDDL(ddl.get());
203 
204     // We want a new lazy proxy target for each recorded DDL so force the (lazy proxy-backed)
205     // SkSurface to be regenerated for each DDL.
206     fSurface = nullptr;
207     return ddl;
208 }
209 
210 #ifndef SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
makePromiseTexture(const GrBackendFormat & backendFormat,int width,int height,GrMipmapped mipMapped,GrSurfaceOrigin origin,SkColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,PromiseImageTextureFulfillProc textureFulfillProc,PromiseImageTextureReleaseProc textureReleaseProc,PromiseImageTextureContext textureContext)211 sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
212         const GrBackendFormat& backendFormat,
213         int width,
214         int height,
215         GrMipmapped mipMapped,
216         GrSurfaceOrigin origin,
217         SkColorType colorType,
218         SkAlphaType alphaType,
219         sk_sp<SkColorSpace> colorSpace,
220         PromiseImageTextureFulfillProc textureFulfillProc,
221         PromiseImageTextureReleaseProc textureReleaseProc,
222         PromiseImageTextureContext textureContext) {
223     if (!fContext) {
224         return nullptr;
225     }
226     return SkImage::MakePromiseTexture(fContext->threadSafeProxy(),
227                                        backendFormat,
228                                        {width, height},
229                                        mipMapped,
230                                        origin,
231                                        colorType,
232                                        alphaType,
233                                        std::move(colorSpace),
234                                        textureFulfillProc,
235                                        textureReleaseProc,
236                                        textureContext);
237 }
238 
makeYUVAPromiseTexture(const GrYUVABackendTextureInfo & backendTextureInfo,sk_sp<SkColorSpace> imageColorSpace,PromiseImageTextureFulfillProc textureFulfillProc,PromiseImageTextureReleaseProc textureReleaseProc,PromiseImageTextureContext textureContexts[])239 sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
240         const GrYUVABackendTextureInfo& backendTextureInfo,
241         sk_sp<SkColorSpace> imageColorSpace,
242         PromiseImageTextureFulfillProc textureFulfillProc,
243         PromiseImageTextureReleaseProc textureReleaseProc,
244         PromiseImageTextureContext textureContexts[]) {
245     if (!fContext) {
246         return nullptr;
247     }
248     return SkImage::MakePromiseYUVATexture(fContext->threadSafeProxy(),
249                                            backendTextureInfo,
250                                            std::move(imageColorSpace),
251                                            textureFulfillProc,
252                                            textureReleaseProc,
253                                            textureContexts);
254 }
255 #endif // !SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
256 
257 #endif
258