Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrProxyProvider.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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
9
20#include "src/core/SkMipmap.h"
33#include "src/gpu/ganesh/SkGr.h"
35
36#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(fImageContext->priv().singleOwner())
37
38GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {}
39
41 if (this->renderingDirectly()) {
42 // In DDL-mode a proxy provider can still have extant uniquely keyed proxies (since
43 // they need their unique keys to, potentially, find a cached resource when the
44 // DDL is played) but, in non-DDL-mode they should all have been cleaned up by this point.
45 SkASSERT(!fUniquelyKeyedProxies.count());
46 }
47}
48
51 SkASSERT(key.isValid());
52 if (this->isAbandoned() || !proxy) {
53 return false;
54 }
55
56 // Only the proxyProvider that created a proxy should be assigning unique keys to it.
57 SkASSERT(this->isDDLProvider() == proxy->creatingProvider());
58
59#ifdef SK_DEBUG
60 {
61 auto direct = fImageContext->asDirectContext();
62 if (direct) {
63 GrResourceCache* resourceCache = direct->priv().getResourceCache();
64 // If there is already a GrResource with this key then the caller has violated the
65 // normal usage pattern of uniquely keyed resources (e.g., they have created one w/o
66 // first seeing if it already existed in the cache).
67 SkASSERT(!resourceCache->findAndRefUniqueResource(key));
68 }
69 }
70#endif
71
72 SkASSERT(!fUniquelyKeyedProxies.find(key)); // multiple proxies can't get the same key
73
74 proxy->cacheAccess().setUniqueKey(this, key);
75 SkASSERT(proxy->getUniqueKey() == key);
76 fUniquelyKeyedProxies.add(proxy);
77 return true;
78}
79
81 SkASSERT(surf->getUniqueKey().isValid());
82 proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
83 SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
84 // multiple proxies can't get the same key
85 SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
86 fUniquelyKeyedProxies.add(proxy);
87}
88
91 SkASSERT(proxy);
92 SkASSERT(proxy->getUniqueKey().isValid());
93
94 if (this->isAbandoned()) {
95 return;
96 }
97
99}
100
103
104 if (this->isAbandoned()) {
105 return nullptr;
106 }
107
108 GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
109 if (proxy) {
110 return sk_ref_sp(proxy);
111 }
112 return nullptr;
113}
114
115///////////////////////////////////////////////////////////////////////////////
116
117#if defined(GR_TEST_UTILS)
118sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
119 SkISize dimensions,
120 const GrBackendFormat& format,
121 GrRenderable renderable,
122 int renderTargetSampleCnt,
123 SkBackingFit fit,
124 skgpu::Budgeted budgeted,
125 GrProtected isProtected) {
127 if (this->isAbandoned()) {
128 return nullptr;
129 }
130 auto direct = fImageContext->asDirectContext();
131 if (!direct) {
132 return nullptr;
133 }
134
135 if (this->caps()->isFormatCompressed(format)) {
136 // TODO: Allow this to go to GrResourceProvider::createCompressedTexture() once we no longer
137 // rely on GrColorType to get a swizzle for the proxy.
138 return nullptr;
139 }
140
141 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
143
144 if (SkBackingFit::kApprox == fit) {
146 dimensions,
147 format,
148 format.textureType(),
149 renderable,
150 renderTargetSampleCnt,
151 isProtected,
152 /*label=*/"InstantiatedProxyViaApproxTexture_Test");
153 } else {
154 tex = resourceProvider->createTexture(dimensions,
155 format,
156 format.textureType(),
157 renderable,
158 renderTargetSampleCnt,
159 skgpu::Mipmapped::kNo,
160 budgeted,
161 isProtected,
162 /*label=*/"InstantiatedProxyViaTexture_Test");
163 }
164 if (!tex) {
165 return nullptr;
166 }
167
168 return this->createWrapped(std::move(tex), UseAllocator::kYes);
169}
170
171sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
172 SkISize dimensions,
174 GrRenderable renderable,
175 int renderTargetSampleCnt,
176 SkBackingFit fit,
177 skgpu::Budgeted budgeted,
178 GrProtected isProtected) {
180 if (this->isAbandoned()) {
181 return nullptr;
182 }
183 auto format = this->caps()->getDefaultBackendFormat(colorType, renderable);
184 return this->testingOnly_createInstantiatedProxy(dimensions,
185 format,
186 renderable,
187 renderTargetSampleCnt,
188 fit,
189 budgeted,
190 isProtected);
191}
192
193sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createWrapped(sk_sp<GrTexture> tex) {
194 return this->createWrapped(std::move(tex), UseAllocator::kYes);
195}
196#endif
197
198sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex,
199 UseAllocator useAllocator) {
200#ifdef SK_DEBUG
201 if (tex->getUniqueKey().isValid()) {
202 SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey()));
203 }
204#endif
205
206 if (tex->asRenderTarget()) {
208 std::move(tex), useAllocator, this->isDDLProvider()));
209 } else {
211 new GrTextureProxy(std::move(tex), useAllocator, this->isDDLProvider()));
212 }
213}
214
216 UseAllocator useAllocator) {
218
219 if (this->isAbandoned()) {
220 return nullptr;
221 }
222
224 if (result) {
225 return result;
226 }
227
228 auto direct = fImageContext->asDirectContext();
229 if (!direct) {
230 return nullptr;
231 }
232
233 GrResourceCache* resourceCache = direct->priv().getResourceCache();
234
235 GrGpuResource* resource = resourceCache->findAndRefUniqueResource(key);
236 if (!resource) {
237 return nullptr;
238 }
239
240 sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
242
243 result = this->createWrapped(std::move(texture), useAllocator);
244 SkASSERT(result->getUniqueKey() == key);
245 // createWrapped should've added this for us
246 SkASSERT(fUniquelyKeyedProxies.find(key));
247 return result;
248}
249
251 const skgpu::UniqueKey& key,
252 GrSurfaceOrigin origin,
253 GrColorType ct,
254 int sampleCnt) {
255 auto proxy = this->findOrCreateProxyByUniqueKey(key);
256 if (!proxy) {
257 return {};
258 }
259 const GrCaps* caps = fImageContext->priv().caps();
260
261 // Assume that we used a fallback color type if and only if the proxy is renderable.
262 if (proxy->asRenderTargetProxy()) {
263 GrBackendFormat expectedFormat;
264 std::tie(ct, expectedFormat) = caps->getFallbackColorTypeAndFormat(ct, sampleCnt);
265 SkASSERT(expectedFormat == proxy->backendFormat());
266 }
267 skgpu::Swizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct);
268 return {std::move(proxy), origin, swizzle};
269}
270
272 skgpu::Mipmapped mipmapped,
273 SkBackingFit fit,
274 skgpu::Budgeted budgeted) {
276 SkASSERT(fit == SkBackingFit::kExact || mipmapped == skgpu::Mipmapped::kNo);
277
278 if (this->isAbandoned()) {
279 return nullptr;
280 }
281
282 if (!SkImageInfoIsValid(bitmap.info())) {
283 return nullptr;
284 }
285
286 ATRACE_ANDROID_FRAMEWORK("Upload %sTexture [%dx%d]",
287 skgpu::Mipmapped::kYes == mipmapped ? "MipMap " : "",
288 bitmap.width(),
289 bitmap.height());
290
291 // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap
292 // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the
293 // upload of the data to the gpu can happen at anytime and the bitmap may change by then.
294 SkBitmap copyBitmap = bitmap;
295 if (!this->renderingDirectly() && !bitmap.isImmutable()) {
296 copyBitmap.allocPixels();
297 if (!bitmap.readPixels(copyBitmap.pixmap())) {
298 return nullptr;
299 }
300 if (mipmapped == skgpu::Mipmapped::kYes && bitmap.fMips) {
301 copyBitmap.fMips = sk_sp<SkMipmap>(SkMipmap::Build(copyBitmap.pixmap(),
302 /* factoryProc= */ nullptr,
303 /* computeContents= */ false));
304 if (copyBitmap.fMips) {
305 for (int i = 0; i < copyBitmap.fMips->countLevels(); ++i) {
306 SkMipmap::Level src, dst;
307 bitmap.fMips->getLevel(i, &src);
308 copyBitmap.fMips->getLevel(i, &dst);
309 src.fPixmap.readPixels(dst.fPixmap);
310 }
311 }
312 }
313 copyBitmap.setImmutable();
314 }
315
317 if (mipmapped == skgpu::Mipmapped::kNo ||
318 !SkMipmap::ComputeLevelCount(copyBitmap.dimensions())) {
319 proxy = this->createNonMippedProxyFromBitmap(copyBitmap, fit, budgeted);
320 } else {
321 proxy = this->createMippedProxyFromBitmap(copyBitmap, budgeted);
322 }
323
324 if (!proxy) {
325 return nullptr;
326 }
327
328 auto direct = fImageContext->asDirectContext();
329 if (direct) {
330 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
331
332 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
333 // we're better off instantiating the proxy immediately here.
334 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
335 return nullptr;
336 }
337 }
338 return proxy;
339}
340
341sk_sp<GrTextureProxy> GrProxyProvider::createNonMippedProxyFromBitmap(const SkBitmap& bitmap,
342 SkBackingFit fit,
343 skgpu::Budgeted budgeted) {
344 auto dims = bitmap.dimensions();
345
346 auto colorType = SkColorTypeToGrColorType(bitmap.colorType());
347 GrBackendFormat format = this->caps()->getDefaultBackendFormat(colorType, GrRenderable::kNo);
348 if (!format.isValid()) {
349 return nullptr;
350 }
351
353 [bitmap](GrResourceProvider* resourceProvider, const LazySurfaceDesc& desc) {
354 SkASSERT(desc.fMipmapped == skgpu::Mipmapped::kNo);
355 GrMipLevel mipLevel = {bitmap.getPixels(), bitmap.rowBytes(), nullptr};
356 auto colorType = SkColorTypeToGrColorType(bitmap.colorType());
358 desc.fFormat,
359 desc.fTextureType,
360 colorType,
361 desc.fRenderable,
362 desc.fSampleCnt,
363 desc.fBudgeted,
364 desc.fFit,
365 desc.fProtected,
366 mipLevel,
367 desc.fLabel));
368 },
369 format,
370 dims,
371 skgpu::Mipmapped::kNo,
374 fit,
375 budgeted,
376 GrProtected::kNo,
377 UseAllocator::kYes,
378 "ProxyProvider_CreateNonMippedProxyFromBitmap");
379
380 if (!proxy) {
381 return nullptr;
382 }
383 SkASSERT(proxy->dimensions() == bitmap.dimensions());
384 return proxy;
385}
386
387sk_sp<GrTextureProxy> GrProxyProvider::createMippedProxyFromBitmap(const SkBitmap& bitmap,
388 skgpu::Budgeted budgeted) {
389 SkASSERT(this->caps()->mipmapSupport());
390
391 auto colorType = SkColorTypeToGrColorType(bitmap.colorType());
392 GrBackendFormat format = this->caps()->getDefaultBackendFormat(colorType, GrRenderable::kNo);
393 if (!format.isValid()) {
394 return nullptr;
395 }
396
397 sk_sp<SkMipmap> mipmaps = bitmap.fMips;
398 if (!mipmaps) {
399 mipmaps.reset(SkMipmap::Build(bitmap.pixmap(), /* factoryProc= */ nullptr));
400 if (!mipmaps) {
401 return nullptr;
402 }
403 }
404
405 auto dims = bitmap.dimensions();
406
408 [bitmap, mipmaps](GrResourceProvider* resourceProvider, const LazySurfaceDesc& desc) {
409 const int mipLevelCount = mipmaps->countLevels() + 1;
410 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
411 auto colorType = SkColorTypeToGrColorType(bitmap.colorType());
412
413 texels[0].fPixels = bitmap.getPixels();
414 texels[0].fRowBytes = bitmap.rowBytes();
415
416 for (int i = 1; i < mipLevelCount; ++i) {
417 SkMipmap::Level generatedMipLevel;
418 mipmaps->getLevel(i - 1, &generatedMipLevel);
419 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
420 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
421 SkASSERT(texels[i].fPixels);
422 SkASSERT(generatedMipLevel.fPixmap.colorType() == bitmap.colorType());
423 }
425 desc.fFormat,
426 desc.fTextureType,
427 colorType,
428 GrRenderable::kNo,
429 1,
430 desc.fBudgeted,
431 skgpu::Mipmapped::kYes,
432 GrProtected::kNo,
433 texels.get(),
434 desc.fLabel));
435 },
436 format,
437 dims,
438 skgpu::Mipmapped::kYes,
442 budgeted,
443 GrProtected::kNo,
444 UseAllocator::kYes,
445 "ProxyProvider_CreateMippedProxyFromBitmap");
446
447 if (!proxy) {
448 return nullptr;
449 }
450
451 SkASSERT(proxy->dimensions() == bitmap.dimensions());
452
453 return proxy;
454}
455
457 SkISize dimensions,
458 GrRenderable renderable,
459 int renderTargetSampleCnt,
460 skgpu::Mipmapped mipmapped,
461 SkBackingFit fit,
462 skgpu::Budgeted budgeted,
463 GrProtected isProtected,
464 std::string_view label,
465 GrInternalSurfaceFlags surfaceFlags,
466 GrSurfaceProxy::UseAllocator useAllocator) {
468 if (this->isAbandoned()) {
469 return nullptr;
470 }
471
472 const GrCaps* caps = this->caps();
473
474 if (caps->isFormatCompressed(format)) {
475 // Deferred proxies for compressed textures are not supported.
476 return nullptr;
477 }
478
479 if (skgpu::Mipmapped::kYes == mipmapped) {
480 // SkMipmap doesn't include the base level in the level count so we have to add 1
481 int mipCount = SkMipmap::ComputeLevelCount(dimensions.fWidth, dimensions.fHeight) + 1;
482 if (1 == mipCount) {
483 mipmapped = skgpu::Mipmapped::kNo;
484 }
485 }
486
487 if (!caps->validateSurfaceParams(dimensions,
488 format,
489 renderable,
490 renderTargetSampleCnt,
491 mipmapped,
493 return nullptr;
494 }
495 GrMipmapStatus mipmapStatus = (skgpu::Mipmapped::kYes == mipmapped)
498 if (renderable == GrRenderable::kYes) {
499 renderTargetSampleCnt = caps->getRenderTargetSampleCount(renderTargetSampleCnt, format);
500 SkASSERT(renderTargetSampleCnt);
502 // We know anything we instantiate later from this deferred path will be
503 // both texturable and renderable
505 format,
506 dimensions,
507 renderTargetSampleCnt,
508 mipmapped,
509 mipmapStatus,
510 fit,
511 budgeted,
512 isProtected,
513 surfaceFlags | extraFlags,
514 useAllocator,
515 this->isDDLProvider(),
516 label));
517 }
518
520 dimensions,
521 mipmapped,
522 mipmapStatus,
523 fit,
524 budgeted,
525 isProtected,
526 surfaceFlags,
527 useAllocator,
528 this->isDDLProvider(),
529 label));
530}
531
533 SkISize dimensions,
534 skgpu::Budgeted budgeted,
535 skgpu::Mipmapped mipmapped,
536 GrProtected isProtected,
537 SkTextureCompressionType compressionType,
538 sk_sp<SkData> data) {
540 if (this->isAbandoned()) {
541 return nullptr;
542 }
543
545
546 if (!this->caps()->isFormatTexturable(format, GrTextureType::k2D)) {
547 return nullptr;
548 }
549
550 GrMipmapStatus mipmapStatus = (skgpu::Mipmapped::kYes == mipmapped)
553
556 return LazyCallbackResult(
558 desc.fFormat,
559 desc.fBudgeted,
560 desc.fMipmapped,
561 desc.fProtected,
562 data.get(),
563 desc.fLabel));
564 },
565 format,
566 dimensions,
567 mipmapped,
568 mipmapStatus,
572 GrProtected::kNo,
573 UseAllocator::kYes,
574 "ProxyProvider_CreateCompressedTextureProxy");
575
576 if (!proxy) {
577 return nullptr;
578 }
579
580 auto direct = fImageContext->asDirectContext();
581 if (direct) {
582 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
583 // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
584 // we're better off instantiating the proxy immediately here.
585 if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
586 return nullptr;
587 }
588 }
589 return proxy;
590}
591
593 const GrBackendTexture& backendTex,
594 GrWrapOwnership ownership,
595 GrWrapCacheable cacheable,
596 GrIOType ioType,
597 sk_sp<skgpu::RefCntedCallback> releaseHelper) {
598 SkASSERT(ioType != kWrite_GrIOType);
599
600 if (this->isAbandoned()) {
601 return nullptr;
602 }
603
604 // This is only supported on a direct GrContext.
605 auto direct = fImageContext->asDirectContext();
606 if (!direct) {
607 return nullptr;
608 }
609
610 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
611
612 sk_sp<GrTexture> tex =
613 resourceProvider->wrapBackendTexture(backendTex, ownership, cacheable, ioType);
614 if (!tex) {
615 return nullptr;
616 }
617
618 if (releaseHelper) {
619 tex->setRelease(std::move(releaseHelper));
620 }
621
622 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
623 // Make sure we match how we created the proxy with skgpu::Budgeted::kNo
624 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
625
627 new GrTextureProxy(std::move(tex), UseAllocator::kNo, this->isDDLProvider()));
628}
629
631 const GrBackendTexture& beTex,
632 GrWrapOwnership ownership,
633 GrWrapCacheable cacheable,
634 sk_sp<skgpu::RefCntedCallback> releaseHelper) {
635 if (this->isAbandoned()) {
636 return nullptr;
637 }
638
639 // This is only supported on a direct GrContext.
640 auto direct = fImageContext->asDirectContext();
641 if (!direct) {
642 return nullptr;
643 }
644
645 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
646
648 cacheable);
649 if (!tex) {
650 return nullptr;
651 }
652
653 if (releaseHelper) {
654 tex->setRelease(std::move(releaseHelper));
655 }
656
657 SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
658 // Make sure we match how we created the proxy with skgpu::Budgeted::kNo
659 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
660
662 new GrTextureProxy(std::move(tex), UseAllocator::kNo, this->isDDLProvider()));
663}
664
666 const GrBackendTexture& backendTex,
667 int sampleCnt,
668 GrWrapOwnership ownership,
669 GrWrapCacheable cacheable,
670 sk_sp<skgpu::RefCntedCallback> releaseHelper) {
671 if (this->isAbandoned()) {
672 return nullptr;
673 }
674
675 // This is only supported on a direct GrContext.
676 auto direct = fImageContext->asDirectContext();
677 if (!direct) {
678 return nullptr;
679 }
680
681 const GrCaps* caps = this->caps();
682
683 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
684
685 sampleCnt = caps->getRenderTargetSampleCount(sampleCnt, backendTex.getBackendFormat());
686 SkASSERT(sampleCnt);
687
689 backendTex, sampleCnt, ownership, cacheable);
690 if (!tex) {
691 return nullptr;
692 }
693
694 if (releaseHelper) {
695 tex->setRelease(std::move(releaseHelper));
696 }
697
698 SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget
699 // Make sure we match how we created the proxy with skgpu::Budgeted::kNo
700 SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
701
703 std::move(tex), UseAllocator::kNo, this->isDDLProvider()));
704}
705
707 GrDirectContext* direct = fImageContext->asDirectContext();
708 if (!direct) {
709 return nullptr;
710 }
711
712 return direct->priv().resourceProvider();
713}
714
716 const GrBackendRenderTarget& backendRT,
717 sk_sp<skgpu::RefCntedCallback> releaseHelper) {
718 if (this->isAbandoned()) {
719 return nullptr;
720 }
721
722 // This is only supported on a direct GrContext.
723 auto direct = fImageContext->asDirectContext();
724 if (!direct) {
725 return nullptr;
726 }
727
728 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
729
731 if (!rt) {
732 return nullptr;
733 }
734
735 if (releaseHelper) {
736 rt->setRelease(std::move(releaseHelper));
737 }
738
739 SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
740 SkASSERT(!rt->getUniqueKey().isValid());
741 // Make sure we match how we created the proxy with skgpu::Budgeted::kNo
742 SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
743
745 new GrRenderTargetProxy(std::move(rt), UseAllocator::kNo, {}));
746}
747
750 const GrBackendFormat& format,
751 SkISize dimensions,
752 skgpu::Mipmapped mipmapped) {
753 if (threadSafeProxy->priv().abandoned()) {
754 return nullptr;
755 }
756 SkASSERT((dimensions.fWidth <= 0 && dimensions.fHeight <= 0) ||
757 (dimensions.fWidth > 0 && dimensions.fHeight > 0));
758
759 if (dimensions.fWidth > threadSafeProxy->priv().caps()->maxTextureSize() ||
760 dimensions.fHeight > threadSafeProxy->priv().caps()->maxTextureSize()) {
761 return nullptr;
762 }
763 if (!threadSafeProxy->priv().caps()->isFormatTexturable(format, format.textureType())) {
764 return nullptr;
765 }
766 // Ganesh assumes that, when wrapping a mipmapped backend texture from a client, that its
767 // mipmaps are fully fleshed out.
768 GrMipmapStatus mipmapStatus = (skgpu::Mipmapped::kYes == mipmapped)
771
772 // We pass kReadOnly here since we should treat content of the client's texture as immutable.
773 // The promise API provides no way for the client to indicate that the texture is protected.
774 auto proxy = sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback),
775 format,
776 dimensions,
777 mipmapped,
778 mipmapStatus,
781 GrProtected::kNo,
785 /*label=*/"PromiseProxy"));
786 proxy->priv().setIsPromiseProxy();
787 return proxy;
788}
789
791 const GrBackendFormat& format,
792 SkISize dimensions,
793 skgpu::Mipmapped mipmapped,
794 GrMipmapStatus mipmapStatus,
795 GrInternalSurfaceFlags surfaceFlags,
796 SkBackingFit fit,
797 skgpu::Budgeted budgeted,
798 GrProtected isProtected,
799 GrSurfaceProxy::UseAllocator useAllocator,
800 std::string_view label) {
802 if (this->isAbandoned()) {
803 return nullptr;
804 }
805 SkASSERT((dimensions.fWidth <= 0 && dimensions.fHeight <= 0) ||
806 (dimensions.fWidth > 0 && dimensions.fHeight > 0));
807
808 if (!format.isValid() || format.backend() != fImageContext->backend()) {
809 return nullptr;
810 }
811
812 if (dimensions.fWidth > this->caps()->maxTextureSize() ||
813 dimensions.fHeight > this->caps()->maxTextureSize()) {
814 return nullptr;
815 }
816
817 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback),
818 format,
819 dimensions,
820 mipmapped,
821 mipmapStatus,
822 fit,
823 budgeted,
824 isProtected,
825 surfaceFlags,
826 useAllocator,
827 this->isDDLProvider(),
828 label));
829}
830
833 const GrBackendFormat& format,
834 SkISize dimensions,
835 int sampleCnt,
836 GrInternalSurfaceFlags surfaceFlags,
837 const TextureInfo* textureInfo,
838 GrMipmapStatus mipmapStatus,
839 SkBackingFit fit,
840 skgpu::Budgeted budgeted,
841 GrProtected isProtected,
842 bool wrapsVkSecondaryCB,
843 UseAllocator useAllocator) {
845 if (this->isAbandoned()) {
846 return nullptr;
847 }
848 SkASSERT((dimensions.fWidth <= 0 && dimensions.fHeight <= 0) ||
849 (dimensions.fWidth > 0 && dimensions.fHeight > 0));
850
851 if (dimensions.fWidth > this->caps()->maxRenderTargetSize() ||
852 dimensions.fHeight > this->caps()->maxRenderTargetSize()) {
853 return nullptr;
854 }
855
856 if (textureInfo) {
857 // Wrapped vulkan secondary command buffers don't support texturing since we won't have an
858 // actual VkImage to texture from.
859 SkASSERT(!wrapsVkSecondaryCB);
861 *this->caps(),
862 std::move(callback),
863 format,
864 dimensions,
865 sampleCnt,
866 textureInfo->fMipmapped,
867 mipmapStatus,
868 fit,
869 budgeted,
870 isProtected,
871 surfaceFlags,
872 useAllocator,
873 this->isDDLProvider(),
874 /*label=*/"TextureRenderTarget_LazyRenderTargetProxy"));
875 }
876
880
882 new GrRenderTargetProxy(std::move(callback),
883 format,
884 dimensions,
885 sampleCnt,
886 fit,
887 budgeted,
888 isProtected,
889 surfaceFlags,
890 useAllocator,
891 vkSCB,
892 /*label=*/"RenderTargetProxy_LazyRenderTargetProxy"));
893}
894
896 const GrBackendFormat& format,
897 GrRenderable renderable,
898 int renderTargetSampleCnt,
899 GrProtected isProtected,
900 const GrCaps& caps,
901 UseAllocator useAllocator) {
902 if (!format.isValid()) {
903 return nullptr;
904 }
905
906 SkASSERT(renderTargetSampleCnt == 1 || renderable == GrRenderable::kYes);
907 // TODO: If we ever have callers requesting specific surface flags then we shouldn't use the
908 // extra deferred flags here. Instead those callers should all pass in exactly what they want.
909 // However, as of today all uses of this essentially create a deferred proxy in the end.
911
912 // MakeFullyLazyProxy is only called at flush time so we know these texture proxies are
913 // not being created by a DDL provider.
914 static constexpr SkISize kLazyDims = {-1, -1};
915 if (GrRenderable::kYes == renderable) {
918 std::move(callback),
919 format,
920 kLazyDims,
921 renderTargetSampleCnt,
922 skgpu::Mipmapped::kNo,
926 isProtected,
927 surfaceFlags,
928 useAllocator,
930 /*label=*/"TextureRenderTarget_FullyLazyProxy"));
931 } else {
932 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback),
933 format,
934 kLazyDims,
935 skgpu::Mipmapped::kNo,
939 isProtected,
940 surfaceFlags,
941 useAllocator,
943 /*label=*/"Texture_FullyLazyProxy"));
944 }
945}
946
948 GrTextureProxy* proxy,
949 InvalidateGPUResource invalidateGPUResource) {
950 this->processInvalidUniqueKeyImpl(key, proxy, invalidateGPUResource, RemoveTableEntry::kYes);
951}
952
953void GrProxyProvider::processInvalidUniqueKeyImpl(const skgpu::UniqueKey& key,
954 GrTextureProxy* proxy,
955 InvalidateGPUResource invalidateGPUResource,
956 RemoveTableEntry removeTableEntry) {
957 SkASSERT(key.isValid());
958
959 if (!proxy) {
960 proxy = fUniquelyKeyedProxies.find(key);
961 }
962 SkASSERT(!proxy || proxy->getUniqueKey() == key);
963
964 // Locate the corresponding GrGpuResource (if it needs to be invalidated) before clearing the
965 // proxy's unique key. We must do it in this order because 'key' may alias the proxy's key.
966 sk_sp<GrGpuResource> invalidGpuResource;
967 if (InvalidateGPUResource::kYes == invalidateGPUResource) {
968 auto direct = fImageContext->asDirectContext();
969 if (direct) {
970 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
971 invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(key);
972 }
973 SkASSERT(!invalidGpuResource || invalidGpuResource->getUniqueKey() == key);
974 }
975
976 // Note: this method is called for the whole variety of GrGpuResources so often 'key'
977 // will not be in 'fUniquelyKeyedProxies'.
978 if (proxy) {
979 if (removeTableEntry == RemoveTableEntry::kYes) {
980 fUniquelyKeyedProxies.remove(key);
981 }
982 proxy->cacheAccess().clearUniqueKey();
983 }
984
985 if (invalidGpuResource) {
986 invalidGpuResource->resourcePriv().removeUniqueKey();
987 }
988}
989
993
995 return fImageContext->priv().contextID();
996}
997
999 return fImageContext->priv().caps();
1000}
1001
1003 return fImageContext->priv().refCaps();
1004}
1005
1007 return fImageContext->priv().abandoned();
1008}
1009
1011 fUniquelyKeyedProxies.foreach([&](GrTextureProxy* proxy){
1012 proxy->fProxyProvider = nullptr;
1013 });
1014}
1015
1017 fUniquelyKeyedProxies.foreach([&](GrTextureProxy* proxy){
1018 // It's not safe to remove table entries while iterating with foreach(),
1019 // but since we're going to remove them all anyway, simply save that for the end.
1020 this->processInvalidUniqueKeyImpl(proxy->getUniqueKey(), proxy,
1022 RemoveTableEntry::kNo);
1023 });
1024 // Removing all those table entries is safe now.
1025 fUniquelyKeyedProxies.reset();
1026}
1027
1029 return fImageContext->asDirectContext();
1030}
GrWrapCacheable
Definition GrTypesPriv.h:84
GrDDLProvider
Definition GrTypesPriv.h:70
GrIOType
@ kWrite_GrIOType
GrMipmapStatus
GrWrapOwnership
Definition GrTypesPriv.h:76
GrColorType
GrInternalSurfaceFlags
static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct)
GrSurfaceOrigin
Definition GrTypes.h:147
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBackingFit
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static bool SkImageInfoIsValid(const SkImageInfo &info)
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
#define ATRACE_ANDROID_FRAMEWORK(fmt,...)
GrBackendFormat getBackendFormat() const
sk_sp< const GrCaps > refCaps() const
uint32_t contextID() const
const GrCaps * caps() const
std::tuple< GrColorType, GrBackendFormat > getFallbackColorTypeAndFormat(GrColorType, int sampleCount) const
Definition GrCaps.cpp:499
virtual GrInternalSurfaceFlags getExtraSurfaceFlagsForDeferredRT() const
Definition GrCaps.h:533
virtual bool isFormatTexturable(const GrBackendFormat &, GrTextureType) const =0
int maxTextureSize() const
Definition GrCaps.h:229
virtual GrBackendFormat getBackendFormatFromCompressionType(SkTextureCompressionType) const =0
GrBackendFormat getDefaultBackendFormat(GrColorType, GrRenderable) const
Definition GrCaps.cpp:400
bool isFormatCompressed(const GrBackendFormat &format) const
Definition GrCaps.cpp:457
bool validateSurfaceParams(const SkISize &, const GrBackendFormat &, GrRenderable renderable, int renderTargetSampleCnt, skgpu::Mipmapped, GrTextureType) const
Definition GrCaps.cpp:327
virtual int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat &) const =0
skgpu::Swizzle getReadSwizzle(const GrBackendFormat &format, GrColorType colorType) const
Definition GrCaps.cpp:443
GrContextThreadSafeProxyPriv priv()
virtual GrDirectContext * asDirectContext()
SK_API GrBackendApi backend() const
GrResourceProvider * resourceProvider()
GrDirectContextPriv priv()
const skgpu::UniqueKey & getUniqueKey() const
GrImageContextPriv priv()
uint32_t contextID() const
void removeUniqueKeyFromProxy(GrTextureProxy *)
sk_sp< GrRenderTargetProxy > createLazyRenderTargetProxy(LazyInstantiateCallback &&, const GrBackendFormat &, SkISize dimensions, int renderTargetSampleCnt, GrInternalSurfaceFlags, const TextureInfo *, GrMipmapStatus, SkBackingFit, skgpu::Budgeted, GrProtected, bool wrapsVkSecondaryCB, UseAllocator useAllocator)
GrSurfaceProxyView findCachedProxyWithColorTypeFallback(const skgpu::UniqueKey &, GrSurfaceOrigin, GrColorType, int sampleCnt)
GrResourceProvider * resourceProvider() const
sk_sp< const GrCaps > refCaps() const
bool isAbandoned() const
GrProxyProvider(GrImageContext *)
sk_sp< GrTextureProxy > findProxyByUniqueKey(const skgpu::UniqueKey &)
sk_sp< GrTextureProxy > createLazyProxy(LazyInstantiateCallback &&, const GrBackendFormat &, SkISize dimensions, skgpu::Mipmapped, GrMipmapStatus, GrInternalSurfaceFlags, SkBackingFit, skgpu::Budgeted, GrProtected, UseAllocator, std::string_view label)
sk_sp< GrTextureProxy > wrapBackendTexture(const GrBackendTexture &, GrWrapOwnership, GrWrapCacheable, GrIOType, sk_sp< skgpu::RefCntedCallback >=nullptr)
GrSurfaceProxy::LazyCallbackResult LazyCallbackResult
sk_sp< GrTextureProxy > createProxy(const GrBackendFormat &, SkISize dimensions, GrRenderable, int renderTargetSampleCnt, skgpu::Mipmapped, SkBackingFit, skgpu::Budgeted, GrProtected, std::string_view label, GrInternalSurfaceFlags=GrInternalSurfaceFlags::kNone, UseAllocator useAllocator=UseAllocator::kYes)
GrDDLProvider isDDLProvider() const
sk_sp< GrTextureProxy > wrapCompressedBackendTexture(const GrBackendTexture &, GrWrapOwnership, GrWrapCacheable, sk_sp< skgpu::RefCntedCallback >)
static sk_sp< GrTextureProxy > CreatePromiseProxy(GrContextThreadSafeProxy *, LazyInstantiateCallback &&, const GrBackendFormat &, SkISize dimensions, skgpu::Mipmapped)
bool assignUniqueKeyToProxy(const skgpu::UniqueKey &, GrTextureProxy *)
sk_sp< GrTextureProxy > findOrCreateProxyByUniqueKey(const skgpu::UniqueKey &, UseAllocator=UseAllocator::kYes)
void processInvalidUniqueKey(const skgpu::UniqueKey &, GrTextureProxy *, InvalidateGPUResource)
sk_sp< GrTextureProxy > wrapRenderableBackendTexture(const GrBackendTexture &, int sampleCnt, GrWrapOwnership, GrWrapCacheable, sk_sp< skgpu::RefCntedCallback > releaseHelper)
void adoptUniqueKeyFromSurface(GrTextureProxy *proxy, const GrSurface *)
sk_sp< GrSurfaceProxy > wrapBackendRenderTarget(const GrBackendRenderTarget &, sk_sp< skgpu::RefCntedCallback > releaseHelper)
static sk_sp< GrTextureProxy > MakeFullyLazyProxy(LazyInstantiateCallback &&, const GrBackendFormat &, GrRenderable, int renderTargetSampleCnt, GrProtected, const GrCaps &, UseAllocator)
bool renderingDirectly() const
sk_sp< GrTextureProxy > createProxyFromBitmap(const SkBitmap &, skgpu::Mipmapped, SkBackingFit, skgpu::Budgeted)
GrSurfaceProxy::LazySurfaceDesc LazySurfaceDesc
GrSurfaceProxy::LazyInstantiateCallback LazyInstantiateCallback
sk_sp< GrTextureProxy > createCompressedTextureProxy(SkISize dimensions, skgpu::Budgeted, skgpu::Mipmapped, GrProtected, SkTextureCompressionType, sk_sp< SkData > data)
const GrCaps * caps() const
GrGpuResource * findAndRefUniqueResource(const skgpu::UniqueKey &key)
sk_sp< GrRenderTarget > wrapBackendRenderTarget(const GrBackendRenderTarget &)
std::enable_if< std::is_base_of< GrGpuResource, T >::value, sk_sp< T > >::type findByUniqueKey(const skgpu::UniqueKey &key)
sk_sp< GrTexture > createApproxTexture(SkISize dimensions, const GrBackendFormat &format, GrTextureType textureType, skgpu::Renderable renderable, int renderTargetSampleCnt, skgpu::Protected isProtected, std::string_view label)
sk_sp< GrTexture > wrapBackendTexture(const GrBackendTexture &tex, GrWrapOwnership, GrWrapCacheable, GrIOType)
GrResourceProviderPriv priv()
sk_sp< GrTexture > createTexture(SkISize dimensions, const GrBackendFormat &format, GrTextureType textureType, skgpu::Renderable renderable, int renderTargetSampleCnt, skgpu::Mipmapped mipmapped, skgpu::Budgeted budgeted, skgpu::Protected isProtected, std::string_view label)
sk_sp< GrTexture > createCompressedTexture(SkISize dimensions, const GrBackendFormat &, skgpu::Budgeted, skgpu::Mipmapped, skgpu::Protected, SkData *data, std::string_view label)
sk_sp< GrTexture > wrapCompressedBackendTexture(const GrBackendTexture &tex, GrWrapOwnership, GrWrapCacheable)
sk_sp< GrTexture > wrapRenderableBackendTexture(const GrBackendTexture &tex, int sampleCnt, GrWrapOwnership, GrWrapCacheable)
const skgpu::UniqueKey & getUniqueKey() const override
bool isImmutable() const
Definition SkBitmap.cpp:396
const SkImageInfo & info() const
Definition SkBitmap.h:139
static SkMipmap * Build(const SkPixmap &src, SkDiscardableFactoryProc, bool computeContents=true)
Definition SkMipmap.cpp:45
static int ComputeLevelCount(int baseWidth, int baseHeight)
Definition SkMipmap.cpp:134
size_t rowBytes() const
Definition SkPixmap.h:145
SkColorType colorType() const
Definition SkPixmap.h:173
const void * addr() const
Definition SkPixmap.h:153
T * find(const Key &key) const
void remove(const Key &key)
void foreach(Fn &&fn)
int count() const
void add(T *entry)
void reset(T *ptr=nullptr)
Definition SkRefCnt.h:310
bool isValid() const
Definition ResourceKey.h:55
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
uint32_t uint32_t * format
#define ASSERT_SINGLE_OWNER
Definition Device.cpp:120
FlTexture * texture
Budgeted
Definition GpuTypes.h:35
Renderable
Definition GpuTypes.h:69
Mipmapped
Definition GpuTypes.h:53
Protected
Definition GpuTypes.h:61
int32_t fHeight
Definition SkSize.h:18
int32_t fWidth
Definition SkSize.h:17
SkPixmap fPixmap
Definition SkMipmap.h:71