blob: 7742fbad177943b460448ee81dbb1dab59fabb9f [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 Daniel81b98972019-12-13 11:09:43 -050048static SkColorType proxy_color_type(GrSurfaceProxy* proxy) {
Brian Salomon729fc0c2019-09-30 16:33:11 +000049 SkColorType colorType;
50 if (!GrPixelConfigToColorType(proxy->config(), &colorType)) {
51 colorType = kUnknown_SkColorType;
52 }
53 return colorType;
54}
55
56SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, SkAlphaType at,
Greg Daniel81b98972019-12-13 11:09:43 -050057 GrSurfaceProxyView view, sk_sp<SkColorSpace> colorSpace)
58 : INHERITED(std::move(context), view.proxy()->backingStoreDimensions(), uniqueID,
59 proxy_color_type(view.proxy()), at, colorSpace)
60 , fView(std::move(view)) {}
piotaixrcef04f82014-07-14 07:48:04 -070061
Brian Salomon729fc0c2019-09-30 16:33:11 +000062SkImage_Gpu::~SkImage_Gpu() {}
63
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040064GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrContext* context, const GrFlushInfo& info) {
65 if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
66 return GrSemaphoresSubmitted::kNo;
67 }
68
Greg Daniel81b98972019-12-13 11:09:43 -050069 GrSurfaceProxy* p[1] = {fView.proxy()};
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040070 return context->priv().flushSurfaces(p, 1, info);
71}
72
Robert Phillips6603a172019-03-05 12:35:44 -050073sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
74 SkColorType targetCT,
Brian Osmanf48c9962019-01-14 11:15:50 -050075 sk_sp<SkColorSpace> targetCS) const {
Robert Phillips6603a172019-03-05 12:35:44 -050076 if (!context || !fContext->priv().matches(context)) {
77 return nullptr;
78 }
79
Brian Salomon5ad6fd32019-03-21 15:30:08 -040080 auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
81 targetCS.get(), this->alphaType());
Brian Osmanf48c9962019-01-14 11:15:50 -050082 SkASSERT(xform || targetCT != this->colorType());
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050083
Brian Salomonbf6b9792019-08-21 09:38:10 -040084 auto renderTargetContext = context->priv().makeDeferredRenderTargetContextWithFallback(
85 SkBackingFit::kExact, this->width(), this->height(), SkColorTypeToGrColorType(targetCT),
86 nullptr);
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050087 if (!renderTargetContext) {
88 return nullptr;
89 }
90
91 GrPaint paint;
92 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
Greg Daniel81b98972019-12-13 11:09:43 -050093 sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
Brian Salomonfc118442019-11-22 19:09:27 -050094 paint.addColorTextureProcessor(std::move(proxy), this->alphaType(), SkMatrix::I());
Brian Osmanf48c9962019-01-14 11:15:50 -050095 if (xform) {
96 paint.addColorFragmentProcessor(std::move(xform));
97 }
Jim Van Verth3e4c2f32019-01-11 13:32:45 -050098
99 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
100 SkRect::MakeIWH(this->width(), this->height()));
101 if (!renderTargetContext->asTextureProxy()) {
102 return nullptr;
103 }
104
105 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Brian Salomon729fc0c2019-09-30 16:33:11 +0000106 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
Greg Daniel46e366a2019-12-16 14:38:36 -0500107 renderTargetContext->readSurfaceView(), std::move(targetCS));
Jim Van Verth3e4c2f32019-01-11 13:32:45 -0500108}
109
Brian Osmand5148372019-08-14 16:14:51 -0400110sk_sp<SkImage> SkImage_Gpu::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
Greg Daniel81b98972019-12-13 11:09:43 -0500111 return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(), fView,
Brian Salomon729fc0c2019-09-30 16:33:11 +0000112 std::move(newCS));
Brian Osmand5148372019-08-14 16:14:51 -0400113}
114
reed8b26b992015-05-07 15:36:17 -0700115///////////////////////////////////////////////////////////////////////////////////////////////////
116
Greg Daniel7ef28f32017-04-20 16:41:55 +0000117static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
118 const GrBackendTexture& backendTex,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400119 GrColorType colorType, GrSurfaceOrigin origin,
brianosmandddbe382016-07-20 13:55:39 -0700120 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
121 GrWrapOwnership ownership,
reed7fb4f8b2016-03-11 04:33:52 -0800122 SkImage::TextureReleaseProc releaseProc,
123 SkImage::ReleaseContext releaseCtx) {
Greg Daniel66aebf32018-04-09 09:15:56 -0400124 if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700125 return nullptr;
reed8b26b992015-05-07 15:36:17 -0700126 }
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400127
Robert Phillips9da87e02019-02-04 13:26:26 -0500128 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500129 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400130 proxyProvider->wrapBackendTexture(backendTex, colorType, origin, ownership,
131 GrWrapCacheable::kNo, kRead_GrIOType,
132 releaseProc, releaseCtx);
Robert Phillipsadbe1322018-01-17 13:35:46 -0500133 if (!proxy) {
Robert Phillipse201ebc2018-01-17 18:12:50 +0000134 return nullptr;
135 }
Greg Daniel81b98972019-12-13 11:09:43 -0500136
Greg Daniel14b57212019-12-17 16:18:06 -0500137 GrSwizzle swizzle = ctx->priv().caps()->getReadSwizzle(proxy->backendFormat(), colorType);
Greg Daniel81b98972019-12-13 11:09:43 -0500138 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
139 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(view),
Brian Salomon729fc0c2019-09-30 16:33:11 +0000140 std::move(colorSpace));
bsalomon6dc6f5f2015-06-18 09:12:16 -0700141}
142
Robert Phillipsb915c942019-12-17 14:44:37 -0500143sk_sp<SkImage> SkImage::MakeFromCompressedTexture(GrContext* ctx,
144 const GrBackendTexture& tex,
145 GrSurfaceOrigin origin,
146 SkAlphaType at,
147 sk_sp<SkColorSpace> cs,
148 TextureReleaseProc releaseP,
149 ReleaseContext releaseC) {
Robert Phillipsead321b2019-12-19 10:16:32 -0500150 if (!ctx) {
151 return nullptr;
152 }
153
154 const GrCaps* caps = ctx->priv().caps();
155
156 if (!SkImage_GpuBase::ValidateCompressedBackendTexture(caps, tex, at)) {
157 return nullptr;
158 }
159
160 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
161 sk_sp<GrTextureProxy> proxy =
162 proxyProvider->wrapCompressedBackendTexture(tex, origin, kBorrow_GrWrapOwnership,
163 GrWrapCacheable::kNo, releaseP, releaseC);
164 if (!proxy) {
165 return nullptr;
166 }
167
168 GrSurfaceProxyView view(std::move(proxy), origin, GrSwizzle::RGBA());
169 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(view),
170 std::move(cs));
Robert Phillipsb915c942019-12-17 14:44:37 -0500171}
172
Greg Danielf5d87582017-12-18 14:48:15 -0500173sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
174 const GrBackendTexture& tex, GrSurfaceOrigin origin,
175 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
176 TextureReleaseProc releaseP, ReleaseContext releaseC) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500177 if (!ctx) {
178 return nullptr;
179 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400180
Robert Phillips62221e72019-07-24 15:07:38 -0400181 const GrCaps* caps = ctx->priv().caps();
182
183 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400184 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400185 return nullptr;
186 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400187
Robert Phillips62221e72019-07-24 15:07:38 -0400188 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400189 return nullptr;
190 }
191
Robert Phillips62221e72019-07-24 15:07:38 -0400192 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomonbfd27492018-03-19 14:08:51 -0400193 kBorrow_GrWrapOwnership, releaseP, releaseC);
Greg Danielf5d87582017-12-18 14:48:15 -0500194}
195
Greg Daniel94403452017-04-18 15:52:36 -0400196sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
197 const GrBackendTexture& tex, GrSurfaceOrigin origin,
Brian Salomon42409c22018-03-20 13:48:41 -0400198 SkColorType ct, SkAlphaType at,
199 sk_sp<SkColorSpace> cs) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500200 if (!ctx || !ctx->priv().resourceProvider()) {
Greg Danielf2336e42018-01-23 16:38:14 -0500201 // We have a DDL context and we don't support adopted textures for them.
202 return nullptr;
203 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400204
Robert Phillips62221e72019-07-24 15:07:38 -0400205 const GrCaps* caps = ctx->priv().caps();
206
207 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400208 if (GrColorType::kUnknown == grColorType) {
Robert Phillips97256382019-07-17 15:26:36 -0400209 return nullptr;
210 }
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400211
Robert Phillips62221e72019-07-24 15:07:38 -0400212 if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400213 return nullptr;
214 }
215
Robert Phillips62221e72019-07-24 15:07:38 -0400216 return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
Brian Salomon42409c22018-03-20 13:48:41 -0400217 kAdopt_GrWrapOwnership, nullptr, nullptr);
Greg Danielf5d87582017-12-18 14:48:15 -0500218}
219
Jim Van Verthee06b332019-01-18 10:36:32 -0500220sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
221 int width, int height, CompressionType type) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500222 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Salomonbb8dde82019-06-27 10:52:13 -0400223 sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
224 width, height, SkBudgeted::kYes, type, std::move(data));
Jim Van Verthee06b332019-01-18 10:36:32 -0500225 if (!proxy) {
226 return nullptr;
227 }
Greg Daniel81b98972019-12-13 11:09:43 -0500228 // TODO: remove asserts when proxy doesn't hold origin or swizzle
229 SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
230 SkASSERT(proxy->textureSwizzle() == GrSwizzle());
231 GrSurfaceProxyView view(std::move(proxy));
Brian Salomon729fc0c2019-09-30 16:33:11 +0000232
233 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
Greg Daniel81b98972019-12-13 11:09:43 -0500234 std::move(view), nullptr);
Jim Van Verthee06b332019-01-18 10:36:32 -0500235}
236
Brian Salomonf05e6d32018-12-20 08:41:41 -0500237sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
238 const GrBackendTexture yuvaTextures[],
239 const SkYUVAIndex yuvaIndices[4], SkISize size,
240 GrSurfaceOrigin origin,
241 GrRenderTargetContext* renderTargetContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400242 SkASSERT(renderTargetContext);
243
Jim Van Verth0e671942018-11-09 12:03:57 -0500244 int numTextures;
245 if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500246 return nullptr;
247 }
Robert Phillipsba5c4392018-07-25 12:37:14 -0400248
Jim Van Verth0e671942018-11-09 12:03:57 -0500249 sk_sp<GrTextureProxy> tempTextureProxies[4];
Jim Van Verth53275362018-11-09 15:42:35 -0500250 if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
251 origin, tempTextureProxies)) {
Jim Van Verth0e671942018-11-09 12:03:57 -0500252 return nullptr;
253 }
254
255 const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
Brian Osmane9560492019-02-05 17:00:03 -0500256 if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
Jim Van Verth0e671942018-11-09 12:03:57 -0500257 tempTextureProxies, yuvaIndices)) {
258 return nullptr;
259 }
Robert Phillipsb726d582017-03-09 16:36:32 -0500260
Jim Van Verth53275362018-11-09 15:42:35 -0500261 SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillipsb726d582017-03-09 16:36:32 -0500262 // MDB: this call is okay bc we know 'renderTargetContext' was exact
Brian Salomon729fc0c2019-09-30 16:33:11 +0000263 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
Greg Daniel46e366a2019-12-16 14:38:36 -0500264 renderTargetContext->readSurfaceView(),
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400265 renderTargetContext->colorInfo().refColorSpace());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400266}
267
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400268sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
269 SkYUVColorSpace yuvColorSpace,
270 const GrBackendTexture yuvaTextures[],
271 const SkYUVAIndex yuvaIndices[4],
272 SkISize imageSize,
273 GrSurfaceOrigin imageOrigin,
274 sk_sp<SkColorSpace> imageColorSpace) {
275 const int width = imageSize.width();
276 const int height = imageSize.height();
Brian Salomond2fcfb52018-09-17 21:57:11 -0400277
278 // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400279 auto renderTargetContext = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400280 SkBackingFit::kExact, width, height, GrColorType::kRGBA_8888,
Brian Salomonbf6b9792019-08-21 09:38:10 -0400281 std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400282 if (!renderTargetContext) {
283 return nullptr;
284 }
285
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400286 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500287 imageSize, imageOrigin, renderTargetContext.get());
Brian Salomond2fcfb52018-09-17 21:57:11 -0400288}
289
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400290sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
Brian Salomond2fcfb52018-09-17 21:57:11 -0400291 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400292 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400293 const GrBackendTexture yuvaTextures[],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400294 const SkYUVAIndex yuvaIndices[4],
295 SkISize imageSize,
296 GrSurfaceOrigin imageOrigin,
297 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400298 sk_sp<SkColorSpace> imageColorSpace,
299 TextureReleaseProc textureReleaseProc,
300 ReleaseContext releaseContext) {
Robert Phillips62221e72019-07-24 15:07:38 -0400301 const GrCaps* caps = ctx->priv().caps();
Robert Phillipsdd399802019-07-18 12:28:00 +0000302
Robert Phillips62221e72019-07-24 15:07:38 -0400303 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, kRGBA_8888_SkColorType,
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400304 backendTexture.getBackendFormat());
305 if (GrColorType::kUnknown == grColorType) {
306 return nullptr;
307 }
308
Jim Van Verth53275362018-11-09 15:42:35 -0500309 SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
Robert Phillips62221e72019-07-24 15:07:38 -0400310 if (!SkImage_Gpu::ValidateBackendTexture(caps, backendTexture, grColorType,
311 kRGBA_8888_SkColorType, at, nullptr)) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400312 return nullptr;
313 }
314
315 // Needs to create a render target with external texture
316 // in order to draw to it for the yuv->rgb conversion.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400317 auto renderTargetContext = ctx->priv().makeBackendTextureRenderTargetContext(
318 backendTexture, imageOrigin, 1, grColorType, std::move(imageColorSpace), nullptr,
319 textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400320 if (!renderTargetContext) {
321 return nullptr;
322 }
323
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400324 return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
Brian Salomonf05e6d32018-12-20 08:41:41 -0500325 imageSize, imageOrigin, renderTargetContext.get());
Robert Phillipsc25db632017-12-13 09:22:45 -0500326}
327
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400328sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400329 const GrBackendTexture yuvTextures[3],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400330 GrSurfaceOrigin imageOrigin,
Brian Salomon6a426c12018-03-15 12:16:02 -0400331 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400332 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
333 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400334 SkYUVAIndex{0, SkColorChannel::kR},
335 SkYUVAIndex{1, SkColorChannel::kR},
336 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400337 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400338 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400339 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
340 size, imageOrigin, std::move(imageColorSpace));
bsalomon993a4212015-05-29 11:37:25 -0700341}
reed56179002015-07-07 06:11:19 -0700342
Brian Salomond2fcfb52018-09-17 21:57:11 -0400343sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400344 GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
345 GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400346 sk_sp<SkColorSpace> imageColorSpace) {
347 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400348 SkYUVAIndex{0, SkColorChannel::kR},
349 SkYUVAIndex{1, SkColorChannel::kR},
350 SkYUVAIndex{2, SkColorChannel::kR},
Robert Phillips66a97342018-10-04 09:10:29 -0400351 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400352 SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400353 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
354 ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400355 std::move(imageColorSpace), nullptr, nullptr);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400356}
357
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400358sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
Brian Salomon6a426c12018-03-15 12:16:02 -0400359 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400360 GrSurfaceOrigin imageOrigin,
brianosmandddbe382016-07-20 13:55:39 -0700361 sk_sp<SkColorSpace> imageColorSpace) {
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400362 // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
363 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400364 SkYUVAIndex{0, SkColorChannel::kR},
365 SkYUVAIndex{1, SkColorChannel::kR},
366 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400367 SkYUVAIndex{-1, SkColorChannel::kA}};
Weiliang Chenbed9d5e2018-05-22 18:44:02 -0400368 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400369 return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
370 size, imageOrigin, std::move(imageColorSpace));
Robert Phillipsc25db632017-12-13 09:22:45 -0500371}
372
Brian Salomond2fcfb52018-09-17 21:57:11 -0400373sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
374 GrContext* ctx,
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400375 SkYUVColorSpace yuvColorSpace,
Brian Salomond2fcfb52018-09-17 21:57:11 -0400376 const GrBackendTexture nv12Textures[2],
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400377 GrSurfaceOrigin imageOrigin,
378 const GrBackendTexture& backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400379 sk_sp<SkColorSpace> imageColorSpace,
380 TextureReleaseProc textureReleaseProc,
381 ReleaseContext releaseContext) {
Brian Salomond2fcfb52018-09-17 21:57:11 -0400382 SkYUVAIndex yuvaIndices[4] = {
Robert Phillips94ade752018-10-09 12:32:31 -0400383 SkYUVAIndex{0, SkColorChannel::kR},
384 SkYUVAIndex{1, SkColorChannel::kR},
385 SkYUVAIndex{1, SkColorChannel::kG},
Robert Phillips66a97342018-10-04 09:10:29 -0400386 SkYUVAIndex{-1, SkColorChannel::kA}};
Brian Salomond2fcfb52018-09-17 21:57:11 -0400387 SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
Robert Phillipsb6df1c12018-10-05 10:31:34 -0400388 return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
389 ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
Robert Phillipseb3eb982019-08-19 13:35:48 -0400390 std::move(imageColorSpace), textureReleaseProc, releaseContext);
Brian Salomond2fcfb52018-09-17 21:57:11 -0400391}
392
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400393static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
394 SkAlphaType at, uint32_t id,
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400395 GrMipMapped mipMapped) {
Greg Daniel81b98972019-12-13 11:09:43 -0500396 // TODO: have texture producer return a GrSurfaceProxyView
Brian Osman6064e1c2018-10-19 14:27:54 -0400397 sk_sp<GrTextureProxy> proxy(producer->refTextureProxy(mipMapped));
Robert Phillips3798c862017-03-27 11:08:16 -0400398 if (!proxy) {
Brian Osman041f7df2017-02-07 11:23:28 -0500399 return nullptr;
400 }
Greg Daniel81b98972019-12-13 11:09:43 -0500401 GrSurfaceOrigin origin = proxy->origin();
402 const GrSwizzle& swizzle = proxy->textureSwizzle();
403 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
404 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, at, std::move(view),
Brian Salomon729fc0c2019-09-30 16:33:11 +0000405 sk_ref_sp(producer->colorSpace()));
Brian Osman041f7df2017-02-07 11:23:28 -0500406}
407
Brian Osmand566e2e2019-08-14 13:19:04 -0400408sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, GrMipMapped mipMapped) const {
Brian Osman041f7df2017-02-07 11:23:28 -0500409 if (!context) {
410 return nullptr;
411 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500412
413 if (this->isTextureBacked()) {
414 if (!as_IB(this)->context()->priv().matches(context)) {
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400415 return nullptr;
416 }
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500417
Robert Phillips6603a172019-03-05 12:35:44 -0500418 sk_sp<GrTextureProxy> proxy = as_IB(this)->asTextureProxyRef(context);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400419 SkASSERT(proxy);
420 if (GrMipMapped::kNo == mipMapped || proxy->mipMapped() == mipMapped) {
421 return sk_ref_sp(const_cast<SkImage*>(this));
422 }
Brian Salomon1a217eb2019-10-24 10:50:36 -0400423 GrTextureAdjuster adjuster(context, std::move(proxy), this->imageInfo().colorInfo(),
424 this->uniqueID());
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400425 return create_image_from_producer(context, &adjuster, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400426 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500427 }
428
Brian Osmandf7e0752017-04-26 16:20:28 -0400429 if (this->isLazyGenerated()) {
430 GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400431 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400432 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500433 }
434
435 if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
436 GrBitmapTextureMaker maker(context, *bmp);
Greg Daniel5f4b09d2018-06-12 16:39:59 -0400437 return create_image_from_producer(context, &maker, this->alphaType(),
Brian Osmane7fd8c32018-10-19 13:30:39 -0400438 this->uniqueID(), mipMapped);
Brian Osman041f7df2017-02-07 11:23:28 -0500439 }
440 return nullptr;
441}
442
Greg Daniel7278d682018-03-16 14:57:21 -0400443///////////////////////////////////////////////////////////////////////////////////////////////////
444
Greg Daniela8d92112018-03-09 12:05:04 -0500445sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
446 const GrBackendFormat& backendFormat,
447 int width,
448 int height,
449 GrMipMapped mipMapped,
450 GrSurfaceOrigin origin,
451 SkColorType colorType,
452 SkAlphaType alphaType,
453 sk_sp<SkColorSpace> colorSpace,
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500454 PromiseImageTextureFulfillProc textureFulfillProc,
455 PromiseImageTextureReleaseProc textureReleaseProc,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500456 PromiseImageTextureDoneProc textureDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500457 PromiseImageTextureContext textureContext,
458 PromiseImageApiVersion version) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400459 // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500460 // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
461 // responsibility for calling the done proc.
Brian Salomonf55e8d52019-01-30 17:28:20 -0500462 if (!textureDoneProc) {
Robert Phillipsef85d192018-10-09 11:24:09 -0400463 return nullptr;
464 }
Brian Salomonf55e8d52019-01-30 17:28:20 -0500465 SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
Robert Phillipsef85d192018-10-09 11:24:09 -0400466
Brian Salomonbe5a0932018-12-10 10:03:26 -0500467 SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
468 if (!SkImageInfoIsValid(info)) {
469 return nullptr;
470 }
Robert Phillipsef85d192018-10-09 11:24:09 -0400471
Greg Daniela8d92112018-03-09 12:05:04 -0500472 if (!context) {
473 return nullptr;
474 }
475
476 if (width <= 0 || height <= 0) {
477 return nullptr;
478 }
479
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400480 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
481 colorType,
482 backendFormat);
483 if (GrColorType::kUnknown == grColorType) {
Greg Daniela8d92112018-03-09 12:05:04 -0500484 return nullptr;
485 }
486
Brian Salomonbe5a0932018-12-10 10:03:26 -0500487 callDone.clear();
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400488 auto proxy = MakePromiseImageLazyProxy(context, width, height, origin,
489 grColorType, backendFormat,
Brian Salomonbe5a0932018-12-10 10:03:26 -0500490 mipMapped, textureFulfillProc, textureReleaseProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500491 textureDoneProc, textureContext, version);
Greg Daniela8d92112018-03-09 12:05:04 -0500492 if (!proxy) {
493 return nullptr;
494 }
Greg Daniel14b57212019-12-17 16:18:06 -0500495 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
Greg Daniel81b98972019-12-13 11:09:43 -0500496 GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
Brian Salomon729fc0c2019-09-30 16:33:11 +0000497 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, alphaType,
Greg Daniel81b98972019-12-13 11:09:43 -0500498 std::move(view), std::move(colorSpace));
Greg Daniela8d92112018-03-09 12:05:04 -0500499}
500
Greg Daniel7278d682018-03-16 14:57:21 -0400501///////////////////////////////////////////////////////////////////////////////////////////////////
502
Brian Osman584b5012018-04-13 15:48:26 -0400503sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
504 const SkPixmap& originalPixmap, bool buildMips,
Brian Osman584b5012018-04-13 15:48:26 -0400505 bool limitToMaxTextureSize) {
Brian Osman63bc48d2017-11-07 10:37:00 -0500506 // Some backends or drivers don't support (safely) moving resources between contexts
Robert Phillips9da87e02019-02-04 13:26:26 -0500507 if (!context || !context->priv().caps()->crossContextTextureSupport()) {
Brian Osman584b5012018-04-13 15:48:26 -0400508 return SkImage::MakeRasterCopy(originalPixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500509 }
510
Greg Daniel9e788112018-02-08 14:29:37 -0500511 // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
512 // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
513 // instead.
Robert Phillips9da87e02019-02-04 13:26:26 -0500514 if (!context->priv().resourceProvider()) {
Brian Osman584b5012018-04-13 15:48:26 -0400515 return SkImage::MakeRasterCopy(originalPixmap);
Greg Daniel9e788112018-02-08 14:29:37 -0500516 }
517
Brian Osman0471a932019-02-07 13:36:56 -0500518 // If non-power-of-two mipmapping isn't supported, ignore the client's request
519 if (!context->priv().caps()->mipMapSupport()) {
520 buildMips = false;
521 }
522
Brian Osman584b5012018-04-13 15:48:26 -0400523 const SkPixmap* pixmap = &originalPixmap;
524 SkAutoPixmapStorage resized;
Robert Phillips9da87e02019-02-04 13:26:26 -0500525 int maxTextureSize = context->priv().caps()->maxTextureSize();
Brian Osman584b5012018-04-13 15:48:26 -0400526 int maxDim = SkTMax(originalPixmap.width(), originalPixmap.height());
527 if (limitToMaxTextureSize && maxDim > maxTextureSize) {
528 float scale = static_cast<float>(maxTextureSize) / maxDim;
529 int newWidth = SkTMin(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
530 int newHeight = SkTMin(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
531 SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
532 if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
533 return nullptr;
534 }
535 pixmap = &resized;
536 }
Robert Phillips9da87e02019-02-04 13:26:26 -0500537 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
Brian Osman63bc48d2017-11-07 10:37:00 -0500538 // Turn the pixmap into a GrTextureProxy
Brian Osman7dcc6162019-03-25 10:12:57 -0400539 SkBitmap bmp;
540 bmp.installPixels(*pixmap);
541 GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
542 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
Brian Osman63bc48d2017-11-07 10:37:00 -0500543 if (!proxy) {
Brian Osman584b5012018-04-13 15:48:26 -0400544 return SkImage::MakeRasterCopy(*pixmap);
Brian Osman63bc48d2017-11-07 10:37:00 -0500545 }
546
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400547 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Brian Osman63bc48d2017-11-07 10:37:00 -0500548
549 // Flush any writes or uploads
Greg Daniel4aa13e72019-04-15 14:42:20 -0400550 context->priv().flushSurface(proxy.get());
Robert Phillips9da87e02019-02-04 13:26:26 -0500551 GrGpu* gpu = context->priv().getGpu();
Brian Osman63bc48d2017-11-07 10:37:00 -0500552
Greg Daniel301015c2019-11-18 14:06:46 -0500553 std::unique_ptr<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
Brian Osman63bc48d2017-11-07 10:37:00 -0500554
555 auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
Brian Osman584b5012018-04-13 15:48:26 -0400556 std::move(sema), pixmap->colorType(),
557 pixmap->alphaType(),
558 pixmap->info().refColorSpace());
Brian Osman63bc48d2017-11-07 10:37:00 -0500559 return SkImage::MakeFromGenerator(std::move(gen));
560}
561
Derek Sollenberger7a869872017-06-27 15:37:25 -0400562#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -0400563sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
Stan Iliev505dd572018-09-13 14:20:03 -0400564 sk_sp<SkColorSpace> cs,
565 GrSurfaceOrigin surfaceOrigin) {
566 auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
Stan Iliev7e910df2017-06-02 10:29:21 -0400567 return SkImage::MakeFromGenerator(std::move(gen));
568}
Greg Danielb6c15ba2019-03-04 13:08:25 -0500569
570sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
571 const SkPixmap& pixmap,
572 AHardwareBuffer* hardwareBuffer,
573 GrSurfaceOrigin surfaceOrigin) {
574 AHardwareBuffer_Desc bufferDesc;
575 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
576
577 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
578 return nullptr;
579 }
580
581 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
582 hardwareBuffer,
583 bufferDesc.format,
584 true);
585
586 if (!backendFormat.isValid()) {
587 return nullptr;
588 }
589
590 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
Stan Ilieva56b04a2019-08-01 14:22:34 -0400591 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
592 GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
Greg Danielb6c15ba2019-03-04 13:08:25 -0500593
594 GrBackendTexture backendTexture =
595 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
596 bufferDesc.width, bufferDesc.height,
Stan Ilieva56b04a2019-08-01 14:22:34 -0400597 &deleteImageProc, &updateImageProc,
598 &deleteImageCtx, false, backendFormat, true);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500599 if (!backendTexture.isValid()) {
600 return nullptr;
601 }
602 SkASSERT(deleteImageProc);
603
604 SkColorType colorType =
605 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
606
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400607 GrColorType grColorType = SkColorTypeToGrColorType(colorType);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500608
609 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
610 if (!proxyProvider) {
611 deleteImageProc(deleteImageCtx);
612 return nullptr;
613 }
614
615 sk_sp<GrTextureProxy> proxy =
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400616 proxyProvider->wrapBackendTexture(backendTexture, grColorType, surfaceOrigin,
Greg Danielb6c15ba2019-03-04 13:08:25 -0500617 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
618 kRW_GrIOType, deleteImageProc, deleteImageCtx);
619 if (!proxy) {
620 deleteImageProc(deleteImageCtx);
621 return nullptr;
622 }
623
624 sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
625 SkAlphaType at = pixmap.alphaType();
626
Greg Daniel14b57212019-12-17 16:18:06 -0500627 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
Greg Daniel81b98972019-12-13 11:09:43 -0500628 GrSurfaceProxyView view(proxy, surfaceOrigin, swizzle);
Brian Salomon729fc0c2019-09-30 16:33:11 +0000629 sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, at,
Greg Daniel81b98972019-12-13 11:09:43 -0500630 std::move(view), cs);
Greg Danielb6c15ba2019-03-04 13:08:25 -0500631 if (!image) {
632 return nullptr;
633 }
634
635 GrDrawingManager* drawingManager = context->priv().drawingManager();
636 if (!drawingManager) {
637 return nullptr;
638 }
639
Greg Daniel46e366a2019-12-16 14:38:36 -0500640 auto surfaceContext =
641 drawingManager->makeSurfaceContext(proxy, SkColorTypeToGrColorType(pixmap.colorType()),
Brian Salomond6287472019-06-24 15:50:07 -0400642 pixmap.alphaType(), cs);
Greg Daniel46e366a2019-12-16 14:38:36 -0500643 if (!surfaceContext) {
Greg Danielb6c15ba2019-03-04 13:08:25 -0500644 return nullptr;
645 }
646
647 SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
648 std::move(cs));
Greg Daniel46e366a2019-12-16 14:38:36 -0500649 surfaceContext->writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), {0, 0});
Greg Danielb6c15ba2019-03-04 13:08:25 -0500650
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400651 GrFlushInfo info;
652 info.fFlags = kSyncCpu_GrFlushFlag;
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400653 GrSurfaceProxy* p[1] = {proxy.get()};
Greg Daniel797efca2019-05-09 14:04:20 -0400654 drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
655 GrPrepareForExternalIORequests());
Greg Danielb6c15ba2019-03-04 13:08:25 -0500656
657 return image;
658}
Stan Iliev7e910df2017-06-02 10:29:21 -0400659#endif
660
reed56179002015-07-07 06:11:19 -0700661///////////////////////////////////////////////////////////////////////////////////////////////////
662
Eric Karl914a36b2017-10-12 12:44:50 -0700663bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
664 sk_sp<SkImage> image,
665 GrBackendTexture* backendTexture,
666 BackendTextureReleaseProc* releaseProc) {
667 if (!image || !ctx || !backendTexture || !releaseProc) {
668 return false;
669 }
670
671 // Ensure we have a texture backed image.
672 if (!image->isTextureBacked()) {
Brian Osmand566e2e2019-08-14 13:19:04 -0400673 image = image->makeTextureImage(ctx);
Eric Karl914a36b2017-10-12 12:44:50 -0700674 if (!image) {
675 return false;
676 }
677 }
678 GrTexture* texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800679 if (!texture) {
680 // In context-loss cases, we may not have a texture.
681 return false;
682 }
Eric Karl914a36b2017-10-12 12:44:50 -0700683
684 // If the image's context doesn't match the provided context, fail.
685 if (texture->getContext() != ctx) {
686 return false;
687 }
688
689 // Flush any pending IO on the texture.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400690 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700691
692 // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
693 // image is not unique, or if the texture wraps an external object.
Robert Phillipsaee18c92019-09-06 11:48:27 -0400694 if (!image->unique() || !texture->unique() ||
Eric Karl914a36b2017-10-12 12:44:50 -0700695 texture->resourcePriv().refsWrappedObjects()) {
696 // onMakeSubset will always copy the image.
Robert Phillips6603a172019-03-05 12:35:44 -0500697 image = as_IB(image)->onMakeSubset(ctx, image->bounds());
Eric Karl914a36b2017-10-12 12:44:50 -0700698 if (!image) {
699 return false;
700 }
701
702 texture = image->getTexture();
Eric Karl36591e52018-01-19 13:45:02 -0800703 if (!texture) {
704 return false;
705 }
Eric Karl914a36b2017-10-12 12:44:50 -0700706
707 // Flush to ensure that the copy is completed before we return the texture.
Greg Daniel4aa13e72019-04-15 14:42:20 -0400708 ctx->priv().flushSurface(as_IB(image)->peekProxy());
Eric Karl914a36b2017-10-12 12:44:50 -0700709 }
710
711 SkASSERT(!texture->resourcePriv().refsWrappedObjects());
Robert Phillipsaee18c92019-09-06 11:48:27 -0400712 SkASSERT(texture->unique());
Eric Karl914a36b2017-10-12 12:44:50 -0700713 SkASSERT(image->unique());
714
715 // Take a reference to the GrTexture and release the image.
716 sk_sp<GrTexture> textureRef(SkSafeRef(texture));
717 image = nullptr;
718
719 // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
720 return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
721}