xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkSecondaryCBDrawContext.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2019 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/private/chromium/GrVkSecondaryCBDrawContext.h"
9 
10 #include "include/core/SkImageInfo.h"
11 #include "include/gpu/ganesh/GrDirectContext.h"
12 #include "include/gpu/ganesh/GrRecordingContext.h"
13 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
14 #include "include/gpu/ganesh/vk/GrVkTypes.h"
15 #include "include/private/chromium/GrDeferredDisplayList.h"
16 #include "include/private/chromium/GrSurfaceCharacterization.h"
17 #include "src/core/SkSurfacePriv.h"
18 #include "src/gpu/ganesh/GrContextThreadSafeProxyPriv.h"
19 #include "src/gpu/ganesh/GrDirectContextPriv.h"
20 #include "src/gpu/ganesh/GrProxyProvider.h"
21 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
22 #include "src/gpu/ganesh/GrRenderTarget.h"
23 #include "src/gpu/ganesh/GrRenderTargetProxy.h"
24 #include "src/gpu/ganesh/GrResourceProvider.h"
25 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
26 
Make(GrRecordingContext * rContext,const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)27 sk_sp<GrVkSecondaryCBDrawContext> GrVkSecondaryCBDrawContext::Make(GrRecordingContext* rContext,
28                                                                    const SkImageInfo& imageInfo,
29                                                                    const GrVkDrawableInfo& vkInfo,
30                                                                    const SkSurfaceProps* props) {
31     if (!rContext) {
32         return nullptr;
33     }
34 
35     if (rContext->backend() != GrBackendApi::kVulkan) {
36         return nullptr;
37     }
38 
39 
40     GrProxyProvider* gpp = rContext->priv().proxyProvider();
41     if (gpp->isAbandoned()) {
42         return nullptr;
43     }
44 
45     GrResourceProvider* resourceProvider = gpp->resourceProvider();
46     if (!resourceProvider) {
47         return nullptr;
48     }
49 
50     sk_sp<GrRenderTarget> rt = resourceProvider->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
51                                                                                      vkInfo);
52     if (!rt) {
53         return nullptr;
54     }
55 
56     SkASSERT(!rt->asTexture());  // A GrRenderTarget that's not textureable
57     SkASSERT(!rt->getUniqueKey().isValid());
58     // This proxy should be unbudgeted because we're just wrapping an external resource
59     SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
60 
61     GrColorType colorType = SkColorTypeToGrColorType(imageInfo.colorType());
62 
63     if (!gpp->caps()->isFormatAsColorTypeRenderable(
64             colorType, GrBackendFormats::MakeVk(vkInfo.fFormat), /*sampleCount=*/1)) {
65         return nullptr;
66     }
67 
68     sk_sp<GrRenderTargetProxy> proxy(
69             new GrRenderTargetProxy(std::move(rt),
70                                     GrSurfaceProxy::UseAllocator::kNo,
71                                     GrRenderTargetProxy::WrapsVkSecondaryCB::kYes));
72 
73     if (!proxy) {
74         return nullptr;
75     }
76 
77     SkASSERT(proxy->isInstantiated());
78 
79     auto device = rContext->priv().createDevice(SkColorTypeToGrColorType(imageInfo.colorType()),
80                                                 std::move(proxy),
81                                                 imageInfo.refColorSpace(),
82                                                 kTopLeft_GrSurfaceOrigin,
83                                                 SkSurfacePropsCopyOrDefault(props),
84                                                 skgpu::ganesh::Device::InitContents::kUninit);
85     if (!device) {
86         return nullptr;
87     }
88 
89     return sk_sp<GrVkSecondaryCBDrawContext>(new GrVkSecondaryCBDrawContext(std::move(device),
90                                                                             props));
91 }
92 
GrVkSecondaryCBDrawContext(sk_sp<skgpu::ganesh::Device> device,const SkSurfaceProps * props)93 GrVkSecondaryCBDrawContext::GrVkSecondaryCBDrawContext(sk_sp<skgpu::ganesh::Device> device,
94                                                        const SkSurfaceProps* props)
95         : fDevice(std::move(device)), fProps(SkSurfacePropsCopyOrDefault(props)) {}
96 
~GrVkSecondaryCBDrawContext()97 GrVkSecondaryCBDrawContext::~GrVkSecondaryCBDrawContext() {
98     SkASSERT(!fDevice);
99     SkASSERT(!fCachedCanvas.get());
100 }
101 
getCanvas()102 SkCanvas* GrVkSecondaryCBDrawContext::getCanvas() {
103     if (!fCachedCanvas) {
104         fCachedCanvas = std::make_unique<SkCanvas>(fDevice);
105     }
106     return fCachedCanvas.get();
107 }
108 
flush()109 void GrVkSecondaryCBDrawContext::flush() {
110     auto dContext = GrAsDirectContext(fDevice->recordingContext());
111 
112     if (dContext) {
113         dContext->priv().flushSurface(fDevice->targetProxy());
114         dContext->submit();
115     }
116 }
117 
wait(int numSemaphores,const GrBackendSemaphore waitSemaphores[],bool deleteSemaphoresAfterWait)118 bool GrVkSecondaryCBDrawContext::wait(int numSemaphores,
119                                       const GrBackendSemaphore waitSemaphores[],
120                                       bool deleteSemaphoresAfterWait) {
121     return fDevice->wait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
122 }
123 
releaseResources()124 void GrVkSecondaryCBDrawContext::releaseResources() {
125     fCachedCanvas.reset();
126     fDevice.reset();
127 }
128 
characterize(GrSurfaceCharacterization * characterization) const129 bool GrVkSecondaryCBDrawContext::characterize(GrSurfaceCharacterization* characterization) const {
130     auto direct = fDevice->recordingContext()->asDirectContext();
131     if (!direct) {
132         return false;
133     }
134 
135     SkImageInfo ii = fDevice->imageInfo();
136     if (ii.colorType() == kUnknown_SkColorType) {
137         return false;
138     }
139 
140     GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
141     size_t maxResourceBytes = direct->getResourceCacheLimit();
142 
143     // We current don't support textured GrVkSecondaryCBDrawContexts.
144     SkASSERT(!readSurfaceView.asTextureProxy());
145 
146     GrBackendFormat format = readSurfaceView.asRenderTargetProxy()->backendFormat();
147     int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
148     GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
149 
150     characterization->set(direct->threadSafeProxy(),
151                           maxResourceBytes,
152                           ii,
153                           format,
154                           readSurfaceView.origin(),
155                           numSamples,
156                           GrSurfaceCharacterization::Textureable(false),
157                           skgpu::Mipmapped::kNo,
158                           GrSurfaceCharacterization::UsesGLFBO0(false),
159                           GrSurfaceCharacterization::VkRTSupportsInputAttachment(false),
160                           GrSurfaceCharacterization::VulkanSecondaryCBCompatible(true),
161                           isProtected,
162                           this->props());
163 
164     return true;
165 }
166 
isCompatible(const GrSurfaceCharacterization & characterization) const167 bool GrVkSecondaryCBDrawContext::isCompatible(
168         const GrSurfaceCharacterization& characterization) const {
169 
170     auto dContext = fDevice->recordingContext()->asDirectContext();
171     if (!dContext) {
172         return false;
173     }
174 
175     if (!characterization.isValid()) {
176         return false;
177     }
178 
179     if (!characterization.vulkanSecondaryCBCompatible()) {
180         return false;
181     }
182 
183     if (characterization.isTextureable()) {
184         // We don't support textureable DDL when rendering to a GrVkSecondaryCBDrawContext.
185         return false;
186     }
187 
188     if (characterization.usesGLFBO0()) {
189         return false;
190     }
191 
192     SkImageInfo ii = fDevice->imageInfo();
193     if (ii.colorType() == kUnknown_SkColorType) {
194         return false;
195     }
196 
197     GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
198     // As long as the current state in the context allows for greater or equal resources,
199     // we allow the DDL to be replayed.
200     // DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
201     size_t maxResourceBytes = dContext->getResourceCacheLimit();
202 
203     GrBackendFormat format = readSurfaceView.asRenderTargetProxy()->backendFormat();
204     int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
205     GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
206 
207     return characterization.contextInfo() &&
208            characterization.contextInfo()->priv().matches(dContext) &&
209            characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
210            characterization.origin() == readSurfaceView.origin() &&
211            characterization.backendFormat() == format &&
212            characterization.width() == ii.width() &&
213            characterization.height() == ii.height() &&
214            characterization.colorType() == ii.colorType() &&
215            characterization.sampleCount() == numSamples &&
216            SkColorSpace::Equals(characterization.colorSpace(), ii.colorInfo().colorSpace()) &&
217            characterization.isProtected() == isProtected &&
218            characterization.surfaceProps() == fDevice->surfaceProps();
219 }
220 
221 #ifndef SK_DDL_IS_UNIQUE_POINTER
draw(sk_sp<const GrDeferredDisplayList> ddl)222 bool GrVkSecondaryCBDrawContext::draw(sk_sp<const GrDeferredDisplayList> ddl) {
223 #else
224 bool GrVkSecondaryCBDrawContext::draw(const GrDeferredDisplayList* ddl) {
225 #endif
226     if (!ddl || !this->isCompatible(ddl->characterization())) {
227         return false;
228     }
229 
230     auto direct = fDevice->recordingContext()->asDirectContext();
231     if (!direct) {
232         return false;
233     }
234 
235     GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
236 
237     direct->priv().createDDLTask(std::move(ddl), readSurfaceView.asRenderTargetProxyRef());
238     return true;
239 }
240