1 /*
2 * Copyright 2020 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 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
8
9 #include "include/core/SkAlphaType.h"
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkSize.h"
12 #include "include/core/SkSurfaceProps.h"
13 #include "include/gpu/ganesh/GrBackendSurface.h"
14 #include "include/gpu/ganesh/GrContextOptions.h"
15 #include "include/private/gpu/ganesh/GrContext_Base.h"
16 #include "include/private/gpu/ganesh/GrTypesPriv.h"
17 #include "src/gpu/RefCntedCallback.h"
18 #include "src/gpu/Swizzle.h"
19 #include "src/gpu/ganesh/Device.h"
20 #include "src/gpu/ganesh/GrCaps.h"
21 #include "src/gpu/ganesh/GrDrawingManager.h"
22 #include "src/gpu/ganesh/GrImageInfo.h"
23 #include "src/gpu/ganesh/GrProxyProvider.h"
24 #include "src/gpu/ganesh/GrShaderCaps.h"
25 #include "src/gpu/ganesh/GrSurfaceProxy.h"
26 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
27 #include "src/gpu/ganesh/GrTextureProxy.h"
28 #include "src/gpu/ganesh/SurfaceContext.h"
29 #include "src/gpu/ganesh/SurfaceDrawContext.h"
30 #include "src/gpu/ganesh/SurfaceFillContext.h"
31
32 #include <utility>
33
addOnFlushCallbackObject(GrOnFlushCallbackObject * onFlushCBObject)34 void GrRecordingContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
35 this->context()->addOnFlushCallbackObject(onFlushCBObject);
36 }
37
createDevice(GrColorType colorType,sk_sp<GrSurfaceProxy> proxy,sk_sp<SkColorSpace> colorSpace,GrSurfaceOrigin origin,const SkSurfaceProps & props,skgpu::ganesh::Device::InitContents init)38 sk_sp<skgpu::ganesh::Device> GrRecordingContextPriv::createDevice(
39 GrColorType colorType,
40 sk_sp<GrSurfaceProxy> proxy,
41 sk_sp<SkColorSpace> colorSpace,
42 GrSurfaceOrigin origin,
43 const SkSurfaceProps& props,
44 skgpu::ganesh::Device::InitContents init) {
45 return skgpu::ganesh::Device::Make(this->context(),
46 colorType,
47 std::move(proxy),
48 std::move(colorSpace),
49 origin,
50 props,
51 init);
52 }
53
createDevice(skgpu::Budgeted budgeted,const SkImageInfo & ii,SkBackingFit fit,int sampleCount,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrSurfaceOrigin origin,const SkSurfaceProps & props,skgpu::ganesh::Device::InitContents init)54 sk_sp<skgpu::ganesh::Device> GrRecordingContextPriv::createDevice(
55 skgpu::Budgeted budgeted,
56 const SkImageInfo& ii,
57 SkBackingFit fit,
58 int sampleCount,
59 skgpu::Mipmapped mipmapped,
60 GrProtected isProtected,
61 GrSurfaceOrigin origin,
62 const SkSurfaceProps& props,
63 skgpu::ganesh::Device::InitContents init) {
64 return skgpu::ganesh::Device::Make(this->context(),
65 budgeted,
66 ii,
67 fit,
68 sampleCount,
69 mipmapped,
70 isProtected,
71 origin,
72 props,
73 init);
74 }
75
moveRenderTasksToDDL(GrDeferredDisplayList * ddl)76 void GrRecordingContextPriv::moveRenderTasksToDDL(GrDeferredDisplayList* ddl) {
77 this->context()->drawingManager()->moveRenderTasksToDDL(ddl);
78 }
79
getSubRunControl(bool useSDFTForSmallText) const80 sktext::gpu::SubRunControl GrRecordingContextPriv::getSubRunControl(
81 bool useSDFTForSmallText) const {
82 #if !defined(SK_DISABLE_SDF_TEXT)
83 return sktext::gpu::SubRunControl{
84 this->caps()->shaderCaps()->supportsDistanceFieldText(),
85 useSDFTForSmallText,
86 !this->caps()->disablePerspectiveSDFText(),
87 this->options().fMinDistanceFieldFontSize,
88 this->options().fGlyphsAsPathsFontSize};
89 #else
90 return sktext::gpu::SubRunControl{};
91 #endif
92 }
93
makeSC(GrSurfaceProxyView readView,const GrColorInfo & info)94 std::unique_ptr<skgpu::ganesh::SurfaceContext> GrRecordingContextPriv::makeSC(
95 GrSurfaceProxyView readView, const GrColorInfo& info) {
96 // It is probably not necessary to check if the context is abandoned here since uses of the
97 // SurfaceContext which need the context will mostly likely fail later on w/o an issue.
98 // However having this here adds some reassurance in case there is a path that doesn't
99 // handle an abandoned context correctly. It also lets us early out of some extra work.
100 if (this->context()->abandoned()) {
101 return nullptr;
102 }
103 GrSurfaceProxy* proxy = readView.proxy();
104 SkASSERT(proxy && proxy->asTextureProxy());
105
106 std::unique_ptr<skgpu::ganesh::SurfaceContext> sc;
107 if (proxy->asRenderTargetProxy()) {
108 // Will we ever want a swizzle that is not the default write swizzle for the format and
109 // colorType here? If so we will need to manually pass that in.
110 skgpu::Swizzle writeSwizzle;
111 if (info.colorType() != GrColorType::kUnknown) {
112 writeSwizzle = this->caps()->getWriteSwizzle(proxy->backendFormat(),
113 info.colorType());
114 }
115 GrSurfaceProxyView writeView(readView.refProxy(), readView.origin(), writeSwizzle);
116 if (info.alphaType() == kPremul_SkAlphaType ||
117 info.alphaType() == kOpaque_SkAlphaType) {
118 sc = std::make_unique<skgpu::ganesh::SurfaceDrawContext>(this->context(),
119 std::move(readView),
120 std::move(writeView),
121 info.colorType(),
122 info.refColorSpace(),
123 SkSurfaceProps());
124 } else {
125 sc = std::make_unique<skgpu::ganesh::SurfaceFillContext>(
126 this->context(), std::move(readView), std::move(writeView), info);
127 }
128 } else {
129 sc = std::make_unique<skgpu::ganesh::SurfaceContext>(
130 this->context(), std::move(readView), info);
131 }
132 SkDEBUGCODE(sc->validate();)
133 return sc;
134 }
135
makeSC(const GrImageInfo & info,const GrBackendFormat & format,std::string_view label,SkBackingFit fit,GrSurfaceOrigin origin,GrRenderable renderable,int sampleCount,skgpu::Mipmapped mipmapped,GrProtected isProtected,skgpu::Budgeted budgeted)136 std::unique_ptr<skgpu::ganesh::SurfaceContext> GrRecordingContextPriv::makeSC(
137 const GrImageInfo& info,
138 const GrBackendFormat& format,
139 std::string_view label,
140 SkBackingFit fit,
141 GrSurfaceOrigin origin,
142 GrRenderable renderable,
143 int sampleCount,
144 skgpu::Mipmapped mipmapped,
145 GrProtected isProtected,
146 skgpu::Budgeted budgeted) {
147 SkASSERT(renderable == GrRenderable::kYes || sampleCount == 1);
148 if (this->abandoned()) {
149 return nullptr;
150 }
151 sk_sp<GrTextureProxy> proxy =
152 this->proxyProvider()->createProxy(format,
153 info.dimensions(),
154 renderable,
155 sampleCount,
156 mipmapped,
157 fit,
158 budgeted,
159 isProtected,
160 label);
161 if (!proxy) {
162 return nullptr;
163 }
164
165 skgpu::Swizzle swizzle;
166 if (info.colorType() != GrColorType::kUnknown &&
167 !this->caps()->isFormatCompressed(format)) {
168 swizzle = this->caps()->getReadSwizzle(format, info.colorType());
169 }
170
171 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
172 return this->makeSC(std::move(view), info.colorInfo());
173 }
174
makeSFC(GrImageInfo info,std::string_view label,SkBackingFit fit,int sampleCount,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrSurfaceOrigin origin,skgpu::Budgeted budgeted)175 std::unique_ptr<skgpu::ganesh::SurfaceFillContext> GrRecordingContextPriv::makeSFC(
176 GrImageInfo info,
177 std::string_view label,
178 SkBackingFit fit,
179 int sampleCount,
180 skgpu::Mipmapped mipmapped,
181 GrProtected isProtected,
182 GrSurfaceOrigin origin,
183 skgpu::Budgeted budgeted) {
184 if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
185 return skgpu::ganesh::SurfaceDrawContext::Make(this->context(),
186 info.colorType(),
187 info.refColorSpace(),
188 fit,
189 info.dimensions(),
190 SkSurfaceProps(),
191 label,
192 sampleCount,
193 mipmapped,
194 isProtected,
195 origin,
196 budgeted);
197 }
198 GrBackendFormat format = this->caps()->getDefaultBackendFormat(info.colorType(),
199 GrRenderable::kYes);
200 sk_sp<GrTextureProxy> proxy =
201 this->proxyProvider()->createProxy(format,
202 info.dimensions(),
203 GrRenderable::kYes,
204 sampleCount,
205 mipmapped,
206 fit,
207 budgeted,
208 isProtected,
209 label);
210 if (!proxy) {
211 return nullptr;
212 }
213 skgpu::Swizzle readSwizzle = this->caps()->getReadSwizzle (format, info.colorType());
214 skgpu::Swizzle writeSwizzle = this->caps()->getWriteSwizzle(format, info.colorType());
215
216 GrSurfaceProxyView readView( proxy, origin, readSwizzle);
217 GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
218 std::unique_ptr<skgpu::ganesh::SurfaceFillContext> sfc;
219 sfc = std::make_unique<skgpu::ganesh::SurfaceFillContext>(
220 this->context(), std::move(readView), std::move(writeView), info.colorInfo());
221 sfc->discard();
222 return sfc;
223 }
224
makeSFC(SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,SkISize dimensions,SkBackingFit fit,const GrBackendFormat & format,int sampleCount,skgpu::Mipmapped mipmapped,GrProtected isProtected,skgpu::Swizzle readSwizzle,skgpu::Swizzle writeSwizzle,GrSurfaceOrigin origin,skgpu::Budgeted budgeted,std::string_view label)225 std::unique_ptr<skgpu::ganesh::SurfaceFillContext> GrRecordingContextPriv::makeSFC(
226 SkAlphaType alphaType,
227 sk_sp<SkColorSpace> colorSpace,
228 SkISize dimensions,
229 SkBackingFit fit,
230 const GrBackendFormat& format,
231 int sampleCount,
232 skgpu::Mipmapped mipmapped,
233 GrProtected isProtected,
234 skgpu::Swizzle readSwizzle,
235 skgpu::Swizzle writeSwizzle,
236 GrSurfaceOrigin origin,
237 skgpu::Budgeted budgeted,
238 std::string_view label) {
239 SkASSERT(!dimensions.isEmpty());
240 SkASSERT(sampleCount >= 1);
241 SkASSERT(format.isValid() && format.backend() == fContext->backend());
242 if (alphaType == kPremul_SkAlphaType || alphaType == kOpaque_SkAlphaType) {
243 return skgpu::ganesh::SurfaceDrawContext::Make(this->context(),
244 std::move(colorSpace),
245 fit,
246 dimensions,
247 format,
248 sampleCount,
249 mipmapped,
250 isProtected,
251 readSwizzle,
252 writeSwizzle,
253 origin,
254 budgeted,
255 SkSurfaceProps(),
256 label);
257 }
258
259 sk_sp<GrTextureProxy> proxy =
260 this->proxyProvider()->createProxy(format,
261 dimensions,
262 GrRenderable::kYes,
263 sampleCount,
264 mipmapped,
265 fit,
266 budgeted,
267 isProtected,
268 label);
269 if (!proxy) {
270 return nullptr;
271 }
272 GrImageInfo info(GrColorType::kUnknown, alphaType, std::move(colorSpace), dimensions);
273 GrSurfaceProxyView readView( proxy, origin, readSwizzle);
274 GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
275 std::unique_ptr<skgpu::ganesh::SurfaceFillContext> sfc;
276 sfc = std::make_unique<skgpu::ganesh::SurfaceFillContext>(
277 this->context(), std::move(readView), std::move(writeView), info.colorInfo());
278 sfc->discard();
279 return sfc;
280 }
281
makeSFCWithFallback(GrImageInfo info,SkBackingFit fit,int sampleCount,skgpu::Mipmapped mipmapped,GrProtected isProtected,GrSurfaceOrigin origin,skgpu::Budgeted budgeted)282 std::unique_ptr<skgpu::ganesh::SurfaceFillContext> GrRecordingContextPriv::makeSFCWithFallback(
283 GrImageInfo info,
284 SkBackingFit fit,
285 int sampleCount,
286 skgpu::Mipmapped mipmapped,
287 GrProtected isProtected,
288 GrSurfaceOrigin origin,
289 skgpu::Budgeted budgeted) {
290 if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
291 return skgpu::ganesh::SurfaceDrawContext::MakeWithFallback(this->context(),
292 info.colorType(),
293 info.refColorSpace(),
294 fit,
295 info.dimensions(),
296 SkSurfaceProps(),
297 sampleCount,
298 mipmapped,
299 isProtected,
300 origin,
301 budgeted);
302 }
303 const GrCaps* caps = this->caps();
304
305 auto [ct, _] = caps->getFallbackColorTypeAndFormat(info.colorType(), sampleCount);
306 if (ct == GrColorType::kUnknown) {
307 return nullptr;
308 }
309 info = info.makeColorType(ct);
310 return this->makeSFC(info, "MakeSurfaceContextWithFallback",
311 fit,
312 sampleCount,
313 mipmapped,
314 isProtected,
315 origin,
316 budgeted);
317 }
318
319 std::unique_ptr<skgpu::ganesh::SurfaceFillContext>
makeSFCFromBackendTexture(GrColorInfo info,const GrBackendTexture & tex,int sampleCount,GrSurfaceOrigin origin,sk_sp<skgpu::RefCntedCallback> releaseHelper)320 GrRecordingContextPriv::makeSFCFromBackendTexture(GrColorInfo info,
321 const GrBackendTexture& tex,
322 int sampleCount,
323 GrSurfaceOrigin origin,
324 sk_sp<skgpu::RefCntedCallback> releaseHelper) {
325 SkASSERT(sampleCount > 0);
326
327 if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
328 return skgpu::ganesh::SurfaceDrawContext::MakeFromBackendTexture(this->context(),
329 info.colorType(),
330 info.refColorSpace(),
331 tex,
332 sampleCount,
333 origin,
334 SkSurfaceProps(),
335 std::move(releaseHelper));
336 }
337
338 if (info.colorType() == GrColorType::kUnknown) {
339 return nullptr;
340 }
341
342 const GrBackendFormat& format = tex.getBackendFormat();
343 if (!this->caps()->areColorTypeAndFormatCompatible(info.colorType(), format)) {
344 return nullptr;
345 }
346 skgpu::Swizzle readSwizzle = this->caps()->getReadSwizzle (format, info.colorType());
347 skgpu::Swizzle writeSwizzle = this->caps()->getWriteSwizzle(format, info.colorType());
348
349 sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture(
350 tex, sampleCount, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
351 std::move(releaseHelper)));
352 if (!proxy) {
353 return nullptr;
354 }
355
356 GrSurfaceProxyView readView( proxy, origin, readSwizzle);
357 GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
358
359 return std::make_unique<skgpu::ganesh::SurfaceFillContext>(
360 this->context(), std::move(readView), std::move(writeView), std::move(info));
361 }
362