blob: 1c670135154e6b803692b3682c2e412ea6020ce1 [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
Brian Salomon7226c232018-07-30 13:13:17 -040012#include "GrAHardwareBufferImageGenerator.h"
Greg Danielb6c15ba2019-03-04 13:08:25 -050013#include "GrAHardwareBufferUtils.h"
Greg Daniel7ef28f32017-04-20 16:41:55 +000014#include "GrBackendSurface.h"
Brian Osman13dddce2017-05-09 13:19:50 -040015#include "GrBackendTextureImageGenerator.h"
Brian Osman3b66ab62016-11-28 09:26:31 -050016#include "GrBitmapTextureMaker.h"
reed856e9d92015-09-30 12:21:45 -070017#include "GrCaps.h"
Robert Phillips79730ac2018-09-25 10:40:04 -040018#include "GrClip.h"
Brian Osman47c27512018-06-18 10:58:51 -040019#include "GrColorSpaceXform.h"
robertphillips@google.com97b6b072012-10-31 14:48:39 +000020#include "GrContext.h"
Robert Phillipse2f7d182016-12-15 09:23:05 -050021#include "GrContextPriv.h"
Greg Danielb6c15ba2019-03-04 13:08:25 -050022#include "GrDrawingManager.h"
Brian Osman2c2bc112017-02-28 10:02:49 -050023#include "GrGpu.h"
Brian Osman3b66ab62016-11-28 09:26:31 -050024#include "GrImageTextureMaker.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050025#include "GrProxyProvider.h"
Robert Phillips6603a172019-03-05 12:35:44 -050026#include "GrRecordingContext.h"
27#include "GrRecordingContextPriv.h"
Brian Osman11052242016-10-27 14:47:55 -040028#include "GrRenderTargetContext.h"
Brian Osman32342f02017-03-04 08:12:46 -050029#include "GrResourceProvider.h"
Robert Phillips79730ac2018-09-25 10:40:04 -040030#include "GrResourceProviderPriv.h"
Brian Osmanfe3b5162017-03-02 15:09:20 -050031#include "GrSemaphore.h"
Eric Karl914a36b2017-10-12 12:44:50 -070032#include "GrSurfacePriv.h"
Robert Phillips646e4292017-06-13 12:44:56 -040033#include "GrTexture.h"
Brian Salomon7226c232018-07-30 13:13:17 -040034#include "GrTextureAdjuster.h"
Greg Danielb6c15ba2019-03-04 13:08:25 -050035#include "GrTextureContext.h"
Eric Karl914a36b2017-10-12 12:44:50 -070036#include "GrTexturePriv.h"
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -050037#include "GrTextureProxy.h"
Greg Daniele3204862018-04-16 11:24:10 -040038#include "GrTextureProxyPriv.h"
Brian Salomon7226c232018-07-30 13:13:17 -040039#include "SkAutoPixmapStorage.h"
reed262a71b2015-12-05 13:07:27 -080040#include "SkBitmapCache.h"
Brian Salomon7226c232018-07-30 13:13:17 -040041#include "SkCanvas.h"
Brian Osman3b655982017-03-07 16:58:08 -050042#include "SkGr.h"
Matt Sarettcb6266b2017-01-17 10:48:53 -050043#include "SkImageInfoPriv.h"
Brian Salomon7226c232018-07-30 13:13:17 -040044#include "SkImage_Gpu.h"
ericrkb4da01d2016-06-13 11:18:14 -070045#include "SkMipMap.h"
Brian Salomonbe5a0932018-12-10 10:03:26 -050046#include "SkScopeExit.h"
Greg Danielbc54fad2018-02-09 16:40:32 -050047#include "SkTraceEvent.h"
Brian Salomon7226c232018-07-30 13:13:17 -040048#include "effects/GrYUVtoRGBEffect.h"
49#include "gl/GrGLTexture.h"
bsalomon993a4212015-05-29 11:37:25 -070050
Brian Salomon5ad6fd32019-03-21 15:30:08 -040051static SkColorType proxy_color_type(GrTextureProxy* proxy) {
52 SkColorType colorType;
53 if (!GrPixelConfigToColorType(proxy->config(), &colorType)) {
54 colorType = kUnknown_SkColorType;
55 }
56 return colorType;
57}
58
Brian Salomon8a8dd332018-05-24 14:08:31 -040059SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, SkAlphaType at,
Brian Salomonf05e6d32018-12-20 08:41:41 -050060 sk_sp<GrTextureProxy> proxy, sk_sp<SkColorSpace> colorSpace)
Jim Van Verth8026ccc2018-10-04 13:10:39 -040061 : INHERITED(std::move(context), proxy->worstCaseWidth(), proxy->worstCaseHeight(), uniqueID,
Brian Salomon5ad6fd32019-03-21 15:30:08 -040062 proxy_color_type(proxy.get()), at, colorSpace)
Jim Van Verth8026ccc2018-10-04 13:10:39 -040063 , fProxy(std::move(proxy)) {}
piotaixrcef04f82014-07-14 07:48:04 -070064
Mike Reed30301c42018-07-19 09:39:21 -040065SkImage_Gpu::~SkImage_Gpu() {}
reed6f1216a2015-08-04 08:10:13 -070066
Robert Phillips6603a172019-03-05 12:35:44 -050067sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
68 SkColorType targetCT,
Brian Osmanf48c9962019-01-14 11:15:50 -050069 sk_sp<SkColorSpace> targetCS) const {
Robert Phillips6603a172019-03-05 12:35:44 -050070 if (!context || !fContext->priv().matches(context)) {
71 return nullptr;
72 }
73
Brian Salomon5ad6fd32019-03-21 15:30:08 -040074 auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
75 targetCS.get(), this->alphaType());
Brian Osmanf48c9962019-01-14 11:15:50 -050076 SkASSERT(xform || targetCT != this->colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050077
Robert Phillips6603a172019-03-05 12:35:44 -050078 sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050079
80 GrBackendFormat format = proxy->backendFormat().makeTexture2D();
81 if (!format.isValid()) {
82 return nullptr;
83 }
84
85 sk_sp<GrRenderTargetContext> renderTargetContext(
Robert Phillips6603a172019-03-05 12:35:44 -050086 context->priv().makeDeferredRenderTargetContextWithFallback(
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050087 format, SkBackingFit::kExact, this->width(), this->height(),
Brian Osmanf48c9962019-01-14 11:15:50 -050088 SkColorType2GrPixelConfig(targetCT), nullptr));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050089 if (!renderTargetContext) {
90 return nullptr;
91 }
92
93 GrPaint paint;
94 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
95 paint.addColorTextureProcessor(std::move(proxy), SkMatrix::I());
Brian Osmanf48c9962019-01-14 11:15:50 -050096 if (xform) {
97 paint.addColorFragmentProcessor(std::move(xform));
98 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050099
100 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
101 SkRect::MakeIWH(this->width(), this->height()));
102 if (!renderTargetContext->asTextureProxy()) {
103 return nullptr;
104 }
105
106 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400107 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
Brian Osmanf48c9962019-01-14 11:15:50 -0500108 renderTargetContext->asTextureProxyRef(), std::move(targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500109}
110
reed8b26b992015-05-07 15:36:17 -0700111///////////////////////////////////////////////////////////////////////////////////////////////////
112
Greg Daniel7ef28f32017-04-20 16:41:55 +0000113static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
114 const GrBackendTexture& backendTex,
115 GrSurfaceOrigin origin,
brianosmandddbe382016-07-20 13:55:39 -0700116 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
117 GrWrapOwnership ownership,
reed7fb4f8b2016-03-11 04:33:52 -0800118 SkImage::TextureReleaseProc releaseProc,
119 SkImage::ReleaseContext releaseCtx) {
Greg Daniel66aebf32018-04-09 09:15:56 -0400120 if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700121 return nullptr;
reed8b26b992015-05-07 15:36:17 -0700122 }
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400123
Robert Phillips9da87e02019-02-04 13:26:26 -0500124 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500125 sk_sp<GrTextureProxy> proxy =
126 proxyProvider->wrapBackendTexture(backendTex, origin, ownership, GrWrapCacheable::kNo,
127 kRead_GrIOType, releaseProc, releaseCtx);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500128 if (!proxy) {
Robert Phillipse201ebc2018-01-17 18:12:50 +0000129 return nullptr;
130 }
Brian Salomon8a8dd332018-05-24 14:08:31 -0400131 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(proxy),
Brian Salomonf05e6d32018-12-20 08:41:41 -0500132 std::move(colorSpace));
bsalomon6dc6f5f2015-06-18 09:12:16 -0700133}
134
Greg Danielf5d87582017-12-18 14:48:15 -0500135sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
136 const GrBackendTexture& tex, GrSurfaceOrigin origin,
137 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
138 TextureReleaseProc releaseP, ReleaseContext releaseC) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500139 if (!ctx) {
140 return nullptr;
141 }
Greg Danielf5d87582017-12-18 14:48:15 -0500142 GrBackendTexture texCopy = tex;
Jim Van Verth8026ccc2018-10-04 13:10:39 -0400143 if (!SkImage_GpuBase::ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) {
Greg Danielf5d87582017-12-18 14:48:15 -0500144 return nullptr;
145 }
Brian Salomonbfd27492018-03-19 14:08:51 -0400146 return new_wrapped_texture_common(ctx, texCopy, origin, at, std::move(cs),
147 kBorrow_GrWrapOwnership, releaseP, releaseC);
Greg Danielf5d87582017-12-18 14:48:15 -0500148}
149
Greg Daniel94403452017-04-18 15:52:36 -0400150sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
151 const GrBackendTexture& tex, GrSurfaceOrigin origin,
Brian Salomon42409c22018-03-20 13:48:41 -0400152 SkColorType ct, SkAlphaType at,
153 sk_sp<SkColorSpace> cs) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500154 if (!ctx || !ctx->priv().resourceProvider()) {
Greg Danielf2336e42018-01-23 16:38:14 -0500155 // We have a DDL context and we don't support adopted textures for them.
156 return nullptr;
157 }
Greg Danielf5d87582017-12-18 14:48:15 -0500158 GrBackendTexture texCopy = tex;
Jim Van Verth8026ccc2018-10-04 13:10:39 -0400159 if (!SkImage_GpuBase::ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) {
Greg Danielf5d87582017-12-18 14:48:15 -0500160 return nullptr;
161 }
Brian Salomon42409c22018-03-20 13:48:41 -0400162 return new_wrapped_texture_common(ctx, texCopy, origin, at, std::move(cs),
163 kAdopt_GrWrapOwnership, nullptr, nullptr);
Greg Danielf5d87582017-12-18 14:48:15 -0500164}
165
Jim Van Verthee06b332019-01-18 10:36:32 -0500166sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
167 int width, int height, CompressionType type) {
168 // create the backing texture
169 GrSurfaceDesc desc;
170 desc.fFlags = kNone_GrSurfaceFlags;
171 desc.fWidth = width;
172 desc.fHeight = height;
173 switch (type) {
174 case kETC1_CompressionType:
175 desc.fConfig = kRGB_ETC1_GrPixelConfig;
176 break;
177 default:
178 desc.fConfig = kUnknown_GrPixelConfig;
179 break;
180 }
181 desc.fSampleCnt = 1;
182
Robert Phillips9da87e02019-02-04 13:26:26 -0500183 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Jim Van Verthee06b332019-01-18 10:36:32 -0500184 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(std::move(data), desc);
185
186 if (!proxy) {
187 return nullptr;
188 }
189
190 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
191 std::move(proxy), nullptr);
192}
193
Brian Salomonf05e6d32018-12-20 08:41:41 -0500194sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
195 const GrBackendTexture yuvaTextures[],
196 const SkYUVAIndex yuvaIndices[4], SkISize size,
197 GrSurfaceOrigin origin,
198 GrRenderTargetContext* renderTargetContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400199 SkASSERT(renderTargetContext);
200
Jim Van Verth0e671942018-11-09 12:03:57 -0500201 int numTextures;
202 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500203 return nullptr;
204 }
Robert Phillipsba5c4392018-07-25 12:37:14 -0400205
Jim Van Verth0e671942018-11-09 12:03:57 -0500206 sk_sp<GrTextureProxy> tempTextureProxies[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500207 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
208 origin, tempTextureProxies)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500209 return nullptr;
210 }
211
212 const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
Brian Osmane9560492019-02-05 17:00:03 -0500213 if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
Jim Van Verth0e671942018-11-09 12:03:57 -0500214 tempTextureProxies, yuvaIndices)) {
215 return nullptr;
216 }
Robert Phillipsb726d582017-03-09 16:36:32 -0500217
Jim Van Verth53275362018-11-09 15:42:35 -0500218 SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillipsb726d582017-03-09 16:36:32 -0500219 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Jim Van Verth53275362018-11-09 15:42:35 -0500220 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
Brian Salomonf3569f02017-10-24 12:52:33 -0400221 renderTargetContext->asTextureProxyRef(),
Brian Salomonf05e6d32018-12-20 08:41:41 -0500222 renderTargetContext->colorSpaceInfo().refColorSpace());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400223}
224
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400225sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
226 SkYUVColorSpace yuvColorSpace,
227 const GrBackendTexture yuvaTextures[],
228 const SkYUVAIndex yuvaIndices[4],
229 SkISize imageSize,
230 GrSurfaceOrigin imageOrigin,
231 sk_sp<SkColorSpace> imageColorSpace) {
232 const int width = imageSize.width();
233 const int height = imageSize.height();
Brian Salomond2fcfb52018-09-17 21:57:11 -0400234
Greg Daniel4065d452018-11-16 15:43:41 -0500235 const GrBackendFormat format =
Robert Phillips9da87e02019-02-04 13:26:26 -0500236 ctx->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
Greg Daniel4065d452018-11-16 15:43:41 -0500237
Brian Salomond2fcfb52018-09-17 21:57:11 -0400238 // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
239 sk_sp<GrRenderTargetContext> renderTargetContext(
Robert Phillips9da87e02019-02-04 13:26:26 -0500240 ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500241 format, SkBackingFit::kExact, width, height, kRGBA_8888_GrPixelConfig,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400242 std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin));
Brian Salomond2fcfb52018-09-17 21:57:11 -0400243 if (!renderTargetContext) {
244 return nullptr;
245 }
246
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400247 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500248 imageSize, imageOrigin, renderTargetContext.get());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400249}
250
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400251sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
Brian Salomond2fcfb52018-09-17 21:57:11 -0400252 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400253 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400254 const GrBackendTexture yuvaTextures[],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400255 const SkYUVAIndex yuvaIndices[4],
256 SkISize imageSize,
257 GrSurfaceOrigin imageOrigin,
258 const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400259 sk_sp<SkColorSpace> imageColorSpace) {
260 GrBackendTexture backendTextureCopy = backendTexture;
261
Jim Van Verth53275362018-11-09 15:42:35 -0500262 SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400263 if (!SkImage_Gpu::ValidateBackendTexture(ctx, backendTextureCopy, &backendTextureCopy.fConfig,
Jim Van Verth53275362018-11-09 15:42:35 -0500264 kRGBA_8888_SkColorType, at, nullptr)) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400265 return nullptr;
266 }
267
268 // Needs to create a render target with external texture
269 // in order to draw to it for the yuv->rgb conversion.
270 sk_sp<GrRenderTargetContext> renderTargetContext(
Robert Phillips9da87e02019-02-04 13:26:26 -0500271 ctx->priv().makeBackendTextureRenderTargetContext(backendTextureCopy,
272 imageOrigin, 1,
273 std::move(imageColorSpace)));
Brian Salomond2fcfb52018-09-17 21:57:11 -0400274
275 if (!renderTargetContext) {
276 return nullptr;
277 }
278
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400279 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500280 imageSize, imageOrigin, renderTargetContext.get());
Robert Phillipsc25db632017-12-13 09:22:45 -0500281}
282
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400283sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400284 const GrBackendTexture yuvTextures[3],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400285 GrSurfaceOrigin imageOrigin,
Brian Salomon6a426c12018-03-15 12:16:02 -0400286 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400287 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
288 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400289 SkYUVAIndex{0, SkColorChannel::kR},
290 SkYUVAIndex{1, SkColorChannel::kR},
291 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400292 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400293 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400294 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
295 size, imageOrigin, std::move(imageColorSpace));
bsalomon993a4212015-05-29 11:37:25 -0700296}
reed56179002015-07-07 06:11:19 -0700297
Brian Salomond2fcfb52018-09-17 21:57:11 -0400298sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400299 GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
300 GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400301 sk_sp<SkColorSpace> imageColorSpace) {
302 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400303 SkYUVAIndex{0, SkColorChannel::kR},
304 SkYUVAIndex{1, SkColorChannel::kR},
305 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400306 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400307 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400308 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
309 ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400310 std::move(imageColorSpace));
311}
312
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400313sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400314 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400315 GrSurfaceOrigin imageOrigin,
brianosmandddbe382016-07-20 13:55:39 -0700316 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400317 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
318 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400319 SkYUVAIndex{0, SkColorChannel::kR},
320 SkYUVAIndex{1, SkColorChannel::kR},
321 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400322 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400323 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400324 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
325 size, imageOrigin, std::move(imageColorSpace));
Robert Phillipsc25db632017-12-13 09:22:45 -0500326}
327
Brian Salomond2fcfb52018-09-17 21:57:11 -0400328sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
329 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400330 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400331 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400332 GrSurfaceOrigin imageOrigin,
333 const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400334 sk_sp<SkColorSpace> imageColorSpace) {
335 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400336 SkYUVAIndex{0, SkColorChannel::kR},
337 SkYUVAIndex{1, SkColorChannel::kR},
338 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400339 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400340 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400341 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
342 ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400343 std::move(imageColorSpace));
344}
345
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400346static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
347 SkAlphaType at, uint32_t id,
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400348 GrMipMapped mipMapped) {
Brian Osman6064e1c2018-10-19 14:27:54 -0400349 sk_sp<GrTextureProxy> proxy(producer->refTextureProxy(mipMapped));
Robert Phillips3798c862017-03-27 11:08:16 -0400350 if (!proxy) {
Brian Osman041f7df2017-02-07 11:23:28 -0500351 return nullptr;
352 }
Brian Salomon8a8dd332018-05-24 14:08:31 -0400353 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, at, std::move(proxy),
Brian Salomonf05e6d32018-12-20 08:41:41 -0500354 sk_ref_sp(producer->colorSpace()));
Brian Osman041f7df2017-02-07 11:23:28 -0500355}
356
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400357sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, SkColorSpace* dstColorSpace,
358 GrMipMapped mipMapped) const {
Brian Osman041f7df2017-02-07 11:23:28 -0500359 if (!context) {
360 return nullptr;
361 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500362
363 if (this->isTextureBacked()) {
364 if (!as_IB(this)->context()->priv().matches(context)) {
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400365 return nullptr;
366 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500367
Robert Phillips6603a172019-03-05 12:35:44 -0500368 sk_sp<GrTextureProxy> proxy = as_IB(this)->asTextureProxyRef(context);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400369 SkASSERT(proxy);
370 if (GrMipMapped::kNo == mipMapped || proxy->mipMapped() == mipMapped) {
371 return sk_ref_sp(const_cast<SkImage*>(this));
372 }
373 GrTextureAdjuster adjuster(context, std::move(proxy), this->alphaType(),
374 this->uniqueID(), this->colorSpace());
375 return create_image_from_producer(context, &adjuster, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400376 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500377 }
378
Brian Osmandf7e0752017-04-26 16:20:28 -0400379 if (this->isLazyGenerated()) {
380 GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400381 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400382 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500383 }
384
385 if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
386 GrBitmapTextureMaker maker(context, *bmp);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400387 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400388 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500389 }
390 return nullptr;
391}
392
Greg Daniel7278d682018-03-16 14:57:21 -0400393///////////////////////////////////////////////////////////////////////////////////////////////////
394
Greg Daniela8d92112018-03-09 12:05:04 -0500395sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
396 const GrBackendFormat& backendFormat,
397 int width,
398 int height,
399 GrMipMapped mipMapped,
400 GrSurfaceOrigin origin,
401 SkColorType colorType,
402 SkAlphaType alphaType,
403 sk_sp<SkColorSpace> colorSpace,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500404 PromiseImageTextureFulfillProc textureFulfillProc,
405 PromiseImageTextureReleaseProc textureReleaseProc,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500406 PromiseImageTextureDoneProc textureDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500407 PromiseImageTextureContext textureContext,
408 PromiseImageApiVersion version) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400409 // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500410 // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
411 // responsibility for calling the done proc.
Brian Salomonf55e8d52019-01-30 17:28:20 -0500412 if (!textureDoneProc) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400413 return nullptr;
414 }
Brian Salomonf55e8d52019-01-30 17:28:20 -0500415 SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
Robert Phillipsef85d192018-10-09 11:24:09 -0400416
Brian Salomonbe5a0932018-12-10 10:03:26 -0500417 SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
418 if (!SkImageInfoIsValid(info)) {
419 return nullptr;
420 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400421
Greg Daniela8d92112018-03-09 12:05:04 -0500422 if (!context) {
423 return nullptr;
424 }
425
426 if (width <= 0 || height <= 0) {
427 return nullptr;
428 }
429
Brian Salomonf391d0f2018-12-14 09:18:50 -0500430 GrPixelConfig config =
Robert Phillips9da87e02019-02-04 13:26:26 -0500431 context->priv().caps()->getConfigFromBackendFormat(backendFormat, colorType);
Brian Salomonf391d0f2018-12-14 09:18:50 -0500432 if (config == kUnknown_GrPixelConfig) {
Greg Daniela8d92112018-03-09 12:05:04 -0500433 return nullptr;
434 }
435
Brian Salomonbe5a0932018-12-10 10:03:26 -0500436 callDone.clear();
437 auto proxy = MakePromiseImageLazyProxy(context, width, height, origin, config, backendFormat,
438 mipMapped, textureFulfillProc, textureReleaseProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500439 textureDoneProc, textureContext, version);
Greg Daniela8d92112018-03-09 12:05:04 -0500440 if (!proxy) {
441 return nullptr;
442 }
Brian Salomon8a8dd332018-05-24 14:08:31 -0400443 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, alphaType,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500444 std::move(proxy), std::move(colorSpace));
Greg Daniela8d92112018-03-09 12:05:04 -0500445}
446
Greg Daniel7278d682018-03-16 14:57:21 -0400447///////////////////////////////////////////////////////////////////////////////////////////////////
448
Brian Osman13dddce2017-05-09 13:19:50 -0400449sk_sp<SkImage> SkImage::MakeCrossContextFromEncoded(GrContext* context, sk_sp<SkData> encoded,
Brian Osman584b5012018-04-13 15:48:26 -0400450 bool buildMips, SkColorSpace* dstColorSpace,
451 bool limitToMaxTextureSize) {
Brian Osman13dddce2017-05-09 13:19:50 -0400452 sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded));
453 if (!codecImage) {
454 return nullptr;
455 }
456
457 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500458 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman13dddce2017-05-09 13:19:50 -0400459 return codecImage;
460 }
461
Brian Osman0471a932019-02-07 13:36:56 -0500462 // If non-power-of-two mipmapping isn't supported, ignore the client's request
463 if (!context->priv().caps()->mipMapSupport()) {
464 buildMips = false;
465 }
466
Robert Phillips9da87e02019-02-04 13:26:26 -0500467 auto maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400468 if (limitToMaxTextureSize &&
469 (codecImage->width() > maxTextureSize || codecImage->height() > maxTextureSize)) {
Brian Osman584b5012018-04-13 15:48:26 -0400470 SkAutoPixmapStorage pmap;
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400471 SkImageInfo info = codecImage->imageInfo();
Brian Osman584b5012018-04-13 15:48:26 -0400472 if (!dstColorSpace) {
473 info = info.makeColorSpace(nullptr);
474 }
475 if (!pmap.tryAlloc(info) || !codecImage->readPixels(pmap, 0, 0, kDisallow_CachingHint)) {
476 return nullptr;
477 }
478 return MakeCrossContextFromPixmap(context, pmap, buildMips, dstColorSpace, true);
479 }
480
Brian Osman13dddce2017-05-09 13:19:50 -0400481 // Turn the codec image into a GrTextureProxy
482 GrImageTextureMaker maker(context, codecImage.get(), kDisallow_CachingHint);
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400483 GrSamplerState samplerState(
484 GrSamplerState::WrapMode::kClamp,
485 buildMips ? GrSamplerState::Filter::kMipMap : GrSamplerState::Filter::kBilerp);
Brian Osman0471a932019-02-07 13:36:56 -0500486 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
487 sk_sp<GrTextureProxy> proxy(maker.refTextureProxyForParams(samplerState, scaleAdjust));
488 // Given that we disable mipmaps if non-power-of-two mipmapping isn't supported, we always
489 // expect the created texture to be unscaled.
490 SkASSERT(scaleAdjust[0] == 1.0f && scaleAdjust[1] == 1.0f);
Brian Osman13dddce2017-05-09 13:19:50 -0400491 if (!proxy) {
492 return codecImage;
493 }
494
Brian Osman13dddce2017-05-09 13:19:50 -0400495 // Flush any writes or uploads
Robert Phillips9da87e02019-02-04 13:26:26 -0500496 context->priv().prepareSurfaceForExternalIO(proxy.get());
Robert Phillipsacc10fa2019-04-01 09:50:20 -0400497 if (!proxy->isInstantiated()) {
498 return codecImage;
499 }
Brian Osman13dddce2017-05-09 13:19:50 -0400500
Robert Phillips73cc4e82019-04-01 07:46:13 -0400501 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
502
Robert Phillips9da87e02019-02-04 13:26:26 -0500503 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500504 sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman13dddce2017-05-09 13:19:50 -0400505
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400506 auto gen = GrBackendTextureImageGenerator::Make(
507 std::move(texture), proxy->origin(), std::move(sema), codecImage->colorType(),
508 codecImage->alphaType(), codecImage->refColorSpace());
Brian Osman13dddce2017-05-09 13:19:50 -0400509 return SkImage::MakeFromGenerator(std::move(gen));
510}
511
Brian Osman584b5012018-04-13 15:48:26 -0400512sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
513 const SkPixmap& originalPixmap, bool buildMips,
514 SkColorSpace* dstColorSpace,
515 bool limitToMaxTextureSize) {
Brian Osman63bc48d2017-11-07 10:37:00 -0500516 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500517 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman584b5012018-04-13 15:48:26 -0400518 return SkImage::MakeRasterCopy(originalPixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500519 }
520
Greg Daniel9e788112018-02-08 14:29:37 -0500521 // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
522 // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
523 // instead.
Robert Phillips9da87e02019-02-04 13:26:26 -0500524 if (!context->priv().resourceProvider()) {
Brian Osman584b5012018-04-13 15:48:26 -0400525 return SkImage::MakeRasterCopy(originalPixmap);
Greg Daniel9e788112018-02-08 14:29:37 -0500526 }
527
Brian Osman0471a932019-02-07 13:36:56 -0500528 // If non-power-of-two mipmapping isn't supported, ignore the client's request
529 if (!context->priv().caps()->mipMapSupport()) {
530 buildMips = false;
531 }
532
Brian Osman584b5012018-04-13 15:48:26 -0400533 const SkPixmap* pixmap = &originalPixmap;
534 SkAutoPixmapStorage resized;
Robert Phillips9da87e02019-02-04 13:26:26 -0500535 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Osman584b5012018-04-13 15:48:26 -0400536 int maxDim = SkTMax(originalPixmap.width(), originalPixmap.height());
537 if (limitToMaxTextureSize && maxDim > maxTextureSize) {
538 float scale = static_cast<float>(maxTextureSize) / maxDim;
539 int newWidth = SkTMin(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
540 int newHeight = SkTMin(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
541 SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
542 if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
543 return nullptr;
544 }
545 pixmap = &resized;
546 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500547 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Osman63bc48d2017-11-07 10:37:00 -0500548 // Turn the pixmap into a GrTextureProxy
Brian Osman7dcc6162019-03-25 10:12:57 -0400549 SkBitmap bmp;
550 bmp.installPixels(*pixmap);
551 GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
552 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
Brian Osman63bc48d2017-11-07 10:37:00 -0500553 if (!proxy) {
Brian Osman584b5012018-04-13 15:48:26 -0400554 return SkImage::MakeRasterCopy(*pixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500555 }
556
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400557 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Brian Osman63bc48d2017-11-07 10:37:00 -0500558
559 // Flush any writes or uploads
Robert Phillips9da87e02019-02-04 13:26:26 -0500560 context->priv().prepareSurfaceForExternalIO(proxy.get());
561 GrGpu* gpu = context->priv().getGpu();
Brian Osman63bc48d2017-11-07 10:37:00 -0500562
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500563 sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman63bc48d2017-11-07 10:37:00 -0500564
565 auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
Brian Osman584b5012018-04-13 15:48:26 -0400566 std::move(sema), pixmap->colorType(),
567 pixmap->alphaType(),
568 pixmap->info().refColorSpace());
Brian Osman63bc48d2017-11-07 10:37:00 -0500569 return SkImage::MakeFromGenerator(std::move(gen));
570}
571
Derek Sollenberger7a869872017-06-27 15:37:25 -0400572#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -0400573sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
Stan Iliev505dd572018-09-13 14:20:03 -0400574 sk_sp<SkColorSpace> cs,
575 GrSurfaceOrigin surfaceOrigin) {
576 auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
Stan Iliev7e910df2017-06-02 10:29:21 -0400577 return SkImage::MakeFromGenerator(std::move(gen));
578}
Greg Danielb6c15ba2019-03-04 13:08:25 -0500579
580sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
581 const SkPixmap& pixmap,
582 AHardwareBuffer* hardwareBuffer,
583 GrSurfaceOrigin surfaceOrigin) {
584 AHardwareBuffer_Desc bufferDesc;
585 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
586
587 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
588 return nullptr;
589 }
590
591 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
592 hardwareBuffer,
593 bufferDesc.format,
594 true);
595
596 if (!backendFormat.isValid()) {
597 return nullptr;
598 }
599
600 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
601 GrAHardwareBufferUtils::DeleteImageCtx deleteImageCtx = nullptr;
602
603 GrBackendTexture backendTexture =
604 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
605 bufferDesc.width, bufferDesc.height,
606 &deleteImageProc, &deleteImageCtx,
607 false, backendFormat, true);
608 if (!backendTexture.isValid()) {
609 return nullptr;
610 }
611 SkASSERT(deleteImageProc);
612
613 SkColorType colorType =
614 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
615
616 backendTexture.fConfig = context->priv().caps()->getConfigFromBackendFormat(backendFormat,
617 colorType);
618
619 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
620 if (!proxyProvider) {
621 deleteImageProc(deleteImageCtx);
622 return nullptr;
623 }
624
625 sk_sp<GrTextureProxy> proxy =
626 proxyProvider->wrapBackendTexture(backendTexture, surfaceOrigin,
627 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
628 kRW_GrIOType, deleteImageProc, deleteImageCtx);
629 if (!proxy) {
630 deleteImageProc(deleteImageCtx);
631 return nullptr;
632 }
633
634 sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
635 SkAlphaType at = pixmap.alphaType();
636
637 sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, at,
638 proxy, cs);
639 if (!image) {
640 return nullptr;
641 }
642
643 GrDrawingManager* drawingManager = context->priv().drawingManager();
644 if (!drawingManager) {
645 return nullptr;
646 }
647
648 sk_sp<GrTextureContext> texContext = drawingManager->makeTextureContext(proxy, cs);
649 if (!texContext) {
650 return nullptr;
651 }
652
653 SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
654 std::move(cs));
655 texContext->writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), 0, 0);
656
657 drawingManager->flush(proxy.get(), SkSurface::BackendSurfaceAccess::kNoAccess,
Greg Danielb9990e42019-04-10 16:28:52 -0400658 kSyncCpu_GrFlushFlag, 0, nullptr);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500659
660 return image;
661}
Stan Iliev7e910df2017-06-02 10:29:21 -0400662#endif
663
reed56179002015-07-07 06:11:19 -0700664///////////////////////////////////////////////////////////////////////////////////////////////////
665
Eric Karl914a36b2017-10-12 12:44:50 -0700666bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
667 sk_sp<SkImage> image,
668 GrBackendTexture* backendTexture,
669 BackendTextureReleaseProc* releaseProc) {
670 if (!image || !ctx || !backendTexture || !releaseProc) {
671 return false;
672 }
673
674 // Ensure we have a texture backed image.
675 if (!image->isTextureBacked()) {
676 image = image->makeTextureImage(ctx, nullptr);
677 if (!image) {
678 return false;
679 }
680 }
681 GrTexture* texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800682 if (!texture) {
683 // In context-loss cases, we may not have a texture.
684 return false;
685 }
Eric Karl914a36b2017-10-12 12:44:50 -0700686
687 // If the image's context doesn't match the provided context, fail.
688 if (texture->getContext() != ctx) {
689 return false;
690 }
691
692 // Flush any pending IO on the texture.
Robert Phillips9da87e02019-02-04 13:26:26 -0500693 ctx->priv().prepareSurfaceForExternalIO(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700694 SkASSERT(!texture->surfacePriv().hasPendingIO());
695
696 // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
697 // image is not unique, or if the texture wraps an external object.
698 if (!image->unique() || !texture->surfacePriv().hasUniqueRef() ||
699 texture->resourcePriv().refsWrappedObjects()) {
700 // onMakeSubset will always copy the image.
Robert Phillips6603a172019-03-05 12:35:44 -0500701 image = as_IB(image)->onMakeSubset(ctx, image->bounds());
Eric Karl914a36b2017-10-12 12:44:50 -0700702 if (!image) {
703 return false;
704 }
705
706 texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800707 if (!texture) {
708 return false;
709 }
Eric Karl914a36b2017-10-12 12:44:50 -0700710
711 // Flush to ensure that the copy is completed before we return the texture.
Robert Phillips9da87e02019-02-04 13:26:26 -0500712 ctx->priv().prepareSurfaceForExternalIO(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700713 SkASSERT(!texture->surfacePriv().hasPendingIO());
714 }
715
716 SkASSERT(!texture->resourcePriv().refsWrappedObjects());
717 SkASSERT(texture->surfacePriv().hasUniqueRef());
718 SkASSERT(image->unique());
719
720 // Take a reference to the GrTexture and release the image.
721 sk_sp<GrTexture> textureRef(SkSafeRef(texture));
722 image = nullptr;
723
724 // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
725 return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
726}