blob: 3abe49ac52cd792f156ba8b011ff4d9e2a8a28bf [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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "include/private/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/private/SkImageInfoPriv.h"
17#include "src/core/SkAutoPixmapStorage.h"
18#include "src/core/SkBitmapCache.h"
19#include "src/core/SkMipMap.h"
20#include "src/core/SkScopeExit.h"
21#include "src/core/SkTraceEvent.h"
22#include "src/gpu/GrAHardwareBufferImageGenerator.h"
23#include "src/gpu/GrAHardwareBufferUtils.h"
24#include "src/gpu/GrBackendTextureImageGenerator.h"
25#include "src/gpu/GrBitmapTextureMaker.h"
26#include "src/gpu/GrCaps.h"
Weston Tracey074414f2020-05-29 12:55:06 +000027#include "src/gpu/GrClip.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/gpu/GrColorSpaceXform.h"
29#include "src/gpu/GrContextPriv.h"
30#include "src/gpu/GrDrawingManager.h"
31#include "src/gpu/GrGpu.h"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040032#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050033#include "src/gpu/GrImageTextureMaker.h"
34#include "src/gpu/GrProxyProvider.h"
35#include "src/gpu/GrRecordingContextPriv.h"
36#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050037#include "src/gpu/GrSemaphore.h"
38#include "src/gpu/GrSurfacePriv.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000039#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050040#include "src/gpu/GrTextureAdjuster.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050041#include "src/gpu/GrTexturePriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040042#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050043#include "src/gpu/GrTextureProxyPriv.h"
44#include "src/gpu/SkGr.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050045#include "src/gpu/gl/GrGLTexture.h"
46#include "src/image/SkImage_Gpu.h"
bsalomon993a4212015-05-29 11:37:25 -070047
Greg Daniel7c165a42020-01-22 12:22:36 -050048SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, GrSurfaceProxyView view,
49 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> colorSpace)
Greg Daniel81b98972019-12-13 11:09:43 -050050 : INHERITED(std::move(context), view.proxy()->backingStoreDimensions(), uniqueID,
Greg Daniel7c165a42020-01-22 12:22:36 -050051 ct, at, colorSpace)
52 , fView(std::move(view)) {
53#ifdef SK_DEBUG
54 const GrBackendFormat& format = fView.proxy()->backendFormat();
55 GrColorType grCT = SkColorTypeToGrColorType(ct);
56 const GrCaps* caps = this->context()->priv().caps();
57 if (caps->isFormatSRGB(format)) {
58 SkASSERT(grCT == GrColorType::kRGBA_8888);
59 grCT = GrColorType::kRGBA_8888_SRGB;
60 }
61 SkASSERT(caps->isFormatCompressed(format) ||
62 caps->areColorTypeAndFormatCompatible(grCT, format));
63#endif
64}
piotaixrcef04f82014-07-14 07:48:04 -070065
Brian Salomon729fc0c2019-09-30 16:33:11 +000066SkImage_Gpu::~SkImage_Gpu() {}
67
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040068GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrContext* context, const GrFlushInfo& info) {
69 if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
Greg Daniel55822f12020-05-26 11:26:45 -040070 if (info.fSubmittedProc) {
71 info.fSubmittedProc(info.fSubmittedContext, false);
72 }
73 if (info.fFinishedProc) {
74 info.fFinishedProc(info.fFinishedContext);
75 }
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040076 return GrSemaphoresSubmitted::kNo;
77 }
78
Greg Daniel81b98972019-12-13 11:09:43 -050079 GrSurfaceProxy* p[1] = {fView.proxy()};
Greg Daniel55f040b2020-02-13 15:38:32 +000080 return context->priv().flushSurfaces(p, 1, info);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040081}
82
Robert Phillips6603a172019-03-05 12:35:44 -050083sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
84 SkColorType targetCT,
Brian Osmanf48c9962019-01-14 11:15:50 -050085 sk_sp<SkColorSpace> targetCS) const {
Robert Phillips6603a172019-03-05 12:35:44 -050086 if (!context || !fContext->priv().matches(context)) {
87 return nullptr;
88 }
89
Brian Salomon5ad6fd32019-03-21 15:30:08 -040090 auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
91 targetCS.get(), this->alphaType());
Brian Osmanf48c9962019-01-14 11:15:50 -050092 SkASSERT(xform || targetCT != this->colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050093
Greg Daniele20fcad2020-01-08 11:52:34 -050094 auto renderTargetContext = GrRenderTargetContext::MakeWithFallback(
95 context, SkColorTypeToGrColorType(targetCT), nullptr, SkBackingFit::kExact,
96 this->dimensions());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050097 if (!renderTargetContext) {
98 return nullptr;
99 }
100
101 GrPaint paint;
102 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
Greg Danield2ccbb52020-02-05 10:45:39 -0500103 paint.addColorFragmentProcessor(GrTextureEffect::Make(*this->view(context), this->alphaType()));
Brian Osmanf48c9962019-01-14 11:15:50 -0500104 if (xform) {
105 paint.addColorFragmentProcessor(std::move(xform));
106 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500107
Weston Tracey074414f2020-05-29 12:55:06 +0000108 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500109 SkRect::MakeIWH(this->width(), this->height()));
110 if (!renderTargetContext->asTextureProxy()) {
111 return nullptr;
112 }
113
Greg Daniel7c165a42020-01-22 12:22:36 -0500114 targetCT = GrColorTypeToSkColorType(renderTargetContext->colorInfo().colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500115 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Greg Daniel7c165a42020-01-22 12:22:36 -0500116 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
117 renderTargetContext->readSurfaceView(), targetCT,
118 this->alphaType(), std::move(targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500119}
120
Brian Osmand5148372019-08-14 16:14:51 -0400121sk_sp<SkImage> SkImage_Gpu::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Greg Daniel7c165a42020-01-22 12:22:36 -0500122 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, fView, this->colorType(),
123 this->alphaType(), std::move(newCS));
Brian Osmand5148372019-08-14 16:14:51 -0400124}
125
reed8b26b992015-05-07 15:36:17 -0700126///////////////////////////////////////////////////////////////////////////////////////////////////
127
Greg Daniel7ef28f32017-04-20 16:41:55 +0000128static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
129 const GrBackendTexture& backendTex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400130 GrColorType colorType, GrSurfaceOrigin origin,
brianosmandddbe382016-07-20 13:55:39 -0700131 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
132 GrWrapOwnership ownership,
reed7fb4f8b2016-03-11 04:33:52 -0800133 SkImage::TextureReleaseProc releaseProc,
134 SkImage::ReleaseContext releaseCtx) {
Greg Daniel66aebf32018-04-09 09:15:56 -0400135 if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700136 return nullptr;
reed8b26b992015-05-07 15:36:17 -0700137 }
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400138
Robert Phillips9da87e02019-02-04 13:26:26 -0500139 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Greg Daniel3a365112020-02-14 10:47:18 -0500140 sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400141 backendTex, ownership, GrWrapCacheable::kNo, kRead_GrIOType, releaseProc, releaseCtx);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500142 if (!proxy) {
Robert Phillipse201ebc2018-01-17 18:12:50 +0000143 return nullptr;
144 }
Greg Daniel81b98972019-12-13 11:09:43 -0500145
Greg Daniel14b57212019-12-17 16:18:06 -0500146 GrSwizzle swizzle = ctx->priv().caps()->getReadSwizzle(proxy->backendFormat(), colorType);
Greg Daniel81b98972019-12-13 11:09:43 -0500147 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
Greg Daniel7c165a42020-01-22 12:22:36 -0500148 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, std::move(view),
149 GrColorTypeToSkColorType(colorType), at, std::move(colorSpace));
bsalomon6dc6f5f2015-06-18 09:12:16 -0700150}
151
Robert Phillipsb915c942019-12-17 14:44:37 -0500152sk_sp<SkImage> SkImage::MakeFromCompressedTexture(GrContext* ctx,
153 const GrBackendTexture& tex,
154 GrSurfaceOrigin origin,
155 SkAlphaType at,
156 sk_sp<SkColorSpace> cs,
157 TextureReleaseProc releaseP,
158 ReleaseContext releaseC) {
Robert Phillipsead321b2019-12-19 10:16:32 -0500159 if (!ctx) {
160 return nullptr;
161 }
162
163 const GrCaps* caps = ctx->priv().caps();
164
165 if (!SkImage_GpuBase::ValidateCompressedBackendTexture(caps, tex, at)) {
166 return nullptr;
167 }
168
169 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Greg Daniel3a365112020-02-14 10:47:18 -0500170 sk_sp<GrTextureProxy> proxy = proxyProvider->wrapCompressedBackendTexture(
171 tex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseP, releaseC);
Robert Phillipsead321b2019-12-19 10:16:32 -0500172 if (!proxy) {
173 return nullptr;
174 }
175
Greg Daniel7c165a42020-01-22 12:22:36 -0500176 CompressionType type = caps->compressionType(tex.getBackendFormat());
177 SkColorType ct = GrCompressionTypeToSkColorType(type);
178
Robert Phillipsead321b2019-12-19 10:16:32 -0500179 GrSurfaceProxyView view(std::move(proxy), origin, GrSwizzle::RGBA());
Greg Daniel7c165a42020-01-22 12:22:36 -0500180 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, std::move(view), ct, at,
Robert Phillipsead321b2019-12-19 10:16:32 -0500181 std::move(cs));
Robert Phillipsb915c942019-12-17 14:44:37 -0500182}
183
Greg Danielf5d87582017-12-18 14:48:15 -0500184sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
185 const GrBackendTexture& tex, GrSurfaceOrigin origin,
186 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
187 TextureReleaseProc releaseP, ReleaseContext releaseC) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500188 if (!ctx) {
189 return nullptr;
190 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400191
Robert Phillips62221e72019-07-24 15:07:38 -0400192 const GrCaps* caps = ctx->priv().caps();
193
194 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400195 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400196 return nullptr;
197 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400198
Robert Phillips62221e72019-07-24 15:07:38 -0400199 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400200 return nullptr;
201 }
202
Robert Phillips62221e72019-07-24 15:07:38 -0400203 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomonbfd27492018-03-19 14:08:51 -0400204 kBorrow_GrWrapOwnership, releaseP, releaseC);
Greg Danielf5d87582017-12-18 14:48:15 -0500205}
206
Greg Daniel94403452017-04-18 15:52:36 -0400207sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
208 const GrBackendTexture& tex, GrSurfaceOrigin origin,
Brian Salomon42409c22018-03-20 13:48:41 -0400209 SkColorType ct, SkAlphaType at,
210 sk_sp<SkColorSpace> cs) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500211 if (!ctx || !ctx->priv().resourceProvider()) {
Greg Danielf2336e42018-01-23 16:38:14 -0500212 // We have a DDL context and we don't support adopted textures for them.
213 return nullptr;
214 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400215
Robert Phillips62221e72019-07-24 15:07:38 -0400216 const GrCaps* caps = ctx->priv().caps();
217
218 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400219 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400220 return nullptr;
221 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400222
Robert Phillips62221e72019-07-24 15:07:38 -0400223 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400224 return nullptr;
225 }
226
Robert Phillips62221e72019-07-24 15:07:38 -0400227 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomon42409c22018-03-20 13:48:41 -0400228 kAdopt_GrWrapOwnership, nullptr, nullptr);
Greg Danielf5d87582017-12-18 14:48:15 -0500229}
230
Robert Phillips45c94872020-01-28 15:59:31 -0500231sk_sp<SkImage> SkImage::MakeTextureFromCompressed(GrContext* context, sk_sp<SkData> data,
232 int width, int height, CompressionType type,
233 GrMipMapped mipMapped,
234 GrProtected isProtected) {
Robert Phillips99dead92020-01-27 16:11:57 -0500235 if (!context || !data) {
236 return nullptr;
237 }
238
239 GrBackendFormat beFormat = context->compressedBackendFormat(type);
240 if (!beFormat.isValid()) {
241 sk_sp<SkImage> tmp = MakeRasterFromCompressed(std::move(data), width, height, type);
242 if (!tmp) {
243 return nullptr;
244 }
245 return tmp->makeTextureImage(context, mipMapped);
246 }
247
Robert Phillips9da87e02019-02-04 13:26:26 -0500248 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Salomonbb8dde82019-06-27 10:52:13 -0400249 sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
Robert Phillips3a833922020-01-21 15:25:58 -0500250 {width, height}, SkBudgeted::kYes, mipMapped, isProtected, type, std::move(data));
Jim Van Verthee06b332019-01-18 10:36:32 -0500251 if (!proxy) {
252 return nullptr;
253 }
Greg Daniel81b98972019-12-13 11:09:43 -0500254 GrSurfaceProxyView view(std::move(proxy));
Brian Salomon729fc0c2019-09-30 16:33:11 +0000255
Greg Daniel7c165a42020-01-22 12:22:36 -0500256 SkColorType colorType = GrCompressionTypeToSkColorType(type);
257
258 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, std::move(view),
259 colorType, kOpaque_SkAlphaType, nullptr);
Jim Van Verthee06b332019-01-18 10:36:32 -0500260}
261
Brian Salomonf05e6d32018-12-20 08:41:41 -0500262sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
263 const GrBackendTexture yuvaTextures[],
264 const SkYUVAIndex yuvaIndices[4], SkISize size,
265 GrSurfaceOrigin origin,
266 GrRenderTargetContext* renderTargetContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400267 SkASSERT(renderTargetContext);
268
Jim Van Verth0e671942018-11-09 12:03:57 -0500269 int numTextures;
270 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500271 return nullptr;
272 }
Robert Phillipsba5c4392018-07-25 12:37:14 -0400273
Greg Danielc7672092020-02-06 14:32:54 -0500274 GrSurfaceProxyView tempViews[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500275 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
Greg Danielc7672092020-02-06 14:32:54 -0500276 origin, tempViews)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500277 return nullptr;
278 }
279
280 const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
Brian Osmane9560492019-02-05 17:00:03 -0500281 if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
Greg Danielc7672092020-02-06 14:32:54 -0500282 tempViews, yuvaIndices)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500283 return nullptr;
284 }
Robert Phillipsb726d582017-03-09 16:36:32 -0500285
Greg Daniel7c165a42020-01-22 12:22:36 -0500286 SkColorType ct = GrColorTypeToSkColorType(renderTargetContext->colorInfo().colorType());
Jim Van Verth53275362018-11-09 15:42:35 -0500287 SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillipsb726d582017-03-09 16:36:32 -0500288 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Greg Daniel7c165a42020-01-22 12:22:36 -0500289 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID,
290 renderTargetContext->readSurfaceView(), ct, at,
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400291 renderTargetContext->colorInfo().refColorSpace());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400292}
293
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400294sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
295 SkYUVColorSpace yuvColorSpace,
296 const GrBackendTexture yuvaTextures[],
297 const SkYUVAIndex yuvaIndices[4],
298 SkISize imageSize,
299 GrSurfaceOrigin imageOrigin,
300 sk_sp<SkColorSpace> imageColorSpace) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500301 auto renderTargetContext = GrRenderTargetContext::Make(
302 ctx, GrColorType::kRGBA_8888, std::move(imageColorSpace), SkBackingFit::kExact,
303 imageSize, 1, GrMipMapped::kNo, GrProtected::kNo, imageOrigin);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400304 if (!renderTargetContext) {
305 return nullptr;
306 }
307
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400308 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500309 imageSize, imageOrigin, renderTargetContext.get());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400310}
311
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400312sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
Brian Salomond2fcfb52018-09-17 21:57:11 -0400313 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400314 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400315 const GrBackendTexture yuvaTextures[],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400316 const SkYUVAIndex yuvaIndices[4],
317 SkISize imageSize,
318 GrSurfaceOrigin imageOrigin,
319 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400320 sk_sp<SkColorSpace> imageColorSpace,
321 TextureReleaseProc textureReleaseProc,
322 ReleaseContext releaseContext) {
Robert Phillips62221e72019-07-24 15:07:38 -0400323 const GrCaps* caps = ctx->priv().caps();
Robert Phillipsdd399802019-07-18 12:28:00 +0000324
Robert Phillips62221e72019-07-24 15:07:38 -0400325 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, kRGBA_8888_SkColorType,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400326 backendTexture.getBackendFormat());
327 if (GrColorType::kUnknown == grColorType) {
328 return nullptr;
329 }
330
Jim Van Verth53275362018-11-09 15:42:35 -0500331 SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillips62221e72019-07-24 15:07:38 -0400332 if (!SkImage_Gpu::ValidateBackendTexture(caps, backendTexture, grColorType,
333 kRGBA_8888_SkColorType, at, nullptr)) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400334 return nullptr;
335 }
336
337 // Needs to create a render target with external texture
338 // in order to draw to it for the yuv->rgb conversion.
Greg Danielba0ff782020-01-07 15:42:57 -0500339 auto renderTargetContext = GrRenderTargetContext::MakeFromBackendTexture(
340 ctx, grColorType, std::move(imageColorSpace), backendTexture, 1, imageOrigin,
341 nullptr, textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400342 if (!renderTargetContext) {
343 return nullptr;
344 }
345
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400346 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500347 imageSize, imageOrigin, renderTargetContext.get());
Robert Phillipsc25db632017-12-13 09:22:45 -0500348}
349
Brian Salomonc505a452020-04-06 10:29:02 -0400350// Some YUVA factories infer the YUVAIndices. This helper identifies the channel to use for single
351// channel textures.
352static SkColorChannel get_single_channel(const GrBackendTexture& tex) {
353 switch (tex.getBackendFormat().channelMask()) {
354 case kGray_SkColorChannelFlag: // Gray can be read as any of kR, kG, kB.
355 case kRed_SkColorChannelFlag:
356 return SkColorChannel::kR;
357 case kAlpha_SkColorChannelFlag:
358 return SkColorChannel::kA;
359 default: // multiple channels in the texture. Guess kR.
360 return SkColorChannel::kR;
361 }
362}
363
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400364sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400365 const GrBackendTexture yuvTextures[3],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400366 GrSurfaceOrigin imageOrigin,
Brian Salomon6a426c12018-03-15 12:16:02 -0400367 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400368 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
369 SkYUVAIndex yuvaIndices[4] = {
Brian Salomonc505a452020-04-06 10:29:02 -0400370 SkYUVAIndex{0, get_single_channel(yuvTextures[0])},
371 SkYUVAIndex{1, get_single_channel(yuvTextures[1])},
372 SkYUVAIndex{2, get_single_channel(yuvTextures[2])},
Robert Phillips66a97342018-10-04 09:10:29 -0400373 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400374 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400375 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
376 size, imageOrigin, std::move(imageColorSpace));
bsalomon993a4212015-05-29 11:37:25 -0700377}
reed56179002015-07-07 06:11:19 -0700378
Brian Salomond2fcfb52018-09-17 21:57:11 -0400379sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400380 GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
381 GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400382 sk_sp<SkColorSpace> imageColorSpace) {
383 SkYUVAIndex yuvaIndices[4] = {
Brian Salomonc505a452020-04-06 10:29:02 -0400384 SkYUVAIndex{0, get_single_channel(yuvTextures[0])},
385 SkYUVAIndex{1, get_single_channel(yuvTextures[1])},
386 SkYUVAIndex{2, get_single_channel(yuvTextures[2])},
Robert Phillips66a97342018-10-04 09:10:29 -0400387 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400388 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400389 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
390 ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400391 std::move(imageColorSpace), nullptr, nullptr);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400392}
393
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400394sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400395 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400396 GrSurfaceOrigin imageOrigin,
brianosmandddbe382016-07-20 13:55:39 -0700397 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400398 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
399 SkYUVAIndex yuvaIndices[4] = {
Brian Salomonc505a452020-04-06 10:29:02 -0400400 SkYUVAIndex{0, get_single_channel(nv12Textures[0])},
Robert Phillips94ade752018-10-09 12:32:31 -0400401 SkYUVAIndex{1, SkColorChannel::kR},
402 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400403 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400404 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400405 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
406 size, imageOrigin, std::move(imageColorSpace));
Robert Phillipsc25db632017-12-13 09:22:45 -0500407}
408
Brian Salomond2fcfb52018-09-17 21:57:11 -0400409sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
410 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400411 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400412 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400413 GrSurfaceOrigin imageOrigin,
414 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400415 sk_sp<SkColorSpace> imageColorSpace,
416 TextureReleaseProc textureReleaseProc,
417 ReleaseContext releaseContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400418 SkYUVAIndex yuvaIndices[4] = {
Brian Salomonc505a452020-04-06 10:29:02 -0400419 SkYUVAIndex{0, get_single_channel(nv12Textures[0])},
Robert Phillips94ade752018-10-09 12:32:31 -0400420 SkYUVAIndex{1, SkColorChannel::kR},
421 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400422 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400423 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400424 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
425 ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400426 std::move(imageColorSpace), textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400427}
428
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400429static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
Greg Daniel7c165a42020-01-22 12:22:36 -0500430 uint32_t id, GrMipMapped mipMapped) {
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500431 auto view = producer->view(mipMapped);
432 if (!view) {
Brian Osman041f7df2017-02-07 11:23:28 -0500433 return nullptr;
434 }
Greg Daniel7c165a42020-01-22 12:22:36 -0500435 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, std::move(view),
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500436 GrColorTypeToSkColorType(producer->colorType()),
Greg Daniel7c165a42020-01-22 12:22:36 -0500437 producer->alphaType(), sk_ref_sp(producer->colorSpace()));
Brian Osman041f7df2017-02-07 11:23:28 -0500438}
439
Brian Salomonbc074a62020-03-18 10:06:13 -0400440sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context,
441 GrMipMapped mipMapped,
442 SkBudgeted budgeted) const {
Brian Osman041f7df2017-02-07 11:23:28 -0500443 if (!context) {
444 return nullptr;
445 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500446
447 if (this->isTextureBacked()) {
448 if (!as_IB(this)->context()->priv().matches(context)) {
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400449 return nullptr;
450 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500451
Brian Salomonbc074a62020-03-18 10:06:13 -0400452 // TODO: Don't flatten YUVA images here.
Greg Daniel37c127f2020-02-05 10:37:27 -0500453 const GrSurfaceProxyView* view = as_IB(this)->view(context);
454 SkASSERT(view && view->asTextureProxy());
Brian Salomonbc074a62020-03-18 10:06:13 -0400455
456 if (mipMapped == GrMipMapped::kNo || view->asTextureProxy()->mipMapped() == mipMapped ||
457 !context->priv().caps()->mipMapSupport()) {
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400458 return sk_ref_sp(const_cast<SkImage*>(this));
459 }
Brian Salomonc5243782020-04-02 12:50:34 -0400460 auto copy = GrCopyBaseMipMapToView(context->priv().asRecordingContext(), *view, budgeted);
Brian Salomonbc074a62020-03-18 10:06:13 -0400461 if (!copy) {
462 return nullptr;
463 }
Brian Salomonc5243782020-04-02 12:50:34 -0400464 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), this->uniqueID(), copy,
Brian Salomonbc074a62020-03-18 10:06:13 -0400465 this->colorType(), this->alphaType(), this->refColorSpace());
Brian Osman041f7df2017-02-07 11:23:28 -0500466 }
467
Brian Salomonbc074a62020-03-18 10:06:13 -0400468 auto policy = budgeted == SkBudgeted::kYes ? GrImageTexGenPolicy::kNew_Uncached_Budgeted
469 : GrImageTexGenPolicy::kNew_Uncached_Unbudgeted;
Brian Osmandf7e0752017-04-26 16:20:28 -0400470 if (this->isLazyGenerated()) {
Brian Salomonbc074a62020-03-18 10:06:13 -0400471 GrImageTextureMaker maker(context, this, policy);
Greg Daniel7c165a42020-01-22 12:22:36 -0500472 return create_image_from_producer(context, &maker, this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500473 }
474
475 if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
Brian Salomonbc074a62020-03-18 10:06:13 -0400476 GrBitmapTextureMaker maker(context, *bmp, policy);
Greg Daniel7c165a42020-01-22 12:22:36 -0500477 return create_image_from_producer(context, &maker, this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500478 }
479 return nullptr;
480}
481
Greg Daniel7278d682018-03-16 14:57:21 -0400482///////////////////////////////////////////////////////////////////////////////////////////////////
483
Greg Daniela8d92112018-03-09 12:05:04 -0500484sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
485 const GrBackendFormat& backendFormat,
486 int width,
487 int height,
488 GrMipMapped mipMapped,
489 GrSurfaceOrigin origin,
490 SkColorType colorType,
491 SkAlphaType alphaType,
492 sk_sp<SkColorSpace> colorSpace,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500493 PromiseImageTextureFulfillProc textureFulfillProc,
494 PromiseImageTextureReleaseProc textureReleaseProc,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500495 PromiseImageTextureDoneProc textureDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500496 PromiseImageTextureContext textureContext,
497 PromiseImageApiVersion version) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400498 // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500499 // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
500 // responsibility for calling the done proc.
Brian Salomonf55e8d52019-01-30 17:28:20 -0500501 if (!textureDoneProc) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400502 return nullptr;
503 }
Brian Salomonf55e8d52019-01-30 17:28:20 -0500504 SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
Robert Phillipsef85d192018-10-09 11:24:09 -0400505
Brian Salomonbe5a0932018-12-10 10:03:26 -0500506 SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
507 if (!SkImageInfoIsValid(info)) {
508 return nullptr;
509 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400510
Greg Daniela8d92112018-03-09 12:05:04 -0500511 if (!context) {
512 return nullptr;
513 }
514
515 if (width <= 0 || height <= 0) {
516 return nullptr;
517 }
518
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400519 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
520 colorType,
521 backendFormat);
522 if (GrColorType::kUnknown == grColorType) {
Greg Daniela8d92112018-03-09 12:05:04 -0500523 return nullptr;
524 }
525
Brian Salomonbe5a0932018-12-10 10:03:26 -0500526 callDone.clear();
Brian Salomonc3ce54a2020-04-01 16:52:37 -0400527 auto proxy = MakePromiseImageLazyProxy(context, width, height, backendFormat,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500528 mipMapped, textureFulfillProc, textureReleaseProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500529 textureDoneProc, textureContext, version);
Greg Daniela8d92112018-03-09 12:05:04 -0500530 if (!proxy) {
531 return nullptr;
532 }
Greg Daniel14b57212019-12-17 16:18:06 -0500533 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
Greg Daniel81b98972019-12-13 11:09:43 -0500534 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
Greg Daniel7c165a42020-01-22 12:22:36 -0500535 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, std::move(view),
536 colorType, alphaType, std::move(colorSpace));
Greg Daniela8d92112018-03-09 12:05:04 -0500537}
538
Greg Daniel7278d682018-03-16 14:57:21 -0400539///////////////////////////////////////////////////////////////////////////////////////////////////
540
Brian Osman584b5012018-04-13 15:48:26 -0400541sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
542 const SkPixmap& originalPixmap, bool buildMips,
Brian Osman584b5012018-04-13 15:48:26 -0400543 bool limitToMaxTextureSize) {
Brian Osman63bc48d2017-11-07 10:37:00 -0500544 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500545 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman584b5012018-04-13 15:48:26 -0400546 return SkImage::MakeRasterCopy(originalPixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500547 }
548
Greg Daniel9e788112018-02-08 14:29:37 -0500549 // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
550 // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
551 // instead.
Robert Phillips9da87e02019-02-04 13:26:26 -0500552 if (!context->priv().resourceProvider()) {
Brian Osman584b5012018-04-13 15:48:26 -0400553 return SkImage::MakeRasterCopy(originalPixmap);
Greg Daniel9e788112018-02-08 14:29:37 -0500554 }
555
Brian Osman0471a932019-02-07 13:36:56 -0500556 // If non-power-of-two mipmapping isn't supported, ignore the client's request
557 if (!context->priv().caps()->mipMapSupport()) {
558 buildMips = false;
559 }
560
Brian Osman584b5012018-04-13 15:48:26 -0400561 const SkPixmap* pixmap = &originalPixmap;
562 SkAutoPixmapStorage resized;
Robert Phillips9da87e02019-02-04 13:26:26 -0500563 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Osman788b9162020-02-07 10:36:46 -0500564 int maxDim = std::max(originalPixmap.width(), originalPixmap.height());
Brian Osman584b5012018-04-13 15:48:26 -0400565 if (limitToMaxTextureSize && maxDim > maxTextureSize) {
566 float scale = static_cast<float>(maxTextureSize) / maxDim;
Brian Osman788b9162020-02-07 10:36:46 -0500567 int newWidth = std::min(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
568 int newHeight = std::min(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
Brian Osman584b5012018-04-13 15:48:26 -0400569 SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
570 if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
571 return nullptr;
572 }
573 pixmap = &resized;
574 }
Brian Osman63bc48d2017-11-07 10:37:00 -0500575 // Turn the pixmap into a GrTextureProxy
Brian Osman7dcc6162019-03-25 10:12:57 -0400576 SkBitmap bmp;
577 bmp.installPixels(*pixmap);
Brian Salomonbc074a62020-03-18 10:06:13 -0400578 GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
Brian Osman7dcc6162019-03-25 10:12:57 -0400579 GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500580 auto view = bitmapMaker.view(mipMapped);
581 if (!view) {
Brian Osman584b5012018-04-13 15:48:26 -0400582 return SkImage::MakeRasterCopy(*pixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500583 }
584
Greg Danielcc104db2020-02-03 14:17:08 -0500585 sk_sp<GrTexture> texture = sk_ref_sp(view.proxy()->peekTexture());
Brian Osman63bc48d2017-11-07 10:37:00 -0500586
587 // Flush any writes or uploads
Greg Daniel55f040b2020-02-13 15:38:32 +0000588 context->priv().flushSurface(view.proxy());
Robert Phillips9da87e02019-02-04 13:26:26 -0500589 GrGpu* gpu = context->priv().getGpu();
Brian Osman63bc48d2017-11-07 10:37:00 -0500590
Greg Daniel301015c2019-11-18 14:06:46 -0500591 std::unique_ptr<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman63bc48d2017-11-07 10:37:00 -0500592
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500593 SkColorType skCT = GrColorTypeToSkColorType(bitmapMaker.colorType());
Greg Danielcc104db2020-02-03 14:17:08 -0500594 auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), view.origin(),
Greg Daniel82c6b102020-01-21 10:33:22 -0500595 std::move(sema), skCT,
Brian Osman584b5012018-04-13 15:48:26 -0400596 pixmap->alphaType(),
597 pixmap->info().refColorSpace());
Brian Osman63bc48d2017-11-07 10:37:00 -0500598 return SkImage::MakeFromGenerator(std::move(gen));
599}
600
Derek Sollenberger7a869872017-06-27 15:37:25 -0400601#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -0400602sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
Stan Iliev505dd572018-09-13 14:20:03 -0400603 sk_sp<SkColorSpace> cs,
604 GrSurfaceOrigin surfaceOrigin) {
605 auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
Stan Iliev7e910df2017-06-02 10:29:21 -0400606 return SkImage::MakeFromGenerator(std::move(gen));
607}
Greg Danielb6c15ba2019-03-04 13:08:25 -0500608
609sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
610 const SkPixmap& pixmap,
611 AHardwareBuffer* hardwareBuffer,
612 GrSurfaceOrigin surfaceOrigin) {
613 AHardwareBuffer_Desc bufferDesc;
614 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
615
616 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
617 return nullptr;
618 }
619
620 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
621 hardwareBuffer,
622 bufferDesc.format,
623 true);
624
625 if (!backendFormat.isValid()) {
626 return nullptr;
627 }
628
629 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
Stan Ilieva56b04a2019-08-01 14:22:34 -0400630 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
631 GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
Greg Danielb6c15ba2019-03-04 13:08:25 -0500632
633 GrBackendTexture backendTexture =
634 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
635 bufferDesc.width, bufferDesc.height,
Stan Ilieva56b04a2019-08-01 14:22:34 -0400636 &deleteImageProc, &updateImageProc,
637 &deleteImageCtx, false, backendFormat, true);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500638 if (!backendTexture.isValid()) {
639 return nullptr;
640 }
641 SkASSERT(deleteImageProc);
642
643 SkColorType colorType =
644 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
645
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400646 GrColorType grColorType = SkColorTypeToGrColorType(colorType);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500647
648 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
649 if (!proxyProvider) {
650 deleteImageProc(deleteImageCtx);
651 return nullptr;
652 }
653
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400654 sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
655 backendTexture, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType,
656 deleteImageProc, deleteImageCtx);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500657 if (!proxy) {
658 deleteImageProc(deleteImageCtx);
659 return nullptr;
660 }
661
662 sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
663 SkAlphaType at = pixmap.alphaType();
664
Greg Daniel14b57212019-12-17 16:18:06 -0500665 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
Greg Daniel3912a4b2020-01-14 09:56:04 -0500666 GrSurfaceProxyView view(std::move(proxy), surfaceOrigin, swizzle);
Greg Daniel7c165a42020-01-22 12:22:36 -0500667 sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, view,
668 colorType, at, cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500669 if (!image) {
670 return nullptr;
671 }
672
673 GrDrawingManager* drawingManager = context->priv().drawingManager();
674 if (!drawingManager) {
675 return nullptr;
676 }
677
Greg Daniel3912a4b2020-01-14 09:56:04 -0500678 GrSurfaceContext surfaceContext(context, std::move(view),
Greg Danielbfa19c42019-12-19 16:41:40 -0500679 SkColorTypeToGrColorType(pixmap.colorType()),
Greg Daniel3912a4b2020-01-14 09:56:04 -0500680 pixmap.alphaType(), cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500681
682 SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
683 std::move(cs));
Greg Danielbfa19c42019-12-19 16:41:40 -0500684 surfaceContext.writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), {0, 0});
Greg Danielb6c15ba2019-03-04 13:08:25 -0500685
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400686 GrFlushInfo info;
687 info.fFlags = kSyncCpu_GrFlushFlag;
Greg Danielbfa19c42019-12-19 16:41:40 -0500688 GrSurfaceProxy* p[1] = {surfaceContext.asSurfaceProxy()};
Greg Daniel797efca2019-05-09 14:04:20 -0400689 drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
690 GrPrepareForExternalIORequests());
Greg Danielb6c15ba2019-03-04 13:08:25 -0500691
692 return image;
693}
Stan Iliev7e910df2017-06-02 10:29:21 -0400694#endif
695
reed56179002015-07-07 06:11:19 -0700696///////////////////////////////////////////////////////////////////////////////////////////////////
697
Eric Karl914a36b2017-10-12 12:44:50 -0700698bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
699 sk_sp<SkImage> image,
700 GrBackendTexture* backendTexture,
701 BackendTextureReleaseProc* releaseProc) {
702 if (!image || !ctx || !backendTexture || !releaseProc) {
703 return false;
704 }
705
706 // Ensure we have a texture backed image.
707 if (!image->isTextureBacked()) {
Brian Osmand566e2e2019-08-14 13:19:04 -0400708 image = image->makeTextureImage(ctx);
Eric Karl914a36b2017-10-12 12:44:50 -0700709 if (!image) {
710 return false;
711 }
712 }
Greg Daniel7c902112020-03-06 13:07:10 -0500713 SkImage_GpuBase* gpuImage = static_cast<SkImage_GpuBase*>(as_IB(image));
714 GrTexture* texture = gpuImage->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800715 if (!texture) {
716 // In context-loss cases, we may not have a texture.
717 return false;
718 }
Eric Karl914a36b2017-10-12 12:44:50 -0700719
720 // If the image's context doesn't match the provided context, fail.
721 if (texture->getContext() != ctx) {
722 return false;
723 }
724
725 // Flush any pending IO on the texture.
Greg Daniel55f040b2020-02-13 15:38:32 +0000726 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700727
728 // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
729 // image is not unique, or if the texture wraps an external object.
Robert Phillipsaee18c92019-09-06 11:48:27 -0400730 if (!image->unique() || !texture->unique() ||
Eric Karl914a36b2017-10-12 12:44:50 -0700731 texture->resourcePriv().refsWrappedObjects()) {
732 // onMakeSubset will always copy the image.
Robert Phillips6603a172019-03-05 12:35:44 -0500733 image = as_IB(image)->onMakeSubset(ctx, image->bounds());
Eric Karl914a36b2017-10-12 12:44:50 -0700734 if (!image) {
735 return false;
736 }
737
Greg Daniel7c902112020-03-06 13:07:10 -0500738 texture = gpuImage->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800739 if (!texture) {
740 return false;
741 }
Eric Karl914a36b2017-10-12 12:44:50 -0700742
743 // Flush to ensure that the copy is completed before we return the texture.
Greg Daniel55f040b2020-02-13 15:38:32 +0000744 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700745 }
746
747 SkASSERT(!texture->resourcePriv().refsWrappedObjects());
Robert Phillipsaee18c92019-09-06 11:48:27 -0400748 SkASSERT(texture->unique());
Eric Karl914a36b2017-10-12 12:44:50 -0700749 SkASSERT(image->unique());
750
751 // Take a reference to the GrTexture and release the image.
752 sk_sp<GrTexture> textureRef(SkSafeRef(texture));
753 image = nullptr;
754
755 // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
756 return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
757}