blob: 88e0b1172d49cc309aaef7aa9407941dae608b48 [file] [log] [blame]
reed@google.com5d4ba882012-07-31 15:45:27 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
cblume33e0cb52016-08-30 12:09:23 -07008#include <cstddef>
9#include <cstring>
10#include <type_traits>
11
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkCanvas.h"
13#include "include/gpu/GrBackendSurface.h"
14#include "include/gpu/GrContext.h"
15#include "include/gpu/GrTexture.h"
16#include "include/private/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "include/private/SkImageInfoPriv.h"
18#include "src/core/SkAutoPixmapStorage.h"
19#include "src/core/SkBitmapCache.h"
20#include "src/core/SkMipMap.h"
21#include "src/core/SkScopeExit.h"
22#include "src/core/SkTraceEvent.h"
23#include "src/gpu/GrAHardwareBufferImageGenerator.h"
24#include "src/gpu/GrAHardwareBufferUtils.h"
25#include "src/gpu/GrBackendTextureImageGenerator.h"
26#include "src/gpu/GrBitmapTextureMaker.h"
27#include "src/gpu/GrCaps.h"
28#include "src/gpu/GrClip.h"
29#include "src/gpu/GrColorSpaceXform.h"
30#include "src/gpu/GrContextPriv.h"
31#include "src/gpu/GrDrawingManager.h"
32#include "src/gpu/GrGpu.h"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040033#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050034#include "src/gpu/GrImageTextureMaker.h"
35#include "src/gpu/GrProxyProvider.h"
36#include "src/gpu/GrRecordingContextPriv.h"
37#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050038#include "src/gpu/GrSemaphore.h"
39#include "src/gpu/GrSurfacePriv.h"
40#include "src/gpu/GrTextureAdjuster.h"
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()) {
70 return GrSemaphoresSubmitted::kNo;
71 }
72
Greg Daniel81b98972019-12-13 11:09:43 -050073 GrSurfaceProxy* p[1] = {fView.proxy()};
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040074 return context->priv().flushSurfaces(p, 1, info);
75}
76
Robert Phillips6603a172019-03-05 12:35:44 -050077sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
78 SkColorType targetCT,
Brian Osmanf48c9962019-01-14 11:15:50 -050079 sk_sp<SkColorSpace> targetCS) const {
Robert Phillips6603a172019-03-05 12:35:44 -050080 if (!context || !fContext->priv().matches(context)) {
81 return nullptr;
82 }
83
Brian Salomon5ad6fd32019-03-21 15:30:08 -040084 auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
85 targetCS.get(), this->alphaType());
Brian Osmanf48c9962019-01-14 11:15:50 -050086 SkASSERT(xform || targetCT != this->colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050087
Greg Daniele20fcad2020-01-08 11:52:34 -050088 auto renderTargetContext = GrRenderTargetContext::MakeWithFallback(
89 context, SkColorTypeToGrColorType(targetCT), nullptr, SkBackingFit::kExact,
90 this->dimensions());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050091 if (!renderTargetContext) {
92 return nullptr;
93 }
94
95 GrPaint paint;
96 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
Greg Daniel81b98972019-12-13 11:09:43 -050097 sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
Brian Salomonbfb72112020-01-13 10:51:50 -050098 paint.addColorFragmentProcessor(GrTextureEffect::Make(std::move(proxy), this->alphaType()));
Brian Osmanf48c9962019-01-14 11:15:50 -050099 if (xform) {
100 paint.addColorFragmentProcessor(std::move(xform));
101 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500102
103 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
104 SkRect::MakeIWH(this->width(), this->height()));
105 if (!renderTargetContext->asTextureProxy()) {
106 return nullptr;
107 }
108
Greg Daniel7c165a42020-01-22 12:22:36 -0500109 targetCT = GrColorTypeToSkColorType(renderTargetContext->colorInfo().colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500110 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Greg Daniel7c165a42020-01-22 12:22:36 -0500111 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
112 renderTargetContext->readSurfaceView(), targetCT,
113 this->alphaType(), std::move(targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500114}
115
Brian Osmand5148372019-08-14 16:14:51 -0400116sk_sp<SkImage> SkImage_Gpu::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Greg Daniel7c165a42020-01-22 12:22:36 -0500117 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, fView, this->colorType(),
118 this->alphaType(), std::move(newCS));
Brian Osmand5148372019-08-14 16:14:51 -0400119}
120
reed8b26b992015-05-07 15:36:17 -0700121///////////////////////////////////////////////////////////////////////////////////////////////////
122
Greg Daniel7ef28f32017-04-20 16:41:55 +0000123static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
124 const GrBackendTexture& backendTex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400125 GrColorType colorType, GrSurfaceOrigin origin,
brianosmandddbe382016-07-20 13:55:39 -0700126 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
127 GrWrapOwnership ownership,
reed7fb4f8b2016-03-11 04:33:52 -0800128 SkImage::TextureReleaseProc releaseProc,
129 SkImage::ReleaseContext releaseCtx) {
Greg Daniel66aebf32018-04-09 09:15:56 -0400130 if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700131 return nullptr;
reed8b26b992015-05-07 15:36:17 -0700132 }
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400133
Robert Phillips9da87e02019-02-04 13:26:26 -0500134 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500135 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400136 proxyProvider->wrapBackendTexture(backendTex, colorType, origin, ownership,
137 GrWrapCacheable::kNo, kRead_GrIOType,
138 releaseProc, releaseCtx);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500139 if (!proxy) {
Robert Phillipse201ebc2018-01-17 18:12:50 +0000140 return nullptr;
141 }
Greg Daniel81b98972019-12-13 11:09:43 -0500142
Greg Daniel14b57212019-12-17 16:18:06 -0500143 GrSwizzle swizzle = ctx->priv().caps()->getReadSwizzle(proxy->backendFormat(), colorType);
Greg Daniel81b98972019-12-13 11:09:43 -0500144 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
Greg Daniel7c165a42020-01-22 12:22:36 -0500145 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, std::move(view),
146 GrColorTypeToSkColorType(colorType), at, std::move(colorSpace));
bsalomon6dc6f5f2015-06-18 09:12:16 -0700147}
148
Robert Phillipsb915c942019-12-17 14:44:37 -0500149sk_sp<SkImage> SkImage::MakeFromCompressedTexture(GrContext* ctx,
150 const GrBackendTexture& tex,
151 GrSurfaceOrigin origin,
152 SkAlphaType at,
153 sk_sp<SkColorSpace> cs,
154 TextureReleaseProc releaseP,
155 ReleaseContext releaseC) {
Robert Phillipsead321b2019-12-19 10:16:32 -0500156 if (!ctx) {
157 return nullptr;
158 }
159
160 const GrCaps* caps = ctx->priv().caps();
161
162 if (!SkImage_GpuBase::ValidateCompressedBackendTexture(caps, tex, at)) {
163 return nullptr;
164 }
165
166 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
167 sk_sp<GrTextureProxy> proxy =
168 proxyProvider->wrapCompressedBackendTexture(tex, origin, kBorrow_GrWrapOwnership,
169 GrWrapCacheable::kNo, releaseP, releaseC);
170 if (!proxy) {
171 return nullptr;
172 }
173
Greg Daniel7c165a42020-01-22 12:22:36 -0500174 CompressionType type = caps->compressionType(tex.getBackendFormat());
175 SkColorType ct = GrCompressionTypeToSkColorType(type);
176
Robert Phillipsead321b2019-12-19 10:16:32 -0500177 GrSurfaceProxyView view(std::move(proxy), origin, GrSwizzle::RGBA());
Greg Daniel7c165a42020-01-22 12:22:36 -0500178 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, std::move(view), ct, at,
Robert Phillipsead321b2019-12-19 10:16:32 -0500179 std::move(cs));
Robert Phillipsb915c942019-12-17 14:44:37 -0500180}
181
Greg Danielf5d87582017-12-18 14:48:15 -0500182sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
183 const GrBackendTexture& tex, GrSurfaceOrigin origin,
184 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
185 TextureReleaseProc releaseP, ReleaseContext releaseC) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500186 if (!ctx) {
187 return nullptr;
188 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400189
Robert Phillips62221e72019-07-24 15:07:38 -0400190 const GrCaps* caps = ctx->priv().caps();
191
192 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400193 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400194 return nullptr;
195 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400196
Robert Phillips62221e72019-07-24 15:07:38 -0400197 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400198 return nullptr;
199 }
200
Robert Phillips62221e72019-07-24 15:07:38 -0400201 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomonbfd27492018-03-19 14:08:51 -0400202 kBorrow_GrWrapOwnership, releaseP, releaseC);
Greg Danielf5d87582017-12-18 14:48:15 -0500203}
204
Greg Daniel94403452017-04-18 15:52:36 -0400205sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
206 const GrBackendTexture& tex, GrSurfaceOrigin origin,
Brian Salomon42409c22018-03-20 13:48:41 -0400207 SkColorType ct, SkAlphaType at,
208 sk_sp<SkColorSpace> cs) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500209 if (!ctx || !ctx->priv().resourceProvider()) {
Greg Danielf2336e42018-01-23 16:38:14 -0500210 // We have a DDL context and we don't support adopted textures for them.
211 return nullptr;
212 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400213
Robert Phillips62221e72019-07-24 15:07:38 -0400214 const GrCaps* caps = ctx->priv().caps();
215
216 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400217 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400218 return nullptr;
219 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400220
Robert Phillips62221e72019-07-24 15:07:38 -0400221 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400222 return nullptr;
223 }
224
Robert Phillips62221e72019-07-24 15:07:38 -0400225 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomon42409c22018-03-20 13:48:41 -0400226 kAdopt_GrWrapOwnership, nullptr, nullptr);
Greg Danielf5d87582017-12-18 14:48:15 -0500227}
228
Jim Van Verthee06b332019-01-18 10:36:32 -0500229sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
Robert Phillipse4720c62020-01-14 14:33:24 -0500230 int width, int height, CompressionType type,
Robert Phillips3a833922020-01-21 15:25:58 -0500231 GrMipMapped mipMapped, GrProtected isProtected) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500232 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Salomonbb8dde82019-06-27 10:52:13 -0400233 sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
Robert Phillips3a833922020-01-21 15:25:58 -0500234 {width, height}, SkBudgeted::kYes, mipMapped, isProtected, type, std::move(data));
Jim Van Verthee06b332019-01-18 10:36:32 -0500235 if (!proxy) {
236 return nullptr;
237 }
Greg Daniel81b98972019-12-13 11:09:43 -0500238 // TODO: remove asserts when proxy doesn't hold origin or swizzle
239 SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
240 SkASSERT(proxy->textureSwizzle() == GrSwizzle());
241 GrSurfaceProxyView view(std::move(proxy));
Brian Salomon729fc0c2019-09-30 16:33:11 +0000242
Greg Daniel7c165a42020-01-22 12:22:36 -0500243 SkColorType colorType = GrCompressionTypeToSkColorType(type);
244
245 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, std::move(view),
246 colorType, kOpaque_SkAlphaType, nullptr);
Jim Van Verthee06b332019-01-18 10:36:32 -0500247}
248
Brian Salomonf05e6d32018-12-20 08:41:41 -0500249sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
250 const GrBackendTexture yuvaTextures[],
251 const SkYUVAIndex yuvaIndices[4], SkISize size,
252 GrSurfaceOrigin origin,
253 GrRenderTargetContext* renderTargetContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400254 SkASSERT(renderTargetContext);
255
Jim Van Verth0e671942018-11-09 12:03:57 -0500256 int numTextures;
257 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500258 return nullptr;
259 }
Robert Phillipsba5c4392018-07-25 12:37:14 -0400260
Jim Van Verth0e671942018-11-09 12:03:57 -0500261 sk_sp<GrTextureProxy> tempTextureProxies[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500262 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
263 origin, tempTextureProxies)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500264 return nullptr;
265 }
266
267 const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
Brian Osmane9560492019-02-05 17:00:03 -0500268 if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
Jim Van Verth0e671942018-11-09 12:03:57 -0500269 tempTextureProxies, yuvaIndices)) {
270 return nullptr;
271 }
Robert Phillipsb726d582017-03-09 16:36:32 -0500272
Greg Daniel7c165a42020-01-22 12:22:36 -0500273 SkColorType ct = GrColorTypeToSkColorType(renderTargetContext->colorInfo().colorType());
Jim Van Verth53275362018-11-09 15:42:35 -0500274 SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillipsb726d582017-03-09 16:36:32 -0500275 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Greg Daniel7c165a42020-01-22 12:22:36 -0500276 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID,
277 renderTargetContext->readSurfaceView(), ct, at,
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400278 renderTargetContext->colorInfo().refColorSpace());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400279}
280
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400281sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
282 SkYUVColorSpace yuvColorSpace,
283 const GrBackendTexture yuvaTextures[],
284 const SkYUVAIndex yuvaIndices[4],
285 SkISize imageSize,
286 GrSurfaceOrigin imageOrigin,
287 sk_sp<SkColorSpace> imageColorSpace) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500288 auto renderTargetContext = GrRenderTargetContext::Make(
289 ctx, GrColorType::kRGBA_8888, std::move(imageColorSpace), SkBackingFit::kExact,
290 imageSize, 1, GrMipMapped::kNo, GrProtected::kNo, imageOrigin);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400291 if (!renderTargetContext) {
292 return nullptr;
293 }
294
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400295 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500296 imageSize, imageOrigin, renderTargetContext.get());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400297}
298
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400299sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
Brian Salomond2fcfb52018-09-17 21:57:11 -0400300 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400301 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400302 const GrBackendTexture yuvaTextures[],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400303 const SkYUVAIndex yuvaIndices[4],
304 SkISize imageSize,
305 GrSurfaceOrigin imageOrigin,
306 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400307 sk_sp<SkColorSpace> imageColorSpace,
308 TextureReleaseProc textureReleaseProc,
309 ReleaseContext releaseContext) {
Robert Phillips62221e72019-07-24 15:07:38 -0400310 const GrCaps* caps = ctx->priv().caps();
Robert Phillipsdd399802019-07-18 12:28:00 +0000311
Robert Phillips62221e72019-07-24 15:07:38 -0400312 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, kRGBA_8888_SkColorType,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400313 backendTexture.getBackendFormat());
314 if (GrColorType::kUnknown == grColorType) {
315 return nullptr;
316 }
317
Jim Van Verth53275362018-11-09 15:42:35 -0500318 SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillips62221e72019-07-24 15:07:38 -0400319 if (!SkImage_Gpu::ValidateBackendTexture(caps, backendTexture, grColorType,
320 kRGBA_8888_SkColorType, at, nullptr)) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400321 return nullptr;
322 }
323
324 // Needs to create a render target with external texture
325 // in order to draw to it for the yuv->rgb conversion.
Greg Danielba0ff782020-01-07 15:42:57 -0500326 auto renderTargetContext = GrRenderTargetContext::MakeFromBackendTexture(
327 ctx, grColorType, std::move(imageColorSpace), backendTexture, 1, imageOrigin,
328 nullptr, textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400329 if (!renderTargetContext) {
330 return nullptr;
331 }
332
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400333 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500334 imageSize, imageOrigin, renderTargetContext.get());
Robert Phillipsc25db632017-12-13 09:22:45 -0500335}
336
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400337sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400338 const GrBackendTexture yuvTextures[3],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400339 GrSurfaceOrigin imageOrigin,
Brian Salomon6a426c12018-03-15 12:16:02 -0400340 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400341 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
342 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400343 SkYUVAIndex{0, SkColorChannel::kR},
344 SkYUVAIndex{1, SkColorChannel::kR},
345 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400346 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400347 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400348 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
349 size, imageOrigin, std::move(imageColorSpace));
bsalomon993a4212015-05-29 11:37:25 -0700350}
reed56179002015-07-07 06:11:19 -0700351
Brian Salomond2fcfb52018-09-17 21:57:11 -0400352sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400353 GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
354 GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400355 sk_sp<SkColorSpace> imageColorSpace) {
356 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400357 SkYUVAIndex{0, SkColorChannel::kR},
358 SkYUVAIndex{1, SkColorChannel::kR},
359 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400360 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400361 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400362 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
363 ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400364 std::move(imageColorSpace), nullptr, nullptr);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400365}
366
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400367sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400368 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400369 GrSurfaceOrigin imageOrigin,
brianosmandddbe382016-07-20 13:55:39 -0700370 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400371 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
372 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400373 SkYUVAIndex{0, SkColorChannel::kR},
374 SkYUVAIndex{1, SkColorChannel::kR},
375 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400376 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400377 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400378 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
379 size, imageOrigin, std::move(imageColorSpace));
Robert Phillipsc25db632017-12-13 09:22:45 -0500380}
381
Brian Salomond2fcfb52018-09-17 21:57:11 -0400382sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
383 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400384 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400385 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400386 GrSurfaceOrigin imageOrigin,
387 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400388 sk_sp<SkColorSpace> imageColorSpace,
389 TextureReleaseProc textureReleaseProc,
390 ReleaseContext releaseContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400391 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400392 SkYUVAIndex{0, SkColorChannel::kR},
393 SkYUVAIndex{1, SkColorChannel::kR},
394 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400395 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400396 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400397 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
398 ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400399 std::move(imageColorSpace), textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400400}
401
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400402static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
Greg Daniel7c165a42020-01-22 12:22:36 -0500403 uint32_t id, GrMipMapped mipMapped) {
Greg Daniel81b98972019-12-13 11:09:43 -0500404 // TODO: have texture producer return a GrSurfaceProxyView
Greg Daniel82c6b102020-01-21 10:33:22 -0500405 auto [proxy, colorType] = producer->refTextureProxy(mipMapped);
Robert Phillips3798c862017-03-27 11:08:16 -0400406 if (!proxy) {
Brian Osman041f7df2017-02-07 11:23:28 -0500407 return nullptr;
408 }
Greg Daniel81b98972019-12-13 11:09:43 -0500409 GrSurfaceOrigin origin = proxy->origin();
410 const GrSwizzle& swizzle = proxy->textureSwizzle();
411 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
Greg Daniel7c165a42020-01-22 12:22:36 -0500412 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, std::move(view),
413 GrColorTypeToSkColorType(colorType),
414 producer->alphaType(), sk_ref_sp(producer->colorSpace()));
Brian Osman041f7df2017-02-07 11:23:28 -0500415}
416
Brian Osmand566e2e2019-08-14 13:19:04 -0400417sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, GrMipMapped mipMapped) const {
Brian Osman041f7df2017-02-07 11:23:28 -0500418 if (!context) {
419 return nullptr;
420 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500421
422 if (this->isTextureBacked()) {
423 if (!as_IB(this)->context()->priv().matches(context)) {
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400424 return nullptr;
425 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500426
Robert Phillips6603a172019-03-05 12:35:44 -0500427 sk_sp<GrTextureProxy> proxy = as_IB(this)->asTextureProxyRef(context);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400428 SkASSERT(proxy);
429 if (GrMipMapped::kNo == mipMapped || proxy->mipMapped() == mipMapped) {
430 return sk_ref_sp(const_cast<SkImage*>(this));
431 }
Brian Salomon1a217eb2019-10-24 10:50:36 -0400432 GrTextureAdjuster adjuster(context, std::move(proxy), this->imageInfo().colorInfo(),
433 this->uniqueID());
Greg Daniel7c165a42020-01-22 12:22:36 -0500434 return create_image_from_producer(context, &adjuster, this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500435 }
436
Brian Osmandf7e0752017-04-26 16:20:28 -0400437 if (this->isLazyGenerated()) {
438 GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
Greg Daniel7c165a42020-01-22 12:22:36 -0500439 return create_image_from_producer(context, &maker, this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500440 }
441
442 if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
443 GrBitmapTextureMaker maker(context, *bmp);
Greg Daniel7c165a42020-01-22 12:22:36 -0500444 return create_image_from_producer(context, &maker, this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500445 }
446 return nullptr;
447}
448
Greg Daniel7278d682018-03-16 14:57:21 -0400449///////////////////////////////////////////////////////////////////////////////////////////////////
450
Greg Daniela8d92112018-03-09 12:05:04 -0500451sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
452 const GrBackendFormat& backendFormat,
453 int width,
454 int height,
455 GrMipMapped mipMapped,
456 GrSurfaceOrigin origin,
457 SkColorType colorType,
458 SkAlphaType alphaType,
459 sk_sp<SkColorSpace> colorSpace,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500460 PromiseImageTextureFulfillProc textureFulfillProc,
461 PromiseImageTextureReleaseProc textureReleaseProc,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500462 PromiseImageTextureDoneProc textureDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500463 PromiseImageTextureContext textureContext,
464 PromiseImageApiVersion version) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400465 // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500466 // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
467 // responsibility for calling the done proc.
Brian Salomonf55e8d52019-01-30 17:28:20 -0500468 if (!textureDoneProc) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400469 return nullptr;
470 }
Brian Salomonf55e8d52019-01-30 17:28:20 -0500471 SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
Robert Phillipsef85d192018-10-09 11:24:09 -0400472
Brian Salomonbe5a0932018-12-10 10:03:26 -0500473 SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
474 if (!SkImageInfoIsValid(info)) {
475 return nullptr;
476 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400477
Greg Daniela8d92112018-03-09 12:05:04 -0500478 if (!context) {
479 return nullptr;
480 }
481
482 if (width <= 0 || height <= 0) {
483 return nullptr;
484 }
485
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400486 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
487 colorType,
488 backendFormat);
489 if (GrColorType::kUnknown == grColorType) {
Greg Daniela8d92112018-03-09 12:05:04 -0500490 return nullptr;
491 }
492
Brian Salomonbe5a0932018-12-10 10:03:26 -0500493 callDone.clear();
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400494 auto proxy = MakePromiseImageLazyProxy(context, width, height, origin,
495 grColorType, backendFormat,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500496 mipMapped, textureFulfillProc, textureReleaseProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500497 textureDoneProc, textureContext, version);
Greg Daniela8d92112018-03-09 12:05:04 -0500498 if (!proxy) {
499 return nullptr;
500 }
Greg Daniel14b57212019-12-17 16:18:06 -0500501 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
Greg Daniel81b98972019-12-13 11:09:43 -0500502 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
Greg Daniel7c165a42020-01-22 12:22:36 -0500503 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, std::move(view),
504 colorType, alphaType, std::move(colorSpace));
Greg Daniela8d92112018-03-09 12:05:04 -0500505}
506
Greg Daniel7278d682018-03-16 14:57:21 -0400507///////////////////////////////////////////////////////////////////////////////////////////////////
508
Brian Osman584b5012018-04-13 15:48:26 -0400509sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
510 const SkPixmap& originalPixmap, bool buildMips,
Brian Osman584b5012018-04-13 15:48:26 -0400511 bool limitToMaxTextureSize) {
Brian Osman63bc48d2017-11-07 10:37:00 -0500512 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500513 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman584b5012018-04-13 15:48:26 -0400514 return SkImage::MakeRasterCopy(originalPixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500515 }
516
Greg Daniel9e788112018-02-08 14:29:37 -0500517 // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
518 // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
519 // instead.
Robert Phillips9da87e02019-02-04 13:26:26 -0500520 if (!context->priv().resourceProvider()) {
Brian Osman584b5012018-04-13 15:48:26 -0400521 return SkImage::MakeRasterCopy(originalPixmap);
Greg Daniel9e788112018-02-08 14:29:37 -0500522 }
523
Brian Osman0471a932019-02-07 13:36:56 -0500524 // If non-power-of-two mipmapping isn't supported, ignore the client's request
525 if (!context->priv().caps()->mipMapSupport()) {
526 buildMips = false;
527 }
528
Brian Osman584b5012018-04-13 15:48:26 -0400529 const SkPixmap* pixmap = &originalPixmap;
530 SkAutoPixmapStorage resized;
Robert Phillips9da87e02019-02-04 13:26:26 -0500531 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Osman584b5012018-04-13 15:48:26 -0400532 int maxDim = SkTMax(originalPixmap.width(), originalPixmap.height());
533 if (limitToMaxTextureSize && maxDim > maxTextureSize) {
534 float scale = static_cast<float>(maxTextureSize) / maxDim;
535 int newWidth = SkTMin(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
536 int newHeight = SkTMin(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
537 SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
538 if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
539 return nullptr;
540 }
541 pixmap = &resized;
542 }
Brian Osman63bc48d2017-11-07 10:37:00 -0500543 // Turn the pixmap into a GrTextureProxy
Brian Osman7dcc6162019-03-25 10:12:57 -0400544 SkBitmap bmp;
545 bmp.installPixels(*pixmap);
Greg Daniel82c6b102020-01-21 10:33:22 -0500546 GrBitmapTextureMaker bitmapMaker(context, bmp, false, false);
Brian Osman7dcc6162019-03-25 10:12:57 -0400547 GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
Greg Daniel82c6b102020-01-21 10:33:22 -0500548 auto [proxy, grCT] = bitmapMaker.refTextureProxy(mipMapped);
Brian Osman63bc48d2017-11-07 10:37:00 -0500549 if (!proxy) {
Brian Osman584b5012018-04-13 15:48:26 -0400550 return SkImage::MakeRasterCopy(*pixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500551 }
552
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400553 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Brian Osman63bc48d2017-11-07 10:37:00 -0500554
555 // Flush any writes or uploads
Greg Daniel4aa13e72019-04-15 14:42:20 -0400556 context->priv().flushSurface(proxy.get());
Robert Phillips9da87e02019-02-04 13:26:26 -0500557 GrGpu* gpu = context->priv().getGpu();
Brian Osman63bc48d2017-11-07 10:37:00 -0500558
Greg Daniel301015c2019-11-18 14:06:46 -0500559 std::unique_ptr<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman63bc48d2017-11-07 10:37:00 -0500560
Greg Daniel82c6b102020-01-21 10:33:22 -0500561 SkColorType skCT = GrColorTypeToSkColorType(grCT);
Brian Osman63bc48d2017-11-07 10:37:00 -0500562 auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
Greg Daniel82c6b102020-01-21 10:33:22 -0500563 std::move(sema), skCT,
Brian Osman584b5012018-04-13 15:48:26 -0400564 pixmap->alphaType(),
565 pixmap->info().refColorSpace());
Brian Osman63bc48d2017-11-07 10:37:00 -0500566 return SkImage::MakeFromGenerator(std::move(gen));
567}
568
Derek Sollenberger7a869872017-06-27 15:37:25 -0400569#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -0400570sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
Stan Iliev505dd572018-09-13 14:20:03 -0400571 sk_sp<SkColorSpace> cs,
572 GrSurfaceOrigin surfaceOrigin) {
573 auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
Stan Iliev7e910df2017-06-02 10:29:21 -0400574 return SkImage::MakeFromGenerator(std::move(gen));
575}
Greg Danielb6c15ba2019-03-04 13:08:25 -0500576
577sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
578 const SkPixmap& pixmap,
579 AHardwareBuffer* hardwareBuffer,
580 GrSurfaceOrigin surfaceOrigin) {
581 AHardwareBuffer_Desc bufferDesc;
582 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
583
584 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
585 return nullptr;
586 }
587
588 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
589 hardwareBuffer,
590 bufferDesc.format,
591 true);
592
593 if (!backendFormat.isValid()) {
594 return nullptr;
595 }
596
597 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
Stan Ilieva56b04a2019-08-01 14:22:34 -0400598 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
599 GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
Greg Danielb6c15ba2019-03-04 13:08:25 -0500600
601 GrBackendTexture backendTexture =
602 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
603 bufferDesc.width, bufferDesc.height,
Stan Ilieva56b04a2019-08-01 14:22:34 -0400604 &deleteImageProc, &updateImageProc,
605 &deleteImageCtx, false, backendFormat, true);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500606 if (!backendTexture.isValid()) {
607 return nullptr;
608 }
609 SkASSERT(deleteImageProc);
610
611 SkColorType colorType =
612 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
613
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400614 GrColorType grColorType = SkColorTypeToGrColorType(colorType);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500615
616 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
617 if (!proxyProvider) {
618 deleteImageProc(deleteImageCtx);
619 return nullptr;
620 }
621
622 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400623 proxyProvider->wrapBackendTexture(backendTexture, grColorType, surfaceOrigin,
Greg Danielb6c15ba2019-03-04 13:08:25 -0500624 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
625 kRW_GrIOType, deleteImageProc, deleteImageCtx);
626 if (!proxy) {
627 deleteImageProc(deleteImageCtx);
628 return nullptr;
629 }
630
631 sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
632 SkAlphaType at = pixmap.alphaType();
633
Greg Daniel14b57212019-12-17 16:18:06 -0500634 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
Greg Daniel3912a4b2020-01-14 09:56:04 -0500635 GrSurfaceProxyView view(std::move(proxy), surfaceOrigin, swizzle);
Greg Daniel7c165a42020-01-22 12:22:36 -0500636 sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, view,
637 colorType, at, cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500638 if (!image) {
639 return nullptr;
640 }
641
642 GrDrawingManager* drawingManager = context->priv().drawingManager();
643 if (!drawingManager) {
644 return nullptr;
645 }
646
Greg Daniel3912a4b2020-01-14 09:56:04 -0500647 GrSurfaceContext surfaceContext(context, std::move(view),
Greg Danielbfa19c42019-12-19 16:41:40 -0500648 SkColorTypeToGrColorType(pixmap.colorType()),
Greg Daniel3912a4b2020-01-14 09:56:04 -0500649 pixmap.alphaType(), cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500650
651 SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
652 std::move(cs));
Greg Danielbfa19c42019-12-19 16:41:40 -0500653 surfaceContext.writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), {0, 0});
Greg Danielb6c15ba2019-03-04 13:08:25 -0500654
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400655 GrFlushInfo info;
656 info.fFlags = kSyncCpu_GrFlushFlag;
Greg Danielbfa19c42019-12-19 16:41:40 -0500657 GrSurfaceProxy* p[1] = {surfaceContext.asSurfaceProxy()};
Greg Daniel797efca2019-05-09 14:04:20 -0400658 drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
659 GrPrepareForExternalIORequests());
Greg Danielb6c15ba2019-03-04 13:08:25 -0500660
661 return image;
662}
Stan Iliev7e910df2017-06-02 10:29:21 -0400663#endif
664
reed56179002015-07-07 06:11:19 -0700665///////////////////////////////////////////////////////////////////////////////////////////////////
666
Eric Karl914a36b2017-10-12 12:44:50 -0700667bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
668 sk_sp<SkImage> image,
669 GrBackendTexture* backendTexture,
670 BackendTextureReleaseProc* releaseProc) {
671 if (!image || !ctx || !backendTexture || !releaseProc) {
672 return false;
673 }
674
675 // Ensure we have a texture backed image.
676 if (!image->isTextureBacked()) {
Brian Osmand566e2e2019-08-14 13:19:04 -0400677 image = image->makeTextureImage(ctx);
Eric Karl914a36b2017-10-12 12:44:50 -0700678 if (!image) {
679 return false;
680 }
681 }
682 GrTexture* texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800683 if (!texture) {
684 // In context-loss cases, we may not have a texture.
685 return false;
686 }
Eric Karl914a36b2017-10-12 12:44:50 -0700687
688 // If the image's context doesn't match the provided context, fail.
689 if (texture->getContext() != ctx) {
690 return false;
691 }
692
693 // Flush any pending IO on the texture.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400694 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700695
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.
Robert Phillipsaee18c92019-09-06 11:48:27 -0400698 if (!image->unique() || !texture->unique() ||
Eric Karl914a36b2017-10-12 12:44:50 -0700699 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.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400712 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700713 }
714
715 SkASSERT(!texture->resourcePriv().refsWrappedObjects());
Robert Phillipsaee18c92019-09-06 11:48:27 -0400716 SkASSERT(texture->unique());
Eric Karl914a36b2017-10-12 12:44:50 -0700717 SkASSERT(image->unique());
718
719 // Take a reference to the GrTexture and release the image.
720 sk_sp<GrTexture> textureRef(SkSafeRef(texture));
721 image = nullptr;
722
723 // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
724 return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
725}