Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/image/SkImage_Gpu.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2012 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
#include "src/image/SkImage_Gpu.h"
9
10
#include "include/core/SkCanvas.h"
11
#include "include/gpu/GrBackendSurface.h"
12
#include "include/gpu/GrDirectContext.h"
13
#include "include/gpu/GrRecordingContext.h"
14
#include "include/gpu/GrYUVABackendTextures.h"
15
#include "include/private/SkImageInfoPriv.h"
16
#include "src/core/SkAutoPixmapStorage.h"
17
#include "src/core/SkBitmapCache.h"
18
#include "src/core/SkMipmap.h"
19
#include "src/core/SkScopeExit.h"
20
#include "src/core/SkTraceEvent.h"
21
#include "src/gpu/GrAHardwareBufferImageGenerator.h"
22
#include "src/gpu/GrAHardwareBufferUtils.h"
23
#include "src/gpu/GrBackendTextureImageGenerator.h"
24
#include "src/gpu/GrBackendUtils.h"
25
#include "src/gpu/GrCaps.h"
26
#include "src/gpu/GrColorSpaceXform.h"
27
#include "src/gpu/GrContextThreadSafeProxyPriv.h"
28
#include "src/gpu/GrDirectContextPriv.h"
29
#include "src/gpu/GrDrawingManager.h"
30
#include "src/gpu/GrGpu.h"
31
#include "src/gpu/GrImageContextPriv.h"
32
#include "src/gpu/GrImageInfo.h"
33
#include "src/gpu/GrProxyProvider.h"
34
#include "src/gpu/GrRecordingContextPriv.h"
35
#include "src/gpu/GrSemaphore.h"
36
#include "src/gpu/GrTexture.h"
37
#include "src/gpu/GrTextureProxy.h"
38
#include "src/gpu/GrTextureProxyPriv.h"
39
#include "src/gpu/GrYUVATextureProxies.h"
40
#include "src/gpu/SurfaceFillContext.h"
41
#include "src/gpu/effects/GrTextureEffect.h"
42
#include "src/gpu/gl/GrGLTexture.h"
43
44
#include <cstddef>
45
#include <cstring>
46
#include <type_traits>
47
48
inline SkImage_Gpu::ProxyChooser::ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy)
49
14.2k
        : fStableProxy(std::move(stableProxy)) {
50
14.2k
    SkASSERT(fStableProxy);
51
14.2k
}
52
53
inline SkImage_Gpu::ProxyChooser::ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy,
54
                                               sk_sp<GrSurfaceProxy> volatileProxy,
55
                                               sk_sp<GrRenderTask> copyTask,
56
                                               int volatileProxyTargetCount)
57
        : fStableProxy(std::move(stableProxy))
58
        , fVolatileProxy(std::move(volatileProxy))
59
        , fVolatileToStableCopyTask(std::move(copyTask))
60
0
        , fVolatileProxyTargetCount(volatileProxyTargetCount) {
61
0
    SkASSERT(fStableProxy);
62
0
    SkASSERT(fVolatileProxy);
63
0
    SkASSERT(fVolatileToStableCopyTask);
64
0
}
Unexecuted instantiation: SkImage_Gpu::ProxyChooser::ProxyChooser(sk_sp<GrSurfaceProxy>, sk_sp<GrSurfaceProxy>, sk_sp<GrRenderTask>, int)
Unexecuted instantiation: SkImage_Gpu::ProxyChooser::ProxyChooser(sk_sp<GrSurfaceProxy>, sk_sp<GrSurfaceProxy>, sk_sp<GrRenderTask>, int)
65
66
14.2k
inline SkImage_Gpu::ProxyChooser::~ProxyChooser() {
67
    // The image is being destroyed. If there is a stable copy proxy but we've been able to use
68
    // the volatile proxy for all requests then we can skip the copy.
69
14.2k
    if (fVolatileToStableCopyTask) {
70
0
        fVolatileToStableCopyTask->makeSkippable();
71
0
    }
72
14.2k
}
73
74
14.2k
inline sk_sp<GrSurfaceProxy> SkImage_Gpu::ProxyChooser::chooseProxy(GrRecordingContext* context) {
75
14.2k
    SkAutoSpinlock hold(fLock);
76
14.2k
    if (fVolatileProxy) {
77
0
        SkASSERT(fVolatileProxyTargetCount <= fVolatileProxy->getTaskTargetCount());
78
        // If this image is used off the direct context it originated on, i.e. on a recording-only
79
        // context, we don't know how the recording context's actions are ordered WRT direct context
80
        // actions until the recording context's DAG is imported into the direct context.
81
0
        if (context->asDirectContext() &&
82
0
            fVolatileProxyTargetCount == fVolatileProxy->getTaskTargetCount()) {
83
0
            return fVolatileProxy;
84
0
        }
85
0
        fVolatileProxy.reset();
86
0
        fVolatileToStableCopyTask.reset();
87
0
        return fStableProxy;
88
0
    }
89
14.2k
    return fStableProxy;
90
14.2k
}
91
92
0
inline sk_sp<GrSurfaceProxy> SkImage_Gpu::ProxyChooser::switchToStableProxy() {
93
0
    SkAutoSpinlock hold(fLock);
94
0
    fVolatileProxy.reset();
95
0
    fVolatileToStableCopyTask.reset();
96
0
    return fStableProxy;
97
0
}
98
99
15
inline sk_sp<GrSurfaceProxy> SkImage_Gpu::ProxyChooser::makeVolatileProxyStable() {
100
15
    SkAutoSpinlock hold(fLock);
101
15
    if (fVolatileProxy) {
102
0
        fStableProxy = std::move(fVolatileProxy);
103
0
        fVolatileToStableCopyTask->makeSkippable();
104
0
        fVolatileToStableCopyTask.reset();
105
0
    }
106
15
    return fStableProxy;
107
15
}
108
109
0
inline bool SkImage_Gpu::ProxyChooser::surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const {
110
0
    SkAutoSpinlock hold(fLock);
111
0
    return surfaceProxy->underlyingUniqueID() == fStableProxy->underlyingUniqueID();
112
0
}
113
114
0
inline size_t SkImage_Gpu::ProxyChooser::gpuMemorySize() const {
115
0
    SkAutoSpinlock hold(fLock);
116
0
    size_t size = fStableProxy->gpuMemorySize();
117
0
    if (fVolatileProxy) {
118
0
        SkASSERT(fVolatileProxy->gpuMemorySize() == size);
119
0
    }
120
0
    return size;
121
0
}
Unexecuted instantiation: SkImage_Gpu::ProxyChooser::gpuMemorySize() const
Unexecuted instantiation: SkImage_Gpu::ProxyChooser::gpuMemorySize() const
122
123
0
inline GrMipmapped SkImage_Gpu::ProxyChooser::mipmapped() const {
124
0
    SkAutoSpinlock hold(fLock);
125
0
    GrMipmapped mipmapped = fStableProxy->asTextureProxy()->mipmapped();
126
0
    if (fVolatileProxy) {
127
0
        SkASSERT(fVolatileProxy->asTextureProxy()->mipmapped() == mipmapped);
128
0
    }
129
0
    return mipmapped;
130
0
}
Unexecuted instantiation: SkImage_Gpu::ProxyChooser::mipmapped() const
Unexecuted instantiation: SkImage_Gpu::ProxyChooser::mipmapped() const
131
132
#ifdef SK_DEBUG
133
0
inline GrBackendFormat SkImage_Gpu::ProxyChooser::backendFormat() {
134
0
    SkAutoSpinlock hold(fLock);
135
0
    if (fVolatileProxy) {
136
0
        SkASSERT(fVolatileProxy->backendFormat() == fStableProxy->backendFormat());
137
0
    }
138
0
    return fStableProxy->backendFormat();
139
0
}
140
#endif
141
142
//////////////////////////////////////////////////////////////////////////////
143
144
SkImage_Gpu::SkImage_Gpu(sk_sp<GrImageContext> context,
145
                         uint32_t uniqueID,
146
                         GrSurfaceProxyView view,
147
                         SkColorInfo info)
148
        : INHERITED(std::move(context),
149
                    SkImageInfo::Make(view.proxy()->backingStoreDimensions(), std::move(info)),
150
                    uniqueID)
151
        , fChooser(view.detachProxy())
152
        , fSwizzle(view.swizzle())
153
14.2k
        , fOrigin(view.origin()) {
154
#ifdef SK_DEBUG
155
    const GrBackendFormat& format = fChooser.backendFormat();
156
    const GrCaps* caps = this->context()->priv().caps();
157
    GrColorType grCT = SkColorTypeAndFormatToGrColorType(caps, this->colorType(), format);
158
    SkASSERT(caps->isFormatCompressed(format) ||
159
             caps->areColorTypeAndFormatCompatible(grCT, format));
160
#endif
161
14.2k
}
162
163
SkImage_Gpu::SkImage_Gpu(sk_sp<GrDirectContext> dContext,
164
                         GrSurfaceProxyView volatileSrc,
165
                         sk_sp<GrSurfaceProxy> stableCopy,
166
                         sk_sp<GrRenderTask> copyTask,
167
                         int volatileSrcTargetCount,
168
                         SkColorInfo info)
169
        : INHERITED(std::move(dContext),
170
                    SkImageInfo::Make(volatileSrc.proxy()->backingStoreDimensions(),
171
                                      std::move(info)),
172
                    kNeedNewImageUniqueID)
173
        , fChooser(std::move(stableCopy),
174
                   volatileSrc.detachProxy(),
175
                   std::move(copyTask),
176
                   volatileSrcTargetCount)
177
        , fSwizzle(volatileSrc.swizzle())
178
0
        , fOrigin(volatileSrc.origin()) {
179
#ifdef SK_DEBUG
180
    const GrBackendFormat& format = fChooser.backendFormat();
181
    const GrCaps* caps = this->context()->priv().caps();
182
    GrColorType grCT = SkColorTypeAndFormatToGrColorType(caps, this->colorType(), format);
183
0
    SkASSERT(caps->isFormatCompressed(format) ||
184
             caps->areColorTypeAndFormatCompatible(grCT, format));
185
#endif
186
0
}
Unexecuted instantiation: SkImage_Gpu::SkImage_Gpu(sk_sp<GrDirectContext>, GrSurfaceProxyView, sk_sp<GrSurfaceProxy>, sk_sp<GrRenderTask>, int, SkColorInfo)
Unexecuted instantiation: SkImage_Gpu::SkImage_Gpu(sk_sp<GrDirectContext>, GrSurfaceProxyView, sk_sp<GrSurfaceProxy>, sk_sp<GrRenderTask>, int, SkColorInfo)
187
188
sk_sp<SkImage> SkImage_Gpu::MakeWithVolatileSrc(sk_sp<GrRecordingContext> rContext,
189
                                                GrSurfaceProxyView volatileSrc,
190
0
                                                SkColorInfo colorInfo) {
191
0
    SkASSERT(rContext);
192
0
    SkASSERT(volatileSrc);
193
0
    SkASSERT(volatileSrc.proxy()->asTextureProxy());
194
0
    GrMipmapped mm = volatileSrc.proxy()->asTextureProxy()->mipmapped();
195
0
    sk_sp<GrRenderTask> copyTask;
196
0
    auto copy = GrSurfaceProxy::Copy(rContext.get(),
197
0
                                     volatileSrc.refProxy(),
198
0
                                     volatileSrc.origin(),
199
0
                                     mm,
200
0
                                     SkBackingFit::kExact,
201
0
                                     SkBudgeted::kYes,
202
0
                                     &copyTask);
203
0
    if (!copy) {
204
0
        return nullptr;
205
0
    }
206
    // We only attempt to make a dual-proxy image on a direct context. This optimziation requires
207
    // knowing how things are ordered and recording-only contexts are not well ordered WRT other
208
    // recording contexts.
209
0
    if (auto direct = sk_ref_sp(rContext->asDirectContext())) {
210
0
        int targetCount = volatileSrc.proxy()->getTaskTargetCount();
211
0
        return sk_sp<SkImage>(new SkImage_Gpu(std::move(direct),
212
0
                                              std::move(volatileSrc),
213
0
                                              std::move(copy),
214
0
                                              std::move(copyTask),
215
0
                                              targetCount,
216
0
                                              std::move(colorInfo)));
217
0
    }
218
0
    GrSurfaceProxyView copyView(std::move(copy), volatileSrc.origin(), volatileSrc.swizzle());
219
0
    return sk_make_sp<SkImage_Gpu>(std::move(rContext),
220
0
                                   kNeedNewImageUniqueID,
221
0
                                   std::move(copyView),
222
0
                                   std::move(colorInfo));
223
0
}
Unexecuted instantiation: SkImage_Gpu::MakeWithVolatileSrc(sk_sp<GrRecordingContext>, GrSurfaceProxyView, SkColorInfo)
Unexecuted instantiation: SkImage_Gpu::MakeWithVolatileSrc(sk_sp<GrRecordingContext>, GrSurfaceProxyView, SkColorInfo)
224
225
14.2k
SkImage_Gpu::~SkImage_Gpu() = default;
226
227
0
bool SkImage_Gpu::surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const {
228
0
    return fChooser.surfaceMustCopyOnWrite(surfaceProxy);
229
0
}
230
231
0
bool SkImage_Gpu::onHasMipmaps() const { return fChooser.mipmapped() == GrMipmapped::kYes; }
232
233
0
GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrDirectContext* dContext, const GrFlushInfo& info) {
234
0
    if (!fContext->priv().matches(dContext) || dContext->abandoned()) {
235
0
        if (info.fSubmittedProc) {
236
0
            info.fSubmittedProc(info.fSubmittedContext, false);
237
0
        }
238
0
        if (info.fFinishedProc) {
239
0
            info.fFinishedProc(info.fFinishedContext);
240
0
        }
241
0
        return GrSemaphoresSubmitted::kNo;
242
0
    }
243
244
0
    sk_sp<GrSurfaceProxy> proxy = fChooser.chooseProxy(dContext);
245
0
    return dContext->priv().flushSurface(proxy.get(),
246
0
                                         SkSurface::BackendSurfaceAccess::kNoAccess,
247
0
                                         info);
248
0
}
249
250
GrBackendTexture SkImage_Gpu::onGetBackendTexture(bool flushPendingGrContextIO,
251
0
                                                  GrSurfaceOrigin* origin) const {
252
0
    auto direct = fContext->asDirectContext();
253
0
    if (!direct) {
254
        // This image was created with a DDL context and cannot be instantiated.
255
0
        return GrBackendTexture();  // invalid
256
0
    }
257
0
    if (direct->abandoned()) {
258
0
        return GrBackendTexture();  // invalid;
259
0
    }
260
261
    // We don't know how client's use of the texture will be ordered WRT Skia's. Ensure the
262
    // texture seen by the client won't be mutated by a SkSurface.
263
0
    sk_sp<GrSurfaceProxy> proxy = fChooser.switchToStableProxy();
264
265
0
    if (!proxy->isInstantiated()) {
266
0
        auto resourceProvider = direct->priv().resourceProvider();
267
268
0
        if (!proxy->instantiate(resourceProvider)) {
269
0
            return GrBackendTexture();  // invalid
270
0
        }
271
0
    }
272
273
0
    GrTexture* texture = proxy->peekTexture();
274
0
    if (texture) {
275
0
        if (flushPendingGrContextIO) {
276
0
            direct->priv().flushSurface(proxy.get());
277
0
        }
278
0
        if (origin) {
279
0
            *origin = fOrigin;
280
0
        }
281
0
        return texture->getBackendTexture();
282
0
    }
283
0
    return GrBackendTexture();  // invalid
284
0
}
285
286
0
size_t SkImage_Gpu::onTextureSize() const { return fChooser.gpuMemorySize(); }
287
288
sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(SkColorType targetCT,
289
                                                         sk_sp<SkColorSpace> targetCS,
290
0
                                                         GrDirectContext* dContext) const {
291
0
    SkColorInfo info(targetCT, this->alphaType(), std::move(targetCS));
292
0
    if (!fContext->priv().matches(dContext)) {
293
0
        return nullptr;
294
0
    }
295
296
0
    auto sfc = dContext->priv().makeSFCWithFallback(GrImageInfo(info, this->dimensions()),
297
0
                                                    SkBackingFit::kExact);
298
0
    if (!sfc) {
299
0
        return nullptr;
300
0
    }
301
    // We respecify info's CT because we called MakeWithFallback.
302
0
    auto ct = GrColorTypeToSkColorType(sfc->colorInfo().colorType());
303
0
    info = info.makeColorType(ct);
304
305
    // Draw this image's texture into the SFC.
306
0
    auto [view, _] = this->asView(dContext, GrMipmapped(this->hasMipmaps()));
307
0
    auto texFP = GrTextureEffect::Make(std::move(view), this->alphaType());
308
0
    auto colorFP = GrColorSpaceXformEffect::Make(std::move(texFP),
309
0
                                                 this->imageInfo().colorInfo(),
310
0
                                                 info);
311
0
    sfc->fillWithFP(std::move(colorFP));
312
313
0
    return sk_make_sp<SkImage_Gpu>(sk_ref_sp(dContext),
314
0
                                   kNeedNewImageUniqueID,
315
0
                                   sfc->readSurfaceView(),
316
0
                                   std::move(info));
317
0
}
318
319
0
sk_sp<SkImage> SkImage_Gpu::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
320
    // It doesn't seem worth the complexity of trying to share the ProxyChooser among multiple
321
    // images. Just fall back to the stable copy.
322
0
    GrSurfaceProxyView view(fChooser.switchToStableProxy(), fOrigin, fSwizzle);
323
0
    return sk_make_sp<SkImage_Gpu>(fContext,
324
0
                                   kNeedNewImageUniqueID,
325
0
                                   std::move(view),
326
0
                                   this->imageInfo().colorInfo().makeColorSpace(std::move(newCS)));
327
0
}
328
329
void SkImage_Gpu::onAsyncRescaleAndReadPixels(const SkImageInfo& info,
330
                                              const SkIRect& srcRect,
331
                                              RescaleGamma rescaleGamma,
332
                                              RescaleMode rescaleMode,
333
                                              ReadPixelsCallback callback,
334
0
                                              ReadPixelsContext context) {
335
0
    auto dContext = fContext->asDirectContext();
336
0
    if (!dContext) {
337
        // DDL TODO: buffer up the readback so it occurs when the DDL is drawn?
338
0
        callback(context, nullptr);
339
0
        return;
340
0
    }
341
0
    auto ctx = dContext->priv().makeSC(this->makeView(dContext), this->imageInfo().colorInfo());
342
0
    if (!ctx) {
343
0
        callback(context, nullptr);
344
0
        return;
345
0
    }
346
0
    ctx->asyncRescaleAndReadPixels(dContext, info, srcRect, rescaleGamma, rescaleMode,
347
0
                                   callback, context);
348
0
}
349
350
void SkImage_Gpu::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
351
                                                    sk_sp<SkColorSpace> dstColorSpace,
352
                                                    const SkIRect& srcRect,
353
                                                    const SkISize& dstSize,
354
                                                    RescaleGamma rescaleGamma,
355
                                                    RescaleMode rescaleMode,
356
                                                    ReadPixelsCallback callback,
357
0
                                                    ReadPixelsContext context) {
358
0
    auto dContext = fContext->asDirectContext();
359
0
    if (!dContext) {
360
        // DDL TODO: buffer up the readback so it occurs when the DDL is drawn?
361
0
        callback(context, nullptr);
362
0
        return;
363
0
    }
364
0
    auto ctx = dContext->priv().makeSC(this->makeView(dContext), this->imageInfo().colorInfo());
365
0
    if (!ctx) {
366
0
        callback(context, nullptr);
367
0
        return;
368
0
    }
369
0
    ctx->asyncRescaleAndReadPixelsYUV420(dContext,
370
0
                                         yuvColorSpace,
371
0
                                         std::move(dstColorSpace),
372
0
                                         srcRect,
373
0
                                         dstSize,
374
0
                                         rescaleGamma,
375
0
                                         rescaleMode,
376
0
                                         callback,
377
0
                                         context);
378
0
}
379
380
15
void SkImage_Gpu::generatingSurfaceIsDeleted() { fChooser.makeVolatileProxyStable(); }
381
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
384
static sk_sp<SkImage> new_wrapped_texture_common(GrRecordingContext* rContext,
385
                                                 const GrBackendTexture& backendTex,
386
                                                 GrColorType colorType,
387
                                                 GrSurfaceOrigin origin,
388
                                                 SkAlphaType at,
389
                                                 sk_sp<SkColorSpace> colorSpace,
390
                                                 GrWrapOwnership ownership,
391
0
                                                 sk_sp<GrRefCntedCallback> releaseHelper) {
392
0
    if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
393
0
        return nullptr;
394
0
    }
395
396
0
    GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
397
0
    sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
398
0
            backendTex, ownership, GrWrapCacheable::kNo, kRead_GrIOType, std::move(releaseHelper));
399
0
    if (!proxy) {
400
0
        return nullptr;
401
0
    }
402
403
0
    GrSwizzle swizzle = rContext->priv().caps()->getReadSwizzle(proxy->backendFormat(), colorType);
404
0
    GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
405
0
    SkColorInfo info(GrColorTypeToSkColorType(colorType), at, std::move(colorSpace));
406
0
    return sk_make_sp<SkImage_Gpu>(sk_ref_sp(rContext),
407
0
                                   kNeedNewImageUniqueID,
408
0
                                   std::move(view),
409
0
                                   std::move(info));
410
0
}
411
412
sk_sp<SkImage> SkImage::MakeFromCompressedTexture(GrRecordingContext* rContext,
413
                                                  const GrBackendTexture& tex,
414
                                                  GrSurfaceOrigin origin,
415
                                                  SkAlphaType at,
416
                                                  sk_sp<SkColorSpace> cs,
417
                                                  TextureReleaseProc releaseP,
418
0
                                                  ReleaseContext releaseC) {
419
0
    auto releaseHelper = GrRefCntedCallback::Make(releaseP, releaseC);
420
421
0
    if (!rContext) {
422
0
        return nullptr;
423
0
    }
424
425
0
    const GrCaps* caps = rContext->priv().caps();
426
427
0
    if (!SkImage_GpuBase::ValidateCompressedBackendTexture(caps, tex, at)) {
428
0
        return nullptr;
429
0
    }
430
431
0
    GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
432
0
    sk_sp<GrTextureProxy> proxy = proxyProvider->wrapCompressedBackendTexture(
433
0
            tex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, std::move(releaseHelper));
434
0
    if (!proxy) {
435
0
        return nullptr;
436
0
    }
437
438
0
    CompressionType type = GrBackendFormatToCompressionType(tex.getBackendFormat());
439
0
    SkColorType ct = GrCompressionTypeToSkColorType(type);
440
441
0
    GrSurfaceProxyView view(std::move(proxy), origin, GrSwizzle::RGBA());
442
0
    return sk_make_sp<SkImage_Gpu>(sk_ref_sp(rContext),
443
0
                                   kNeedNewImageUniqueID,
444
0
                                   std::move(view),
445
0
                                   SkColorInfo(ct, at, std::move(cs)));
446
0
}
447
448
sk_sp<SkImage> SkImage::MakeFromTexture(GrRecordingContext* rContext,
449
                                        const GrBackendTexture& tex, GrSurfaceOrigin origin,
450
                                        SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
451
0
                                        TextureReleaseProc releaseP, ReleaseContext releaseC) {
452
0
    auto releaseHelper = GrRefCntedCallback::Make(releaseP, releaseC);
453
454
0
    if (!rContext) {
455
0
        return nullptr;
456
0
    }
457
458
0
    const GrCaps* caps = rContext->priv().caps();
459
460
0
    GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
461
0
    if (GrColorType::kUnknown == grColorType) {
462
0
        return nullptr;
463
0
    }
464
465
0
    if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
466
0
        return nullptr;
467
0
    }
468
469
0
    return new_wrapped_texture_common(rContext, tex, grColorType, origin, at, std::move(cs),
470
0
                                      kBorrow_GrWrapOwnership, std::move(releaseHelper));
471
0
}
472
473
sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrRecordingContext* rContext,
474
                                               const GrBackendTexture& tex, GrSurfaceOrigin origin,
475
                                               SkColorType ct, SkAlphaType at,
476
0
                                               sk_sp<SkColorSpace> cs) {
477
0
    auto dContext = GrAsDirectContext(rContext);
478
0
    if (!dContext) {
479
        // We have a DDL context and we don't support adopted textures for them.
480
0
        return nullptr;
481
0
    }
482
483
0
    const GrCaps* caps = dContext->priv().caps();
484
485
0
    GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
486
0
    if (GrColorType::kUnknown == grColorType) {
487
0
        return nullptr;
488
0
    }
489
490
0
    if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
491
0
        return nullptr;
492
0
    }
493
494
0
    return new_wrapped_texture_common(dContext, tex, grColorType, origin, at, std::move(cs),
495
0
                                      kAdopt_GrWrapOwnership, nullptr);
496
0
}
497
498
sk_sp<SkImage> SkImage::MakeTextureFromCompressed(GrDirectContext* direct, sk_sp<SkData> data,
499
                                                  int width, int height, CompressionType type,
500
                                                  GrMipmapped mipMapped,
501
0
                                                  GrProtected isProtected) {
502
0
    if (!direct || !data) {
503
0
        return nullptr;
504
0
    }
505
506
0
    GrBackendFormat beFormat = direct->compressedBackendFormat(type);
507
0
    if (!beFormat.isValid()) {
508
0
        sk_sp<SkImage> tmp = MakeRasterFromCompressed(std::move(data), width, height, type);
509
0
        if (!tmp) {
510
0
            return nullptr;
511
0
        }
512
0
        return tmp->makeTextureImage(direct, mipMapped);
513
0
    }
514
515
0
    GrProxyProvider* proxyProvider = direct->priv().proxyProvider();
516
0
    sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
517
0
            {width, height}, SkBudgeted::kYes, mipMapped, isProtected, type, std::move(data));
518
0
    if (!proxy) {
519
0
        return nullptr;
520
0
    }
521
0
    GrSurfaceProxyView view(std::move(proxy));
522
523
0
    SkColorType colorType = GrCompressionTypeToSkColorType(type);
524
525
0
    return sk_make_sp<SkImage_Gpu>(sk_ref_sp(direct),
526
0
                                   kNeedNewImageUniqueID,
527
0
                                   std::move(view),
528
0
                                   SkColorInfo(colorType, kOpaque_SkAlphaType, nullptr));
529
0
}
530
531
sk_sp<SkImage> SkImage::makeTextureImage(GrDirectContext* dContext,
532
                                         GrMipmapped mipmapped,
533
0
                                         SkBudgeted budgeted) const {
534
0
    if (!dContext) {
535
0
        return nullptr;
536
0
    }
537
0
    if (!dContext->priv().caps()->mipmapSupport() || this->dimensions().area() <= 1) {
538
0
        mipmapped = GrMipmapped::kNo;
539
0
    }
540
541
0
    if (this->isTextureBacked()) {
542
0
        if (!as_IB(this)->context()->priv().matches(dContext)) {
543
0
            return nullptr;
544
0
        }
545
546
0
        if (this->isTextureBacked() && (mipmapped == GrMipmapped::kNo || this->hasMipmaps())) {
547
0
            return sk_ref_sp(const_cast<SkImage*>(this));
548
0
        }
549
0
    }
550
0
    GrImageTexGenPolicy policy = budgeted == SkBudgeted::kYes
551
0
                                         ? GrImageTexGenPolicy::kNew_Uncached_Budgeted
552
0
                                         : GrImageTexGenPolicy::kNew_Uncached_Unbudgeted;
553
    // TODO: Don't flatten YUVA images here. Add mips to the planes instead.
554
0
    auto [view, ct] = as_IB(this)->asView(dContext, mipmapped, policy);
555
0
    if (!view) {
556
0
        return nullptr;
557
0
    }
558
0
    SkASSERT(view.asTextureProxy());
559
0
    SkASSERT(mipmapped == GrMipmapped::kNo ||
560
0
             view.asTextureProxy()->mipmapped() == GrMipmapped::kYes);
561
0
    SkColorInfo colorInfo(GrColorTypeToSkColorType(ct), this->alphaType(), this->refColorSpace());
562
0
    return sk_make_sp<SkImage_Gpu>(sk_ref_sp(dContext),
563
0
                                   this->uniqueID(),
564
0
                                   std::move(view),
565
0
                                   std::move(colorInfo));
566
0
}
Unexecuted instantiation: SkImage::makeTextureImage(GrDirectContext*, GrMipmapped, SkBudgeted) const
Unexecuted instantiation: SkImage::makeTextureImage(GrDirectContext*, GrMipmapped, SkBudgeted) const
567
568
///////////////////////////////////////////////////////////////////////////////////////////////////
569
570
sk_sp<SkImage> SkImage::MakePromiseTexture(sk_sp<GrContextThreadSafeProxy> threadSafeProxy,
571
                                           const GrBackendFormat& backendFormat,
572
                                           SkISize dimensions,
573
                                           GrMipmapped mipMapped,
574
                                           GrSurfaceOrigin origin,
575
                                           SkColorType colorType,
576
                                           SkAlphaType alphaType,
577
                                           sk_sp<SkColorSpace> colorSpace,
578
                                           PromiseImageTextureFulfillProc textureFulfillProc,
579
                                           PromiseImageTextureReleaseProc textureReleaseProc,
580
0
                                           PromiseImageTextureContext textureContext) {
581
    // Our contract is that we will always call the release proc even on failure.
582
    // We use the helper to convey the context, so we need to ensure make doesn't fail.
583
0
    textureReleaseProc = textureReleaseProc ? textureReleaseProc : [](void*) {};
Unexecuted instantiation: SkImage_Gpu.cpp:SkImage::MakePromiseTexture(sk_sp<GrContextThreadSafeProxy>, GrBackendFormat const&, SkISize, GrMipmapped, GrSurfaceOrigin, SkColorType, SkAlphaType, sk_sp<SkColorSpace>, sk_sp<SkPromiseImageTexture> (*)(void*), void (*)(void*), void*)::$_1::operator()(void*) const
Unexecuted instantiation: SkImage_Gpu.cpp:SkImage::MakePromiseTexture(sk_sp<GrContextThreadSafeProxy>, GrBackendFormat const&, SkISize, GrMipmapped, GrSurfaceOrigin, SkColorType, SkAlphaType, sk_sp<SkColorSpace>, sk_sp<SkPromiseImageTexture> (*)(void*), void (*)(void*), void*)::$_8::operator()(void*) const
584
0
    auto releaseHelper = GrRefCntedCallback::Make(textureReleaseProc, textureContext);
585
0
    SkImageInfo info = SkImageInfo::Make(dimensions, colorType, alphaType, colorSpace);
586
0
    if (!SkImageInfoIsValid(info)) {
587
0
        return nullptr;
588
0
    }
589
590
0
    if (!threadSafeProxy) {
591
0
        return nullptr;
592
0
    }
593
594
0
    if (dimensions.isEmpty()) {
595
0
        return nullptr;
596
0
    }
597
598
0
    GrColorType grColorType = SkColorTypeAndFormatToGrColorType(threadSafeProxy->priv().caps(),
599
0
                                                                colorType,
600
0
                                                                backendFormat);
601
0
    if (GrColorType::kUnknown == grColorType) {
602
0
        return nullptr;
603
0
    }
604
605
0
    if (!threadSafeProxy->priv().caps()->areColorTypeAndFormatCompatible(grColorType,
606
0
                                                                         backendFormat)) {
607
0
        return nullptr;
608
0
    }
609
610
0
    auto proxy = SkImage_GpuBase::MakePromiseImageLazyProxy(threadSafeProxy.get(),
611
0
                                                            dimensions,
612
0
                                                            backendFormat,
613
0
                                                            mipMapped,
614
0
                                                            textureFulfillProc,
615
0
                                                            std::move(releaseHelper));
616
0
    if (!proxy) {
617
0
        return nullptr;
618
0
    }
619
0
    GrSwizzle swizzle = threadSafeProxy->priv().caps()->getReadSwizzle(backendFormat, grColorType);
620
0
    GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
621
0
    sk_sp<GrImageContext> ctx(GrImageContextPriv::MakeForPromiseImage(std::move(threadSafeProxy)));
622
0
    return sk_make_sp<SkImage_Gpu>(std::move(ctx),
623
0
                                   kNeedNewImageUniqueID,
624
0
                                   std::move(view),
625
0
                                   SkColorInfo(colorType, alphaType, std::move(colorSpace)));
626
0
}
627
628
///////////////////////////////////////////////////////////////////////////////////////////////////
629
630
sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrDirectContext* dContext,
631
                                                   const SkPixmap& originalPixmap, bool buildMips,
632
0
                                                   bool limitToMaxTextureSize) {
633
    // Some backends or drivers don't support (safely) moving resources between contexts
634
0
    if (!dContext || !dContext->priv().caps()->crossContextTextureSupport()) {
635
0
        return SkImage::MakeRasterCopy(originalPixmap);
636
0
    }
637
638
    // If non-power-of-two mipmapping isn't supported, ignore the client's request
639
0
    if (!dContext->priv().caps()->mipmapSupport()) {
640
0
        buildMips = false;
641
0
    }
642
643
0
    const SkPixmap* pixmap = &originalPixmap;
644
0
    SkAutoPixmapStorage resized;
645
0
    int maxTextureSize = dContext->priv().caps()->maxTextureSize();
646
0
    int maxDim = std::max(originalPixmap.width(), originalPixmap.height());
647
0
    if (limitToMaxTextureSize && maxDim > maxTextureSize) {
648
0
        float scale = static_cast<float>(maxTextureSize) / maxDim;
649
0
        int newWidth = std::min(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
650
0
        int newHeight = std::min(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
651
0
        SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
652
0
        SkSamplingOptions sampling(SkFilterMode::kLinear);
653
0
        if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, sampling)) {
654
0
            return nullptr;
655
0
        }
656
0
        pixmap = &resized;
657
0
    }
658
    // Turn the pixmap into a GrTextureProxy
659
0
    SkBitmap bmp;
660
0
    bmp.installPixels(*pixmap);
661
0
    GrMipmapped mipmapped = buildMips ? GrMipmapped::kYes : GrMipmapped::kNo;
662
0
    auto [view, ct] = GrMakeUncachedBitmapProxyView(dContext, bmp, mipmapped);
663
0
    if (!view) {
664
0
        return SkImage::MakeRasterCopy(*pixmap);
665
0
    }
666
667
0
    sk_sp<GrTexture> texture = sk_ref_sp(view.proxy()->peekTexture());
668
669
    // Flush any writes or uploads
670
0
    dContext->priv().flushSurface(view.proxy());
671
0
    GrGpu* gpu = dContext->priv().getGpu();
672
673
0
    std::unique_ptr<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
674
675
0
    SkColorType skCT = GrColorTypeToSkColorType(ct);
676
0
    auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), view.origin(),
677
0
                                                    std::move(sema), skCT,
678
0
                                                    pixmap->alphaType(),
679
0
                                                    pixmap->info().refColorSpace());
680
0
    return SkImage::MakeFromGenerator(std::move(gen));
681
0
}
682
683
#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
684
sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
685
                                                sk_sp<SkColorSpace> cs,
686
                                                GrSurfaceOrigin surfaceOrigin) {
687
    auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
688
    return SkImage::MakeFromGenerator(std::move(gen));
689
}
690
691
sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrDirectContext* dContext,
692
                                                        const SkPixmap& pixmap,
693
                                                        AHardwareBuffer* hardwareBuffer,
694
                                                        GrSurfaceOrigin surfaceOrigin) {
695
    AHardwareBuffer_Desc bufferDesc;
696
    AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
697
698
    if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
699
        return nullptr;
700
    }
701
702
703
    GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(dContext,
704
                                                                             hardwareBuffer,
705
                                                                             bufferDesc.format,
706
                                                                             true);
707
708
    if (!backendFormat.isValid()) {
709
        return nullptr;
710
    }
711
712
    GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
713
    GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
714
    GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
715
716
    const bool isRenderable = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER);
717
718
    GrBackendTexture backendTexture =
719
            GrAHardwareBufferUtils::MakeBackendTexture(dContext, hardwareBuffer,
720
                                                       bufferDesc.width, bufferDesc.height,
721
                                                       &deleteImageProc, &updateImageProc,
722
                                                       &deleteImageCtx, false, backendFormat,
723
                                                       isRenderable);
724
    if (!backendTexture.isValid()) {
725
        return nullptr;
726
    }
727
    SkASSERT(deleteImageProc);
728
729
    auto releaseHelper = GrRefCntedCallback::Make(deleteImageProc, deleteImageCtx);
730
731
    SkColorType colorType =
732
            GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
733
734
    GrColorType grColorType = SkColorTypeToGrColorType(colorType);
735
736
    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
737
    if (!proxyProvider) {
738
        return nullptr;
739
    }
740
741
    sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
742
            backendTexture, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType,
743
            std::move(releaseHelper));
744
    if (!proxy) {
745
        return nullptr;
746
    }
747
748
    GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(backendFormat, grColorType);
749
    GrSurfaceProxyView framebufferView(std::move(proxy), surfaceOrigin, swizzle);
750
    SkColorInfo colorInfo = pixmap.info().colorInfo().makeColorType(colorType);
751
    sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(dContext),
752
                                                   kNeedNewImageUniqueID,
753
                                                   framebufferView,
754
                                                   std::move(colorInfo));
755
    if (!image) {
756
        return nullptr;
757
    }
758
759
    GrDrawingManager* drawingManager = dContext->priv().drawingManager();
760
    if (!drawingManager) {
761
        return nullptr;
762
    }
763
764
    skgpu::SurfaceContext surfaceContext(
765
            dContext, std::move(framebufferView),image->imageInfo().colorInfo());
766
767
    surfaceContext.writePixels(dContext, pixmap, {0, 0});
768
769
    GrSurfaceProxy* p[1] = {surfaceContext.asSurfaceProxy()};
770
    drawingManager->flush(SkMakeSpan(p), SkSurface::BackendSurfaceAccess::kNoAccess, {}, nullptr);
771
772
    return image;
773
}
774
#endif
775
776
///////////////////////////////////////////////////////////////////////////////////////////////////
777
778
bool SkImage::MakeBackendTextureFromSkImage(GrDirectContext* direct,
779
                                            sk_sp<SkImage> image,
780
                                            GrBackendTexture* backendTexture,
781
0
                                            BackendTextureReleaseProc* releaseProc) {
782
0
    if (!image || !backendTexture || !releaseProc) {
783
0
        return false;
784
0
    }
785
786
0
    auto [view, ct] = as_IB(image)->asView(direct, GrMipmapped::kNo);
787
788
0
    if (!view) {
789
0
        return false;
790
0
    }
791
792
    // Flush any pending IO on the texture.
793
0
    direct->priv().flushSurface(view.proxy());
794
795
0
    GrTexture* texture = view.asTextureProxy()->peekTexture();
796
0
    if (!texture) {
797
0
        return false;
798
0
    }
799
    // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
800
    // image is not unique, or if the texture wraps an external object.
801
0
    if (!image->unique() || !texture->unique() ||
802
0
        texture->resourcePriv().refsWrappedObjects()) {
803
        // onMakeSubset will always copy the image.
804
0
        image = as_IB(image)->onMakeSubset(image->bounds(), direct);
805
0
        if (!image) {
806
0
            return false;
807
0
        }
808
0
        return MakeBackendTextureFromSkImage(direct, std::move(image), backendTexture, releaseProc);
809
0
    }
810
811
0
    SkASSERT(!texture->resourcePriv().refsWrappedObjects());
812
0
    SkASSERT(texture->unique());
813
0
    SkASSERT(image->unique());
814
815
    // Take a reference to the GrTexture and release the image.
816
0
    sk_sp<GrTexture> textureRef = sk_ref_sp(texture);
817
0
    view.reset();
818
0
    image = nullptr;
819
0
    SkASSERT(textureRef->unique());
820
821
    // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
822
0
    return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
823
0
}
Unexecuted instantiation: SkImage::MakeBackendTextureFromSkImage(GrDirectContext*, sk_sp<SkImage>, GrBackendTexture*, std::__1::function<void (GrBackendTexture)>*)
Unexecuted instantiation: SkImage::MakeBackendTextureFromSkImage(GrDirectContext*, sk_sp<SkImage>, GrBackendTexture*, std::__1::function<void (GrBackendTexture)>*)
824
825
std::tuple<GrSurfaceProxyView, GrColorType> SkImage_Gpu::onAsView(
826
        GrRecordingContext* recordingContext,
827
        GrMipmapped mipmapped,
828
14.2k
        GrImageTexGenPolicy policy) const {
829
14.2k
    if (!fContext->priv().matches(recordingContext)) {
830
0
        return {};
831
0
    }
832
14.2k
    if (policy != GrImageTexGenPolicy::kDraw) {
833
0
        return {CopyView(recordingContext, this->makeView(recordingContext), mipmapped, policy),
834
0
                SkColorTypeToGrColorType(this->colorType())};
835
0
    }
836
14.2k
    GrSurfaceProxyView view = this->makeView(recordingContext);
837
14.2k
    GrColorType ct = SkColorTypeAndFormatToGrColorType(recordingContext->priv().caps(),
838
14.2k
                                                       this->colorType(),
839
14.2k
                                                       view.proxy()->backendFormat());
840
14.2k
    if (mipmapped == GrMipmapped::kYes) {
841
0
        view = FindOrMakeCachedMipmappedView(recordingContext, std::move(view), this->uniqueID());
842
0
    }
843
14.2k
    return {std::move(view), ct};
844
14.2k
}
845
846
std::unique_ptr<GrFragmentProcessor> SkImage_Gpu::onAsFragmentProcessor(
847
        GrRecordingContext* rContext,
848
        SkSamplingOptions sampling,
849
        const SkTileMode tileModes[2],
850
        const SkMatrix& m,
851
        const SkRect* subset,
852
1.79k
        const SkRect* domain) const {
853
1.79k
    if (!fContext->priv().matches(rContext)) {
854
0
        return {};
855
0
    }
856
1.79k
    auto mm = sampling.mipmap == SkMipmapMode::kNone ? GrMipmapped::kNo : GrMipmapped::kYes;
857
1.79k
    return MakeFragmentProcessorFromView(rContext,
858
1.79k
                                         std::get<0>(this->asView(rContext, mm)),
859
1.79k
                                         this->alphaType(),
860
1.79k
                                         sampling,
861
1.79k
                                         tileModes,
862
1.79k
                                         m,
863
1.79k
                                         subset,
864
1.79k
                                         domain);
865
1.79k
}
866
867
14.2k
GrSurfaceProxyView SkImage_Gpu::makeView(GrRecordingContext* rContext) const {
868
14.2k
    return {fChooser.chooseProxy(rContext), fOrigin, fSwizzle};
869
14.2k
}