Flutter Engine
The Flutter Engine
GrResourceProvider.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 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
12#include "include/core/SkData.h"
13#include "include/core/SkRect.h"
14#include "include/core/SkSize.h"
17#include "include/gpu/GrTypes.h"
20#include "src/base/SkMathPriv.h"
21#include "src/core/SkMipmap.h"
23#include "src/gpu/ResourceKey.h"
38
39#include <algorithm>
40#include <utility>
41
42struct SkImageInfo;
43
44using namespace skia_private;
45
46#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(fSingleOwner)
47
50 skgpu::SingleOwner* owner)
51 : fCache(cache)
52 , fGpu(gpu)
53#ifdef SK_DEBUG
54 , fSingleOwner(owner)
55#endif
56{
57 fCaps = sk_ref_sp(fGpu->caps());
58}
59
62 GrTextureType textureType,
64 GrRenderable renderable,
65 int renderTargetSampleCnt,
66 skgpu::Budgeted budgeted,
67 skgpu::Mipmapped mipmapped,
68 GrProtected isProtected,
69 const GrMipLevel texels[],
70 std::string_view label) {
72
73 if (this->isAbandoned()) {
74 return nullptr;
75 }
76
77 int numMipLevels = 1;
78 if (mipmapped == skgpu::Mipmapped::kYes) {
80 }
81
83 format,
84 renderable,
85 renderTargetSampleCnt,
86 mipmapped,
87 textureType)) {
88 return nullptr;
89 }
90 // Current rule is that you can provide no level data, just the base, or all the levels.
91 bool hasPixels = texels[0].fPixels;
92 auto scratch = this->getExactScratch(dimensions,
93 format,
94 textureType,
95 renderable,
96 renderTargetSampleCnt,
97 budgeted,
98 mipmapped,
99 isProtected,
100 label);
101 if (scratch) {
102 if (!hasPixels) {
103 return scratch;
104 }
105 return this->writePixels(std::move(scratch), colorType, dimensions, texels, numMipLevels);
106 }
109 GrColorType tempColorType = GrColorType::kUnknown;
110 if (hasPixels) {
111 tempColorType = this->prepareLevels(format, colorType, dimensions, texels, numMipLevels,
112 &tmpTexels, &tmpDatas);
113 if (tempColorType == GrColorType::kUnknown) {
114 return nullptr;
115 }
116 }
117 return fGpu->createTexture(dimensions,
118 format,
119 textureType,
120 renderable,
121 renderTargetSampleCnt,
122 budgeted,
123 isProtected,
124 colorType,
125 tempColorType,
126 tmpTexels.get(),
127 numMipLevels,
128 label);
129}
130
131sk_sp<GrTexture> GrResourceProvider::getExactScratch(SkISize dimensions,
132 const GrBackendFormat& format,
133 GrTextureType textureType,
134 GrRenderable renderable,
135 int renderTargetSampleCnt,
136 skgpu::Budgeted budgeted,
137 skgpu::Mipmapped mipmapped,
138 GrProtected isProtected,
139 std::string_view label) {
140 sk_sp<GrTexture> tex(this->findAndRefScratchTexture(dimensions,
141 format,
142 textureType,
143 renderable,
144 renderTargetSampleCnt,
145 mipmapped,
146 isProtected,
147 label));
148 if (tex && skgpu::Budgeted::kNo == budgeted) {
149 tex->resourcePriv().makeUnbudgeted();
150 }
151
152 return tex;
153}
154
156 const GrBackendFormat& format,
157 GrTextureType textureType,
159 GrRenderable renderable,
160 int renderTargetSampleCnt,
161 skgpu::Budgeted budgeted,
162 SkBackingFit fit,
163 GrProtected isProtected,
164 const GrMipLevel& mipLevel,
165 std::string_view label) {
167
168 if (!mipLevel.fPixels) {
169 return nullptr;
170 }
171
172 if (SkBackingFit::kApprox == fit) {
173 if (this->isAbandoned()) {
174 return nullptr;
175 }
177 format,
178 renderable,
179 renderTargetSampleCnt,
181 textureType)) {
182 return nullptr;
183 }
184
185 auto tex = this->createApproxTexture(dimensions,
186 format,
187 textureType,
188 renderable,
189 renderTargetSampleCnt,
190 isProtected,
191 label);
192 if (!tex) {
193 return nullptr;
194 }
195 return this->writePixels(std::move(tex), colorType, dimensions, &mipLevel, 1);
196 } else {
197 return this->createTexture(dimensions,
198 format,
199 textureType,
200 colorType,
201 renderable,
202 renderTargetSampleCnt,
203 budgeted,
205 isProtected,
206 &mipLevel,
207 label);
208 }
209}
210
212 const GrBackendFormat& format,
213 skgpu::Budgeted budgeted,
214 skgpu::Mipmapped mipmapped,
215 GrProtected isProtected,
216 SkData* data,
217 std::string_view label) {
219 if (this->isAbandoned()) {
220 return nullptr;
221 }
223 format,
224 budgeted,
225 mipmapped,
226 isProtected,
227 data->data(),
228 data->size());
229}
230
232 const GrBackendFormat& format,
233 GrTextureType textureType,
234 GrRenderable renderable,
235 int renderTargetSampleCnt,
236 skgpu::Mipmapped mipmapped,
237 skgpu::Budgeted budgeted,
238 GrProtected isProtected,
239 std::string_view label) {
241 if (this->isAbandoned()) {
242 return nullptr;
243 }
244
245 if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
246 mipmapped, textureType)) {
247 return nullptr;
248 }
249
250 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
251 // textures should be created through the createCompressedTexture function.
252 SkASSERT(!this->caps()->isFormatCompressed(format));
253
254 // TODO: Support skgpu::Mipmapped::kYes in scratch texture lookup here.
255 sk_sp<GrTexture> tex =
256 this->getExactScratch(dimensions,
257 format,
258 textureType,
259 renderable,
260 renderTargetSampleCnt,
261 budgeted,
262 mipmapped,
263 isProtected,
264 label);
265 if (tex) {
266 return tex;
267 }
268
269 return fGpu->createTexture(dimensions,
270 format,
271 textureType,
272 renderable,
273 renderTargetSampleCnt,
274 mipmapped,
275 budgeted,
276 isProtected,
277 label);
278}
279
281 const GrBackendFormat& format,
282 GrTextureType textureType,
283 GrRenderable renderable,
284 int renderTargetSampleCnt,
285 GrProtected isProtected,
286 std::string_view label) {
288
289 if (this->isAbandoned()) {
290 return nullptr;
291 }
292
293 // Currently we don't recycle compressed textures as scratch. Additionally all compressed
294 // textures should be created through the createCompressedTexture function.
295 SkASSERT(!this->caps()->isFormatCompressed(format));
296
298 format,
299 renderable,
300 renderTargetSampleCnt,
302 textureType)) {
303 return nullptr;
304 }
305
306 auto copyDimensions = skgpu::GetApproxSize(dimensions);
307
308 if (auto tex = this->findAndRefScratchTexture(copyDimensions,
309 format,
310 textureType,
311 renderable,
312 renderTargetSampleCnt,
314 isProtected,
315 label)) {
316 return tex;
317 }
318
319 return fGpu->createTexture(copyDimensions,
320 format,
321 textureType,
322 renderable,
323 renderTargetSampleCnt,
326 isProtected,
327 label);
328}
329
331 std::string_view label) {
333 SkASSERT(!this->isAbandoned());
334 SkASSERT(key.isValid());
335
338 GrSurface* surface = static_cast<GrSurface*>(resource);
339 resource->setLabel(std::move(label));
340 return sk_sp<GrTexture>(surface->asTexture());
341 }
342 return nullptr;
343}
344
346 const GrBackendFormat& format,
347 GrTextureType textureType,
348 GrRenderable renderable,
349 int renderTargetSampleCnt,
350 skgpu::Mipmapped mipmapped,
351 GrProtected isProtected,
352 std::string_view label) {
354 SkASSERT(!this->isAbandoned());
355 SkASSERT(!this->caps()->isFormatCompressed(format));
357 format,
358 renderable,
359 renderTargetSampleCnt,
361 textureType));
362
363 // We could make initial clears work with scratch textures but it is a rare case so we just opt
364 // to fall back to making a new texture.
365 if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
367 GrTexture::ComputeScratchKey(*this->caps(), format, dimensions, renderable,
368 renderTargetSampleCnt, mipmapped, isProtected, &key);
369 return this->findAndRefScratchTexture(key, label);
370 }
371
372 return nullptr;
373}
374
376 GrWrapOwnership ownership,
377 GrWrapCacheable cacheable,
378 GrIOType ioType) {
380 if (this->isAbandoned()) {
381 return nullptr;
382 }
383 return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
384}
385
387 GrWrapOwnership ownership,
388 GrWrapCacheable cacheable) {
390 if (this->isAbandoned()) {
391 return nullptr;
392 }
393
394 return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
395}
396
397
399 int sampleCnt,
400 GrWrapOwnership ownership,
401 GrWrapCacheable cacheable) {
403 if (this->isAbandoned()) {
404 return nullptr;
405 }
406 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
407}
408
410 const GrBackendRenderTarget& backendRT) {
412 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
413}
414
416 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
418 return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
419 vkInfo);
420
421}
422
426 if (this->isAbandoned() || !resource) {
427 return;
428 }
429 resource->resourcePriv().setUniqueKey(key);
430}
431
432sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const skgpu::UniqueKey& key) {
434 return this->isAbandoned() ? nullptr
436}
437
439 size_t size,
440 const void* staticData,
441 const skgpu::UniqueKey& key) {
442 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
443 return buffer;
444 }
445
446 auto buffer = this->createBuffer(staticData, size, intendedType, kStatic_GrAccessPattern);
447 if (!buffer) {
448 return nullptr;
449 }
450
451 // We shouldn't bin and/or cache static buffers.
452 SkASSERT(buffer->size() == size);
453 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
454
455 buffer->resourcePriv().setUniqueKey(key);
456
457 return buffer;
458}
459
461 GrGpuBufferType intendedType,
462 size_t size,
463 const skgpu::UniqueKey& uniqueKey,
464 InitializeBufferFn initializeBufferFn) {
465 if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(uniqueKey)) {
466 return buffer;
467 }
468
469 auto buffer = this->createBuffer(size,
470 intendedType,
473 if (!buffer) {
474 return nullptr;
475 }
476
477 // We shouldn't bin and/or cache static buffers.
478 SkASSERT(buffer->size() == size);
479 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
480
481 buffer->resourcePriv().setUniqueKey(uniqueKey);
482
483 // Map the buffer. Use a staging buffer on the heap if mapping isn't supported.
484 skgpu::VertexWriter vertexWriter = {buffer->map(), size};
485 AutoTMalloc<char> stagingBuffer;
486 if (!vertexWriter) {
487 SkASSERT(!buffer->isMapped());
488 vertexWriter = {stagingBuffer.reset(size), size};
489 }
490
491 initializeBufferFn(std::move(vertexWriter), size);
492
493 if (buffer->isMapped()) {
494 buffer->unmap();
495 } else {
496 buffer->updateData(stagingBuffer, /*offset=*/0, size, /*preserve=*/false);
497 }
498
499 return buffer;
500}
501
502sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(
503 const uint16_t* pattern,
504 int patternSize,
505 int reps,
506 int vertCount,
507 const skgpu::UniqueKey* key) {
508 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
509
510 sk_sp<GrGpuBuffer> buffer = this->createBuffer(bufferSize,
514 if (!buffer) {
515 return nullptr;
516 }
517 uint16_t* data = (uint16_t*) buffer->map();
519 if (!data) {
520 temp.reset(reps * patternSize);
521 data = temp.get();
522 }
523 for (int i = 0; i < reps; ++i) {
524 int baseIdx = i * patternSize;
525 uint16_t baseVert = (uint16_t)(i * vertCount);
526 for (int j = 0; j < patternSize; ++j) {
527 data[baseIdx+j] = baseVert + pattern[j];
528 }
529 }
530 if (temp.get()) {
531 if (!buffer->updateData(data, /*offset=*/0, bufferSize, /*preserve=*/false)) {
532 return nullptr;
533 }
534 } else {
535 buffer->unmap();
536 }
537 if (key) {
538 SkASSERT(key->isValid());
539 this->assignUniqueKeyToResource(*key, buffer.get());
540 }
541 return buffer;
542}
543
544///////////////////////////////////////////////////////////////////////////////////////////////////
545static constexpr int kMaxNumNonAAQuads = 1 << 12; // max possible: (1 << 14) - 1;
546static const int kVertsPerNonAAQuad = 4;
547static const int kIndicesPerNonAAQuad = 6;
548
549sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
550 static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535); // indices fit in a uint16_t
551
552 static const uint16_t kNonAAQuadIndexPattern[] = {
553 0, 1, 2, 2, 1, 3
554 };
555
556 static_assert(std::size(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
557
558 return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
560}
561
565
566///////////////////////////////////////////////////////////////////////////////////////////////////
567static constexpr int kMaxNumAAQuads = 1 << 9; // max possible: (1 << 13) - 1;
568static const int kVertsPerAAQuad = 8;
569static const int kIndicesPerAAQuad = 30;
570
571sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
572 static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535); // indices fit in a uint16_t
573
574 // clang-format off
575 static const uint16_t kAAQuadIndexPattern[] = {
576 0, 1, 2, 1, 3, 2,
577 0, 4, 1, 4, 5, 1,
578 0, 6, 4, 0, 2, 6,
579 2, 3, 6, 3, 7, 6,
580 1, 5, 3, 3, 5, 7,
581 };
582 // clang-format on
583
584 static_assert(std::size(kAAQuadIndexPattern) == kIndicesPerAAQuad);
585
586 return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
588}
589
593
594///////////////////////////////////////////////////////////////////////////////////////////////////
595
597 GrGpuBufferType intendedType,
598 GrAccessPattern accessPattern,
599 ZeroInit zeroInit) {
600 if (this->isAbandoned()) {
601 return nullptr;
602 }
603 if (kDynamic_GrAccessPattern != accessPattern) {
604 if (this->caps()->buffersAreInitiallyZero()) {
605 zeroInit = ZeroInit::kNo;
606 }
607 sk_sp<GrGpuBuffer> buffer = this->gpu()->createBuffer(size, intendedType, accessPattern);
608 if (buffer && zeroInit == ZeroInit::kYes && !buffer->clearToZero()) {
609 return nullptr;
610 }
611 return buffer;
612 }
613 // bin by pow2+midpoint with a reasonable min
614 static const size_t MIN_SIZE = 1 << 12;
615 static const size_t MIN_UNIFORM_SIZE = 1 << 7;
616 size_t allocSize = intendedType == GrGpuBufferType::kUniform ? std::max(size, MIN_UNIFORM_SIZE)
617 : std::max(size, MIN_SIZE);
618 size_t ceilPow2 = GrNextSizePow2(allocSize);
619 size_t floorPow2 = ceilPow2 >> 1;
620 size_t mid = floorPow2 + (floorPow2 >> 1);
621 allocSize = (allocSize <= mid) ? mid : ceilPow2;
622
624 GrGpuBuffer::ComputeScratchKeyForDynamicBuffer(allocSize, intendedType, &key);
625 auto buffer =
626 sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
627 key)));
628 if (!buffer) {
629 if (this->caps()->buffersAreInitiallyZero()) {
630 zeroInit = ZeroInit::kNo;
631 }
632 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
633 }
634 if (buffer && zeroInit == ZeroInit::kYes && !buffer->clearToZero()) {
635 return nullptr;
636 }
637 return buffer;
638}
639
641 size_t size,
643 GrAccessPattern pattern) {
644 SkASSERT(data);
645 auto buffer = this->createBuffer(size, type, pattern, ZeroInit::kNo);
646 if (!buffer) {
647 return nullptr;
648 }
649 if (!buffer->updateData(data, /*offset=*/0, size, /*preserve=*/false)) {
650 return nullptr;
651 }
652 return buffer;
653}
654
655static int num_stencil_samples(const GrRenderTarget* rt, bool useMSAASurface, const GrCaps& caps) {
656 int numSamples = rt->numSamples();
657 if (numSamples == 1 && useMSAASurface) { // Are we using dynamic msaa?
658 numSamples = caps.internalMultisampleCount(rt->backendFormat());
659 SkASSERT(numSamples > 1); // Caller must ensure dmsaa is supported before trying to use it.
660 }
661 return numSamples;
662}
663
665 SkASSERT(rt);
666 SkASSERT(!this->caps()->avoidStencilBuffers());
667
668 GrAttachment* stencil = rt->getStencilAttachment(useMSAASurface);
669 if (stencil) {
670 SkASSERT(stencil->numSamples() == num_stencil_samples(rt, useMSAASurface, *this->caps()));
671 return true;
672 }
673
674 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment(useMSAASurface)) {
675 skgpu::UniqueKey sbKey;
676
677#if 0
678 if (this->caps()->oversizedStencilSupport()) {
681 }
682#endif
683 GrBackendFormat stencilFormat = this->gpu()->getPreferredStencilFormat(rt->backendFormat());
684 if (!stencilFormat.isValid()) {
685 return false;
686 }
688 int numStencilSamples = num_stencil_samples(rt, useMSAASurface, *this->caps());
690 stencilFormat,
691 rt->dimensions(),
693 numStencilSamples,
695 isProtected,
697 &sbKey);
698 auto keyedStencil = this->findByUniqueKey<GrAttachment>(sbKey);
699 if (!keyedStencil) {
700 // Need to try and create a new stencil
701 keyedStencil = this->gpu()->makeStencilAttachment(rt->backendFormat(), rt->dimensions(),
702 numStencilSamples);
703 if (!keyedStencil) {
704 return false;
705 }
706 this->assignUniqueKeyToResource(sbKey, keyedStencil.get());
707 }
708 rt->attachStencilAttachment(std::move(keyedStencil), useMSAASurface);
709 }
710 stencil = rt->getStencilAttachment(useMSAASurface);
711 SkASSERT(!stencil ||
712 stencil->numSamples() == num_stencil_samples(rt, useMSAASurface, *this->caps()));
713 return stencil != nullptr;
714}
715
717 const GrBackendFormat& format,
718 int sampleCnt,
719 GrProtected isProtected,
720 GrMemoryless memoryless) {
722
723 SkASSERT(sampleCnt > 1);
724
725 if (this->isAbandoned()) {
726 return nullptr;
727 }
728
730 format,
732 sampleCnt,
735 return nullptr;
736 }
737
740 format,
743 sampleCnt,
745 isProtected,
746 memoryless,
747 &key);
748 auto msaaAttachment = this->findByUniqueKey<GrAttachment>(key);
749 if (msaaAttachment) {
750 return msaaAttachment;
751 }
752 msaaAttachment = this->makeMSAAAttachment(dimensions, format, sampleCnt, isProtected,
753 memoryless);
754 if (msaaAttachment) {
755 this->assignUniqueKeyToResource(key, msaaAttachment.get());
756 }
757 return msaaAttachment;
758}
759
761 const GrBackendFormat& format,
762 int sampleCnt,
763 GrProtected isProtected,
764 GrMemoryless memoryless) {
766
767 SkASSERT(sampleCnt > 1);
768
769 if (this->isAbandoned()) {
770 return nullptr;
771 }
772
774 format,
776 sampleCnt,
779 return nullptr;
780 }
781
782 auto scratch = this->refScratchMSAAAttachment(dimensions,
783 format,
784 sampleCnt,
785 isProtected,
786 memoryless,
787 /*label=*/"MakeMSAAAttachment");
788 if (scratch) {
789 return scratch;
790 }
791
792 return fGpu->makeMSAAAttachment(dimensions, format, sampleCnt, isProtected, memoryless);
793}
794
795sk_sp<GrAttachment> GrResourceProvider::refScratchMSAAAttachment(SkISize dimensions,
796 const GrBackendFormat& format,
797 int sampleCnt,
798 GrProtected isProtected,
799 GrMemoryless memoryless,
800 std::string_view label) {
802 SkASSERT(!this->isAbandoned());
803 SkASSERT(!this->caps()->isFormatCompressed(format));
805 format,
807 sampleCnt,
810
813 format,
816 sampleCnt,
818 isProtected,
819 memoryless,
820 &key);
822 if (resource) {
824 GrAttachment* attachment = static_cast<GrAttachment*>(resource);
825 resource->setLabel(std::move(label));
826 return sk_sp<GrAttachment>(attachment);
827 }
828
829 return nullptr;
830}
831
832[[nodiscard]] std::unique_ptr<GrSemaphore> GrResourceProvider::makeSemaphore(bool isOwned) {
833 return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
834}
835
836std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
837 const GrBackendSemaphore& semaphore,
838 GrSemaphoreWrapType wrapType,
839 GrWrapOwnership ownership) {
841 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
842 wrapType,
843 ownership);
844}
845
846// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
847// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
848static bool prepare_level(const GrMipLevel& inLevel,
850 bool rowBytesSupport,
851 GrColorType origColorType,
852 GrColorType allowedColorType,
853 GrMipLevel* outLevel,
854 std::unique_ptr<char[]>* data) {
855 if (!inLevel.fPixels) {
856 outLevel->fPixels = nullptr;
857 outLevel->fRowBytes = 0;
858 return true;
859 }
860 size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
861 size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
862 if (actualRB < minRB) {
863 return false;
864 }
865 if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
866 outLevel->fRowBytes = actualRB;
867 outLevel->fPixels = inLevel.fPixels;
868 return true;
869 }
870 auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
871 data->reset(new char[tempRB * dimensions.fHeight]);
872 outLevel->fPixels = data->get();
873 outLevel->fRowBytes = tempRB;
874 GrImageInfo srcInfo( origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
875 GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
876 return GrConvertPixels( GrPixmap(dstInfo, data->get(), tempRB),
877 GrCPixmap(srcInfo, inLevel.fPixels, actualRB));
878}
879
880GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
882 SkISize baseSize,
883 const GrMipLevel texels[],
884 int mipLevelCount,
885 TempLevels* tempLevels,
886 TempLevelDatas* tempLevelDatas) const {
887 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
888
889 auto allowedColorType =
891 if (allowedColorType == GrColorType::kUnknown) {
893 }
894 bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
895 tempLevels->reset(mipLevelCount);
896 tempLevelDatas->reset(mipLevelCount);
897 auto size = baseSize;
898 for (int i = 0; i < mipLevelCount; ++i) {
899 if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
900 &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
902 }
903 size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
904 }
905 return allowedColorType;
906}
907
908sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
910 SkISize baseSize,
911 const GrMipLevel texels[],
912 int mipLevelCount) const {
913 SkASSERT(!this->isAbandoned());
916 SkASSERT(mipLevelCount && texels && texels[0].fPixels);
917
920 auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
921 mipLevelCount, &tmpTexels, &tmpDatas);
922 if (tempColorType == GrColorType::kUnknown) {
923 return nullptr;
924 }
926 SkIRect::MakeSize(baseSize),
927 colorType,
928 tempColorType,
929 tmpTexels.get(),
930 mipLevelCount));
931 return texture;
932}
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
bool GrConvertPixels(const GrPixmap &dst, const GrCPixmap &src, bool flipY)
static const int kIndicesPerNonAAQuad
static int num_stencil_samples(const GrRenderTarget *rt, bool useMSAASurface, const GrCaps &caps)
static constexpr int kMaxNumAAQuads
static const int kVertsPerAAQuad
static constexpr int kMaxNumNonAAQuads
static const int kIndicesPerAAQuad
static bool prepare_level(const GrMipLevel &inLevel, SkISize dimensions, bool rowBytesSupport, GrColorType origColorType, GrColorType allowedColorType, GrMipLevel *outLevel, std::unique_ptr< char[]> *data)
static const int kVertsPerNonAAQuad
#define ASSERT_SINGLE_OWNER
GrWrapCacheable
Definition: GrTypesPriv.h:85
static constexpr size_t GrColorTypeBytesPerPixel(GrColorType ct)
Definition: GrTypesPriv.h:896
GrIOType
Definition: GrTypesPriv.h:402
GrWrapOwnership
Definition: GrTypesPriv.h:77
GrGpuBufferType
Definition: GrTypesPriv.h:411
GrMemoryless
Definition: GrTypesPriv.h:123
GrSemaphoreWrapType
Definition: GrTypesPriv.h:146
GrTextureType
Definition: GrTypesPriv.h:268
GrColorType
Definition: GrTypesPriv.h:540
GrAccessPattern
Definition: GrTypesPriv.h:424
@ kDynamic_GrAccessPattern
Definition: GrTypesPriv.h:426
@ kStatic_GrAccessPattern
Definition: GrTypesPriv.h:428
kUnpremul_SkAlphaType
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBackingFit
Definition: SkBackingFit.h:16
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
#define SK_DEBUG
static int SkNextPow2(int value)
Definition: SkMathPriv.h:272
static size_t GrNextSizePow2(size_t n)
Definition: SkMathPriv.h:309
static SkString resource(SkPDFResourceType type, int index)
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
GLenum type
int numSamples() const
Definition: GrAttachment.h:38
static void ComputeScratchKey(const GrCaps &caps, const GrBackendFormat &format, SkISize dimensions, UsageFlags requiredUsage, int sampleCnt, skgpu::Mipmapped mipmapped, GrProtected, GrMemoryless, skgpu::ScratchKey *key)
static void ComputeSharedAttachmentUniqueKey(const GrCaps &caps, const GrBackendFormat &format, SkISize dimensions, UsageFlags requiredUsage, int sampleCnt, skgpu::Mipmapped mipmapped, GrProtected isProtected, GrMemoryless memoryless, skgpu::UniqueKey *key)
bool isValid() const
Definition: GrCaps.h:57
virtual SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType, const GrBackendFormat &surfaceFormat, GrColorType srcColorType) const =0
bool validateSurfaceParams(const SkISize &, const GrBackendFormat &, GrRenderable renderable, int renderTargetSampleCnt, skgpu::Mipmapped, GrTextureType) const
Definition: GrCaps.cpp:327
bool writePixelsRowBytesSupport() const
Definition: GrCaps.h:354
bool reuseScratchTextures() const
Definition: GrCaps.h:217
int internalMultisampleCount(const GrBackendFormat &format) const
Definition: GrCaps.h:271
static void ComputeScratchKeyForDynamicBuffer(size_t size, GrGpuBufferType, skgpu::ScratchKey *)
Definition: GrGpuBuffer.cpp:86
bool wasDestroyed() const
void incNumScratchTexturesReused()
Definition: GrGpu.h:544
void incNumScratchMSAAAttachmentsReused()
Definition: GrGpu.h:545
Definition: GrGpu.h:62
virtual std::unique_ptr< GrSemaphore > makeSemaphore(bool isOwned=true)=0
bool writePixels(GrSurface *surface, SkIRect rect, GrColorType surfaceColorType, GrColorType srcColorType, const GrMipLevel texels[], int mipLevelCount, bool prepForTexSampling=false)
Definition: GrGpu.cpp:461
Stats * stats()
Definition: GrGpu.h:551
const GrCaps * caps() const
Definition: GrGpu.h:73
virtual sk_sp< GrAttachment > makeStencilAttachment(const GrBackendFormat &colorFormat, SkISize dimensions, int numStencilSamples)=0
sk_sp< GrTexture > wrapBackendTexture(const GrBackendTexture &, GrWrapOwnership, GrWrapCacheable, GrIOType)
Definition: GrGpu.cpp:297
virtual sk_sp< GrAttachment > makeMSAAAttachment(SkISize dimensions, const GrBackendFormat &format, int numSamples, GrProtected isProtected, GrMemoryless isMemoryless)=0
sk_sp< GrGpuBuffer > createBuffer(size_t size, GrGpuBufferType intendedType, GrAccessPattern accessPattern)
Definition: GrGpu.cpp:393
virtual GrBackendFormat getPreferredStencilFormat(const GrBackendFormat &)=0
sk_sp< GrRenderTarget > wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo &, const GrVkDrawableInfo &)
Definition: GrGpu.cpp:382
sk_sp< GrRenderTarget > wrapBackendRenderTarget(const GrBackendRenderTarget &)
Definition: GrGpu.cpp:366
sk_sp< GrTexture > wrapCompressedBackendTexture(const GrBackendTexture &, GrWrapOwnership, GrWrapCacheable)
Definition: GrGpu.cpp:318
sk_sp< GrTexture > createTexture(SkISize dimensions, const GrBackendFormat &format, GrTextureType textureType, GrRenderable renderable, int renderTargetSampleCnt, skgpu::Budgeted budgeted, GrProtected isProtected, GrColorType textureColorType, GrColorType srcColorType, const GrMipLevel texels[], int texelLevelCount, std::string_view label)
Definition: GrGpu.cpp:189
virtual std::unique_ptr< GrSemaphore > wrapBackendSemaphore(const GrBackendSemaphore &, GrSemaphoreWrapType, GrWrapOwnership)=0
sk_sp< GrTexture > createCompressedTexture(SkISize dimensions, const GrBackendFormat &format, skgpu::Budgeted budgeted, skgpu::Mipmapped mipmapped, GrProtected isProtected, const void *data, size_t dataSize)
Definition: GrGpu.cpp:260
sk_sp< GrTexture > wrapRenderableBackendTexture(const GrBackendTexture &, int sampleCnt, GrWrapOwnership, GrWrapCacheable)
Definition: GrGpu.cpp:337
void attachStencilAttachment(sk_sp< GrAttachment > stencil, bool useMSAASurface)
int numSamples() const
GrAttachment * getStencilAttachment(bool useMSAASurface) const
virtual bool canAttemptStencilAttachment(bool useMSAASurface) const =0
GrGpuResource * findAndRefScratchResource(const skgpu::ScratchKey &scratchKey)
GrGpuResource * findAndRefUniqueResource(const skgpu::UniqueKey &key)
bool attachStencilAttachment(GrRenderTarget *rt, bool useMSAASurface)
static int NumIndicesPerNonAAQuad()
sk_sp< GrRenderTarget > wrapBackendRenderTarget(const GrBackendRenderTarget &)
sk_sp< GrAttachment > getDiscardableMSAAAttachment(SkISize dimensions, const GrBackendFormat &format, int sampleCnt, skgpu::Protected isProtected, GrMemoryless memoryless)
GrResourceProvider(GrGpu *, GrResourceCache *, skgpu::SingleOwner *)
sk_sp< GrTexture > createApproxTexture(SkISize dimensions, const GrBackendFormat &format, GrTextureType textureType, skgpu::Renderable renderable, int renderTargetSampleCnt, skgpu::Protected isProtected, std::string_view label)
void assignUniqueKeyToResource(const skgpu::UniqueKey &, GrGpuResource *)
std::unique_ptr< GrSemaphore > makeSemaphore(bool isOwned=true)
void(*)(skgpu::VertexWriter, size_t bufferSize) InitializeBufferFn
std::unique_ptr< GrSemaphore > wrapBackendSemaphore(const GrBackendSemaphore &, GrSemaphoreWrapType, GrWrapOwnership=kBorrow_GrWrapOwnership)
sk_sp< GrTexture > wrapBackendTexture(const GrBackendTexture &tex, GrWrapOwnership, GrWrapCacheable, GrIOType)
static int NumIndicesPerAAQuad()
sk_sp< GrGpuBuffer > createBuffer(size_t size, GrGpuBufferType, GrAccessPattern, ZeroInit)
sk_sp< GrTexture > findAndRefScratchTexture(const skgpu::ScratchKey &, std::string_view label)
static int NumVertsPerAAQuad()
static int NumVertsPerNonAAQuad()
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< const GrGpuBuffer > findOrMakeStaticBuffer(GrGpuBufferType intendedType, size_t size, const skgpu::UniqueKey &key, InitializeBufferFn)
sk_sp< GrRenderTarget > wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo &, const GrVkDrawableInfo &)
sk_sp< GrTexture > createCompressedTexture(SkISize dimensions, const GrBackendFormat &, skgpu::Budgeted, skgpu::Mipmapped, skgpu::Protected, SkData *data, std::string_view label)
sk_sp< GrAttachment > makeMSAAAttachment(SkISize dimensions, const GrBackendFormat &format, int sampleCnt, skgpu::Protected isProtected, GrMemoryless isMemoryless)
sk_sp< GrTexture > wrapCompressedBackendTexture(const GrBackendTexture &tex, GrWrapOwnership, GrWrapCacheable)
sk_sp< GrTexture > wrapRenderableBackendTexture(const GrBackendTexture &tex, int sampleCnt, GrWrapOwnership, GrWrapCacheable)
const GrCaps * caps() const
virtual GrBackendFormat backendFormat() const =0
SkISize dimensions() const
Definition: GrSurface.h:27
bool isProtected() const
Definition: GrSurface.h:87
static void ComputeScratchKey(const GrCaps &caps, const GrBackendFormat &format, SkISize dimensions, GrRenderable, int sampleCnt, skgpu::Mipmapped, GrProtected, skgpu::ScratchKey *key)
Definition: GrTexture.cpp:105
Definition: SkData.h:25
static int ComputeLevelCount(int baseWidth, int baseHeight)
Definition: SkMipmap.cpp:134
void reset(size_t count=0)
Definition: SkTemplates.h:123
T * reset(size_t count=0)
Definition: SkTemplates.h:296
VkSurfaceKHR surface
Definition: main.cc:49
uint32_t uint32_t * format
static float max(float r, float g, float b)
Definition: hsl.cpp:49
FlTexture * texture
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
Definition: switches.h:191
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
SkISize GetApproxSize(SkISize size)
Budgeted
Definition: GpuTypes.h:35
Renderable
Definition: GpuTypes.h:69
Mipmapped
Definition: GpuTypes.h:53
Protected
Definition: GpuTypes.h:61
int32_t height
int32_t width
GrColorType fColorType
Definition: GrCaps.h:318
const void * fPixels
Definition: GrTypesPriv.h:135
size_t fRowBytes
Definition: GrTypesPriv.h:136
static constexpr SkIRect MakeSize(const SkISize &size)
Definition: SkRect.h:66
Definition: SkSize.h:16
int32_t fHeight
Definition: SkSize.h:18
int32_t fWidth
Definition: SkSize.h:17
SkISize dimensions() const
Definition: SkImageInfo.h:421
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63