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