blob: 511af5a62ccf1a81f3465aead1fd330857d215f1 [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"
33#include "src/gpu/GrImageTextureMaker.h"
34#include "src/gpu/GrProxyProvider.h"
35#include "src/gpu/GrRecordingContextPriv.h"
36#include "src/gpu/GrRenderTargetContext.h"
37#include "src/gpu/GrResourceProvider.h"
38#include "src/gpu/GrResourceProviderPriv.h"
39#include "src/gpu/GrSemaphore.h"
40#include "src/gpu/GrSurfacePriv.h"
41#include "src/gpu/GrTextureAdjuster.h"
42#include "src/gpu/GrTextureContext.h"
43#include "src/gpu/GrTexturePriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040044#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050045#include "src/gpu/GrTextureProxyPriv.h"
46#include "src/gpu/SkGr.h"
47#include "src/gpu/effects/GrYUVtoRGBEffect.h"
48#include "src/gpu/gl/GrGLTexture.h"
49#include "src/image/SkImage_Gpu.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
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040067GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrContext* context, const GrFlushInfo& info) {
68 if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
69 return GrSemaphoresSubmitted::kNo;
70 }
71
72 GrSurfaceProxy* p[1] = {fProxy.get()};
73 return context->priv().flushSurfaces(p, 1, info);
74}
75
Robert Phillips6603a172019-03-05 12:35:44 -050076sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
77 SkColorType targetCT,
Brian Osmanf48c9962019-01-14 11:15:50 -050078 sk_sp<SkColorSpace> targetCS) const {
Robert Phillips6603a172019-03-05 12:35:44 -050079 if (!context || !fContext->priv().matches(context)) {
80 return nullptr;
81 }
82
Brian Salomon5ad6fd32019-03-21 15:30:08 -040083 auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
84 targetCS.get(), this->alphaType());
Brian Osmanf48c9962019-01-14 11:15:50 -050085 SkASSERT(xform || targetCT != this->colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050086
Robert Phillips6603a172019-03-05 12:35:44 -050087 sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050088
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050089 sk_sp<GrRenderTargetContext> renderTargetContext(
Brian Salomond6287472019-06-24 15:50:07 -040090 context->priv().makeDeferredRenderTargetContextWithFallback(
Brian Salomon27ae52c2019-07-03 11:27:44 -040091 SkBackingFit::kExact, this->width(), this->height(),
92 SkColorTypeToGrColorType(targetCT), nullptr));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050093 if (!renderTargetContext) {
94 return nullptr;
95 }
96
97 GrPaint paint;
98 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
99 paint.addColorTextureProcessor(std::move(proxy), SkMatrix::I());
Brian Osmanf48c9962019-01-14 11:15:50 -0500100 if (xform) {
101 paint.addColorFragmentProcessor(std::move(xform));
102 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500103
104 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
105 SkRect::MakeIWH(this->width(), this->height()));
106 if (!renderTargetContext->asTextureProxy()) {
107 return nullptr;
108 }
109
110 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400111 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
Brian Osmanf48c9962019-01-14 11:15:50 -0500112 renderTargetContext->asTextureProxyRef(), std::move(targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500113}
114
Brian Osmand5148372019-08-14 16:14:51 -0400115sk_sp<SkImage> SkImage_Gpu::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
116 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(), fProxy,
117 std::move(newCS));
118}
119
reed8b26b992015-05-07 15:36:17 -0700120///////////////////////////////////////////////////////////////////////////////////////////////////
121
Greg Daniel7ef28f32017-04-20 16:41:55 +0000122static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
123 const GrBackendTexture& backendTex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400124 GrColorType colorType, GrSurfaceOrigin origin,
brianosmandddbe382016-07-20 13:55:39 -0700125 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
126 GrWrapOwnership ownership,
reed7fb4f8b2016-03-11 04:33:52 -0800127 SkImage::TextureReleaseProc releaseProc,
128 SkImage::ReleaseContext releaseCtx) {
Greg Daniel66aebf32018-04-09 09:15:56 -0400129 if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700130 return nullptr;
reed8b26b992015-05-07 15:36:17 -0700131 }
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400132
Robert Phillips9da87e02019-02-04 13:26:26 -0500133 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500134 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400135 proxyProvider->wrapBackendTexture(backendTex, colorType, origin, ownership,
136 GrWrapCacheable::kNo, kRead_GrIOType,
137 releaseProc, releaseCtx);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500138 if (!proxy) {
Robert Phillipse201ebc2018-01-17 18:12:50 +0000139 return nullptr;
140 }
Brian Salomon8a8dd332018-05-24 14:08:31 -0400141 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(proxy),
Brian Salomonf05e6d32018-12-20 08:41:41 -0500142 std::move(colorSpace));
bsalomon6dc6f5f2015-06-18 09:12:16 -0700143}
144
Greg Danielf5d87582017-12-18 14:48:15 -0500145sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
146 const GrBackendTexture& tex, GrSurfaceOrigin origin,
147 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
148 TextureReleaseProc releaseP, ReleaseContext releaseC) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500149 if (!ctx) {
150 return nullptr;
151 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400152
Robert Phillips62221e72019-07-24 15:07:38 -0400153 const GrCaps* caps = ctx->priv().caps();
154
155 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400156 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400157 return nullptr;
158 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400159
Robert Phillips62221e72019-07-24 15:07:38 -0400160 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400161 return nullptr;
162 }
163
Robert Phillips62221e72019-07-24 15:07:38 -0400164 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomonbfd27492018-03-19 14:08:51 -0400165 kBorrow_GrWrapOwnership, releaseP, releaseC);
Greg Danielf5d87582017-12-18 14:48:15 -0500166}
167
Greg Daniel94403452017-04-18 15:52:36 -0400168sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
169 const GrBackendTexture& tex, GrSurfaceOrigin origin,
Brian Salomon42409c22018-03-20 13:48:41 -0400170 SkColorType ct, SkAlphaType at,
171 sk_sp<SkColorSpace> cs) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500172 if (!ctx || !ctx->priv().resourceProvider()) {
Greg Danielf2336e42018-01-23 16:38:14 -0500173 // We have a DDL context and we don't support adopted textures for them.
174 return nullptr;
175 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400176
Robert Phillips62221e72019-07-24 15:07:38 -0400177 const GrCaps* caps = ctx->priv().caps();
178
179 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400180 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400181 return nullptr;
182 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400183
Robert Phillips62221e72019-07-24 15:07:38 -0400184 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400185 return nullptr;
186 }
187
Robert Phillips62221e72019-07-24 15:07:38 -0400188 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomon42409c22018-03-20 13:48:41 -0400189 kAdopt_GrWrapOwnership, nullptr, nullptr);
Greg Danielf5d87582017-12-18 14:48:15 -0500190}
191
Jim Van Verthee06b332019-01-18 10:36:32 -0500192sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
193 int width, int height, CompressionType type) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500194 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Salomonbb8dde82019-06-27 10:52:13 -0400195 sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
196 width, height, SkBudgeted::kYes, type, std::move(data));
Jim Van Verthee06b332019-01-18 10:36:32 -0500197
198 if (!proxy) {
199 return nullptr;
200 }
201
202 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
203 std::move(proxy), nullptr);
204}
205
Brian Salomonf05e6d32018-12-20 08:41:41 -0500206sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
207 const GrBackendTexture yuvaTextures[],
208 const SkYUVAIndex yuvaIndices[4], SkISize size,
209 GrSurfaceOrigin origin,
210 GrRenderTargetContext* renderTargetContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400211 SkASSERT(renderTargetContext);
212
Jim Van Verth0e671942018-11-09 12:03:57 -0500213 int numTextures;
214 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500215 return nullptr;
216 }
Robert Phillipsba5c4392018-07-25 12:37:14 -0400217
Jim Van Verth0e671942018-11-09 12:03:57 -0500218 sk_sp<GrTextureProxy> tempTextureProxies[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500219 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
220 origin, tempTextureProxies)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500221 return nullptr;
222 }
223
224 const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
Brian Osmane9560492019-02-05 17:00:03 -0500225 if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
Jim Van Verth0e671942018-11-09 12:03:57 -0500226 tempTextureProxies, yuvaIndices)) {
227 return nullptr;
228 }
Robert Phillipsb726d582017-03-09 16:36:32 -0500229
Jim Van Verth53275362018-11-09 15:42:35 -0500230 SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillipsb726d582017-03-09 16:36:32 -0500231 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Jim Van Verth53275362018-11-09 15:42:35 -0500232 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
Brian Salomonf3569f02017-10-24 12:52:33 -0400233 renderTargetContext->asTextureProxyRef(),
Brian Salomonf05e6d32018-12-20 08:41:41 -0500234 renderTargetContext->colorSpaceInfo().refColorSpace());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400235}
236
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400237sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
238 SkYUVColorSpace yuvColorSpace,
239 const GrBackendTexture yuvaTextures[],
240 const SkYUVAIndex yuvaIndices[4],
241 SkISize imageSize,
242 GrSurfaceOrigin imageOrigin,
243 sk_sp<SkColorSpace> imageColorSpace) {
244 const int width = imageSize.width();
245 const int height = imageSize.height();
Brian Salomond2fcfb52018-09-17 21:57:11 -0400246
247 // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
Brian Salomond6287472019-06-24 15:50:07 -0400248 sk_sp<GrRenderTargetContext> renderTargetContext(ctx->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400249 SkBackingFit::kExact, width, height, GrColorType::kRGBA_8888,
250 std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin));
Brian Salomond2fcfb52018-09-17 21:57:11 -0400251 if (!renderTargetContext) {
252 return nullptr;
253 }
254
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400255 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500256 imageSize, imageOrigin, renderTargetContext.get());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400257}
258
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400259sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
Brian Salomond2fcfb52018-09-17 21:57:11 -0400260 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400261 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400262 const GrBackendTexture yuvaTextures[],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400263 const SkYUVAIndex yuvaIndices[4],
264 SkISize imageSize,
265 GrSurfaceOrigin imageOrigin,
266 const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400267 sk_sp<SkColorSpace> imageColorSpace) {
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.
284 sk_sp<GrRenderTargetContext> renderTargetContext(
Robert Phillips62221e72019-07-24 15:07:38 -0400285 ctx->priv().makeBackendTextureRenderTargetContext(backendTexture, imageOrigin, 1,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400286 grColorType,
Robert Phillips9da87e02019-02-04 13:26:26 -0500287 std::move(imageColorSpace)));
Brian Salomond2fcfb52018-09-17 21:57:11 -0400288
289 if (!renderTargetContext) {
290 return nullptr;
291 }
292
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400293 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500294 imageSize, imageOrigin, renderTargetContext.get());
Robert Phillipsc25db632017-12-13 09:22:45 -0500295}
296
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400297sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400298 const GrBackendTexture yuvTextures[3],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400299 GrSurfaceOrigin imageOrigin,
Brian Salomon6a426c12018-03-15 12:16:02 -0400300 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400301 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
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}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400307 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400308 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
309 size, imageOrigin, std::move(imageColorSpace));
bsalomon993a4212015-05-29 11:37:25 -0700310}
reed56179002015-07-07 06:11:19 -0700311
Brian Salomond2fcfb52018-09-17 21:57:11 -0400312sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400313 GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
314 GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400315 sk_sp<SkColorSpace> imageColorSpace) {
316 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400317 SkYUVAIndex{0, SkColorChannel::kR},
318 SkYUVAIndex{1, SkColorChannel::kR},
319 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400320 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400321 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400322 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
323 ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400324 std::move(imageColorSpace));
325}
326
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400327sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400328 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400329 GrSurfaceOrigin imageOrigin,
brianosmandddbe382016-07-20 13:55:39 -0700330 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400331 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
332 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400333 SkYUVAIndex{0, SkColorChannel::kR},
334 SkYUVAIndex{1, SkColorChannel::kR},
335 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400336 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400337 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400338 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
339 size, imageOrigin, std::move(imageColorSpace));
Robert Phillipsc25db632017-12-13 09:22:45 -0500340}
341
Brian Salomond2fcfb52018-09-17 21:57:11 -0400342sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
343 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400344 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400345 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400346 GrSurfaceOrigin imageOrigin,
347 const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400348 sk_sp<SkColorSpace> imageColorSpace) {
349 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,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400357 std::move(imageColorSpace));
358}
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 Salomon8a8dd332018-05-24 14:08:31 -0400367 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, at, std::move(proxy),
Brian Salomonf05e6d32018-12-20 08:41:41 -0500368 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 Salomond6287472019-06-24 15:50:07 -0400386 GrTextureAdjuster adjuster(context, std::move(proxy),
387 SkColorTypeToGrColorType(this->colorType()), this->alphaType(),
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400388 this->uniqueID(), this->colorSpace());
389 return create_image_from_producer(context, &adjuster, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400390 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500391 }
392
Brian Osmandf7e0752017-04-26 16:20:28 -0400393 if (this->isLazyGenerated()) {
394 GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400395 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400396 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500397 }
398
399 if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
400 GrBitmapTextureMaker maker(context, *bmp);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400401 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400402 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500403 }
404 return nullptr;
405}
406
Greg Daniel7278d682018-03-16 14:57:21 -0400407///////////////////////////////////////////////////////////////////////////////////////////////////
408
Greg Daniela8d92112018-03-09 12:05:04 -0500409sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
410 const GrBackendFormat& backendFormat,
411 int width,
412 int height,
413 GrMipMapped mipMapped,
414 GrSurfaceOrigin origin,
415 SkColorType colorType,
416 SkAlphaType alphaType,
417 sk_sp<SkColorSpace> colorSpace,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500418 PromiseImageTextureFulfillProc textureFulfillProc,
419 PromiseImageTextureReleaseProc textureReleaseProc,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500420 PromiseImageTextureDoneProc textureDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500421 PromiseImageTextureContext textureContext,
422 PromiseImageApiVersion version) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400423 // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500424 // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
425 // responsibility for calling the done proc.
Brian Salomonf55e8d52019-01-30 17:28:20 -0500426 if (!textureDoneProc) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400427 return nullptr;
428 }
Brian Salomonf55e8d52019-01-30 17:28:20 -0500429 SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
Robert Phillipsef85d192018-10-09 11:24:09 -0400430
Brian Salomonbe5a0932018-12-10 10:03:26 -0500431 SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
432 if (!SkImageInfoIsValid(info)) {
433 return nullptr;
434 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400435
Greg Daniela8d92112018-03-09 12:05:04 -0500436 if (!context) {
437 return nullptr;
438 }
439
440 if (width <= 0 || height <= 0) {
441 return nullptr;
442 }
443
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400444 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
445 colorType,
446 backendFormat);
447 if (GrColorType::kUnknown == grColorType) {
Greg Daniela8d92112018-03-09 12:05:04 -0500448 return nullptr;
449 }
450
Brian Salomonbe5a0932018-12-10 10:03:26 -0500451 callDone.clear();
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400452 auto proxy = MakePromiseImageLazyProxy(context, width, height, origin,
453 grColorType, backendFormat,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500454 mipMapped, textureFulfillProc, textureReleaseProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500455 textureDoneProc, textureContext, version);
Greg Daniela8d92112018-03-09 12:05:04 -0500456 if (!proxy) {
457 return nullptr;
458 }
Brian Salomon8a8dd332018-05-24 14:08:31 -0400459 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, alphaType,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500460 std::move(proxy), std::move(colorSpace));
Greg Daniela8d92112018-03-09 12:05:04 -0500461}
462
Greg Daniel7278d682018-03-16 14:57:21 -0400463///////////////////////////////////////////////////////////////////////////////////////////////////
464
Brian Osman13dddce2017-05-09 13:19:50 -0400465sk_sp<SkImage> SkImage::MakeCrossContextFromEncoded(GrContext* context, sk_sp<SkData> encoded,
Brian Osman584b5012018-04-13 15:48:26 -0400466 bool buildMips, SkColorSpace* dstColorSpace,
467 bool limitToMaxTextureSize) {
Brian Osman13dddce2017-05-09 13:19:50 -0400468 sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded));
469 if (!codecImage) {
470 return nullptr;
471 }
472
473 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500474 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman13dddce2017-05-09 13:19:50 -0400475 return codecImage;
476 }
477
Brian Osman0471a932019-02-07 13:36:56 -0500478 // If non-power-of-two mipmapping isn't supported, ignore the client's request
479 if (!context->priv().caps()->mipMapSupport()) {
480 buildMips = false;
481 }
482
Robert Phillips9da87e02019-02-04 13:26:26 -0500483 auto maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400484 if (limitToMaxTextureSize &&
485 (codecImage->width() > maxTextureSize || codecImage->height() > maxTextureSize)) {
Brian Osman584b5012018-04-13 15:48:26 -0400486 SkAutoPixmapStorage pmap;
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400487 SkImageInfo info = codecImage->imageInfo();
Brian Osman584b5012018-04-13 15:48:26 -0400488 if (!dstColorSpace) {
489 info = info.makeColorSpace(nullptr);
490 }
491 if (!pmap.tryAlloc(info) || !codecImage->readPixels(pmap, 0, 0, kDisallow_CachingHint)) {
492 return nullptr;
493 }
494 return MakeCrossContextFromPixmap(context, pmap, buildMips, dstColorSpace, true);
495 }
496
Brian Osman13dddce2017-05-09 13:19:50 -0400497 // Turn the codec image into a GrTextureProxy
498 GrImageTextureMaker maker(context, codecImage.get(), kDisallow_CachingHint);
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400499 GrSamplerState samplerState(
500 GrSamplerState::WrapMode::kClamp,
501 buildMips ? GrSamplerState::Filter::kMipMap : GrSamplerState::Filter::kBilerp);
Brian Osman0471a932019-02-07 13:36:56 -0500502 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
503 sk_sp<GrTextureProxy> proxy(maker.refTextureProxyForParams(samplerState, scaleAdjust));
504 // Given that we disable mipmaps if non-power-of-two mipmapping isn't supported, we always
505 // expect the created texture to be unscaled.
506 SkASSERT(scaleAdjust[0] == 1.0f && scaleAdjust[1] == 1.0f);
Brian Osman13dddce2017-05-09 13:19:50 -0400507 if (!proxy) {
508 return codecImage;
509 }
510
Brian Osman13dddce2017-05-09 13:19:50 -0400511 // Flush any writes or uploads
Greg Daniel4aa13e72019-04-15 14:42:20 -0400512 context->priv().flushSurface(proxy.get());
Robert Phillipsacc10fa2019-04-01 09:50:20 -0400513 if (!proxy->isInstantiated()) {
514 return codecImage;
515 }
Brian Osman13dddce2017-05-09 13:19:50 -0400516
Robert Phillips73cc4e82019-04-01 07:46:13 -0400517 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
518
Robert Phillips9da87e02019-02-04 13:26:26 -0500519 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500520 sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman13dddce2017-05-09 13:19:50 -0400521
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400522 auto gen = GrBackendTextureImageGenerator::Make(
523 std::move(texture), proxy->origin(), std::move(sema), codecImage->colorType(),
524 codecImage->alphaType(), codecImage->refColorSpace());
Brian Osman13dddce2017-05-09 13:19:50 -0400525 return SkImage::MakeFromGenerator(std::move(gen));
526}
527
Brian Osman584b5012018-04-13 15:48:26 -0400528sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
529 const SkPixmap& originalPixmap, bool buildMips,
530 SkColorSpace* dstColorSpace,
531 bool limitToMaxTextureSize) {
Brian Osman63bc48d2017-11-07 10:37:00 -0500532 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500533 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman584b5012018-04-13 15:48:26 -0400534 return SkImage::MakeRasterCopy(originalPixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500535 }
536
Greg Daniel9e788112018-02-08 14:29:37 -0500537 // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
538 // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
539 // instead.
Robert Phillips9da87e02019-02-04 13:26:26 -0500540 if (!context->priv().resourceProvider()) {
Brian Osman584b5012018-04-13 15:48:26 -0400541 return SkImage::MakeRasterCopy(originalPixmap);
Greg Daniel9e788112018-02-08 14:29:37 -0500542 }
543
Brian Osman0471a932019-02-07 13:36:56 -0500544 // If non-power-of-two mipmapping isn't supported, ignore the client's request
545 if (!context->priv().caps()->mipMapSupport()) {
546 buildMips = false;
547 }
548
Brian Osman584b5012018-04-13 15:48:26 -0400549 const SkPixmap* pixmap = &originalPixmap;
550 SkAutoPixmapStorage resized;
Robert Phillips9da87e02019-02-04 13:26:26 -0500551 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Osman584b5012018-04-13 15:48:26 -0400552 int maxDim = SkTMax(originalPixmap.width(), originalPixmap.height());
553 if (limitToMaxTextureSize && maxDim > maxTextureSize) {
554 float scale = static_cast<float>(maxTextureSize) / maxDim;
555 int newWidth = SkTMin(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
556 int newHeight = SkTMin(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
557 SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
558 if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
559 return nullptr;
560 }
561 pixmap = &resized;
562 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500563 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Osman63bc48d2017-11-07 10:37:00 -0500564 // Turn the pixmap into a GrTextureProxy
Brian Osman7dcc6162019-03-25 10:12:57 -0400565 SkBitmap bmp;
566 bmp.installPixels(*pixmap);
567 GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
568 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
Brian Osman63bc48d2017-11-07 10:37:00 -0500569 if (!proxy) {
Brian Osman584b5012018-04-13 15:48:26 -0400570 return SkImage::MakeRasterCopy(*pixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500571 }
572
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400573 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Brian Osman63bc48d2017-11-07 10:37:00 -0500574
575 // Flush any writes or uploads
Greg Daniel4aa13e72019-04-15 14:42:20 -0400576 context->priv().flushSurface(proxy.get());
Robert Phillips9da87e02019-02-04 13:26:26 -0500577 GrGpu* gpu = context->priv().getGpu();
Brian Osman63bc48d2017-11-07 10:37:00 -0500578
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500579 sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman63bc48d2017-11-07 10:37:00 -0500580
581 auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
Brian Osman584b5012018-04-13 15:48:26 -0400582 std::move(sema), pixmap->colorType(),
583 pixmap->alphaType(),
584 pixmap->info().refColorSpace());
Brian Osman63bc48d2017-11-07 10:37:00 -0500585 return SkImage::MakeFromGenerator(std::move(gen));
586}
587
Derek Sollenberger7a869872017-06-27 15:37:25 -0400588#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -0400589sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
Stan Iliev505dd572018-09-13 14:20:03 -0400590 sk_sp<SkColorSpace> cs,
591 GrSurfaceOrigin surfaceOrigin) {
592 auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
Stan Iliev7e910df2017-06-02 10:29:21 -0400593 return SkImage::MakeFromGenerator(std::move(gen));
594}
Greg Danielb6c15ba2019-03-04 13:08:25 -0500595
596sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
597 const SkPixmap& pixmap,
598 AHardwareBuffer* hardwareBuffer,
599 GrSurfaceOrigin surfaceOrigin) {
600 AHardwareBuffer_Desc bufferDesc;
601 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
602
603 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
604 return nullptr;
605 }
606
607 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
608 hardwareBuffer,
609 bufferDesc.format,
610 true);
611
612 if (!backendFormat.isValid()) {
613 return nullptr;
614 }
615
616 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
Stan Ilieva56b04a2019-08-01 14:22:34 -0400617 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
618 GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
Greg Danielb6c15ba2019-03-04 13:08:25 -0500619
620 GrBackendTexture backendTexture =
621 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
622 bufferDesc.width, bufferDesc.height,
Stan Ilieva56b04a2019-08-01 14:22:34 -0400623 &deleteImageProc, &updateImageProc,
624 &deleteImageCtx, false, backendFormat, true);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500625 if (!backendTexture.isValid()) {
626 return nullptr;
627 }
628 SkASSERT(deleteImageProc);
629
630 SkColorType colorType =
631 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
632
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400633 GrColorType grColorType = SkColorTypeToGrColorType(colorType);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500634
635 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
636 if (!proxyProvider) {
637 deleteImageProc(deleteImageCtx);
638 return nullptr;
639 }
640
641 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400642 proxyProvider->wrapBackendTexture(backendTexture, grColorType, surfaceOrigin,
Greg Danielb6c15ba2019-03-04 13:08:25 -0500643 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
644 kRW_GrIOType, deleteImageProc, deleteImageCtx);
645 if (!proxy) {
646 deleteImageProc(deleteImageCtx);
647 return nullptr;
648 }
649
650 sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
651 SkAlphaType at = pixmap.alphaType();
652
653 sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, at,
654 proxy, cs);
655 if (!image) {
656 return nullptr;
657 }
658
659 GrDrawingManager* drawingManager = context->priv().drawingManager();
660 if (!drawingManager) {
661 return nullptr;
662 }
663
Brian Salomone7499c72019-06-24 12:12:36 -0400664 sk_sp<GrTextureContext> texContext =
Brian Salomond6287472019-06-24 15:50:07 -0400665 drawingManager->makeTextureContext(proxy, SkColorTypeToGrColorType(pixmap.colorType()),
666 pixmap.alphaType(), cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500667 if (!texContext) {
668 return nullptr;
669 }
670
671 SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
672 std::move(cs));
Brian Salomon1d435302019-07-01 13:05:28 -0400673 texContext->writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), {0, 0});
Greg Danielb6c15ba2019-03-04 13:08:25 -0500674
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400675 GrFlushInfo info;
676 info.fFlags = kSyncCpu_GrFlushFlag;
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400677 GrSurfaceProxy* p[1] = {proxy.get()};
Greg Daniel797efca2019-05-09 14:04:20 -0400678 drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
679 GrPrepareForExternalIORequests());
Greg Danielb6c15ba2019-03-04 13:08:25 -0500680
681 return image;
682}
Stan Iliev7e910df2017-06-02 10:29:21 -0400683#endif
684
reed56179002015-07-07 06:11:19 -0700685///////////////////////////////////////////////////////////////////////////////////////////////////
686
Eric Karl914a36b2017-10-12 12:44:50 -0700687bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
688 sk_sp<SkImage> image,
689 GrBackendTexture* backendTexture,
690 BackendTextureReleaseProc* releaseProc) {
691 if (!image || !ctx || !backendTexture || !releaseProc) {
692 return false;
693 }
694
695 // Ensure we have a texture backed image.
696 if (!image->isTextureBacked()) {
Brian Osmand566e2e2019-08-14 13:19:04 -0400697 image = image->makeTextureImage(ctx);
Eric Karl914a36b2017-10-12 12:44:50 -0700698 if (!image) {
699 return false;
700 }
701 }
702 GrTexture* texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800703 if (!texture) {
704 // In context-loss cases, we may not have a texture.
705 return false;
706 }
Eric Karl914a36b2017-10-12 12:44:50 -0700707
708 // If the image's context doesn't match the provided context, fail.
709 if (texture->getContext() != ctx) {
710 return false;
711 }
712
713 // Flush any pending IO on the texture.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400714 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700715 SkASSERT(!texture->surfacePriv().hasPendingIO());
716
717 // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
718 // image is not unique, or if the texture wraps an external object.
719 if (!image->unique() || !texture->surfacePriv().hasUniqueRef() ||
720 texture->resourcePriv().refsWrappedObjects()) {
721 // onMakeSubset will always copy the image.
Robert Phillips6603a172019-03-05 12:35:44 -0500722 image = as_IB(image)->onMakeSubset(ctx, image->bounds());
Eric Karl914a36b2017-10-12 12:44:50 -0700723 if (!image) {
724 return false;
725 }
726
727 texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800728 if (!texture) {
729 return false;
730 }
Eric Karl914a36b2017-10-12 12:44:50 -0700731
732 // Flush to ensure that the copy is completed before we return the texture.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400733 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700734 SkASSERT(!texture->surfacePriv().hasPendingIO());
735 }
736
737 SkASSERT(!texture->resourcePriv().refsWrappedObjects());
738 SkASSERT(texture->surfacePriv().hasUniqueRef());
739 SkASSERT(image->unique());
740
741 // Take a reference to the GrTexture and release the image.
742 sk_sp<GrTexture> textureRef(SkSafeRef(texture));
743 image = nullptr;
744
745 // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
746 return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
747}