Coverage Report

Created: 2021-08-22 09:07

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