blob: bfa4dfd886c7b882c6d574e1edf6fd2322eaf3e0 [file] [log] [blame]
reed@google.com5d4ba882012-07-31 15:45:27 +00001/*
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
cblume33e0cb52016-08-30 12:09:23 -07008#include <cstddef>
9#include <cstring>
10#include <type_traits>
11
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkCanvas.h"
13#include "include/gpu/GrBackendSurface.h"
14#include "include/gpu/GrContext.h"
15#include "include/gpu/GrTexture.h"
16#include "include/private/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "include/private/SkImageInfoPriv.h"
18#include "src/core/SkAutoPixmapStorage.h"
19#include "src/core/SkBitmapCache.h"
20#include "src/core/SkMipMap.h"
21#include "src/core/SkScopeExit.h"
22#include "src/core/SkTraceEvent.h"
23#include "src/gpu/GrAHardwareBufferImageGenerator.h"
24#include "src/gpu/GrAHardwareBufferUtils.h"
25#include "src/gpu/GrBackendTextureImageGenerator.h"
26#include "src/gpu/GrBitmapTextureMaker.h"
27#include "src/gpu/GrCaps.h"
28#include "src/gpu/GrClip.h"
29#include "src/gpu/GrColorSpaceXform.h"
30#include "src/gpu/GrContextPriv.h"
31#include "src/gpu/GrDrawingManager.h"
32#include "src/gpu/GrGpu.h"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040033#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050034#include "src/gpu/GrImageTextureMaker.h"
35#include "src/gpu/GrProxyProvider.h"
36#include "src/gpu/GrRecordingContextPriv.h"
37#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050038#include "src/gpu/GrSemaphore.h"
39#include "src/gpu/GrSurfacePriv.h"
40#include "src/gpu/GrTextureAdjuster.h"
41#include "src/gpu/GrTextureContext.h"
42#include "src/gpu/GrTexturePriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040043#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050044#include "src/gpu/GrTextureProxyPriv.h"
45#include "src/gpu/SkGr.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050046#include "src/gpu/gl/GrGLTexture.h"
47#include "src/image/SkImage_Gpu.h"
bsalomon993a4212015-05-29 11:37:25 -070048
Brian Salomon729fc0c2019-09-30 16:33:11 +000049static SkColorType proxy_color_type(GrTextureProxy* proxy) {
50 SkColorType colorType;
51 if (!GrPixelConfigToColorType(proxy->config(), &colorType)) {
52 colorType = kUnknown_SkColorType;
53 }
54 return colorType;
55}
56
57SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, SkAlphaType at,
58 sk_sp<GrTextureProxy> proxy, sk_sp<SkColorSpace> colorSpace)
Robert Phillipse9462dd2019-10-23 12:41:29 -040059 : INHERITED(std::move(context), proxy->backingStoreDimensions(), uniqueID,
Brian Salomon729fc0c2019-09-30 16:33:11 +000060 proxy_color_type(proxy.get()), at, colorSpace)
Jim Van Verth8026ccc2018-10-04 13:10:39 -040061 , fProxy(std::move(proxy)) {}
piotaixrcef04f82014-07-14 07:48:04 -070062
Brian Salomon729fc0c2019-09-30 16:33:11 +000063SkImage_Gpu::~SkImage_Gpu() {}
64
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040065GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrContext* context, const GrFlushInfo& info) {
66 if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
67 return GrSemaphoresSubmitted::kNo;
68 }
69
70 GrSurfaceProxy* p[1] = {fProxy.get()};
71 return context->priv().flushSurfaces(p, 1, info);
72}
73
Robert Phillips6603a172019-03-05 12:35:44 -050074sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
75 SkColorType targetCT,
Brian Osmanf48c9962019-01-14 11:15:50 -050076 sk_sp<SkColorSpace> targetCS) const {
Robert Phillips6603a172019-03-05 12:35:44 -050077 if (!context || !fContext->priv().matches(context)) {
78 return nullptr;
79 }
80
Brian Salomon5ad6fd32019-03-21 15:30:08 -040081 auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
82 targetCS.get(), this->alphaType());
Brian Osmanf48c9962019-01-14 11:15:50 -050083 SkASSERT(xform || targetCT != this->colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050084
Robert Phillips6603a172019-03-05 12:35:44 -050085 sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050086
Brian Salomonbf6b9792019-08-21 09:38:10 -040087 auto renderTargetContext = context->priv().makeDeferredRenderTargetContextWithFallback(
88 SkBackingFit::kExact, this->width(), this->height(), SkColorTypeToGrColorType(targetCT),
89 nullptr);
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050090 if (!renderTargetContext) {
91 return nullptr;
92 }
93
94 GrPaint paint;
95 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
Brian Salomon078e8fa2019-11-22 04:10:18 +000096 paint.addColorTextureProcessor(std::move(proxy), SkColorTypeToGrColorType(this->colorType()),
97 SkMatrix::I());
Brian Osmanf48c9962019-01-14 11:15:50 -050098 if (xform) {
99 paint.addColorFragmentProcessor(std::move(xform));
100 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500101
102 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
103 SkRect::MakeIWH(this->width(), this->height()));
104 if (!renderTargetContext->asTextureProxy()) {
105 return nullptr;
106 }
107
108 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Brian Salomon729fc0c2019-09-30 16:33:11 +0000109 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
110 renderTargetContext->asTextureProxyRef(), std::move(targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500111}
112
Brian Osmand5148372019-08-14 16:14:51 -0400113sk_sp<SkImage> SkImage_Gpu::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Brian Salomon729fc0c2019-09-30 16:33:11 +0000114 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(), fProxy,
115 std::move(newCS));
Brian Osmand5148372019-08-14 16:14:51 -0400116}
117
reed8b26b992015-05-07 15:36:17 -0700118///////////////////////////////////////////////////////////////////////////////////////////////////
119
Greg Daniel7ef28f32017-04-20 16:41:55 +0000120static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
121 const GrBackendTexture& backendTex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400122 GrColorType colorType, GrSurfaceOrigin origin,
brianosmandddbe382016-07-20 13:55:39 -0700123 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
124 GrWrapOwnership ownership,
reed7fb4f8b2016-03-11 04:33:52 -0800125 SkImage::TextureReleaseProc releaseProc,
126 SkImage::ReleaseContext releaseCtx) {
Greg Daniel66aebf32018-04-09 09:15:56 -0400127 if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700128 return nullptr;
reed8b26b992015-05-07 15:36:17 -0700129 }
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400130
Robert Phillips9da87e02019-02-04 13:26:26 -0500131 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500132 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400133 proxyProvider->wrapBackendTexture(backendTex, colorType, origin, ownership,
134 GrWrapCacheable::kNo, kRead_GrIOType,
135 releaseProc, releaseCtx);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500136 if (!proxy) {
Robert Phillipse201ebc2018-01-17 18:12:50 +0000137 return nullptr;
138 }
Brian Salomon729fc0c2019-09-30 16:33:11 +0000139 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(proxy),
140 std::move(colorSpace));
bsalomon6dc6f5f2015-06-18 09:12:16 -0700141}
142
Greg Danielf5d87582017-12-18 14:48:15 -0500143sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
144 const GrBackendTexture& tex, GrSurfaceOrigin origin,
145 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
146 TextureReleaseProc releaseP, ReleaseContext releaseC) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500147 if (!ctx) {
148 return nullptr;
149 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400150
Robert Phillips62221e72019-07-24 15:07:38 -0400151 const GrCaps* caps = ctx->priv().caps();
152
153 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400154 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400155 return nullptr;
156 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400157
Robert Phillips62221e72019-07-24 15:07:38 -0400158 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400159 return nullptr;
160 }
161
Robert Phillips62221e72019-07-24 15:07:38 -0400162 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomonbfd27492018-03-19 14:08:51 -0400163 kBorrow_GrWrapOwnership, releaseP, releaseC);
Greg Danielf5d87582017-12-18 14:48:15 -0500164}
165
Greg Daniel94403452017-04-18 15:52:36 -0400166sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
167 const GrBackendTexture& tex, GrSurfaceOrigin origin,
Brian Salomon42409c22018-03-20 13:48:41 -0400168 SkColorType ct, SkAlphaType at,
169 sk_sp<SkColorSpace> cs) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500170 if (!ctx || !ctx->priv().resourceProvider()) {
Greg Danielf2336e42018-01-23 16:38:14 -0500171 // We have a DDL context and we don't support adopted textures for them.
172 return nullptr;
173 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400174
Robert Phillips62221e72019-07-24 15:07:38 -0400175 const GrCaps* caps = ctx->priv().caps();
176
177 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400178 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400179 return nullptr;
180 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400181
Robert Phillips62221e72019-07-24 15:07:38 -0400182 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400183 return nullptr;
184 }
185
Robert Phillips62221e72019-07-24 15:07:38 -0400186 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomon42409c22018-03-20 13:48:41 -0400187 kAdopt_GrWrapOwnership, nullptr, nullptr);
Greg Danielf5d87582017-12-18 14:48:15 -0500188}
189
Jim Van Verthee06b332019-01-18 10:36:32 -0500190sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
191 int width, int height, CompressionType type) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500192 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Salomonbb8dde82019-06-27 10:52:13 -0400193 sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
194 width, height, SkBudgeted::kYes, type, std::move(data));
Jim Van Verthee06b332019-01-18 10:36:32 -0500195
196 if (!proxy) {
197 return nullptr;
198 }
Brian Salomon729fc0c2019-09-30 16:33:11 +0000199
200 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
201 std::move(proxy), nullptr);
Jim Van Verthee06b332019-01-18 10:36:32 -0500202}
203
Brian Salomonf05e6d32018-12-20 08:41:41 -0500204sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
205 const GrBackendTexture yuvaTextures[],
206 const SkYUVAIndex yuvaIndices[4], SkISize size,
207 GrSurfaceOrigin origin,
208 GrRenderTargetContext* renderTargetContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400209 SkASSERT(renderTargetContext);
210
Jim Van Verth0e671942018-11-09 12:03:57 -0500211 int numTextures;
212 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500213 return nullptr;
214 }
Robert Phillipsba5c4392018-07-25 12:37:14 -0400215
Jim Van Verth0e671942018-11-09 12:03:57 -0500216 sk_sp<GrTextureProxy> tempTextureProxies[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500217 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
218 origin, tempTextureProxies)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500219 return nullptr;
220 }
221
222 const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
Brian Osmane9560492019-02-05 17:00:03 -0500223 if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
Jim Van Verth0e671942018-11-09 12:03:57 -0500224 tempTextureProxies, yuvaIndices)) {
225 return nullptr;
226 }
Robert Phillipsb726d582017-03-09 16:36:32 -0500227
Jim Van Verth53275362018-11-09 15:42:35 -0500228 SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillipsb726d582017-03-09 16:36:32 -0500229 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Brian Salomon729fc0c2019-09-30 16:33:11 +0000230 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
231 renderTargetContext->asTextureProxyRef(),
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400232 renderTargetContext->colorInfo().refColorSpace());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400233}
234
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400235sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
236 SkYUVColorSpace yuvColorSpace,
237 const GrBackendTexture yuvaTextures[],
238 const SkYUVAIndex yuvaIndices[4],
239 SkISize imageSize,
240 GrSurfaceOrigin imageOrigin,
241 sk_sp<SkColorSpace> imageColorSpace) {
242 const int width = imageSize.width();
243 const int height = imageSize.height();
Brian Salomond2fcfb52018-09-17 21:57:11 -0400244
245 // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400246 auto renderTargetContext = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400247 SkBackingFit::kExact, width, height, GrColorType::kRGBA_8888,
Brian Salomonbf6b9792019-08-21 09:38:10 -0400248 std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400249 if (!renderTargetContext) {
250 return nullptr;
251 }
252
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400253 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500254 imageSize, imageOrigin, renderTargetContext.get());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400255}
256
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400257sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
Brian Salomond2fcfb52018-09-17 21:57:11 -0400258 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400259 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400260 const GrBackendTexture yuvaTextures[],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400261 const SkYUVAIndex yuvaIndices[4],
262 SkISize imageSize,
263 GrSurfaceOrigin imageOrigin,
264 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400265 sk_sp<SkColorSpace> imageColorSpace,
266 TextureReleaseProc textureReleaseProc,
267 ReleaseContext releaseContext) {
Robert Phillips62221e72019-07-24 15:07:38 -0400268 const GrCaps* caps = ctx->priv().caps();
Robert Phillipsdd399802019-07-18 12:28:00 +0000269
Robert Phillips62221e72019-07-24 15:07:38 -0400270 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, kRGBA_8888_SkColorType,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400271 backendTexture.getBackendFormat());
272 if (GrColorType::kUnknown == grColorType) {
273 return nullptr;
274 }
275
Jim Van Verth53275362018-11-09 15:42:35 -0500276 SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillips62221e72019-07-24 15:07:38 -0400277 if (!SkImage_Gpu::ValidateBackendTexture(caps, backendTexture, grColorType,
278 kRGBA_8888_SkColorType, at, nullptr)) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400279 return nullptr;
280 }
281
282 // Needs to create a render target with external texture
283 // in order to draw to it for the yuv->rgb conversion.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400284 auto renderTargetContext = ctx->priv().makeBackendTextureRenderTargetContext(
285 backendTexture, imageOrigin, 1, grColorType, std::move(imageColorSpace), nullptr,
286 textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400287 if (!renderTargetContext) {
288 return nullptr;
289 }
290
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400291 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500292 imageSize, imageOrigin, renderTargetContext.get());
Robert Phillipsc25db632017-12-13 09:22:45 -0500293}
294
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400295sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400296 const GrBackendTexture yuvTextures[3],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400297 GrSurfaceOrigin imageOrigin,
Brian Salomon6a426c12018-03-15 12:16:02 -0400298 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400299 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
300 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400301 SkYUVAIndex{0, SkColorChannel::kR},
302 SkYUVAIndex{1, SkColorChannel::kR},
303 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400304 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400305 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400306 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
307 size, imageOrigin, std::move(imageColorSpace));
bsalomon993a4212015-05-29 11:37:25 -0700308}
reed56179002015-07-07 06:11:19 -0700309
Brian Salomond2fcfb52018-09-17 21:57:11 -0400310sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400311 GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
312 GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400313 sk_sp<SkColorSpace> imageColorSpace) {
314 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400315 SkYUVAIndex{0, SkColorChannel::kR},
316 SkYUVAIndex{1, SkColorChannel::kR},
317 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400318 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400319 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400320 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
321 ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400322 std::move(imageColorSpace), nullptr, nullptr);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400323}
324
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400325sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400326 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400327 GrSurfaceOrigin imageOrigin,
brianosmandddbe382016-07-20 13:55:39 -0700328 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400329 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
330 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400331 SkYUVAIndex{0, SkColorChannel::kR},
332 SkYUVAIndex{1, SkColorChannel::kR},
333 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400334 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400335 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400336 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
337 size, imageOrigin, std::move(imageColorSpace));
Robert Phillipsc25db632017-12-13 09:22:45 -0500338}
339
Brian Salomond2fcfb52018-09-17 21:57:11 -0400340sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
341 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400342 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400343 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400344 GrSurfaceOrigin imageOrigin,
345 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400346 sk_sp<SkColorSpace> imageColorSpace,
347 TextureReleaseProc textureReleaseProc,
348 ReleaseContext releaseContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400349 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400350 SkYUVAIndex{0, SkColorChannel::kR},
351 SkYUVAIndex{1, SkColorChannel::kR},
352 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400353 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400354 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400355 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
356 ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400357 std::move(imageColorSpace), textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400358}
359
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400360static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
361 SkAlphaType at, uint32_t id,
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400362 GrMipMapped mipMapped) {
Brian Osman6064e1c2018-10-19 14:27:54 -0400363 sk_sp<GrTextureProxy> proxy(producer->refTextureProxy(mipMapped));
Robert Phillips3798c862017-03-27 11:08:16 -0400364 if (!proxy) {
Brian Osman041f7df2017-02-07 11:23:28 -0500365 return nullptr;
366 }
Brian Salomon729fc0c2019-09-30 16:33:11 +0000367 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, at, std::move(proxy),
368 sk_ref_sp(producer->colorSpace()));
Brian Osman041f7df2017-02-07 11:23:28 -0500369}
370
Brian Osmand566e2e2019-08-14 13:19:04 -0400371sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, GrMipMapped mipMapped) const {
Brian Osman041f7df2017-02-07 11:23:28 -0500372 if (!context) {
373 return nullptr;
374 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500375
376 if (this->isTextureBacked()) {
377 if (!as_IB(this)->context()->priv().matches(context)) {
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400378 return nullptr;
379 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500380
Robert Phillips6603a172019-03-05 12:35:44 -0500381 sk_sp<GrTextureProxy> proxy = as_IB(this)->asTextureProxyRef(context);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400382 SkASSERT(proxy);
383 if (GrMipMapped::kNo == mipMapped || proxy->mipMapped() == mipMapped) {
384 return sk_ref_sp(const_cast<SkImage*>(this));
385 }
Brian Salomon1a217eb2019-10-24 10:50:36 -0400386 GrTextureAdjuster adjuster(context, std::move(proxy), this->imageInfo().colorInfo(),
387 this->uniqueID());
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400388 return create_image_from_producer(context, &adjuster, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400389 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500390 }
391
Brian Osmandf7e0752017-04-26 16:20:28 -0400392 if (this->isLazyGenerated()) {
393 GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400394 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400395 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500396 }
397
398 if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
399 GrBitmapTextureMaker maker(context, *bmp);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400400 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400401 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500402 }
403 return nullptr;
404}
405
Greg Daniel7278d682018-03-16 14:57:21 -0400406///////////////////////////////////////////////////////////////////////////////////////////////////
407
Greg Daniela8d92112018-03-09 12:05:04 -0500408sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
409 const GrBackendFormat& backendFormat,
410 int width,
411 int height,
412 GrMipMapped mipMapped,
413 GrSurfaceOrigin origin,
414 SkColorType colorType,
415 SkAlphaType alphaType,
416 sk_sp<SkColorSpace> colorSpace,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500417 PromiseImageTextureFulfillProc textureFulfillProc,
418 PromiseImageTextureReleaseProc textureReleaseProc,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500419 PromiseImageTextureDoneProc textureDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500420 PromiseImageTextureContext textureContext,
421 PromiseImageApiVersion version) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400422 // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500423 // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
424 // responsibility for calling the done proc.
Brian Salomonf55e8d52019-01-30 17:28:20 -0500425 if (!textureDoneProc) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400426 return nullptr;
427 }
Brian Salomonf55e8d52019-01-30 17:28:20 -0500428 SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
Robert Phillipsef85d192018-10-09 11:24:09 -0400429
Brian Salomonbe5a0932018-12-10 10:03:26 -0500430 SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
431 if (!SkImageInfoIsValid(info)) {
432 return nullptr;
433 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400434
Greg Daniela8d92112018-03-09 12:05:04 -0500435 if (!context) {
436 return nullptr;
437 }
438
439 if (width <= 0 || height <= 0) {
440 return nullptr;
441 }
442
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400443 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
444 colorType,
445 backendFormat);
446 if (GrColorType::kUnknown == grColorType) {
Greg Daniela8d92112018-03-09 12:05:04 -0500447 return nullptr;
448 }
449
Brian Salomonbe5a0932018-12-10 10:03:26 -0500450 callDone.clear();
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400451 auto proxy = MakePromiseImageLazyProxy(context, width, height, origin,
452 grColorType, backendFormat,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500453 mipMapped, textureFulfillProc, textureReleaseProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500454 textureDoneProc, textureContext, version);
Greg Daniela8d92112018-03-09 12:05:04 -0500455 if (!proxy) {
456 return nullptr;
457 }
Brian Salomon729fc0c2019-09-30 16:33:11 +0000458 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, alphaType,
459 std::move(proxy), std::move(colorSpace));
Greg Daniela8d92112018-03-09 12:05:04 -0500460}
461
Greg Daniel7278d682018-03-16 14:57:21 -0400462///////////////////////////////////////////////////////////////////////////////////////////////////
463
Brian Osman584b5012018-04-13 15:48:26 -0400464sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
465 const SkPixmap& originalPixmap, bool buildMips,
Brian Osman584b5012018-04-13 15:48:26 -0400466 bool limitToMaxTextureSize) {
Brian Osman63bc48d2017-11-07 10:37:00 -0500467 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500468 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman584b5012018-04-13 15:48:26 -0400469 return SkImage::MakeRasterCopy(originalPixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500470 }
471
Greg Daniel9e788112018-02-08 14:29:37 -0500472 // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
473 // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
474 // instead.
Robert Phillips9da87e02019-02-04 13:26:26 -0500475 if (!context->priv().resourceProvider()) {
Brian Osman584b5012018-04-13 15:48:26 -0400476 return SkImage::MakeRasterCopy(originalPixmap);
Greg Daniel9e788112018-02-08 14:29:37 -0500477 }
478
Brian Osman0471a932019-02-07 13:36:56 -0500479 // If non-power-of-two mipmapping isn't supported, ignore the client's request
480 if (!context->priv().caps()->mipMapSupport()) {
481 buildMips = false;
482 }
483
Brian Osman584b5012018-04-13 15:48:26 -0400484 const SkPixmap* pixmap = &originalPixmap;
485 SkAutoPixmapStorage resized;
Robert Phillips9da87e02019-02-04 13:26:26 -0500486 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Osman584b5012018-04-13 15:48:26 -0400487 int maxDim = SkTMax(originalPixmap.width(), originalPixmap.height());
488 if (limitToMaxTextureSize && maxDim > maxTextureSize) {
489 float scale = static_cast<float>(maxTextureSize) / maxDim;
490 int newWidth = SkTMin(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
491 int newHeight = SkTMin(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
492 SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
493 if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
494 return nullptr;
495 }
496 pixmap = &resized;
497 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500498 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Osman63bc48d2017-11-07 10:37:00 -0500499 // Turn the pixmap into a GrTextureProxy
Brian Osman7dcc6162019-03-25 10:12:57 -0400500 SkBitmap bmp;
501 bmp.installPixels(*pixmap);
502 GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
503 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
Brian Osman63bc48d2017-11-07 10:37:00 -0500504 if (!proxy) {
Brian Osman584b5012018-04-13 15:48:26 -0400505 return SkImage::MakeRasterCopy(*pixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500506 }
507
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400508 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Brian Osman63bc48d2017-11-07 10:37:00 -0500509
510 // Flush any writes or uploads
Greg Daniel4aa13e72019-04-15 14:42:20 -0400511 context->priv().flushSurface(proxy.get());
Robert Phillips9da87e02019-02-04 13:26:26 -0500512 GrGpu* gpu = context->priv().getGpu();
Brian Osman63bc48d2017-11-07 10:37:00 -0500513
Greg Daniel301015c2019-11-18 14:06:46 -0500514 std::unique_ptr<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman63bc48d2017-11-07 10:37:00 -0500515
516 auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
Brian Osman584b5012018-04-13 15:48:26 -0400517 std::move(sema), pixmap->colorType(),
518 pixmap->alphaType(),
519 pixmap->info().refColorSpace());
Brian Osman63bc48d2017-11-07 10:37:00 -0500520 return SkImage::MakeFromGenerator(std::move(gen));
521}
522
Derek Sollenberger7a869872017-06-27 15:37:25 -0400523#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -0400524sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
Stan Iliev505dd572018-09-13 14:20:03 -0400525 sk_sp<SkColorSpace> cs,
526 GrSurfaceOrigin surfaceOrigin) {
527 auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
Stan Iliev7e910df2017-06-02 10:29:21 -0400528 return SkImage::MakeFromGenerator(std::move(gen));
529}
Greg Danielb6c15ba2019-03-04 13:08:25 -0500530
531sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
532 const SkPixmap& pixmap,
533 AHardwareBuffer* hardwareBuffer,
534 GrSurfaceOrigin surfaceOrigin) {
535 AHardwareBuffer_Desc bufferDesc;
536 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
537
538 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
539 return nullptr;
540 }
541
542 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
543 hardwareBuffer,
544 bufferDesc.format,
545 true);
546
547 if (!backendFormat.isValid()) {
548 return nullptr;
549 }
550
551 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
Stan Ilieva56b04a2019-08-01 14:22:34 -0400552 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
553 GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
Greg Danielb6c15ba2019-03-04 13:08:25 -0500554
555 GrBackendTexture backendTexture =
556 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
557 bufferDesc.width, bufferDesc.height,
Stan Ilieva56b04a2019-08-01 14:22:34 -0400558 &deleteImageProc, &updateImageProc,
559 &deleteImageCtx, false, backendFormat, true);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500560 if (!backendTexture.isValid()) {
561 return nullptr;
562 }
563 SkASSERT(deleteImageProc);
564
565 SkColorType colorType =
566 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
567
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400568 GrColorType grColorType = SkColorTypeToGrColorType(colorType);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500569
570 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
571 if (!proxyProvider) {
572 deleteImageProc(deleteImageCtx);
573 return nullptr;
574 }
575
576 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400577 proxyProvider->wrapBackendTexture(backendTexture, grColorType, surfaceOrigin,
Greg Danielb6c15ba2019-03-04 13:08:25 -0500578 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
579 kRW_GrIOType, deleteImageProc, deleteImageCtx);
580 if (!proxy) {
581 deleteImageProc(deleteImageCtx);
582 return nullptr;
583 }
584
585 sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
586 SkAlphaType at = pixmap.alphaType();
587
Brian Salomon729fc0c2019-09-30 16:33:11 +0000588 sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, at,
589 proxy, cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500590 if (!image) {
591 return nullptr;
592 }
593
594 GrDrawingManager* drawingManager = context->priv().drawingManager();
595 if (!drawingManager) {
596 return nullptr;
597 }
598
Brian Salomonbf6b9792019-08-21 09:38:10 -0400599 auto texContext =
Brian Salomond6287472019-06-24 15:50:07 -0400600 drawingManager->makeTextureContext(proxy, SkColorTypeToGrColorType(pixmap.colorType()),
601 pixmap.alphaType(), cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500602 if (!texContext) {
603 return nullptr;
604 }
605
606 SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
607 std::move(cs));
Brian Salomon1d435302019-07-01 13:05:28 -0400608 texContext->writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), {0, 0});
Greg Danielb6c15ba2019-03-04 13:08:25 -0500609
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400610 GrFlushInfo info;
611 info.fFlags = kSyncCpu_GrFlushFlag;
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400612 GrSurfaceProxy* p[1] = {proxy.get()};
Greg Daniel797efca2019-05-09 14:04:20 -0400613 drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
614 GrPrepareForExternalIORequests());
Greg Danielb6c15ba2019-03-04 13:08:25 -0500615
616 return image;
617}
Stan Iliev7e910df2017-06-02 10:29:21 -0400618#endif
619
reed56179002015-07-07 06:11:19 -0700620///////////////////////////////////////////////////////////////////////////////////////////////////
621
Eric Karl914a36b2017-10-12 12:44:50 -0700622bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
623 sk_sp<SkImage> image,
624 GrBackendTexture* backendTexture,
625 BackendTextureReleaseProc* releaseProc) {
626 if (!image || !ctx || !backendTexture || !releaseProc) {
627 return false;
628 }
629
630 // Ensure we have a texture backed image.
631 if (!image->isTextureBacked()) {
Brian Osmand566e2e2019-08-14 13:19:04 -0400632 image = image->makeTextureImage(ctx);
Eric Karl914a36b2017-10-12 12:44:50 -0700633 if (!image) {
634 return false;
635 }
636 }
637 GrTexture* texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800638 if (!texture) {
639 // In context-loss cases, we may not have a texture.
640 return false;
641 }
Eric Karl914a36b2017-10-12 12:44:50 -0700642
643 // If the image's context doesn't match the provided context, fail.
644 if (texture->getContext() != ctx) {
645 return false;
646 }
647
648 // Flush any pending IO on the texture.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400649 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700650
651 // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
652 // image is not unique, or if the texture wraps an external object.
Robert Phillipsaee18c92019-09-06 11:48:27 -0400653 if (!image->unique() || !texture->unique() ||
Eric Karl914a36b2017-10-12 12:44:50 -0700654 texture->resourcePriv().refsWrappedObjects()) {
655 // onMakeSubset will always copy the image.
Robert Phillips6603a172019-03-05 12:35:44 -0500656 image = as_IB(image)->onMakeSubset(ctx, image->bounds());
Eric Karl914a36b2017-10-12 12:44:50 -0700657 if (!image) {
658 return false;
659 }
660
661 texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800662 if (!texture) {
663 return false;
664 }
Eric Karl914a36b2017-10-12 12:44:50 -0700665
666 // Flush to ensure that the copy is completed before we return the texture.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400667 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700668 }
669
670 SkASSERT(!texture->resourcePriv().refsWrappedObjects());
Robert Phillipsaee18c92019-09-06 11:48:27 -0400671 SkASSERT(texture->unique());
Eric Karl914a36b2017-10-12 12:44:50 -0700672 SkASSERT(image->unique());
673
674 // Take a reference to the GrTexture and release the image.
675 sk_sp<GrTexture> textureRef(SkSafeRef(texture));
676 image = nullptr;
677
678 // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
679 return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
680}