• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #include <cstddef>
9 #include <cstring>
10 #include <type_traits>
11 
12 #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"
17 #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"
44 #include "src/gpu/GrTextureProxy.h"
45 #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"
50 
proxy_color_type(GrTextureProxy * proxy)51 static 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 
SkImage_Gpu(sk_sp<GrContext> context,uint32_t uniqueID,SkAlphaType at,sk_sp<GrTextureProxy> proxy,sk_sp<SkColorSpace> colorSpace)59 SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, SkAlphaType at,
60                          sk_sp<GrTextureProxy> proxy, sk_sp<SkColorSpace> colorSpace)
61         : INHERITED(std::move(context), proxy->worstCaseWidth(), proxy->worstCaseHeight(), uniqueID,
62                     proxy_color_type(proxy.get()), at, colorSpace)
63         , fProxy(std::move(proxy)) {}
64 
~SkImage_Gpu()65 SkImage_Gpu::~SkImage_Gpu() {}
66 
onFlush(GrContext * context,const GrFlushInfo & info)67 GrSemaphoresSubmitted 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 
onMakeColorTypeAndColorSpace(GrRecordingContext * context,SkColorType targetCT,sk_sp<SkColorSpace> targetCS) const76 sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
77                                                          SkColorType targetCT,
78                                                          sk_sp<SkColorSpace> targetCS) const {
79     if (!context || !fContext->priv().matches(context)) {
80         return nullptr;
81     }
82 
83     auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
84                                                targetCS.get(), this->alphaType());
85     SkASSERT(xform || targetCT != this->colorType());
86 
87     sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
88 
89     sk_sp<GrRenderTargetContext> renderTargetContext(
90             context->priv().makeDeferredRenderTargetContextWithFallback(
91                     SkBackingFit::kExact, this->width(), this->height(),
92                     SkColorTypeToGrColorType(targetCT), nullptr));
93     if (!renderTargetContext) {
94         return nullptr;
95     }
96 
97     GrPaint paint;
98     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
99     paint.addColorTextureProcessor(std::move(proxy), SkMatrix::I());
100     if (xform) {
101         paint.addColorFragmentProcessor(std::move(xform));
102     }
103 
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
111     return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
112                                    renderTargetContext->asTextureProxyRef(), std::move(targetCS));
113 }
114 
onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const115 sk_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 
120 ///////////////////////////////////////////////////////////////////////////////////////////////////
121 
new_wrapped_texture_common(GrContext * ctx,const GrBackendTexture & backendTex,GrColorType colorType,GrSurfaceOrigin origin,SkAlphaType at,sk_sp<SkColorSpace> colorSpace,GrWrapOwnership ownership,SkImage::TextureReleaseProc releaseProc,SkImage::ReleaseContext releaseCtx)122 static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
123                                                  const GrBackendTexture& backendTex,
124                                                  GrColorType colorType, GrSurfaceOrigin origin,
125                                                  SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
126                                                  GrWrapOwnership ownership,
127                                                  SkImage::TextureReleaseProc releaseProc,
128                                                  SkImage::ReleaseContext releaseCtx) {
129     if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
130         return nullptr;
131     }
132 
133     GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
134     sk_sp<GrTextureProxy> proxy =
135             proxyProvider->wrapBackendTexture(backendTex, colorType, origin, ownership,
136                                               GrWrapCacheable::kNo, kRead_GrIOType,
137                                               releaseProc, releaseCtx);
138     if (!proxy) {
139         return nullptr;
140     }
141     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(proxy),
142                                    std::move(colorSpace));
143 }
144 
MakeFromTexture(GrContext * ctx,const GrBackendTexture & tex,GrSurfaceOrigin origin,SkColorType ct,SkAlphaType at,sk_sp<SkColorSpace> cs,TextureReleaseProc releaseP,ReleaseContext releaseC)145 sk_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) {
149     if (!ctx) {
150         return nullptr;
151     }
152 
153     const GrCaps* caps = ctx->priv().caps();
154 
155     GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
156     if (GrColorType::kUnknown == grColorType) {
157         return nullptr;
158     }
159 
160     if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
161         return nullptr;
162     }
163 
164     return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
165                                       kBorrow_GrWrapOwnership, releaseP, releaseC);
166 }
167 
MakeFromAdoptedTexture(GrContext * ctx,const GrBackendTexture & tex,GrSurfaceOrigin origin,SkColorType ct,SkAlphaType at,sk_sp<SkColorSpace> cs)168 sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
169                                                const GrBackendTexture& tex, GrSurfaceOrigin origin,
170                                                SkColorType ct, SkAlphaType at,
171                                                sk_sp<SkColorSpace> cs) {
172     if (!ctx || !ctx->priv().resourceProvider()) {
173         // We have a DDL context and we don't support adopted textures for them.
174         return nullptr;
175     }
176 
177     const GrCaps* caps = ctx->priv().caps();
178 
179     GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
180     if (GrColorType::kUnknown == grColorType) {
181         return nullptr;
182     }
183 
184     if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
185         return nullptr;
186     }
187 
188     return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
189                                       kAdopt_GrWrapOwnership, nullptr, nullptr);
190 }
191 
MakeFromCompressed(GrContext * context,sk_sp<SkData> data,int width,int height,CompressionType type)192 sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
193                                            int width, int height, CompressionType type) {
194     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
195     sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
196             width, height, SkBudgeted::kYes, type, std::move(data));
197 
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 
ConvertYUVATexturesToRGB(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize size,GrSurfaceOrigin origin,GrRenderTargetContext * renderTargetContext)206 sk_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) {
211     SkASSERT(renderTargetContext);
212 
213     int numTextures;
214     if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
215         return nullptr;
216     }
217 
218     sk_sp<GrTextureProxy> tempTextureProxies[4];
219     if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
220                                                  origin, tempTextureProxies)) {
221         return nullptr;
222     }
223 
224     const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
225     if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
226                           tempTextureProxies, yuvaIndices)) {
227         return nullptr;
228     }
229 
230     SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
231     // MDB: this call is okay bc we know 'renderTargetContext' was exact
232     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
233                                    renderTargetContext->asTextureProxyRef(),
234                                    renderTargetContext->colorSpaceInfo().refColorSpace());
235 }
236 
MakeFromYUVATexturesCopy(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize imageSize,GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace)237 sk_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();
246 
247     // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
248     sk_sp<GrRenderTargetContext> renderTargetContext(ctx->priv().makeDeferredRenderTargetContext(
249             SkBackingFit::kExact, width, height, GrColorType::kRGBA_8888,
250             std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin));
251     if (!renderTargetContext) {
252         return nullptr;
253     }
254 
255     return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
256                                                  imageSize, imageOrigin, renderTargetContext.get());
257 }
258 
MakeFromYUVATexturesCopyWithExternalBackend(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize imageSize,GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace)259 sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
260         GrContext* ctx,
261         SkYUVColorSpace yuvColorSpace,
262         const GrBackendTexture yuvaTextures[],
263         const SkYUVAIndex yuvaIndices[4],
264         SkISize imageSize,
265         GrSurfaceOrigin imageOrigin,
266         const GrBackendTexture& backendTexture,
267         sk_sp<SkColorSpace> imageColorSpace) {
268     const GrCaps* caps = ctx->priv().caps();
269 
270     GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, kRGBA_8888_SkColorType,
271                                                                 backendTexture.getBackendFormat());
272     if (GrColorType::kUnknown == grColorType) {
273         return nullptr;
274     }
275 
276     SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
277     if (!SkImage_Gpu::ValidateBackendTexture(caps, backendTexture, grColorType,
278                                              kRGBA_8888_SkColorType, at, nullptr)) {
279         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(
285             ctx->priv().makeBackendTextureRenderTargetContext(backendTexture, imageOrigin, 1,
286                                                               grColorType,
287                                                               std::move(imageColorSpace)));
288 
289     if (!renderTargetContext) {
290         return nullptr;
291     }
292 
293     return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
294                                                  imageSize, imageOrigin, renderTargetContext.get());
295 }
296 
MakeFromYUVTexturesCopy(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvTextures[3],GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace)297 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
298                                                 const GrBackendTexture yuvTextures[3],
299                                                 GrSurfaceOrigin imageOrigin,
300                                                 sk_sp<SkColorSpace> imageColorSpace) {
301     // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
302     SkYUVAIndex yuvaIndices[4] = {
303             SkYUVAIndex{0, SkColorChannel::kR},
304             SkYUVAIndex{1, SkColorChannel::kR},
305             SkYUVAIndex{2, SkColorChannel::kR},
306             SkYUVAIndex{-1, SkColorChannel::kA}};
307     SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
308     return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
309                                                  size, imageOrigin, std::move(imageColorSpace));
310 }
311 
MakeFromYUVTexturesCopyWithExternalBackend(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvTextures[3],GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace)312 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
313         GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
314         GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
315         sk_sp<SkColorSpace> imageColorSpace) {
316     SkYUVAIndex yuvaIndices[4] = {
317             SkYUVAIndex{0, SkColorChannel::kR},
318             SkYUVAIndex{1, SkColorChannel::kR},
319             SkYUVAIndex{2, SkColorChannel::kR},
320             SkYUVAIndex{-1, SkColorChannel::kA}};
321     SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
322     return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
323             ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
324             std::move(imageColorSpace));
325 }
326 
MakeFromNV12TexturesCopy(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture nv12Textures[2],GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace)327 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
328                                                  const GrBackendTexture nv12Textures[2],
329                                                  GrSurfaceOrigin imageOrigin,
330                                                  sk_sp<SkColorSpace> imageColorSpace) {
331     // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
332     SkYUVAIndex yuvaIndices[4] = {
333             SkYUVAIndex{0, SkColorChannel::kR},
334             SkYUVAIndex{1, SkColorChannel::kR},
335             SkYUVAIndex{1, SkColorChannel::kG},
336             SkYUVAIndex{-1, SkColorChannel::kA}};
337     SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
338     return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
339                                                  size, imageOrigin, std::move(imageColorSpace));
340 }
341 
MakeFromNV12TexturesCopyWithExternalBackend(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture nv12Textures[2],GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace)342 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
343         GrContext* ctx,
344         SkYUVColorSpace yuvColorSpace,
345         const GrBackendTexture nv12Textures[2],
346         GrSurfaceOrigin imageOrigin,
347         const GrBackendTexture& backendTexture,
348         sk_sp<SkColorSpace> imageColorSpace) {
349     SkYUVAIndex yuvaIndices[4] = {
350             SkYUVAIndex{0, SkColorChannel::kR},
351             SkYUVAIndex{1, SkColorChannel::kR},
352             SkYUVAIndex{1, SkColorChannel::kG},
353             SkYUVAIndex{-1, SkColorChannel::kA}};
354     SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
355     return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
356             ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
357             std::move(imageColorSpace));
358 }
359 
create_image_from_producer(GrContext * context,GrTextureProducer * producer,SkAlphaType at,uint32_t id,GrMipMapped mipMapped)360 static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
361                                                  SkAlphaType at, uint32_t id,
362                                                  GrMipMapped mipMapped) {
363     sk_sp<GrTextureProxy> proxy(producer->refTextureProxy(mipMapped));
364     if (!proxy) {
365         return nullptr;
366     }
367     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, at, std::move(proxy),
368                                    sk_ref_sp(producer->colorSpace()));
369 }
370 
makeTextureImage(GrContext * context,GrMipMapped mipMapped) const371 sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, GrMipMapped mipMapped) const {
372     if (!context) {
373         return nullptr;
374     }
375 
376     if (this->isTextureBacked()) {
377         if (!as_IB(this)->context()->priv().matches(context)) {
378             return nullptr;
379         }
380 
381         sk_sp<GrTextureProxy> proxy = as_IB(this)->asTextureProxyRef(context);
382         SkASSERT(proxy);
383         if (GrMipMapped::kNo == mipMapped || proxy->mipMapped() == mipMapped) {
384             return sk_ref_sp(const_cast<SkImage*>(this));
385         }
386         GrTextureAdjuster adjuster(context, std::move(proxy),
387                                    SkColorTypeToGrColorType(this->colorType()), this->alphaType(),
388                                    this->uniqueID(), this->colorSpace());
389         return create_image_from_producer(context, &adjuster, this->alphaType(),
390                                           this->uniqueID(), mipMapped);
391     }
392 
393     if (this->isLazyGenerated()) {
394         GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
395         return create_image_from_producer(context, &maker, this->alphaType(),
396                                           this->uniqueID(), mipMapped);
397     }
398 
399     if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
400         GrBitmapTextureMaker maker(context, *bmp);
401         return create_image_from_producer(context, &maker, this->alphaType(),
402                                           this->uniqueID(), mipMapped);
403     }
404     return nullptr;
405 }
406 
407 ///////////////////////////////////////////////////////////////////////////////////////////////////
408 
MakePromiseTexture(GrContext * context,const GrBackendFormat & backendFormat,int width,int height,GrMipMapped mipMapped,GrSurfaceOrigin origin,SkColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,PromiseImageTextureFulfillProc textureFulfillProc,PromiseImageTextureReleaseProc textureReleaseProc,PromiseImageTextureDoneProc textureDoneProc,PromiseImageTextureContext textureContext,PromiseImageApiVersion version)409 sk_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,
418                                                PromiseImageTextureFulfillProc textureFulfillProc,
419                                                PromiseImageTextureReleaseProc textureReleaseProc,
420                                                PromiseImageTextureDoneProc textureDoneProc,
421                                                PromiseImageTextureContext textureContext,
422                                                PromiseImageApiVersion version) {
423     // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
424     // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
425     // responsibility for calling the done proc.
426     if (!textureDoneProc) {
427         return nullptr;
428     }
429     SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
430 
431     SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
432     if (!SkImageInfoIsValid(info)) {
433         return nullptr;
434     }
435 
436     if (!context) {
437         return nullptr;
438     }
439 
440     if (width <= 0 || height <= 0) {
441         return nullptr;
442     }
443 
444     GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
445                                                                 colorType,
446                                                                 backendFormat);
447     if (GrColorType::kUnknown == grColorType) {
448         return nullptr;
449     }
450 
451     callDone.clear();
452     auto proxy = MakePromiseImageLazyProxy(context, width, height, origin,
453                                            grColorType, backendFormat,
454                                            mipMapped, textureFulfillProc, textureReleaseProc,
455                                            textureDoneProc, textureContext, version);
456     if (!proxy) {
457         return nullptr;
458     }
459     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, alphaType,
460                                    std::move(proxy), std::move(colorSpace));
461 }
462 
463 ///////////////////////////////////////////////////////////////////////////////////////////////////
464 
MakeCrossContextFromPixmap(GrContext * context,const SkPixmap & originalPixmap,bool buildMips,bool limitToMaxTextureSize)465 sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
466                                                    const SkPixmap& originalPixmap, bool buildMips,
467                                                    bool limitToMaxTextureSize) {
468     // Some backends or drivers don't support (safely) moving resources between contexts
469     if (!context || !context->priv().caps()->crossContextTextureSupport()) {
470         return SkImage::MakeRasterCopy(originalPixmap);
471     }
472 
473     // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
474     // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
475     // instead.
476     if (!context->priv().resourceProvider()) {
477         return SkImage::MakeRasterCopy(originalPixmap);
478     }
479 
480     // If non-power-of-two mipmapping isn't supported, ignore the client's request
481     if (!context->priv().caps()->mipMapSupport()) {
482         buildMips = false;
483     }
484 
485     const SkPixmap* pixmap = &originalPixmap;
486     SkAutoPixmapStorage resized;
487     int maxTextureSize = context->priv().caps()->maxTextureSize();
488     int maxDim = SkTMax(originalPixmap.width(), originalPixmap.height());
489     if (limitToMaxTextureSize && maxDim > maxTextureSize) {
490         float scale = static_cast<float>(maxTextureSize) / maxDim;
491         int newWidth = SkTMin(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
492         int newHeight = SkTMin(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
493         SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
494         if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
495             return nullptr;
496         }
497         pixmap = &resized;
498     }
499     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
500     // Turn the pixmap into a GrTextureProxy
501     SkBitmap bmp;
502     bmp.installPixels(*pixmap);
503     GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
504     sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
505     if (!proxy) {
506         return SkImage::MakeRasterCopy(*pixmap);
507     }
508 
509     sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
510 
511     // Flush any writes or uploads
512     context->priv().flushSurface(proxy.get());
513     GrGpu* gpu = context->priv().getGpu();
514 
515     sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
516 
517     auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
518                                                     std::move(sema), pixmap->colorType(),
519                                                     pixmap->alphaType(),
520                                                     pixmap->info().refColorSpace());
521     return SkImage::MakeFromGenerator(std::move(gen));
522 }
523 
524 #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
MakeFromAHardwareBuffer(AHardwareBuffer * graphicBuffer,SkAlphaType at,sk_sp<SkColorSpace> cs,GrSurfaceOrigin surfaceOrigin)525 sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
526                                                 sk_sp<SkColorSpace> cs,
527                                                 GrSurfaceOrigin surfaceOrigin) {
528     auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
529     return SkImage::MakeFromGenerator(std::move(gen));
530 }
531 
MakeFromAHardwareBufferWithData(GrContext * context,const SkPixmap & pixmap,AHardwareBuffer * hardwareBuffer,GrSurfaceOrigin surfaceOrigin)532 sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
533                                                         const SkPixmap& pixmap,
534                                                         AHardwareBuffer* hardwareBuffer,
535                                                         GrSurfaceOrigin surfaceOrigin) {
536     AHardwareBuffer_Desc bufferDesc;
537     AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
538 
539     if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
540         return nullptr;
541     }
542 
543     GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
544                                                                              hardwareBuffer,
545                                                                              bufferDesc.format,
546                                                                              true);
547 
548     if (!backendFormat.isValid()) {
549         return nullptr;
550     }
551 
552     GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
553     GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
554     GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
555 
556     GrBackendTexture backendTexture =
557             GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
558                                                        bufferDesc.width, bufferDesc.height,
559                                                        &deleteImageProc, &updateImageProc,
560                                                        &deleteImageCtx, false, backendFormat, true);
561     if (!backendTexture.isValid()) {
562         return nullptr;
563     }
564     SkASSERT(deleteImageProc);
565 
566     SkColorType colorType =
567             GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
568 
569     GrColorType grColorType = SkColorTypeToGrColorType(colorType);
570 
571     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
572     if (!proxyProvider) {
573         deleteImageProc(deleteImageCtx);
574         return nullptr;
575     }
576 
577     sk_sp<GrTextureProxy> proxy =
578             proxyProvider->wrapBackendTexture(backendTexture, grColorType, surfaceOrigin,
579                                               kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
580                                               kRW_GrIOType, deleteImageProc, deleteImageCtx);
581     if (!proxy) {
582         deleteImageProc(deleteImageCtx);
583         return nullptr;
584     }
585 
586     sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
587     SkAlphaType at =  pixmap.alphaType();
588 
589     sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, at,
590                                                    proxy, cs);
591     if (!image) {
592         return nullptr;
593     }
594 
595     GrDrawingManager* drawingManager = context->priv().drawingManager();
596     if (!drawingManager) {
597         return nullptr;
598     }
599 
600     sk_sp<GrTextureContext> texContext =
601             drawingManager->makeTextureContext(proxy, SkColorTypeToGrColorType(pixmap.colorType()),
602                                                pixmap.alphaType(), cs);
603     if (!texContext) {
604         return nullptr;
605     }
606 
607     SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
608                                             std::move(cs));
609     texContext->writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), {0, 0});
610 
611     GrFlushInfo info;
612     info.fFlags = kSyncCpu_GrFlushFlag;
613     GrSurfaceProxy* p[1] = {proxy.get()};
614     drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
615                           GrPrepareForExternalIORequests());
616 
617     return image;
618 }
619 #endif
620 
621 ///////////////////////////////////////////////////////////////////////////////////////////////////
622 
MakeBackendTextureFromSkImage(GrContext * ctx,sk_sp<SkImage> image,GrBackendTexture * backendTexture,BackendTextureReleaseProc * releaseProc)623 bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
624                                             sk_sp<SkImage> image,
625                                             GrBackendTexture* backendTexture,
626                                             BackendTextureReleaseProc* releaseProc) {
627     if (!image || !ctx || !backendTexture || !releaseProc) {
628         return false;
629     }
630 
631     // Ensure we have a texture backed image.
632     if (!image->isTextureBacked()) {
633         image = image->makeTextureImage(ctx);
634         if (!image) {
635             return false;
636         }
637     }
638     GrTexture* texture = image->getTexture();
639     if (!texture) {
640         // In context-loss cases, we may not have a texture.
641         return false;
642     }
643 
644     // If the image's context doesn't match the provided context, fail.
645     if (texture->getContext() != ctx) {
646         return false;
647     }
648 
649     // Flush any pending IO on the texture.
650     ctx->priv().flushSurface(as_IB(image)->peekProxy());
651     SkASSERT(!texture->surfacePriv().hasPendingIO());
652 
653     // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
654     // image is not unique, or if the texture wraps an external object.
655     if (!image->unique() || !texture->surfacePriv().hasUniqueRef() ||
656         texture->resourcePriv().refsWrappedObjects()) {
657         // onMakeSubset will always copy the image.
658         image = as_IB(image)->onMakeSubset(ctx, image->bounds());
659         if (!image) {
660             return false;
661         }
662 
663         texture = image->getTexture();
664         if (!texture) {
665             return false;
666         }
667 
668         // Flush to ensure that the copy is completed before we return the texture.
669         ctx->priv().flushSurface(as_IB(image)->peekProxy());
670         SkASSERT(!texture->surfacePriv().hasPendingIO());
671     }
672 
673     SkASSERT(!texture->resourcePriv().refsWrappedObjects());
674     SkASSERT(texture->surfacePriv().hasUniqueRef());
675     SkASSERT(image->unique());
676 
677     // Take a reference to the GrTexture and release the image.
678     sk_sp<GrTexture> textureRef(SkSafeRef(texture));
679     image = nullptr;
680 
681     // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
682     return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
683 }
684