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/GrImageInfo.h"
34 #include "src/gpu/GrImageTextureMaker.h"
35 #include "src/gpu/GrProxyProvider.h"
36 #include "src/gpu/GrRecordingContextPriv.h"
37 #include "src/gpu/GrRenderTargetContext.h"
38 #include "src/gpu/GrSemaphore.h"
39 #include "src/gpu/GrSurfacePriv.h"
40 #include "src/gpu/GrTextureAdjuster.h"
41 #include "src/gpu/GrTextureContext.h"
42 #include "src/gpu/GrTexturePriv.h"
43 #include "src/gpu/GrTextureProxy.h"
44 #include "src/gpu/GrTextureProxyPriv.h"
45 #include "src/gpu/SkGr.h"
46 #include "src/gpu/gl/GrGLTexture.h"
47 #include "src/image/SkImage_Gpu.h"
48 
proxy_color_type(GrTextureProxy * proxy)49 static SkColorType proxy_color_type(GrTextureProxy* proxy) {
50     SkColorType colorType;
51     if (!GrPixelConfigToColorType(proxy->config(), &colorType)) {
52         colorType = kUnknown_SkColorType;
53     }
54     return colorType;
55 }
56 
SkImage_Gpu(sk_sp<GrContext> context,uint32_t uniqueID,SkAlphaType at,sk_sp<GrTextureProxy> proxy,sk_sp<SkColorSpace> colorSpace)57 SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, SkAlphaType at,
58                          sk_sp<GrTextureProxy> proxy, sk_sp<SkColorSpace> colorSpace)
59         : INHERITED(std::move(context), proxy->worstCaseWidth(), proxy->worstCaseHeight(), uniqueID,
60                     proxy_color_type(proxy.get()), at, colorSpace)
61         , fProxy(std::move(proxy)) {}
62 
~SkImage_Gpu()63 SkImage_Gpu::~SkImage_Gpu() {}
64 
onFlush(GrContext * context,const GrFlushInfo & info)65 GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrContext* context, const GrFlushInfo& info) {
66     if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
67         return GrSemaphoresSubmitted::kNo;
68     }
69 
70     GrSurfaceProxy* p[1] = {fProxy.get()};
71     return context->priv().flushSurfaces(p, 1, info);
72 }
73 
onMakeColorTypeAndColorSpace(GrRecordingContext * context,SkColorType targetCT,sk_sp<SkColorSpace> targetCS) const74 sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
75                                                          SkColorType targetCT,
76                                                          sk_sp<SkColorSpace> targetCS) const {
77     if (!context || !fContext->priv().matches(context)) {
78         return nullptr;
79     }
80 
81     auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
82                                                targetCS.get(), this->alphaType());
83     SkASSERT(xform || targetCT != this->colorType());
84 
85     sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
86 
87     auto renderTargetContext = context->priv().makeDeferredRenderTargetContextWithFallback(
88             SkBackingFit::kExact, this->width(), this->height(), SkColorTypeToGrColorType(targetCT),
89             nullptr);
90     if (!renderTargetContext) {
91         return nullptr;
92     }
93 
94     GrPaint paint;
95     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
96     paint.addColorTextureProcessor(std::move(proxy), SkColorTypeToGrColorType(this->colorType()),
97                                    SkMatrix::I());
98     if (xform) {
99         paint.addColorFragmentProcessor(std::move(xform));
100     }
101 
102     renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
103                                   SkRect::MakeIWH(this->width(), this->height()));
104     if (!renderTargetContext->asTextureProxy()) {
105         return nullptr;
106     }
107 
108     // MDB: this call is okay bc we know 'renderTargetContext' was exact
109     return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
110                                    renderTargetContext->asTextureProxyRef(), std::move(targetCS));
111 }
112 
onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const113 sk_sp<SkImage> SkImage_Gpu::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
114     return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(), fProxy,
115                                    std::move(newCS));
116 }
117 
118 ///////////////////////////////////////////////////////////////////////////////////////////////////
119 
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)120 static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
121                                                  const GrBackendTexture& backendTex,
122                                                  GrColorType colorType, GrSurfaceOrigin origin,
123                                                  SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
124                                                  GrWrapOwnership ownership,
125                                                  SkImage::TextureReleaseProc releaseProc,
126                                                  SkImage::ReleaseContext releaseCtx) {
127     if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
128         return nullptr;
129     }
130 
131     GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
132     sk_sp<GrTextureProxy> proxy =
133             proxyProvider->wrapBackendTexture(backendTex, colorType, origin, ownership,
134                                               GrWrapCacheable::kNo, kRead_GrIOType,
135                                               releaseProc, releaseCtx);
136     if (!proxy) {
137         return nullptr;
138     }
139     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(proxy),
140                                    std::move(colorSpace));
141 }
142 
MakeFromTexture(GrContext * ctx,const GrBackendTexture & tex,GrSurfaceOrigin origin,SkColorType ct,SkAlphaType at,sk_sp<SkColorSpace> cs,TextureReleaseProc releaseP,ReleaseContext releaseC)143 sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
144                                         const GrBackendTexture& tex, GrSurfaceOrigin origin,
145                                         SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
146                                         TextureReleaseProc releaseP, ReleaseContext releaseC) {
147     if (!ctx) {
148         return nullptr;
149     }
150 
151     const GrCaps* caps = ctx->priv().caps();
152 
153     GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
154     if (GrColorType::kUnknown == grColorType) {
155         return nullptr;
156     }
157 
158     if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
159         return nullptr;
160     }
161 
162     return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
163                                       kBorrow_GrWrapOwnership, releaseP, releaseC);
164 }
165 
MakeFromAdoptedTexture(GrContext * ctx,const GrBackendTexture & tex,GrSurfaceOrigin origin,SkColorType ct,SkAlphaType at,sk_sp<SkColorSpace> cs)166 sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
167                                                const GrBackendTexture& tex, GrSurfaceOrigin origin,
168                                                SkColorType ct, SkAlphaType at,
169                                                sk_sp<SkColorSpace> cs) {
170     if (!ctx || !ctx->priv().resourceProvider()) {
171         // We have a DDL context and we don't support adopted textures for them.
172         return nullptr;
173     }
174 
175     const GrCaps* caps = ctx->priv().caps();
176 
177     GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, ct, tex.getBackendFormat());
178     if (GrColorType::kUnknown == grColorType) {
179         return nullptr;
180     }
181 
182     if (!SkImage_GpuBase::ValidateBackendTexture(caps, tex, grColorType, ct, at, cs)) {
183         return nullptr;
184     }
185 
186     return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
187                                       kAdopt_GrWrapOwnership, nullptr, nullptr);
188 }
189 
MakeFromCompressed(GrContext * context,sk_sp<SkData> data,int width,int height,CompressionType type)190 sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
191                                            int width, int height, CompressionType type) {
192     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
193     sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
194             width, height, SkBudgeted::kYes, type, std::move(data));
195 
196     if (!proxy) {
197         return nullptr;
198     }
199 
200     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
201                                    std::move(proxy), nullptr);
202 }
203 
ConvertYUVATexturesToRGB(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize size,GrSurfaceOrigin origin,GrRenderTargetContext * renderTargetContext)204 sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
205                                                      const GrBackendTexture yuvaTextures[],
206                                                      const SkYUVAIndex yuvaIndices[4], SkISize size,
207                                                      GrSurfaceOrigin origin,
208                                                      GrRenderTargetContext* renderTargetContext) {
209     SkASSERT(renderTargetContext);
210 
211     int numTextures;
212     if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
213         return nullptr;
214     }
215 
216     sk_sp<GrTextureProxy> tempTextureProxies[4];
217     if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
218                                                  origin, tempTextureProxies)) {
219         return nullptr;
220     }
221 
222     const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
223     if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
224                           tempTextureProxies, yuvaIndices)) {
225         return nullptr;
226     }
227 
228     SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
229     // MDB: this call is okay bc we know 'renderTargetContext' was exact
230     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
231                                    renderTargetContext->asTextureProxyRef(),
232                                    renderTargetContext->colorInfo().refColorSpace());
233 }
234 
MakeFromYUVATexturesCopy(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize imageSize,GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace)235 sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
236                                                  SkYUVColorSpace yuvColorSpace,
237                                                  const GrBackendTexture yuvaTextures[],
238                                                  const SkYUVAIndex yuvaIndices[4],
239                                                  SkISize imageSize,
240                                                  GrSurfaceOrigin imageOrigin,
241                                                  sk_sp<SkColorSpace> imageColorSpace) {
242     const int width = imageSize.width();
243     const int height = imageSize.height();
244 
245     // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
246     auto renderTargetContext = ctx->priv().makeDeferredRenderTargetContext(
247             SkBackingFit::kExact, width, height, GrColorType::kRGBA_8888,
248             std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin);
249     if (!renderTargetContext) {
250         return nullptr;
251     }
252 
253     return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
254                                                  imageSize, imageOrigin, renderTargetContext.get());
255 }
256 
MakeFromYUVATexturesCopyWithExternalBackend(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize imageSize,GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace,TextureReleaseProc textureReleaseProc,ReleaseContext releaseContext)257 sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
258         GrContext* ctx,
259         SkYUVColorSpace yuvColorSpace,
260         const GrBackendTexture yuvaTextures[],
261         const SkYUVAIndex yuvaIndices[4],
262         SkISize imageSize,
263         GrSurfaceOrigin imageOrigin,
264         const GrBackendTexture& backendTexture,
265         sk_sp<SkColorSpace> imageColorSpace,
266         TextureReleaseProc textureReleaseProc,
267         ReleaseContext releaseContext) {
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     auto renderTargetContext = ctx->priv().makeBackendTextureRenderTargetContext(
285             backendTexture, imageOrigin, 1, grColorType, std::move(imageColorSpace), nullptr,
286             textureReleaseProc, releaseContext);
287     if (!renderTargetContext) {
288         return nullptr;
289     }
290 
291     return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
292                                                  imageSize, imageOrigin, renderTargetContext.get());
293 }
294 
MakeFromYUVTexturesCopy(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvTextures[3],GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace)295 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
296                                                 const GrBackendTexture yuvTextures[3],
297                                                 GrSurfaceOrigin imageOrigin,
298                                                 sk_sp<SkColorSpace> imageColorSpace) {
299     // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
300     SkYUVAIndex yuvaIndices[4] = {
301             SkYUVAIndex{0, SkColorChannel::kR},
302             SkYUVAIndex{1, SkColorChannel::kR},
303             SkYUVAIndex{2, SkColorChannel::kR},
304             SkYUVAIndex{-1, SkColorChannel::kA}};
305     SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
306     return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
307                                                  size, imageOrigin, std::move(imageColorSpace));
308 }
309 
MakeFromYUVTexturesCopyWithExternalBackend(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvTextures[3],GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace)310 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
311         GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
312         GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
313         sk_sp<SkColorSpace> imageColorSpace) {
314     SkYUVAIndex yuvaIndices[4] = {
315             SkYUVAIndex{0, SkColorChannel::kR},
316             SkYUVAIndex{1, SkColorChannel::kR},
317             SkYUVAIndex{2, SkColorChannel::kR},
318             SkYUVAIndex{-1, SkColorChannel::kA}};
319     SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
320     return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
321             ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
322             std::move(imageColorSpace), nullptr, nullptr);
323 }
324 
MakeFromNV12TexturesCopy(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture nv12Textures[2],GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace)325 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
326                                                  const GrBackendTexture nv12Textures[2],
327                                                  GrSurfaceOrigin imageOrigin,
328                                                  sk_sp<SkColorSpace> imageColorSpace) {
329     // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
330     SkYUVAIndex yuvaIndices[4] = {
331             SkYUVAIndex{0, SkColorChannel::kR},
332             SkYUVAIndex{1, SkColorChannel::kR},
333             SkYUVAIndex{1, SkColorChannel::kG},
334             SkYUVAIndex{-1, SkColorChannel::kA}};
335     SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
336     return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
337                                                  size, imageOrigin, std::move(imageColorSpace));
338 }
339 
MakeFromNV12TexturesCopyWithExternalBackend(GrContext * ctx,SkYUVColorSpace yuvColorSpace,const GrBackendTexture nv12Textures[2],GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace,TextureReleaseProc textureReleaseProc,ReleaseContext releaseContext)340 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
341         GrContext* ctx,
342         SkYUVColorSpace yuvColorSpace,
343         const GrBackendTexture nv12Textures[2],
344         GrSurfaceOrigin imageOrigin,
345         const GrBackendTexture& backendTexture,
346         sk_sp<SkColorSpace> imageColorSpace,
347         TextureReleaseProc textureReleaseProc,
348         ReleaseContext releaseContext) {
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), textureReleaseProc, releaseContext);
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     auto 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 
652     // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
653     // image is not unique, or if the texture wraps an external object.
654     if (!image->unique() || !texture->unique() ||
655         texture->resourcePriv().refsWrappedObjects()) {
656         // onMakeSubset will always copy the image.
657         image = as_IB(image)->onMakeSubset(ctx, image->bounds());
658         if (!image) {
659             return false;
660         }
661 
662         texture = image->getTexture();
663         if (!texture) {
664             return false;
665         }
666 
667         // Flush to ensure that the copy is completed before we return the texture.
668         ctx->priv().flushSurface(as_IB(image)->peekProxy());
669     }
670 
671     SkASSERT(!texture->resourcePriv().refsWrappedObjects());
672     SkASSERT(texture->unique());
673     SkASSERT(image->unique());
674 
675     // Take a reference to the GrTexture and release the image.
676     sk_sp<GrTexture> textureRef(SkSafeRef(texture));
677     image = nullptr;
678 
679     // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
680     return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
681 }
682