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