1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2010 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpu.h"
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextureCompressionType.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSemaphore.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkMathPriv.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCompressedDataUtils.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/RefCntedCallback.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBackendUtils.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuResourcePriv.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTarget.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRingBuffer.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSemaphore.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrStagingBufferManager.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
35*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
40*c8dee2aaSAndroid Build Coastguard Worker
GrGpu(GrDirectContext * direct)41*c8dee2aaSAndroid Build Coastguard Worker GrGpu::GrGpu(GrDirectContext* direct) : fResetBits(kAll_GrBackendState), fContext(direct) {}
42*c8dee2aaSAndroid Build Coastguard Worker
~GrGpu()43*c8dee2aaSAndroid Build Coastguard Worker GrGpu::~GrGpu() {
44*c8dee2aaSAndroid Build Coastguard Worker this->callSubmittedProcs(false);
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker
initCaps(sk_sp<const GrCaps> caps)47*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::initCaps(sk_sp<const GrCaps> caps) {
48*c8dee2aaSAndroid Build Coastguard Worker fCaps = std::move(caps);
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker
disconnect(DisconnectType type)51*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::disconnect(DisconnectType type) {}
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
54*c8dee2aaSAndroid Build Coastguard Worker
validate_texel_levels(SkISize dimensions,GrColorType texelColorType,const GrMipLevel * texels,int mipLevelCount,const GrCaps * caps)55*c8dee2aaSAndroid Build Coastguard Worker static bool validate_texel_levels(SkISize dimensions, GrColorType texelColorType,
56*c8dee2aaSAndroid Build Coastguard Worker const GrMipLevel* texels, int mipLevelCount, const GrCaps* caps) {
57*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(mipLevelCount > 0);
58*c8dee2aaSAndroid Build Coastguard Worker bool hasBasePixels = texels[0].fPixels;
59*c8dee2aaSAndroid Build Coastguard Worker int levelsWithPixelsCnt = 0;
60*c8dee2aaSAndroid Build Coastguard Worker auto bpp = GrColorTypeBytesPerPixel(texelColorType);
61*c8dee2aaSAndroid Build Coastguard Worker int w = dimensions.fWidth;
62*c8dee2aaSAndroid Build Coastguard Worker int h = dimensions.fHeight;
63*c8dee2aaSAndroid Build Coastguard Worker for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; ++currentMipLevel) {
64*c8dee2aaSAndroid Build Coastguard Worker if (texels[currentMipLevel].fPixels) {
65*c8dee2aaSAndroid Build Coastguard Worker const size_t minRowBytes = w * bpp;
66*c8dee2aaSAndroid Build Coastguard Worker if (caps->writePixelsRowBytesSupport()) {
67*c8dee2aaSAndroid Build Coastguard Worker if (texels[currentMipLevel].fRowBytes < minRowBytes) {
68*c8dee2aaSAndroid Build Coastguard Worker return false;
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker if (texels[currentMipLevel].fRowBytes % bpp) {
71*c8dee2aaSAndroid Build Coastguard Worker return false;
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker } else {
74*c8dee2aaSAndroid Build Coastguard Worker if (texels[currentMipLevel].fRowBytes != minRowBytes) {
75*c8dee2aaSAndroid Build Coastguard Worker return false;
76*c8dee2aaSAndroid Build Coastguard Worker }
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker ++levelsWithPixelsCnt;
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker if (w == 1 && h == 1) {
81*c8dee2aaSAndroid Build Coastguard Worker if (currentMipLevel != mipLevelCount - 1) {
82*c8dee2aaSAndroid Build Coastguard Worker return false;
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker } else {
85*c8dee2aaSAndroid Build Coastguard Worker w = std::max(w / 2, 1);
86*c8dee2aaSAndroid Build Coastguard Worker h = std::max(h / 2, 1);
87*c8dee2aaSAndroid Build Coastguard Worker }
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker // Either just a base layer or a full stack is required.
90*c8dee2aaSAndroid Build Coastguard Worker if (mipLevelCount != 1 && (w != 1 || h != 1)) {
91*c8dee2aaSAndroid Build Coastguard Worker return false;
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker // Can specify just the base, all levels, or no levels.
94*c8dee2aaSAndroid Build Coastguard Worker if (!hasBasePixels) {
95*c8dee2aaSAndroid Build Coastguard Worker return levelsWithPixelsCnt == 0;
96*c8dee2aaSAndroid Build Coastguard Worker }
97*c8dee2aaSAndroid Build Coastguard Worker return levelsWithPixelsCnt == 1 || levelsWithPixelsCnt == mipLevelCount;
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker
createTextureCommon(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Budgeted budgeted,GrProtected isProtected,int mipLevelCount,uint32_t levelClearMask,std::string_view label)100*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGpu::createTextureCommon(SkISize dimensions,
101*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format,
102*c8dee2aaSAndroid Build Coastguard Worker GrTextureType textureType,
103*c8dee2aaSAndroid Build Coastguard Worker GrRenderable renderable,
104*c8dee2aaSAndroid Build Coastguard Worker int renderTargetSampleCnt,
105*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
106*c8dee2aaSAndroid Build Coastguard Worker GrProtected isProtected,
107*c8dee2aaSAndroid Build Coastguard Worker int mipLevelCount,
108*c8dee2aaSAndroid Build Coastguard Worker uint32_t levelClearMask,
109*c8dee2aaSAndroid Build Coastguard Worker std::string_view label) {
110*c8dee2aaSAndroid Build Coastguard Worker if (this->caps()->isFormatCompressed(format)) {
111*c8dee2aaSAndroid Build Coastguard Worker // Call GrGpu::createCompressedTexture.
112*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
113*c8dee2aaSAndroid Build Coastguard Worker }
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped = mipLevelCount > 1 ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo;
116*c8dee2aaSAndroid Build Coastguard Worker if (!this->caps()->validateSurfaceParams(dimensions,
117*c8dee2aaSAndroid Build Coastguard Worker format,
118*c8dee2aaSAndroid Build Coastguard Worker renderable,
119*c8dee2aaSAndroid Build Coastguard Worker renderTargetSampleCnt,
120*c8dee2aaSAndroid Build Coastguard Worker mipmapped,
121*c8dee2aaSAndroid Build Coastguard Worker textureType)) {
122*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker if (renderable == GrRenderable::kYes) {
126*c8dee2aaSAndroid Build Coastguard Worker renderTargetSampleCnt =
127*c8dee2aaSAndroid Build Coastguard Worker this->caps()->getRenderTargetSampleCount(renderTargetSampleCnt, format);
128*c8dee2aaSAndroid Build Coastguard Worker }
129*c8dee2aaSAndroid Build Coastguard Worker // Attempt to catch un- or wrongly initialized sample counts.
130*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(renderTargetSampleCnt > 0 && renderTargetSampleCnt <= 64);
131*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
132*c8dee2aaSAndroid Build Coastguard Worker auto tex = this->onCreateTexture(dimensions,
133*c8dee2aaSAndroid Build Coastguard Worker format,
134*c8dee2aaSAndroid Build Coastguard Worker renderable,
135*c8dee2aaSAndroid Build Coastguard Worker renderTargetSampleCnt,
136*c8dee2aaSAndroid Build Coastguard Worker budgeted,
137*c8dee2aaSAndroid Build Coastguard Worker isProtected,
138*c8dee2aaSAndroid Build Coastguard Worker mipLevelCount,
139*c8dee2aaSAndroid Build Coastguard Worker levelClearMask,
140*c8dee2aaSAndroid Build Coastguard Worker label);
141*c8dee2aaSAndroid Build Coastguard Worker if (tex) {
142*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(tex->backendFormat() == format);
143*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(GrRenderable::kNo == renderable || tex->asRenderTarget());
144*c8dee2aaSAndroid Build Coastguard Worker if (!this->caps()->reuseScratchTextures() && renderable == GrRenderable::kNo) {
145*c8dee2aaSAndroid Build Coastguard Worker tex->resourcePriv().removeScratchKey();
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker fStats.incTextureCreates();
148*c8dee2aaSAndroid Build Coastguard Worker if (renderTargetSampleCnt > 1 && !this->caps()->msaaResolvesAutomatically()) {
149*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(GrRenderable::kYes == renderable);
150*c8dee2aaSAndroid Build Coastguard Worker tex->asRenderTarget()->setRequiresManualMSAAResolve();
151*c8dee2aaSAndroid Build Coastguard Worker }
152*c8dee2aaSAndroid Build Coastguard Worker }
153*c8dee2aaSAndroid Build Coastguard Worker return tex;
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker
createTexture(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Mipmapped mipmapped,skgpu::Budgeted budgeted,GrProtected isProtected,std::string_view label)156*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGpu::createTexture(SkISize dimensions,
157*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format,
158*c8dee2aaSAndroid Build Coastguard Worker GrTextureType textureType,
159*c8dee2aaSAndroid Build Coastguard Worker GrRenderable renderable,
160*c8dee2aaSAndroid Build Coastguard Worker int renderTargetSampleCnt,
161*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped,
162*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
163*c8dee2aaSAndroid Build Coastguard Worker GrProtected isProtected,
164*c8dee2aaSAndroid Build Coastguard Worker std::string_view label) {
165*c8dee2aaSAndroid Build Coastguard Worker int mipLevelCount = 1;
166*c8dee2aaSAndroid Build Coastguard Worker if (mipmapped == skgpu::Mipmapped::kYes) {
167*c8dee2aaSAndroid Build Coastguard Worker mipLevelCount =
168*c8dee2aaSAndroid Build Coastguard Worker 32 - SkCLZ(static_cast<uint32_t>(std::max(dimensions.fWidth, dimensions.fHeight)));
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker uint32_t levelClearMask =
171*c8dee2aaSAndroid Build Coastguard Worker this->caps()->shouldInitializeTextures() ? (1 << mipLevelCount) - 1 : 0;
172*c8dee2aaSAndroid Build Coastguard Worker auto tex = this->createTextureCommon(dimensions,
173*c8dee2aaSAndroid Build Coastguard Worker format,
174*c8dee2aaSAndroid Build Coastguard Worker textureType,
175*c8dee2aaSAndroid Build Coastguard Worker renderable,
176*c8dee2aaSAndroid Build Coastguard Worker renderTargetSampleCnt,
177*c8dee2aaSAndroid Build Coastguard Worker budgeted,
178*c8dee2aaSAndroid Build Coastguard Worker isProtected,
179*c8dee2aaSAndroid Build Coastguard Worker mipLevelCount,
180*c8dee2aaSAndroid Build Coastguard Worker levelClearMask,
181*c8dee2aaSAndroid Build Coastguard Worker label);
182*c8dee2aaSAndroid Build Coastguard Worker if (tex && mipmapped == skgpu::Mipmapped::kYes && levelClearMask) {
183*c8dee2aaSAndroid Build Coastguard Worker tex->markMipmapsClean();
184*c8dee2aaSAndroid Build Coastguard Worker }
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker return tex;
187*c8dee2aaSAndroid Build Coastguard Worker }
188*c8dee2aaSAndroid Build Coastguard Worker
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)189*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGpu::createTexture(SkISize dimensions,
190*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format,
191*c8dee2aaSAndroid Build Coastguard Worker GrTextureType textureType,
192*c8dee2aaSAndroid Build Coastguard Worker GrRenderable renderable,
193*c8dee2aaSAndroid Build Coastguard Worker int renderTargetSampleCnt,
194*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
195*c8dee2aaSAndroid Build Coastguard Worker GrProtected isProtected,
196*c8dee2aaSAndroid Build Coastguard Worker GrColorType textureColorType,
197*c8dee2aaSAndroid Build Coastguard Worker GrColorType srcColorType,
198*c8dee2aaSAndroid Build Coastguard Worker const GrMipLevel texels[],
199*c8dee2aaSAndroid Build Coastguard Worker int texelLevelCount,
200*c8dee2aaSAndroid Build Coastguard Worker std::string_view label) {
201*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
202*c8dee2aaSAndroid Build Coastguard Worker if (texelLevelCount) {
203*c8dee2aaSAndroid Build Coastguard Worker if (!validate_texel_levels(dimensions, srcColorType, texels, texelLevelCount,
204*c8dee2aaSAndroid Build Coastguard Worker this->caps())) {
205*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
206*c8dee2aaSAndroid Build Coastguard Worker }
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker
209*c8dee2aaSAndroid Build Coastguard Worker int mipLevelCount = std::max(1, texelLevelCount);
210*c8dee2aaSAndroid Build Coastguard Worker uint32_t levelClearMask = 0;
211*c8dee2aaSAndroid Build Coastguard Worker if (this->caps()->shouldInitializeTextures()) {
212*c8dee2aaSAndroid Build Coastguard Worker if (texelLevelCount) {
213*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < mipLevelCount; ++i) {
214*c8dee2aaSAndroid Build Coastguard Worker if (!texels->fPixels) {
215*c8dee2aaSAndroid Build Coastguard Worker levelClearMask |= static_cast<uint32_t>(1 << i);
216*c8dee2aaSAndroid Build Coastguard Worker }
217*c8dee2aaSAndroid Build Coastguard Worker }
218*c8dee2aaSAndroid Build Coastguard Worker } else {
219*c8dee2aaSAndroid Build Coastguard Worker levelClearMask = static_cast<uint32_t>((1 << mipLevelCount) - 1);
220*c8dee2aaSAndroid Build Coastguard Worker }
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker auto tex = this->createTextureCommon(dimensions,
224*c8dee2aaSAndroid Build Coastguard Worker format,
225*c8dee2aaSAndroid Build Coastguard Worker textureType,
226*c8dee2aaSAndroid Build Coastguard Worker renderable,
227*c8dee2aaSAndroid Build Coastguard Worker renderTargetSampleCnt,
228*c8dee2aaSAndroid Build Coastguard Worker budgeted,
229*c8dee2aaSAndroid Build Coastguard Worker isProtected,
230*c8dee2aaSAndroid Build Coastguard Worker texelLevelCount,
231*c8dee2aaSAndroid Build Coastguard Worker levelClearMask,
232*c8dee2aaSAndroid Build Coastguard Worker label);
233*c8dee2aaSAndroid Build Coastguard Worker if (tex) {
234*c8dee2aaSAndroid Build Coastguard Worker bool markMipLevelsClean = false;
235*c8dee2aaSAndroid Build Coastguard Worker // Currently if level 0 does not have pixels then no other level may, as enforced by
236*c8dee2aaSAndroid Build Coastguard Worker // validate_texel_levels.
237*c8dee2aaSAndroid Build Coastguard Worker if (texelLevelCount && texels[0].fPixels) {
238*c8dee2aaSAndroid Build Coastguard Worker if (!this->writePixels(tex.get(),
239*c8dee2aaSAndroid Build Coastguard Worker SkIRect::MakeSize(dimensions),
240*c8dee2aaSAndroid Build Coastguard Worker textureColorType,
241*c8dee2aaSAndroid Build Coastguard Worker srcColorType,
242*c8dee2aaSAndroid Build Coastguard Worker texels,
243*c8dee2aaSAndroid Build Coastguard Worker texelLevelCount)) {
244*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
245*c8dee2aaSAndroid Build Coastguard Worker }
246*c8dee2aaSAndroid Build Coastguard Worker // Currently if level[1] of mip map has pixel data then so must all other levels.
247*c8dee2aaSAndroid Build Coastguard Worker // as enforced by validate_texel_levels.
248*c8dee2aaSAndroid Build Coastguard Worker markMipLevelsClean = (texelLevelCount > 1 && !levelClearMask && texels[1].fPixels);
249*c8dee2aaSAndroid Build Coastguard Worker fStats.incTextureUploads();
250*c8dee2aaSAndroid Build Coastguard Worker } else if (levelClearMask && mipLevelCount > 1) {
251*c8dee2aaSAndroid Build Coastguard Worker markMipLevelsClean = true;
252*c8dee2aaSAndroid Build Coastguard Worker }
253*c8dee2aaSAndroid Build Coastguard Worker if (markMipLevelsClean) {
254*c8dee2aaSAndroid Build Coastguard Worker tex->markMipmapsClean();
255*c8dee2aaSAndroid Build Coastguard Worker }
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker return tex;
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker
createCompressedTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Budgeted budgeted,skgpu::Mipmapped mipmapped,GrProtected isProtected,const void * data,size_t dataSize)260*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGpu::createCompressedTexture(SkISize dimensions,
261*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format,
262*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
263*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped,
264*c8dee2aaSAndroid Build Coastguard Worker GrProtected isProtected,
265*c8dee2aaSAndroid Build Coastguard Worker const void* data,
266*c8dee2aaSAndroid Build Coastguard Worker size_t dataSize) {
267*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
268*c8dee2aaSAndroid Build Coastguard Worker if (dimensions.width() < 1 || dimensions.width() > this->caps()->maxTextureSize() ||
269*c8dee2aaSAndroid Build Coastguard Worker dimensions.height() < 1 || dimensions.height() > this->caps()->maxTextureSize()) {
270*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
271*c8dee2aaSAndroid Build Coastguard Worker }
272*c8dee2aaSAndroid Build Coastguard Worker // Note if we relax the requirement that data must be provided then we must check
273*c8dee2aaSAndroid Build Coastguard Worker // caps()->shouldInitializeTextures() here.
274*c8dee2aaSAndroid Build Coastguard Worker if (!data) {
275*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
276*c8dee2aaSAndroid Build Coastguard Worker }
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker // TODO: expand CompressedDataIsCorrect to work here too
279*c8dee2aaSAndroid Build Coastguard Worker SkTextureCompressionType compressionType = GrBackendFormatToCompressionType(format);
280*c8dee2aaSAndroid Build Coastguard Worker if (compressionType == SkTextureCompressionType::kNone) {
281*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
282*c8dee2aaSAndroid Build Coastguard Worker }
283*c8dee2aaSAndroid Build Coastguard Worker
284*c8dee2aaSAndroid Build Coastguard Worker if (!this->caps()->isFormatTexturable(format, GrTextureType::k2D)) {
285*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
286*c8dee2aaSAndroid Build Coastguard Worker }
287*c8dee2aaSAndroid Build Coastguard Worker
288*c8dee2aaSAndroid Build Coastguard Worker if (dataSize <
289*c8dee2aaSAndroid Build Coastguard Worker SkCompressedDataSize(
290*c8dee2aaSAndroid Build Coastguard Worker compressionType, dimensions, nullptr, mipmapped == skgpu::Mipmapped::kYes)) {
291*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker return this->onCreateCompressedTexture(dimensions, format, budgeted, mipmapped, isProtected,
294*c8dee2aaSAndroid Build Coastguard Worker data, dataSize);
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker
wrapBackendTexture(const GrBackendTexture & backendTex,GrWrapOwnership ownership,GrWrapCacheable cacheable,GrIOType ioType)297*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
298*c8dee2aaSAndroid Build Coastguard Worker GrWrapOwnership ownership,
299*c8dee2aaSAndroid Build Coastguard Worker GrWrapCacheable cacheable,
300*c8dee2aaSAndroid Build Coastguard Worker GrIOType ioType) {
301*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(ioType != kWrite_GrIOType);
302*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = this->caps();
305*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(caps);
306*c8dee2aaSAndroid Build Coastguard Worker
307*c8dee2aaSAndroid Build Coastguard Worker if (!caps->isFormatTexturable(backendTex.getBackendFormat(), backendTex.textureType())) {
308*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
309*c8dee2aaSAndroid Build Coastguard Worker }
310*c8dee2aaSAndroid Build Coastguard Worker if (backendTex.width() > caps->maxTextureSize() ||
311*c8dee2aaSAndroid Build Coastguard Worker backendTex.height() > caps->maxTextureSize()) {
312*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
313*c8dee2aaSAndroid Build Coastguard Worker }
314*c8dee2aaSAndroid Build Coastguard Worker
315*c8dee2aaSAndroid Build Coastguard Worker return this->onWrapBackendTexture(backendTex, ownership, cacheable, ioType);
316*c8dee2aaSAndroid Build Coastguard Worker }
317*c8dee2aaSAndroid Build Coastguard Worker
wrapCompressedBackendTexture(const GrBackendTexture & backendTex,GrWrapOwnership ownership,GrWrapCacheable cacheable)318*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGpu::wrapCompressedBackendTexture(const GrBackendTexture& backendTex,
319*c8dee2aaSAndroid Build Coastguard Worker GrWrapOwnership ownership,
320*c8dee2aaSAndroid Build Coastguard Worker GrWrapCacheable cacheable) {
321*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
322*c8dee2aaSAndroid Build Coastguard Worker
323*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = this->caps();
324*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(caps);
325*c8dee2aaSAndroid Build Coastguard Worker
326*c8dee2aaSAndroid Build Coastguard Worker if (!caps->isFormatTexturable(backendTex.getBackendFormat(), backendTex.textureType())) {
327*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
328*c8dee2aaSAndroid Build Coastguard Worker }
329*c8dee2aaSAndroid Build Coastguard Worker if (backendTex.width() > caps->maxTextureSize() ||
330*c8dee2aaSAndroid Build Coastguard Worker backendTex.height() > caps->maxTextureSize()) {
331*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
332*c8dee2aaSAndroid Build Coastguard Worker }
333*c8dee2aaSAndroid Build Coastguard Worker
334*c8dee2aaSAndroid Build Coastguard Worker return this->onWrapCompressedBackendTexture(backendTex, ownership, cacheable);
335*c8dee2aaSAndroid Build Coastguard Worker }
336*c8dee2aaSAndroid Build Coastguard Worker
wrapRenderableBackendTexture(const GrBackendTexture & backendTex,int sampleCnt,GrWrapOwnership ownership,GrWrapCacheable cacheable)337*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& backendTex,
338*c8dee2aaSAndroid Build Coastguard Worker int sampleCnt,
339*c8dee2aaSAndroid Build Coastguard Worker GrWrapOwnership ownership,
340*c8dee2aaSAndroid Build Coastguard Worker GrWrapCacheable cacheable) {
341*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
342*c8dee2aaSAndroid Build Coastguard Worker if (sampleCnt < 1) {
343*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
344*c8dee2aaSAndroid Build Coastguard Worker }
345*c8dee2aaSAndroid Build Coastguard Worker
346*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = this->caps();
347*c8dee2aaSAndroid Build Coastguard Worker
348*c8dee2aaSAndroid Build Coastguard Worker if (!caps->isFormatTexturable(backendTex.getBackendFormat(), backendTex.textureType()) ||
349*c8dee2aaSAndroid Build Coastguard Worker !caps->isFormatRenderable(backendTex.getBackendFormat(), sampleCnt)) {
350*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
351*c8dee2aaSAndroid Build Coastguard Worker }
352*c8dee2aaSAndroid Build Coastguard Worker
353*c8dee2aaSAndroid Build Coastguard Worker if (backendTex.width() > caps->maxRenderTargetSize() ||
354*c8dee2aaSAndroid Build Coastguard Worker backendTex.height() > caps->maxRenderTargetSize()) {
355*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
356*c8dee2aaSAndroid Build Coastguard Worker }
357*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> tex =
358*c8dee2aaSAndroid Build Coastguard Worker this->onWrapRenderableBackendTexture(backendTex, sampleCnt, ownership, cacheable);
359*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!tex || tex->asRenderTarget());
360*c8dee2aaSAndroid Build Coastguard Worker if (tex && sampleCnt > 1 && !caps->msaaResolvesAutomatically()) {
361*c8dee2aaSAndroid Build Coastguard Worker tex->asRenderTarget()->setRequiresManualMSAAResolve();
362*c8dee2aaSAndroid Build Coastguard Worker }
363*c8dee2aaSAndroid Build Coastguard Worker return tex;
364*c8dee2aaSAndroid Build Coastguard Worker }
365*c8dee2aaSAndroid Build Coastguard Worker
wrapBackendRenderTarget(const GrBackendRenderTarget & backendRT)366*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
367*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
368*c8dee2aaSAndroid Build Coastguard Worker
369*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = this->caps();
370*c8dee2aaSAndroid Build Coastguard Worker
371*c8dee2aaSAndroid Build Coastguard Worker if (!caps->isFormatRenderable(backendRT.getBackendFormat(), backendRT.sampleCnt())) {
372*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
373*c8dee2aaSAndroid Build Coastguard Worker }
374*c8dee2aaSAndroid Build Coastguard Worker
375*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> rt = this->onWrapBackendRenderTarget(backendRT);
376*c8dee2aaSAndroid Build Coastguard Worker if (backendRT.isFramebufferOnly()) {
377*c8dee2aaSAndroid Build Coastguard Worker rt->setFramebufferOnly();
378*c8dee2aaSAndroid Build Coastguard Worker }
379*c8dee2aaSAndroid Build Coastguard Worker return rt;
380*c8dee2aaSAndroid Build Coastguard Worker }
381*c8dee2aaSAndroid Build Coastguard Worker
wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo)382*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrGpu::wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo& imageInfo,
383*c8dee2aaSAndroid Build Coastguard Worker const GrVkDrawableInfo& vkInfo) {
384*c8dee2aaSAndroid Build Coastguard Worker return this->onWrapVulkanSecondaryCBAsRenderTarget(imageInfo, vkInfo);
385*c8dee2aaSAndroid Build Coastguard Worker }
386*c8dee2aaSAndroid Build Coastguard Worker
onWrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo)387*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrGpu::onWrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo& imageInfo,
388*c8dee2aaSAndroid Build Coastguard Worker const GrVkDrawableInfo& vkInfo) {
389*c8dee2aaSAndroid Build Coastguard Worker // This is only supported on Vulkan so we default to returning nullptr here
390*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
391*c8dee2aaSAndroid Build Coastguard Worker }
392*c8dee2aaSAndroid Build Coastguard Worker
createBuffer(size_t size,GrGpuBufferType intendedType,GrAccessPattern accessPattern)393*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> GrGpu::createBuffer(size_t size,
394*c8dee2aaSAndroid Build Coastguard Worker GrGpuBufferType intendedType,
395*c8dee2aaSAndroid Build Coastguard Worker GrAccessPattern accessPattern) {
396*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
397*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
398*c8dee2aaSAndroid Build Coastguard Worker if ((intendedType == GrGpuBufferType::kXferCpuToGpu ||
399*c8dee2aaSAndroid Build Coastguard Worker intendedType == GrGpuBufferType::kXferGpuToCpu) &&
400*c8dee2aaSAndroid Build Coastguard Worker accessPattern == kStatic_GrAccessPattern) {
401*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
402*c8dee2aaSAndroid Build Coastguard Worker }
403*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> buffer = this->onCreateBuffer(size, intendedType, accessPattern);
404*c8dee2aaSAndroid Build Coastguard Worker if (buffer && !this->caps()->reuseScratchBuffers()) {
405*c8dee2aaSAndroid Build Coastguard Worker buffer->resourcePriv().removeScratchKey();
406*c8dee2aaSAndroid Build Coastguard Worker }
407*c8dee2aaSAndroid Build Coastguard Worker return buffer;
408*c8dee2aaSAndroid Build Coastguard Worker }
409*c8dee2aaSAndroid Build Coastguard Worker
copySurface(GrSurface * dst,const SkIRect & dstRect,GrSurface * src,const SkIRect & srcRect,GrSamplerState::Filter filter)410*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::copySurface(GrSurface* dst, const SkIRect& dstRect,
411*c8dee2aaSAndroid Build Coastguard Worker GrSurface* src, const SkIRect& srcRect,
412*c8dee2aaSAndroid Build Coastguard Worker GrSamplerState::Filter filter) {
413*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
414*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dst && src);
415*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!src->framebufferOnly());
416*c8dee2aaSAndroid Build Coastguard Worker
417*c8dee2aaSAndroid Build Coastguard Worker if (dst->readOnly()) {
418*c8dee2aaSAndroid Build Coastguard Worker return false;
419*c8dee2aaSAndroid Build Coastguard Worker }
420*c8dee2aaSAndroid Build Coastguard Worker
421*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
422*c8dee2aaSAndroid Build Coastguard Worker
423*c8dee2aaSAndroid Build Coastguard Worker return this->onCopySurface(dst, dstRect, src, srcRect, filter);
424*c8dee2aaSAndroid Build Coastguard Worker }
425*c8dee2aaSAndroid Build Coastguard Worker
readPixels(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType dstColorType,void * buffer,size_t rowBytes)426*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::readPixels(GrSurface* surface,
427*c8dee2aaSAndroid Build Coastguard Worker SkIRect rect,
428*c8dee2aaSAndroid Build Coastguard Worker GrColorType surfaceColorType,
429*c8dee2aaSAndroid Build Coastguard Worker GrColorType dstColorType,
430*c8dee2aaSAndroid Build Coastguard Worker void* buffer,
431*c8dee2aaSAndroid Build Coastguard Worker size_t rowBytes) {
432*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
433*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(surface);
434*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!surface->framebufferOnly());
435*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this->caps()->areColorTypeAndFormatCompatible(surfaceColorType,
436*c8dee2aaSAndroid Build Coastguard Worker surface->backendFormat()));
437*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dstColorType != GrColorType::kUnknown);
438*c8dee2aaSAndroid Build Coastguard Worker
439*c8dee2aaSAndroid Build Coastguard Worker if (!SkIRect::MakeSize(surface->dimensions()).contains(rect)) {
440*c8dee2aaSAndroid Build Coastguard Worker return false;
441*c8dee2aaSAndroid Build Coastguard Worker }
442*c8dee2aaSAndroid Build Coastguard Worker
443*c8dee2aaSAndroid Build Coastguard Worker size_t minRowBytes = SkToSizeT(GrColorTypeBytesPerPixel(dstColorType) * rect.width());
444*c8dee2aaSAndroid Build Coastguard Worker if (!this->caps()->readPixelsRowBytesSupport()) {
445*c8dee2aaSAndroid Build Coastguard Worker if (rowBytes != minRowBytes) {
446*c8dee2aaSAndroid Build Coastguard Worker return false;
447*c8dee2aaSAndroid Build Coastguard Worker }
448*c8dee2aaSAndroid Build Coastguard Worker } else {
449*c8dee2aaSAndroid Build Coastguard Worker if (rowBytes < minRowBytes) {
450*c8dee2aaSAndroid Build Coastguard Worker return false;
451*c8dee2aaSAndroid Build Coastguard Worker }
452*c8dee2aaSAndroid Build Coastguard Worker if (rowBytes % GrColorTypeBytesPerPixel(dstColorType)) {
453*c8dee2aaSAndroid Build Coastguard Worker return false;
454*c8dee2aaSAndroid Build Coastguard Worker }
455*c8dee2aaSAndroid Build Coastguard Worker }
456*c8dee2aaSAndroid Build Coastguard Worker
457*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
458*c8dee2aaSAndroid Build Coastguard Worker
459*c8dee2aaSAndroid Build Coastguard Worker return this->onReadPixels(surface, rect, surfaceColorType, dstColorType, buffer, rowBytes);
460*c8dee2aaSAndroid Build Coastguard Worker }
461*c8dee2aaSAndroid Build Coastguard Worker
writePixels(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType srcColorType,const GrMipLevel texels[],int mipLevelCount,bool prepForTexSampling)462*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::writePixels(GrSurface* surface,
463*c8dee2aaSAndroid Build Coastguard Worker SkIRect rect,
464*c8dee2aaSAndroid Build Coastguard Worker GrColorType surfaceColorType,
465*c8dee2aaSAndroid Build Coastguard Worker GrColorType srcColorType,
466*c8dee2aaSAndroid Build Coastguard Worker const GrMipLevel texels[],
467*c8dee2aaSAndroid Build Coastguard Worker int mipLevelCount,
468*c8dee2aaSAndroid Build Coastguard Worker bool prepForTexSampling) {
469*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
470*c8dee2aaSAndroid Build Coastguard Worker ATRACE_ANDROID_FRAMEWORK_ALWAYS("Texture upload(%u) %ix%i",
471*c8dee2aaSAndroid Build Coastguard Worker surface->uniqueID().asUInt(), rect.width(), rect.height());
472*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(surface);
473*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!surface->framebufferOnly());
474*c8dee2aaSAndroid Build Coastguard Worker
475*c8dee2aaSAndroid Build Coastguard Worker if (surface->readOnly()) {
476*c8dee2aaSAndroid Build Coastguard Worker return false;
477*c8dee2aaSAndroid Build Coastguard Worker }
478*c8dee2aaSAndroid Build Coastguard Worker
479*c8dee2aaSAndroid Build Coastguard Worker if (mipLevelCount == 0) {
480*c8dee2aaSAndroid Build Coastguard Worker return false;
481*c8dee2aaSAndroid Build Coastguard Worker } else if (mipLevelCount == 1) {
482*c8dee2aaSAndroid Build Coastguard Worker // We require that if we are not mipped, then the write region is contained in the surface
483*c8dee2aaSAndroid Build Coastguard Worker if (!SkIRect::MakeSize(surface->dimensions()).contains(rect)) {
484*c8dee2aaSAndroid Build Coastguard Worker return false;
485*c8dee2aaSAndroid Build Coastguard Worker }
486*c8dee2aaSAndroid Build Coastguard Worker } else if (rect != SkIRect::MakeSize(surface->dimensions())) {
487*c8dee2aaSAndroid Build Coastguard Worker // We require that if the texels are mipped, than the write region is the entire surface
488*c8dee2aaSAndroid Build Coastguard Worker return false;
489*c8dee2aaSAndroid Build Coastguard Worker }
490*c8dee2aaSAndroid Build Coastguard Worker
491*c8dee2aaSAndroid Build Coastguard Worker if (!validate_texel_levels(rect.size(), srcColorType, texels, mipLevelCount, this->caps())) {
492*c8dee2aaSAndroid Build Coastguard Worker return false;
493*c8dee2aaSAndroid Build Coastguard Worker }
494*c8dee2aaSAndroid Build Coastguard Worker
495*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
496*c8dee2aaSAndroid Build Coastguard Worker if (!this->onWritePixels(surface,
497*c8dee2aaSAndroid Build Coastguard Worker rect,
498*c8dee2aaSAndroid Build Coastguard Worker surfaceColorType,
499*c8dee2aaSAndroid Build Coastguard Worker srcColorType,
500*c8dee2aaSAndroid Build Coastguard Worker texels,
501*c8dee2aaSAndroid Build Coastguard Worker mipLevelCount,
502*c8dee2aaSAndroid Build Coastguard Worker prepForTexSampling)) {
503*c8dee2aaSAndroid Build Coastguard Worker return false;
504*c8dee2aaSAndroid Build Coastguard Worker }
505*c8dee2aaSAndroid Build Coastguard Worker
506*c8dee2aaSAndroid Build Coastguard Worker this->didWriteToSurface(surface, kTopLeft_GrSurfaceOrigin, &rect, mipLevelCount);
507*c8dee2aaSAndroid Build Coastguard Worker fStats.incTextureUploads();
508*c8dee2aaSAndroid Build Coastguard Worker
509*c8dee2aaSAndroid Build Coastguard Worker return true;
510*c8dee2aaSAndroid Build Coastguard Worker }
511*c8dee2aaSAndroid Build Coastguard Worker
transferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,size_t srcOffset,sk_sp<GrGpuBuffer> dst,size_t dstOffset,size_t size)512*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::transferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,
513*c8dee2aaSAndroid Build Coastguard Worker size_t srcOffset,
514*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> dst,
515*c8dee2aaSAndroid Build Coastguard Worker size_t dstOffset,
516*c8dee2aaSAndroid Build Coastguard Worker size_t size) {
517*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(src);
518*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dst);
519*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(srcOffset % this->caps()->transferFromBufferToBufferAlignment() == 0);
520*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dstOffset % this->caps()->transferFromBufferToBufferAlignment() == 0);
521*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(size % this->caps()->transferFromBufferToBufferAlignment() == 0);
522*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(srcOffset + size <= src->size());
523*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dstOffset + size <= dst->size());
524*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(src->intendedType() == GrGpuBufferType::kXferCpuToGpu);
525*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dst->intendedType() != GrGpuBufferType::kXferCpuToGpu);
526*c8dee2aaSAndroid Build Coastguard Worker
527*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
528*c8dee2aaSAndroid Build Coastguard Worker if (!this->onTransferFromBufferToBuffer(std::move(src),
529*c8dee2aaSAndroid Build Coastguard Worker srcOffset,
530*c8dee2aaSAndroid Build Coastguard Worker std::move(dst),
531*c8dee2aaSAndroid Build Coastguard Worker dstOffset,
532*c8dee2aaSAndroid Build Coastguard Worker size)) {
533*c8dee2aaSAndroid Build Coastguard Worker return false;
534*c8dee2aaSAndroid Build Coastguard Worker }
535*c8dee2aaSAndroid Build Coastguard Worker
536*c8dee2aaSAndroid Build Coastguard Worker fStats.incBufferTransfers();
537*c8dee2aaSAndroid Build Coastguard Worker
538*c8dee2aaSAndroid Build Coastguard Worker return true;
539*c8dee2aaSAndroid Build Coastguard Worker }
540*c8dee2aaSAndroid Build Coastguard Worker
transferPixelsTo(GrTexture * texture,SkIRect rect,GrColorType textureColorType,GrColorType bufferColorType,sk_sp<GrGpuBuffer> transferBuffer,size_t offset,size_t rowBytes)541*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::transferPixelsTo(GrTexture* texture,
542*c8dee2aaSAndroid Build Coastguard Worker SkIRect rect,
543*c8dee2aaSAndroid Build Coastguard Worker GrColorType textureColorType,
544*c8dee2aaSAndroid Build Coastguard Worker GrColorType bufferColorType,
545*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> transferBuffer,
546*c8dee2aaSAndroid Build Coastguard Worker size_t offset,
547*c8dee2aaSAndroid Build Coastguard Worker size_t rowBytes) {
548*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
549*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(texture);
550*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(transferBuffer);
551*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(transferBuffer->intendedType() == GrGpuBufferType::kXferCpuToGpu);
552*c8dee2aaSAndroid Build Coastguard Worker
553*c8dee2aaSAndroid Build Coastguard Worker if (texture->readOnly()) {
554*c8dee2aaSAndroid Build Coastguard Worker return false;
555*c8dee2aaSAndroid Build Coastguard Worker }
556*c8dee2aaSAndroid Build Coastguard Worker
557*c8dee2aaSAndroid Build Coastguard Worker // We require that the write region is contained in the texture
558*c8dee2aaSAndroid Build Coastguard Worker if (!SkIRect::MakeSize(texture->dimensions()).contains(rect)) {
559*c8dee2aaSAndroid Build Coastguard Worker return false;
560*c8dee2aaSAndroid Build Coastguard Worker }
561*c8dee2aaSAndroid Build Coastguard Worker
562*c8dee2aaSAndroid Build Coastguard Worker size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
563*c8dee2aaSAndroid Build Coastguard Worker if (this->caps()->writePixelsRowBytesSupport()) {
564*c8dee2aaSAndroid Build Coastguard Worker if (rowBytes < SkToSizeT(bpp*rect.width())) {
565*c8dee2aaSAndroid Build Coastguard Worker return false;
566*c8dee2aaSAndroid Build Coastguard Worker }
567*c8dee2aaSAndroid Build Coastguard Worker if (rowBytes % bpp) {
568*c8dee2aaSAndroid Build Coastguard Worker return false;
569*c8dee2aaSAndroid Build Coastguard Worker }
570*c8dee2aaSAndroid Build Coastguard Worker } else {
571*c8dee2aaSAndroid Build Coastguard Worker if (rowBytes != SkToSizeT(bpp*rect.width())) {
572*c8dee2aaSAndroid Build Coastguard Worker return false;
573*c8dee2aaSAndroid Build Coastguard Worker }
574*c8dee2aaSAndroid Build Coastguard Worker }
575*c8dee2aaSAndroid Build Coastguard Worker
576*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
577*c8dee2aaSAndroid Build Coastguard Worker if (!this->onTransferPixelsTo(texture,
578*c8dee2aaSAndroid Build Coastguard Worker rect,
579*c8dee2aaSAndroid Build Coastguard Worker textureColorType,
580*c8dee2aaSAndroid Build Coastguard Worker bufferColorType,
581*c8dee2aaSAndroid Build Coastguard Worker std::move(transferBuffer),
582*c8dee2aaSAndroid Build Coastguard Worker offset,
583*c8dee2aaSAndroid Build Coastguard Worker rowBytes)) {
584*c8dee2aaSAndroid Build Coastguard Worker return false;
585*c8dee2aaSAndroid Build Coastguard Worker }
586*c8dee2aaSAndroid Build Coastguard Worker
587*c8dee2aaSAndroid Build Coastguard Worker this->didWriteToSurface(texture, kTopLeft_GrSurfaceOrigin, &rect);
588*c8dee2aaSAndroid Build Coastguard Worker fStats.incTransfersToTexture();
589*c8dee2aaSAndroid Build Coastguard Worker
590*c8dee2aaSAndroid Build Coastguard Worker return true;
591*c8dee2aaSAndroid Build Coastguard Worker }
592*c8dee2aaSAndroid Build Coastguard Worker
transferPixelsFrom(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType bufferColorType,sk_sp<GrGpuBuffer> transferBuffer,size_t offset)593*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::transferPixelsFrom(GrSurface* surface,
594*c8dee2aaSAndroid Build Coastguard Worker SkIRect rect,
595*c8dee2aaSAndroid Build Coastguard Worker GrColorType surfaceColorType,
596*c8dee2aaSAndroid Build Coastguard Worker GrColorType bufferColorType,
597*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> transferBuffer,
598*c8dee2aaSAndroid Build Coastguard Worker size_t offset) {
599*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
600*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(surface);
601*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(transferBuffer);
602*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(transferBuffer->intendedType() == GrGpuBufferType::kXferGpuToCpu);
603*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this->caps()->areColorTypeAndFormatCompatible(surfaceColorType,
604*c8dee2aaSAndroid Build Coastguard Worker surface->backendFormat()));
605*c8dee2aaSAndroid Build Coastguard Worker
606*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
607*c8dee2aaSAndroid Build Coastguard Worker auto supportedRead = this->caps()->supportedReadPixelsColorType(
608*c8dee2aaSAndroid Build Coastguard Worker surfaceColorType, surface->backendFormat(), bufferColorType);
609*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(supportedRead.fOffsetAlignmentForTransferBuffer);
610*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(offset % supportedRead.fOffsetAlignmentForTransferBuffer == 0);
611*c8dee2aaSAndroid Build Coastguard Worker #endif
612*c8dee2aaSAndroid Build Coastguard Worker
613*c8dee2aaSAndroid Build Coastguard Worker // We require that the write region is contained in the texture
614*c8dee2aaSAndroid Build Coastguard Worker if (!SkIRect::MakeSize(surface->dimensions()).contains(rect)) {
615*c8dee2aaSAndroid Build Coastguard Worker return false;
616*c8dee2aaSAndroid Build Coastguard Worker }
617*c8dee2aaSAndroid Build Coastguard Worker
618*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
619*c8dee2aaSAndroid Build Coastguard Worker if (!this->onTransferPixelsFrom(surface,
620*c8dee2aaSAndroid Build Coastguard Worker rect,
621*c8dee2aaSAndroid Build Coastguard Worker surfaceColorType,
622*c8dee2aaSAndroid Build Coastguard Worker bufferColorType,
623*c8dee2aaSAndroid Build Coastguard Worker std::move(transferBuffer),
624*c8dee2aaSAndroid Build Coastguard Worker offset)) {
625*c8dee2aaSAndroid Build Coastguard Worker return false;
626*c8dee2aaSAndroid Build Coastguard Worker }
627*c8dee2aaSAndroid Build Coastguard Worker
628*c8dee2aaSAndroid Build Coastguard Worker fStats.incTransfersFromSurface();
629*c8dee2aaSAndroid Build Coastguard Worker
630*c8dee2aaSAndroid Build Coastguard Worker return true;
631*c8dee2aaSAndroid Build Coastguard Worker }
632*c8dee2aaSAndroid Build Coastguard Worker
regenerateMipMapLevels(GrTexture * texture)633*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::regenerateMipMapLevels(GrTexture* texture) {
634*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
635*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(texture);
636*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this->caps()->mipmapSupport());
637*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(texture->mipmapped() == skgpu::Mipmapped::kYes);
638*c8dee2aaSAndroid Build Coastguard Worker if (!texture->mipmapsAreDirty()) {
639*c8dee2aaSAndroid Build Coastguard Worker // This can happen when the proxy expects mipmaps to be dirty, but they are not dirty on the
640*c8dee2aaSAndroid Build Coastguard Worker // actual target. This may be caused by things that the drawingManager could not predict,
641*c8dee2aaSAndroid Build Coastguard Worker // i.e., ops that don't draw anything, aborting a draw for exceptional circumstances, etc.
642*c8dee2aaSAndroid Build Coastguard Worker // NOTE: This goes away once we quit tracking mipmap state on the actual texture.
643*c8dee2aaSAndroid Build Coastguard Worker return true;
644*c8dee2aaSAndroid Build Coastguard Worker }
645*c8dee2aaSAndroid Build Coastguard Worker if (texture->readOnly()) {
646*c8dee2aaSAndroid Build Coastguard Worker return false;
647*c8dee2aaSAndroid Build Coastguard Worker }
648*c8dee2aaSAndroid Build Coastguard Worker if (this->onRegenerateMipMapLevels(texture)) {
649*c8dee2aaSAndroid Build Coastguard Worker texture->markMipmapsClean();
650*c8dee2aaSAndroid Build Coastguard Worker return true;
651*c8dee2aaSAndroid Build Coastguard Worker }
652*c8dee2aaSAndroid Build Coastguard Worker return false;
653*c8dee2aaSAndroid Build Coastguard Worker }
654*c8dee2aaSAndroid Build Coastguard Worker
resetTextureBindings()655*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::resetTextureBindings() {
656*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
657*c8dee2aaSAndroid Build Coastguard Worker this->onResetTextureBindings();
658*c8dee2aaSAndroid Build Coastguard Worker }
659*c8dee2aaSAndroid Build Coastguard Worker
resolveRenderTarget(GrRenderTarget * target,const SkIRect & resolveRect)660*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::resolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect) {
661*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(target);
662*c8dee2aaSAndroid Build Coastguard Worker this->handleDirtyContext();
663*c8dee2aaSAndroid Build Coastguard Worker this->onResolveRenderTarget(target, resolveRect);
664*c8dee2aaSAndroid Build Coastguard Worker }
665*c8dee2aaSAndroid Build Coastguard Worker
didWriteToSurface(GrSurface * surface,GrSurfaceOrigin origin,const SkIRect * bounds,uint32_t mipLevels) const666*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
667*c8dee2aaSAndroid Build Coastguard Worker uint32_t mipLevels) const {
668*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(surface);
669*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!surface->readOnly());
670*c8dee2aaSAndroid Build Coastguard Worker // Mark any MIP chain as dirty if and only if there is a non-empty bounds.
671*c8dee2aaSAndroid Build Coastguard Worker if (nullptr == bounds || !bounds->isEmpty()) {
672*c8dee2aaSAndroid Build Coastguard Worker GrTexture* texture = surface->asTexture();
673*c8dee2aaSAndroid Build Coastguard Worker if (texture) {
674*c8dee2aaSAndroid Build Coastguard Worker if (mipLevels == 1) {
675*c8dee2aaSAndroid Build Coastguard Worker texture->markMipmapsDirty();
676*c8dee2aaSAndroid Build Coastguard Worker } else {
677*c8dee2aaSAndroid Build Coastguard Worker texture->markMipmapsClean();
678*c8dee2aaSAndroid Build Coastguard Worker }
679*c8dee2aaSAndroid Build Coastguard Worker }
680*c8dee2aaSAndroid Build Coastguard Worker }
681*c8dee2aaSAndroid Build Coastguard Worker }
682*c8dee2aaSAndroid Build Coastguard Worker
executeFlushInfo(SkSpan<GrSurfaceProxy * > proxies,SkSurfaces::BackendSurfaceAccess access,const GrFlushInfo & info,std::optional<GrTimerQuery> timerQuery,const skgpu::MutableTextureState * newState)683*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::executeFlushInfo(SkSpan<GrSurfaceProxy*> proxies,
684*c8dee2aaSAndroid Build Coastguard Worker SkSurfaces::BackendSurfaceAccess access,
685*c8dee2aaSAndroid Build Coastguard Worker const GrFlushInfo& info,
686*c8dee2aaSAndroid Build Coastguard Worker std::optional<GrTimerQuery> timerQuery,
687*c8dee2aaSAndroid Build Coastguard Worker const skgpu::MutableTextureState* newState) {
688*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
689*c8dee2aaSAndroid Build Coastguard Worker
690*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider* resourceProvider = fContext->priv().resourceProvider();
691*c8dee2aaSAndroid Build Coastguard Worker
692*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<std::unique_ptr<GrSemaphore>[]> semaphores(
693*c8dee2aaSAndroid Build Coastguard Worker new std::unique_ptr<GrSemaphore>[info.fNumSemaphores]);
694*c8dee2aaSAndroid Build Coastguard Worker if (this->caps()->backendSemaphoreSupport() && info.fNumSemaphores) {
695*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < info.fNumSemaphores; ++i) {
696*c8dee2aaSAndroid Build Coastguard Worker if (info.fSignalSemaphores[i].isInitialized()) {
697*c8dee2aaSAndroid Build Coastguard Worker semaphores[i] = resourceProvider->wrapBackendSemaphore(
698*c8dee2aaSAndroid Build Coastguard Worker info.fSignalSemaphores[i],
699*c8dee2aaSAndroid Build Coastguard Worker GrSemaphoreWrapType::kWillSignal,
700*c8dee2aaSAndroid Build Coastguard Worker kBorrow_GrWrapOwnership);
701*c8dee2aaSAndroid Build Coastguard Worker // If we failed to wrap the semaphore it means the client didn't give us a valid
702*c8dee2aaSAndroid Build Coastguard Worker // semaphore to begin with. Therefore, it is fine to not signal it.
703*c8dee2aaSAndroid Build Coastguard Worker if (semaphores[i]) {
704*c8dee2aaSAndroid Build Coastguard Worker this->insertSemaphore(semaphores[i].get());
705*c8dee2aaSAndroid Build Coastguard Worker }
706*c8dee2aaSAndroid Build Coastguard Worker } else {
707*c8dee2aaSAndroid Build Coastguard Worker semaphores[i] = resourceProvider->makeSemaphore(false);
708*c8dee2aaSAndroid Build Coastguard Worker if (semaphores[i]) {
709*c8dee2aaSAndroid Build Coastguard Worker this->insertSemaphore(semaphores[i].get());
710*c8dee2aaSAndroid Build Coastguard Worker info.fSignalSemaphores[i] = semaphores[i]->backendSemaphore();
711*c8dee2aaSAndroid Build Coastguard Worker }
712*c8dee2aaSAndroid Build Coastguard Worker }
713*c8dee2aaSAndroid Build Coastguard Worker }
714*c8dee2aaSAndroid Build Coastguard Worker }
715*c8dee2aaSAndroid Build Coastguard Worker
716*c8dee2aaSAndroid Build Coastguard Worker if (timerQuery) {
717*c8dee2aaSAndroid Build Coastguard Worker this->endTimerQuery(*timerQuery);
718*c8dee2aaSAndroid Build Coastguard Worker }
719*c8dee2aaSAndroid Build Coastguard Worker
720*c8dee2aaSAndroid Build Coastguard Worker skgpu::AutoCallback callback;
721*c8dee2aaSAndroid Build Coastguard Worker if (info.fFinishedWithStatsProc) {
722*c8dee2aaSAndroid Build Coastguard Worker callback = skgpu::AutoCallback(info.fFinishedWithStatsProc, info.fFinishedContext);
723*c8dee2aaSAndroid Build Coastguard Worker } else {
724*c8dee2aaSAndroid Build Coastguard Worker callback = skgpu::AutoCallback(info.fFinishedProc, info.fFinishedContext);
725*c8dee2aaSAndroid Build Coastguard Worker }
726*c8dee2aaSAndroid Build Coastguard Worker if (callback) {
727*c8dee2aaSAndroid Build Coastguard Worker this->addFinishedCallback(std::move(callback), std::move(timerQuery));
728*c8dee2aaSAndroid Build Coastguard Worker }
729*c8dee2aaSAndroid Build Coastguard Worker
730*c8dee2aaSAndroid Build Coastguard Worker if (info.fSubmittedProc) {
731*c8dee2aaSAndroid Build Coastguard Worker fSubmittedProcs.emplace_back(info.fSubmittedProc, info.fSubmittedContext);
732*c8dee2aaSAndroid Build Coastguard Worker }
733*c8dee2aaSAndroid Build Coastguard Worker
734*c8dee2aaSAndroid Build Coastguard Worker // We currently don't support passing in new surface state for multiple proxies here. The only
735*c8dee2aaSAndroid Build Coastguard Worker // time we have multiple proxies is if we are flushing a yuv SkImage which won't have state
736*c8dee2aaSAndroid Build Coastguard Worker // updates anyways.
737*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!newState || proxies.size() == 1);
738*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!newState || access == SkSurfaces::BackendSurfaceAccess::kNoAccess);
739*c8dee2aaSAndroid Build Coastguard Worker this->prepareSurfacesForBackendAccessAndStateUpdates(proxies, access, newState);
740*c8dee2aaSAndroid Build Coastguard Worker }
741*c8dee2aaSAndroid Build Coastguard Worker
getOpsRenderPass(GrRenderTarget * renderTarget,bool useMSAASurface,GrAttachment * stencil,GrSurfaceOrigin origin,const SkIRect & bounds,const GrOpsRenderPass::LoadAndStoreInfo & colorInfo,const GrOpsRenderPass::StencilLoadAndStoreInfo & stencilInfo,const TArray<GrSurfaceProxy *,true> & sampledProxies,GrXferBarrierFlags renderPassXferBarriers)742*c8dee2aaSAndroid Build Coastguard Worker GrOpsRenderPass* GrGpu::getOpsRenderPass(
743*c8dee2aaSAndroid Build Coastguard Worker GrRenderTarget* renderTarget,
744*c8dee2aaSAndroid Build Coastguard Worker bool useMSAASurface,
745*c8dee2aaSAndroid Build Coastguard Worker GrAttachment* stencil,
746*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin origin,
747*c8dee2aaSAndroid Build Coastguard Worker const SkIRect& bounds,
748*c8dee2aaSAndroid Build Coastguard Worker const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
749*c8dee2aaSAndroid Build Coastguard Worker const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
750*c8dee2aaSAndroid Build Coastguard Worker const TArray<GrSurfaceProxy*, true>& sampledProxies,
751*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers) {
752*c8dee2aaSAndroid Build Coastguard Worker #if SK_HISTOGRAMS_ENABLED
753*c8dee2aaSAndroid Build Coastguard Worker fCurrentSubmitRenderPassCount++;
754*c8dee2aaSAndroid Build Coastguard Worker #endif
755*c8dee2aaSAndroid Build Coastguard Worker fStats.incRenderPasses();
756*c8dee2aaSAndroid Build Coastguard Worker return this->onGetOpsRenderPass(renderTarget, useMSAASurface, stencil, origin, bounds,
757*c8dee2aaSAndroid Build Coastguard Worker colorInfo, stencilInfo, sampledProxies, renderPassXferBarriers);
758*c8dee2aaSAndroid Build Coastguard Worker }
759*c8dee2aaSAndroid Build Coastguard Worker
submitToGpu(const GrSubmitInfo & info)760*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::submitToGpu(const GrSubmitInfo& info) {
761*c8dee2aaSAndroid Build Coastguard Worker this->stats()->incNumSubmitToGpus();
762*c8dee2aaSAndroid Build Coastguard Worker
763*c8dee2aaSAndroid Build Coastguard Worker if (auto manager = this->stagingBufferManager()) {
764*c8dee2aaSAndroid Build Coastguard Worker manager->detachBuffers();
765*c8dee2aaSAndroid Build Coastguard Worker }
766*c8dee2aaSAndroid Build Coastguard Worker
767*c8dee2aaSAndroid Build Coastguard Worker if (auto uniformsBuffer = this->uniformsRingBuffer()) {
768*c8dee2aaSAndroid Build Coastguard Worker uniformsBuffer->startSubmit(this);
769*c8dee2aaSAndroid Build Coastguard Worker }
770*c8dee2aaSAndroid Build Coastguard Worker
771*c8dee2aaSAndroid Build Coastguard Worker bool submitted = this->onSubmitToGpu(info);
772*c8dee2aaSAndroid Build Coastguard Worker
773*c8dee2aaSAndroid Build Coastguard Worker this->callSubmittedProcs(submitted);
774*c8dee2aaSAndroid Build Coastguard Worker
775*c8dee2aaSAndroid Build Coastguard Worker this->reportSubmitHistograms();
776*c8dee2aaSAndroid Build Coastguard Worker
777*c8dee2aaSAndroid Build Coastguard Worker return submitted;
778*c8dee2aaSAndroid Build Coastguard Worker }
779*c8dee2aaSAndroid Build Coastguard Worker
reportSubmitHistograms()780*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::reportSubmitHistograms() {
781*c8dee2aaSAndroid Build Coastguard Worker #if SK_HISTOGRAMS_ENABLED
782*c8dee2aaSAndroid Build Coastguard Worker // The max allowed value for SK_HISTOGRAM_EXACT_LINEAR is 100. If we want to support higher
783*c8dee2aaSAndroid Build Coastguard Worker // values we can add SK_HISTOGRAM_CUSTOM_COUNTS but this has a number of buckets that is less
784*c8dee2aaSAndroid Build Coastguard Worker // than the number of actual values
785*c8dee2aaSAndroid Build Coastguard Worker [[maybe_unused]] static constexpr int kMaxRenderPassBucketValue = 100;
786*c8dee2aaSAndroid Build Coastguard Worker SK_HISTOGRAM_EXACT_LINEAR("SubmitRenderPasses",
787*c8dee2aaSAndroid Build Coastguard Worker std::min(fCurrentSubmitRenderPassCount, kMaxRenderPassBucketValue),
788*c8dee2aaSAndroid Build Coastguard Worker kMaxRenderPassBucketValue);
789*c8dee2aaSAndroid Build Coastguard Worker fCurrentSubmitRenderPassCount = 0;
790*c8dee2aaSAndroid Build Coastguard Worker #endif
791*c8dee2aaSAndroid Build Coastguard Worker
792*c8dee2aaSAndroid Build Coastguard Worker this->onReportSubmitHistograms();
793*c8dee2aaSAndroid Build Coastguard Worker }
794*c8dee2aaSAndroid Build Coastguard Worker
checkAndResetOOMed()795*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::checkAndResetOOMed() {
796*c8dee2aaSAndroid Build Coastguard Worker if (fOOMed) {
797*c8dee2aaSAndroid Build Coastguard Worker fOOMed = false;
798*c8dee2aaSAndroid Build Coastguard Worker return true;
799*c8dee2aaSAndroid Build Coastguard Worker }
800*c8dee2aaSAndroid Build Coastguard Worker return false;
801*c8dee2aaSAndroid Build Coastguard Worker }
802*c8dee2aaSAndroid Build Coastguard Worker
callSubmittedProcs(bool success)803*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::callSubmittedProcs(bool success) {
804*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fSubmittedProcs.size(); ++i) {
805*c8dee2aaSAndroid Build Coastguard Worker fSubmittedProcs[i].fProc(fSubmittedProcs[i].fContext, success);
806*c8dee2aaSAndroid Build Coastguard Worker }
807*c8dee2aaSAndroid Build Coastguard Worker fSubmittedProcs.clear();
808*c8dee2aaSAndroid Build Coastguard Worker }
809*c8dee2aaSAndroid Build Coastguard Worker
810*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_DUMP_GPU
811*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkJSONWriter.h"
812*c8dee2aaSAndroid Build Coastguard Worker
dumpJSON(SkJSONWriter * writer) const813*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::dumpJSON(SkJSONWriter* writer) const {
814*c8dee2aaSAndroid Build Coastguard Worker writer->beginObject();
815*c8dee2aaSAndroid Build Coastguard Worker
816*c8dee2aaSAndroid Build Coastguard Worker // TODO: Is there anything useful in the base class to dump here?
817*c8dee2aaSAndroid Build Coastguard Worker
818*c8dee2aaSAndroid Build Coastguard Worker this->onDumpJSON(writer);
819*c8dee2aaSAndroid Build Coastguard Worker
820*c8dee2aaSAndroid Build Coastguard Worker writer->endObject();
821*c8dee2aaSAndroid Build Coastguard Worker }
822*c8dee2aaSAndroid Build Coastguard Worker #else
dumpJSON(SkJSONWriter * writer) const823*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::dumpJSON(SkJSONWriter* writer) const { }
824*c8dee2aaSAndroid Build Coastguard Worker #endif
825*c8dee2aaSAndroid Build Coastguard Worker
826*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
827*c8dee2aaSAndroid Build Coastguard Worker
828*c8dee2aaSAndroid Build Coastguard Worker #if GR_GPU_STATS
829*c8dee2aaSAndroid Build Coastguard Worker
dump(SkString * out)830*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::Stats::dump(SkString* out) {
831*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Textures Created: %d\n", fTextureCreates);
832*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Texture Uploads: %d\n", fTextureUploads);
833*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
834*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Transfers from Surface: %d\n", fTransfersFromSurface);
835*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
836*c8dee2aaSAndroid Build Coastguard Worker out->appendf("MSAA Attachment Creates: %d\n", fMSAAAttachmentCreates);
837*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Number of draws: %d\n", fNumDraws);
838*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Number of Scratch Textures reused %d\n", fNumScratchTexturesReused);
839*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Number of Scratch MSAA Attachments reused %d\n",
840*c8dee2aaSAndroid Build Coastguard Worker fNumScratchMSAAAttachmentsReused);
841*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Number of Render Passes: %d\n", fRenderPasses);
842*c8dee2aaSAndroid Build Coastguard Worker out->appendf("Reordered DAGs Over Budget: %d\n", fNumReorderedDAGsOverBudget);
843*c8dee2aaSAndroid Build Coastguard Worker
844*c8dee2aaSAndroid Build Coastguard Worker // enable this block to output CSV-style stats for program pre-compilation
845*c8dee2aaSAndroid Build Coastguard Worker #if 0
846*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fNumInlineCompilationFailures == 0);
847*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fNumPreCompilationFailures == 0);
848*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fNumCompilationFailures == 0);
849*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fNumPartialCompilationSuccesses == 0);
850*c8dee2aaSAndroid Build Coastguard Worker
851*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%d, %d, %d, %d, %d\n",
852*c8dee2aaSAndroid Build Coastguard Worker fInlineProgramCacheStats[(int) Stats::ProgramCacheResult::kHit],
853*c8dee2aaSAndroid Build Coastguard Worker fInlineProgramCacheStats[(int) Stats::ProgramCacheResult::kMiss],
854*c8dee2aaSAndroid Build Coastguard Worker fPreProgramCacheStats[(int) Stats::ProgramCacheResult::kHit],
855*c8dee2aaSAndroid Build Coastguard Worker fPreProgramCacheStats[(int) Stats::ProgramCacheResult::kMiss],
856*c8dee2aaSAndroid Build Coastguard Worker fNumCompilationSuccesses);
857*c8dee2aaSAndroid Build Coastguard Worker #endif
858*c8dee2aaSAndroid Build Coastguard Worker }
859*c8dee2aaSAndroid Build Coastguard Worker
dumpKeyValuePairs(TArray<SkString> * keys,TArray<double> * values)860*c8dee2aaSAndroid Build Coastguard Worker void GrGpu::Stats::dumpKeyValuePairs(TArray<SkString>* keys, TArray<double>* values) {
861*c8dee2aaSAndroid Build Coastguard Worker keys->push_back(SkString("render_passes"));
862*c8dee2aaSAndroid Build Coastguard Worker values->push_back(fRenderPasses);
863*c8dee2aaSAndroid Build Coastguard Worker keys->push_back(SkString("reordered_dags_over_budget"));
864*c8dee2aaSAndroid Build Coastguard Worker values->push_back(fNumReorderedDAGsOverBudget);
865*c8dee2aaSAndroid Build Coastguard Worker }
866*c8dee2aaSAndroid Build Coastguard Worker
867*c8dee2aaSAndroid Build Coastguard Worker #endif // GR_GPU_STATS
868*c8dee2aaSAndroid Build Coastguard Worker #endif // defined(GPU_TEST_UTILS)
869*c8dee2aaSAndroid Build Coastguard Worker
CompressedDataIsCorrect(SkISize dimensions,SkTextureCompressionType compressionType,skgpu::Mipmapped mipmapped,const void * data,size_t length)870*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::CompressedDataIsCorrect(SkISize dimensions,
871*c8dee2aaSAndroid Build Coastguard Worker SkTextureCompressionType compressionType,
872*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped,
873*c8dee2aaSAndroid Build Coastguard Worker const void* data,
874*c8dee2aaSAndroid Build Coastguard Worker size_t length) {
875*c8dee2aaSAndroid Build Coastguard Worker size_t computedSize = SkCompressedDataSize(
876*c8dee2aaSAndroid Build Coastguard Worker compressionType, dimensions, nullptr, mipmapped == skgpu::Mipmapped::kYes);
877*c8dee2aaSAndroid Build Coastguard Worker return computedSize == length;
878*c8dee2aaSAndroid Build Coastguard Worker }
879*c8dee2aaSAndroid Build Coastguard Worker
createBackendTexture(SkISize dimensions,const GrBackendFormat & format,GrRenderable renderable,skgpu::Mipmapped mipmapped,GrProtected isProtected,std::string_view label)880*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrGpu::createBackendTexture(SkISize dimensions,
881*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format,
882*c8dee2aaSAndroid Build Coastguard Worker GrRenderable renderable,
883*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped,
884*c8dee2aaSAndroid Build Coastguard Worker GrProtected isProtected,
885*c8dee2aaSAndroid Build Coastguard Worker std::string_view label) {
886*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = this->caps();
887*c8dee2aaSAndroid Build Coastguard Worker
888*c8dee2aaSAndroid Build Coastguard Worker if (!format.isValid()) {
889*c8dee2aaSAndroid Build Coastguard Worker return {};
890*c8dee2aaSAndroid Build Coastguard Worker }
891*c8dee2aaSAndroid Build Coastguard Worker
892*c8dee2aaSAndroid Build Coastguard Worker if (caps->isFormatCompressed(format)) {
893*c8dee2aaSAndroid Build Coastguard Worker // Compressed formats must go through the createCompressedBackendTexture API
894*c8dee2aaSAndroid Build Coastguard Worker return {};
895*c8dee2aaSAndroid Build Coastguard Worker }
896*c8dee2aaSAndroid Build Coastguard Worker
897*c8dee2aaSAndroid Build Coastguard Worker if (dimensions.isEmpty() || dimensions.width() > caps->maxTextureSize() ||
898*c8dee2aaSAndroid Build Coastguard Worker dimensions.height() > caps->maxTextureSize()) {
899*c8dee2aaSAndroid Build Coastguard Worker return {};
900*c8dee2aaSAndroid Build Coastguard Worker }
901*c8dee2aaSAndroid Build Coastguard Worker
902*c8dee2aaSAndroid Build Coastguard Worker if (mipmapped == skgpu::Mipmapped::kYes && !this->caps()->mipmapSupport()) {
903*c8dee2aaSAndroid Build Coastguard Worker return {};
904*c8dee2aaSAndroid Build Coastguard Worker }
905*c8dee2aaSAndroid Build Coastguard Worker
906*c8dee2aaSAndroid Build Coastguard Worker return this->onCreateBackendTexture(
907*c8dee2aaSAndroid Build Coastguard Worker dimensions, format, renderable, mipmapped, isProtected, label);
908*c8dee2aaSAndroid Build Coastguard Worker }
909*c8dee2aaSAndroid Build Coastguard Worker
clearBackendTexture(const GrBackendTexture & backendTexture,sk_sp<skgpu::RefCntedCallback> finishedCallback,std::array<float,4> color)910*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::clearBackendTexture(const GrBackendTexture& backendTexture,
911*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skgpu::RefCntedCallback> finishedCallback,
912*c8dee2aaSAndroid Build Coastguard Worker std::array<float, 4> color) {
913*c8dee2aaSAndroid Build Coastguard Worker if (!backendTexture.isValid()) {
914*c8dee2aaSAndroid Build Coastguard Worker return false;
915*c8dee2aaSAndroid Build Coastguard Worker }
916*c8dee2aaSAndroid Build Coastguard Worker
917*c8dee2aaSAndroid Build Coastguard Worker if (backendTexture.hasMipmaps() && !this->caps()->mipmapSupport()) {
918*c8dee2aaSAndroid Build Coastguard Worker return false;
919*c8dee2aaSAndroid Build Coastguard Worker }
920*c8dee2aaSAndroid Build Coastguard Worker
921*c8dee2aaSAndroid Build Coastguard Worker return this->onClearBackendTexture(backendTexture, std::move(finishedCallback), color);
922*c8dee2aaSAndroid Build Coastguard Worker }
923*c8dee2aaSAndroid Build Coastguard Worker
createCompressedBackendTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Mipmapped mipmapped,GrProtected isProtected)924*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrGpu::createCompressedBackendTexture(SkISize dimensions,
925*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format,
926*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped,
927*c8dee2aaSAndroid Build Coastguard Worker GrProtected isProtected) {
928*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = this->caps();
929*c8dee2aaSAndroid Build Coastguard Worker
930*c8dee2aaSAndroid Build Coastguard Worker if (!format.isValid()) {
931*c8dee2aaSAndroid Build Coastguard Worker return {};
932*c8dee2aaSAndroid Build Coastguard Worker }
933*c8dee2aaSAndroid Build Coastguard Worker
934*c8dee2aaSAndroid Build Coastguard Worker SkTextureCompressionType compressionType = GrBackendFormatToCompressionType(format);
935*c8dee2aaSAndroid Build Coastguard Worker if (compressionType == SkTextureCompressionType::kNone) {
936*c8dee2aaSAndroid Build Coastguard Worker // Uncompressed formats must go through the createBackendTexture API
937*c8dee2aaSAndroid Build Coastguard Worker return {};
938*c8dee2aaSAndroid Build Coastguard Worker }
939*c8dee2aaSAndroid Build Coastguard Worker
940*c8dee2aaSAndroid Build Coastguard Worker if (dimensions.isEmpty() ||
941*c8dee2aaSAndroid Build Coastguard Worker dimensions.width() > caps->maxTextureSize() ||
942*c8dee2aaSAndroid Build Coastguard Worker dimensions.height() > caps->maxTextureSize()) {
943*c8dee2aaSAndroid Build Coastguard Worker return {};
944*c8dee2aaSAndroid Build Coastguard Worker }
945*c8dee2aaSAndroid Build Coastguard Worker
946*c8dee2aaSAndroid Build Coastguard Worker if (mipmapped == skgpu::Mipmapped::kYes && !this->caps()->mipmapSupport()) {
947*c8dee2aaSAndroid Build Coastguard Worker return {};
948*c8dee2aaSAndroid Build Coastguard Worker }
949*c8dee2aaSAndroid Build Coastguard Worker
950*c8dee2aaSAndroid Build Coastguard Worker return this->onCreateCompressedBackendTexture(dimensions, format, mipmapped, isProtected);
951*c8dee2aaSAndroid Build Coastguard Worker }
952*c8dee2aaSAndroid Build Coastguard Worker
updateCompressedBackendTexture(const GrBackendTexture & backendTexture,sk_sp<skgpu::RefCntedCallback> finishedCallback,const void * data,size_t length)953*c8dee2aaSAndroid Build Coastguard Worker bool GrGpu::updateCompressedBackendTexture(const GrBackendTexture& backendTexture,
954*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skgpu::RefCntedCallback> finishedCallback,
955*c8dee2aaSAndroid Build Coastguard Worker const void* data,
956*c8dee2aaSAndroid Build Coastguard Worker size_t length) {
957*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data);
958*c8dee2aaSAndroid Build Coastguard Worker
959*c8dee2aaSAndroid Build Coastguard Worker if (!backendTexture.isValid()) {
960*c8dee2aaSAndroid Build Coastguard Worker return false;
961*c8dee2aaSAndroid Build Coastguard Worker }
962*c8dee2aaSAndroid Build Coastguard Worker
963*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat format = backendTexture.getBackendFormat();
964*c8dee2aaSAndroid Build Coastguard Worker
965*c8dee2aaSAndroid Build Coastguard Worker SkTextureCompressionType compressionType = GrBackendFormatToCompressionType(format);
966*c8dee2aaSAndroid Build Coastguard Worker if (compressionType == SkTextureCompressionType::kNone) {
967*c8dee2aaSAndroid Build Coastguard Worker // Uncompressed formats must go through the createBackendTexture API
968*c8dee2aaSAndroid Build Coastguard Worker return false;
969*c8dee2aaSAndroid Build Coastguard Worker }
970*c8dee2aaSAndroid Build Coastguard Worker
971*c8dee2aaSAndroid Build Coastguard Worker if (backendTexture.hasMipmaps() && !this->caps()->mipmapSupport()) {
972*c8dee2aaSAndroid Build Coastguard Worker return false;
973*c8dee2aaSAndroid Build Coastguard Worker }
974*c8dee2aaSAndroid Build Coastguard Worker
975*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped =
976*c8dee2aaSAndroid Build Coastguard Worker backendTexture.hasMipmaps() ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo;
977*c8dee2aaSAndroid Build Coastguard Worker
978*c8dee2aaSAndroid Build Coastguard Worker if (!CompressedDataIsCorrect(backendTexture.dimensions(),
979*c8dee2aaSAndroid Build Coastguard Worker compressionType,
980*c8dee2aaSAndroid Build Coastguard Worker mipmapped,
981*c8dee2aaSAndroid Build Coastguard Worker data,
982*c8dee2aaSAndroid Build Coastguard Worker length)) {
983*c8dee2aaSAndroid Build Coastguard Worker return false;
984*c8dee2aaSAndroid Build Coastguard Worker }
985*c8dee2aaSAndroid Build Coastguard Worker
986*c8dee2aaSAndroid Build Coastguard Worker return this->onUpdateCompressedBackendTexture(backendTexture,
987*c8dee2aaSAndroid Build Coastguard Worker std::move(finishedCallback),
988*c8dee2aaSAndroid Build Coastguard Worker data,
989*c8dee2aaSAndroid Build Coastguard Worker length);
990*c8dee2aaSAndroid Build Coastguard Worker }
991