• 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 "include/core/SkAlphaType.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkColorType.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkImage.h"
14 #include "include/core/SkImageInfo.h"
15 #include "include/core/SkPixelRef.h"
16 #include "include/core/SkPixmap.h"
17 #include "include/core/SkPoint.h"
18 #include "include/core/SkRect.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkSamplingOptions.h"
21 #include "include/core/SkSize.h"
22 #include "include/core/SkTypes.h"
23 #include "include/private/base/SkMath.h"
24 #include "include/private/base/SkTo.h"
25 #include "src/core/SkCompressedDataUtils.h"
26 #include "src/core/SkConvertPixels.h"
27 #include "src/core/SkImageInfoPriv.h"
28 #include "src/core/SkImagePriv.h"
29 #include "src/core/SkMipmap.h"
30 #include "src/image/SkImage_Base.h"
31 
32 #include <cstddef>
33 #include <cstdint>
34 #include <memory>
35 #include <tuple>
36 #include <utility>
37 
38 class GrDirectContext;
39 class GrFragmentProcessor;
40 class SkMatrix;
41 enum class SkTileMode;
42 
43 #if defined(SK_GANESH)
44 #include "include/gpu/GpuTypes.h"
45 #include "include/gpu/GrBackendSurface.h"
46 #include "include/gpu/GrRecordingContext.h"
47 #include "include/gpu/GrTypes.h"
48 #include "include/private/gpu/ganesh/GrTypesPriv.h"
49 #include "src/gpu/SkBackingFit.h"
50 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
51 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
52 #include "src/gpu/ganesh/SkGr.h"
53 #endif
54 
55 #if defined(SK_GRAPHITE)
56 #include "include/gpu/graphite/GraphiteTypes.h"
57 #include "include/gpu/graphite/Recorder.h"
58 #include "src/gpu/graphite/Buffer.h"
59 #include "src/gpu/graphite/Caps.h"
60 #include "src/gpu/graphite/CommandBuffer.h"
61 #include "src/gpu/graphite/RecorderPriv.h"
62 #include "src/gpu/graphite/TextureUtils.h"
63 #include "src/gpu/graphite/UploadTask.h"
64 #endif
65 
66 // fixes https://bug.skia.org/5096
is_not_subset(const SkBitmap & bm)67 static bool is_not_subset(const SkBitmap& bm) {
68     SkASSERT(bm.pixelRef());
69     SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
70     SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
71     return dim == bm.dimensions();
72 }
73 
74 class SkImage_Raster : public SkImage_Base {
75 public:
ValidArgs(const SkImageInfo & info,size_t rowBytes,size_t * minSize)76     static bool ValidArgs(const SkImageInfo& info, size_t rowBytes, size_t* minSize) {
77         const int maxDimension = SK_MaxS32 >> 2;
78 
79         // TODO(mtklein): eliminate anything here that setInfo() has already checked.
80         SkBitmap b;
81         if (!b.setInfo(info, rowBytes)) {
82             return false;
83         }
84 
85         if (info.width() <= 0 || info.height() <= 0) {
86             return false;
87         }
88         if (info.width() > maxDimension || info.height() > maxDimension) {
89             return false;
90         }
91         if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
92             return false;
93         }
94         if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
95             return false;
96         }
97 
98         if (kUnknown_SkColorType == info.colorType()) {
99             return false;
100         }
101         if (!info.validRowBytes(rowBytes)) {
102             return false;
103         }
104 
105         size_t size = info.computeByteSize(rowBytes);
106         if (SkImageInfo::ByteSizeOverflowed(size)) {
107             return false;
108         }
109 
110         if (minSize) {
111             *minSize = size;
112         }
113         return true;
114     }
115 
116     SkImage_Raster(const SkImageInfo&, sk_sp<SkData>, size_t rb,
117                    uint32_t id = kNeedNewImageUniqueID);
118     ~SkImage_Raster() override;
119 
120     bool onReadPixels(GrDirectContext*, const SkImageInfo&, void*, size_t, int srcX, int srcY,
121                       CachingHint) const override;
122     bool onPeekPixels(SkPixmap*) const override;
onPeekBitmap() const123     const SkBitmap* onPeekBitmap() const override { return &fBitmap; }
124 
125     bool getROPixels(GrDirectContext*, SkBitmap*, CachingHint) const override;
126     sk_sp<SkImage> onMakeSubset(const SkIRect&, GrDirectContext*) const override;
127 #if defined(SK_GRAPHITE)
128     sk_sp<SkImage> onMakeSubset(const SkIRect&,
129                                 skgpu::graphite::Recorder*,
130                                 RequiredImageProperties) const override;
131 #endif
132 
getPixelRef() const133     SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
134 
135     bool onAsLegacyBitmap(GrDirectContext*, SkBitmap*) const override;
136 
SkImage_Raster(const SkBitmap & bm,bool bitmapMayBeMutable=false)137     SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable = false)
138             : INHERITED(bm.info(),
139                         is_not_subset(bm) ? bm.getGenerationID() : (uint32_t)kNeedNewImageUniqueID)
140             , fBitmap(bm) {
141         SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
142     }
143 
144     sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
145                                                 GrDirectContext*) const override;
146 
147     sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const override;
148 
onIsValid(GrRecordingContext * context) const149     bool onIsValid(GrRecordingContext* context) const override { return true; }
notifyAddedToRasterCache() const150     void notifyAddedToRasterCache() const override {
151         // We explicitly DON'T want to call INHERITED::notifyAddedToRasterCache. That ties the
152         // lifetime of derived/cached resources to the image. In this case, we only want cached
153         // data (eg mips) tied to the lifetime of the underlying pixelRef.
154         SkASSERT(fBitmap.pixelRef());
155         fBitmap.pixelRef()->notifyAddedToCache();
156     }
157 
158 #if defined(SK_GANESH)
159     bool onPinAsTexture(GrRecordingContext*) const override;
160     void onUnpinAsTexture(GrRecordingContext*) const override;
161     bool isPinnedOnContext(GrRecordingContext*) const override;
162 #endif
163 
onHasMipmaps() const164     bool onHasMipmaps() const override { return SkToBool(fBitmap.fMips); }
165 
onPeekMips() const166     SkMipmap* onPeekMips() const override { return fBitmap.fMips.get(); }
167 
onMakeWithMipmaps(sk_sp<SkMipmap> mips) const168     sk_sp<SkImage> onMakeWithMipmaps(sk_sp<SkMipmap> mips) const override {
169         // It's dangerous to have two SkBitmaps that share a SkPixelRef but have different SkMipmaps
170         // since various caches key on SkPixelRef's generation ID. Also, SkPixelRefs that back
171         // SkSurfaces are marked "temporarily immutable" and making an image that uses the same
172         // SkPixelRef can interact badly with SkSurface/SkImage copy-on-write. So we just always
173         // make a copy with a new ID.
174         static auto constexpr kCopyMode = SkCopyPixelsMode::kAlways_SkCopyPixelsMode;
175         sk_sp<SkImage> img = SkMakeImageFromRasterBitmap(fBitmap, kCopyMode);
176         auto imgRaster = static_cast<SkImage_Raster*>(img.get());
177         if (mips) {
178             imgRaster->fBitmap.fMips = std::move(mips);
179         } else {
180             imgRaster->fBitmap.fMips.reset(SkMipmap::Build(fBitmap.pixmap(), nullptr));
181         }
182         return img;
183     }
184 
185 private:
186 #if defined(SK_GANESH)
187     std::tuple<GrSurfaceProxyView, GrColorType> onAsView(GrRecordingContext*,
188                                                          GrMipmapped,
189                                                          GrImageTexGenPolicy) const override;
190 
191     std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(GrRecordingContext*,
192                                                                SkSamplingOptions,
193                                                                const SkTileMode[2],
194                                                                const SkMatrix&,
195                                                                const SkRect*,
196                                                                const SkRect*) const override;
197 #endif
198 #if defined(SK_GRAPHITE)
199     sk_sp<SkImage> onMakeTextureImage(skgpu::graphite::Recorder*,
200                                       RequiredImageProperties) const override;
201     sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType targetCT,
202                                                 sk_sp<SkColorSpace> targetCS,
203                                                 skgpu::graphite::Recorder*,
204                                                 RequiredImageProperties) const override;
205 #endif
206 
207     SkBitmap fBitmap;
208 
209 #if defined(SK_GANESH)
210     mutable GrSurfaceProxyView fPinnedView;
211     mutable int32_t fPinnedCount = 0;
212     mutable uint32_t fPinnedUniqueID = SK_InvalidUniqueID;
213     mutable uint32_t fPinnedContextID = SK_InvalidUniqueID;
214     mutable GrColorType fPinnedColorType = GrColorType::kUnknown;
215 #endif
216 
217     using INHERITED = SkImage_Base;
218 };
219 
220 ///////////////////////////////////////////////////////////////////////////////
221 
release_data(void * addr,void * context)222 static void release_data(void* addr, void* context) {
223     SkData* data = static_cast<SkData*>(context);
224     data->unref();
225 }
226 
SkImage_Raster(const SkImageInfo & info,sk_sp<SkData> data,size_t rowBytes,uint32_t id)227 SkImage_Raster::SkImage_Raster(const SkImageInfo& info, sk_sp<SkData> data, size_t rowBytes,
228                                uint32_t id)
229         : INHERITED(info, id) {
230     void* addr = const_cast<void*>(data->data());
231 
232     fBitmap.installPixels(info, addr, rowBytes, release_data, data.release());
233     fBitmap.setImmutable();
234 }
235 
~SkImage_Raster()236 SkImage_Raster::~SkImage_Raster() {
237 #if defined(SK_GANESH)
238     SkASSERT(!fPinnedView);  // want the caller to have manually unpinned
239 #endif
240 }
241 
onReadPixels(GrDirectContext *,const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY,CachingHint) const242 bool SkImage_Raster::onReadPixels(GrDirectContext*,
243                                   const SkImageInfo& dstInfo,
244                                   void* dstPixels,
245                                   size_t dstRowBytes,
246                                   int srcX,
247                                   int srcY,
248                                   CachingHint) const {
249     SkBitmap shallowCopy(fBitmap);
250     return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
251 }
252 
onPeekPixels(SkPixmap * pm) const253 bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
254     return fBitmap.peekPixels(pm);
255 }
256 
getROPixels(GrDirectContext *,SkBitmap * dst,CachingHint) const257 bool SkImage_Raster::getROPixels(GrDirectContext*, SkBitmap* dst, CachingHint) const {
258     *dst = fBitmap;
259     return true;
260 }
261 
262 #if defined(SK_GANESH)
onPinAsTexture(GrRecordingContext * rContext) const263 bool SkImage_Raster::onPinAsTexture(GrRecordingContext* rContext) const {
264     if (fPinnedView) {
265         SkASSERT(fPinnedCount > 0);
266         SkASSERT(fPinnedUniqueID != 0);
267         if (rContext->priv().contextID() != fPinnedContextID) {
268             return false;
269         }
270     } else {
271         SkASSERT(fPinnedCount == 0);
272         SkASSERT(fPinnedUniqueID == 0);
273         std::tie(fPinnedView, fPinnedColorType) =
274                 GrMakeCachedBitmapProxyView(rContext,
275                                             fBitmap,
276                                             /*label=*/"SkImageRaster_PinAsTexture",
277                                             GrMipmapped::kNo);
278         if (!fPinnedView) {
279             fPinnedColorType = GrColorType::kUnknown;
280             return false;
281         }
282         fPinnedUniqueID = fBitmap.getGenerationID();
283         fPinnedContextID = rContext->priv().contextID();
284     }
285     // Note: we only increment if the texture was successfully pinned
286     ++fPinnedCount;
287     return true;
288 }
289 
onUnpinAsTexture(GrRecordingContext * rContext) const290 void SkImage_Raster::onUnpinAsTexture(GrRecordingContext* rContext) const {
291     // Note: we always decrement, even if fPinnedTexture is null
292     SkASSERT(fPinnedCount > 0);
293     SkASSERT(fPinnedUniqueID != 0);
294 #if 0 // This would be better but Android currently calls with an already freed context ptr.
295     if (rContext->priv().contextID() != fPinnedContextID) {
296         return;
297     }
298 #endif
299 
300     if (0 == --fPinnedCount) {
301         fPinnedView = GrSurfaceProxyView();
302         fPinnedUniqueID = SK_InvalidUniqueID;
303         fPinnedContextID = SK_InvalidUniqueID;
304         fPinnedColorType = GrColorType::kUnknown;
305     }
306 }
307 
isPinnedOnContext(GrRecordingContext * rContext) const308 bool SkImage_Raster::isPinnedOnContext(GrRecordingContext* rContext) const {
309     return fPinnedContextID == rContext->priv().contextID();
310 }
311 #endif
312 
copy_bitmap_subset(const SkBitmap & orig,const SkIRect & subset)313 static SkBitmap copy_bitmap_subset(const SkBitmap& orig, const SkIRect& subset) {
314     SkImageInfo info = orig.info().makeDimensions(subset.size());
315     SkBitmap bitmap;
316     if (!bitmap.tryAllocPixels(info)) {
317         return {};
318     }
319 
320     void* dst = bitmap.getPixels();
321     void* src = orig.getAddr(subset.x(), subset.y());
322     if (!dst || !src) {
323         SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
324         return {};
325     }
326 
327     SkRectMemcpy(dst, bitmap.rowBytes(), src, orig.rowBytes(), bitmap.rowBytes(),
328                  subset.height());
329 
330     bitmap.setImmutable();
331     return bitmap;
332 }
333 
onMakeSubset(const SkIRect & subset,GrDirectContext *) const334 sk_sp<SkImage> SkImage_Raster::onMakeSubset(const SkIRect& subset, GrDirectContext*) const {
335     SkBitmap copy = copy_bitmap_subset(fBitmap, subset);
336     if (copy.isNull()) {
337         return nullptr;
338     } else {
339         return copy.asImage();
340     }
341 }
342 
343 #if defined(SK_GRAPHITE)
copy_mipmaps(const SkBitmap & src,SkMipmap * srcMips)344 static sk_sp<SkMipmap> copy_mipmaps(const SkBitmap& src, SkMipmap* srcMips) {
345     if (!srcMips) {
346         return nullptr;
347     }
348 
349     sk_sp<SkMipmap> dst;
350     dst.reset(SkMipmap::Build(src.pixmap(), nullptr, /* computeContents= */ false));
351     for (int i = 0; i < dst->countLevels(); ++i) {
352         SkMipmap::Level srcLevel, dstLevel;
353         srcMips->getLevel(i, &srcLevel);
354         dst->getLevel(i, &dstLevel);
355         srcLevel.fPixmap.readPixels(dstLevel.fPixmap);
356     }
357 
358     return dst;
359 }
360 
onMakeSubset(const SkIRect & subset,skgpu::graphite::Recorder * recorder,RequiredImageProperties requiredProperties) const361 sk_sp<SkImage> SkImage_Raster::onMakeSubset(const SkIRect& subset,
362                                             skgpu::graphite::Recorder* recorder,
363                                             RequiredImageProperties requiredProperties) const {
364     sk_sp<SkImage> img;
365 
366     if (requiredProperties.fMipmapped == skgpu::Mipmapped::kYes) {
367         bool fullCopy = subset == SkIRect::MakeSize(fBitmap.dimensions());
368 
369         sk_sp<SkMipmap> mips = fullCopy ? copy_mipmaps(fBitmap, fBitmap.fMips.get()) : nullptr;
370 
371         // SkImage::withMipmaps will always make a copy for us so we can temporarily share
372         // the pixel ref with fBitmap
373         SkBitmap tmpSubset;
374         if (!fBitmap.extractSubset(&tmpSubset, subset)) {
375             return nullptr;
376         }
377 
378         sk_sp<SkImage> tmp(new SkImage_Raster(tmpSubset, /* bitmapMayBeMutable= */ true));
379 
380         // withMipmaps will auto generate the mipmaps if a nullptr is passed in
381         SkASSERT(!mips || mips->validForRootLevel(tmp->imageInfo()));
382         img = tmp->withMipmaps(std::move(mips));
383     } else {
384         SkBitmap copy = copy_bitmap_subset(fBitmap, subset);
385         if (!copy.isNull()) {
386             img = copy.asImage();
387         }
388     }
389 
390     if (!img) {
391         return nullptr;
392     }
393 
394     if (recorder) {
395         return img->makeTextureImage(recorder, requiredProperties);
396     } else {
397         return img;
398     }
399 }
400 #endif // SK_GRAPHITE
401 
402 ///////////////////////////////////////////////////////////////////////////////
403 
MakeRasterCopyPriv(const SkPixmap & pmap,uint32_t id)404 sk_sp<SkImage> MakeRasterCopyPriv(const SkPixmap& pmap, uint32_t id) {
405     size_t size;
406     if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
407         return nullptr;
408     }
409 
410     // Here we actually make a copy of the caller's pixel data
411     sk_sp<SkData> data(SkData::MakeWithCopy(pmap.addr(), size));
412     return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes(), id);
413 }
414 
MakeRasterCopy(const SkPixmap & pmap)415 sk_sp<SkImage> SkImage::MakeRasterCopy(const SkPixmap& pmap) {
416     return MakeRasterCopyPriv(pmap, kNeedNewImageUniqueID);
417 }
418 
MakeRasterData(const SkImageInfo & info,sk_sp<SkData> data,size_t rowBytes)419 sk_sp<SkImage> SkImage::MakeRasterData(const SkImageInfo& info, sk_sp<SkData> data,
420                                        size_t rowBytes) {
421     size_t size;
422     if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !data) {
423         return nullptr;
424     }
425 
426     // did they give us enough data?
427     if (data->size() < size) {
428         return nullptr;
429     }
430 
431     return sk_make_sp<SkImage_Raster>(info, std::move(data), rowBytes);
432 }
433 
434 // TODO: this could be improved to decode and make use of the mipmap
435 // levels potentially present in the compressed data. For now, any
436 // mipmap levels are discarded.
MakeRasterFromCompressed(sk_sp<SkData> data,int width,int height,CompressionType type)437 sk_sp<SkImage> SkImage::MakeRasterFromCompressed(sk_sp<SkData> data,
438                                                  int width, int height,
439                                                  CompressionType type) {
440     size_t expectedSize = SkCompressedFormatDataSize(type, { width, height }, false);
441     if (!data || data->size() < expectedSize) {
442         return nullptr;
443     }
444 
445     SkAlphaType at = SkCompressionTypeIsOpaque(type) ? kOpaque_SkAlphaType
446                                                      : kPremul_SkAlphaType;
447 
448     SkImageInfo ii = SkImageInfo::MakeN32(width, height, at);
449 
450     if (!SkImage_Raster::ValidArgs(ii, ii.minRowBytes(), nullptr)) {
451         return nullptr;
452     }
453 
454     SkBitmap bitmap;
455     if (!bitmap.tryAllocPixels(ii)) {
456         return nullptr;
457     }
458 
459     if (!SkDecompress(std::move(data), { width, height }, type, &bitmap)) {
460         return nullptr;
461     }
462 
463     bitmap.setImmutable();
464     return MakeFromBitmap(bitmap);
465 }
466 
MakeFromRaster(const SkPixmap & pmap,RasterReleaseProc proc,ReleaseContext ctx)467 sk_sp<SkImage> SkImage::MakeFromRaster(const SkPixmap& pmap, RasterReleaseProc proc,
468                                        ReleaseContext ctx) {
469     size_t size;
470     if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
471         return nullptr;
472     }
473 
474     sk_sp<SkData> data(SkData::MakeWithProc(pmap.addr(), size, proc, ctx));
475     return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes());
476 }
477 
SkMakeImageFromRasterBitmapPriv(const SkBitmap & bm,SkCopyPixelsMode cpm,uint32_t idForCopy)478 sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm,
479                                                uint32_t idForCopy) {
480     if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
481         SkPixmap pmap;
482         if (bm.peekPixels(&pmap)) {
483             return MakeRasterCopyPriv(pmap, idForCopy);
484         } else {
485             return sk_sp<SkImage>();
486         }
487     }
488 
489     return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
490 }
491 
SkMakeImageFromRasterBitmap(const SkBitmap & bm,SkCopyPixelsMode cpm)492 sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
493     if (!SkImageInfoIsValid(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
494         return nullptr;
495     }
496 
497     return SkMakeImageFromRasterBitmapPriv(bm, cpm, kNeedNewImageUniqueID);
498 }
499 
SkBitmapImageGetPixelRef(const SkImage * image)500 const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
501     return ((const SkImage_Raster*)image)->getPixelRef();
502 }
503 
onAsLegacyBitmap(GrDirectContext *,SkBitmap * bitmap) const504 bool SkImage_Raster::onAsLegacyBitmap(GrDirectContext*, SkBitmap* bitmap) const {
505     // When we're a snapshot from a surface, our bitmap may not be marked immutable
506     // even though logically always we are, but in that case we can't physically share our
507     // pixelref since the caller might call setImmutable() themselves
508     // (thus changing our state).
509     if (fBitmap.isImmutable()) {
510         SkIPoint origin = fBitmap.pixelRefOrigin();
511         bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
512         bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()), origin.x(), origin.y());
513         return true;
514     }
515     return this->INHERITED::onAsLegacyBitmap(nullptr, bitmap);
516 }
517 
518 ///////////////////////////////////////////////////////////////////////////////
519 
onMakeColorTypeAndColorSpace(SkColorType targetCT,sk_sp<SkColorSpace> targetCS,GrDirectContext *) const520 sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(SkColorType targetCT,
521                                                             sk_sp<SkColorSpace> targetCS,
522                                                             GrDirectContext*) const {
523     SkPixmap src;
524     SkAssertResult(fBitmap.peekPixels(&src));
525 
526     SkBitmap dst;
527     if (!dst.tryAllocPixels(fBitmap.info().makeColorType(targetCT).makeColorSpace(targetCS))) {
528         return nullptr;
529     }
530 
531     SkAssertResult(dst.writePixels(src));
532     dst.setImmutable();
533     return dst.asImage();
534 }
535 
onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const536 sk_sp<SkImage> SkImage_Raster::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
537     // TODO: If our bitmap is immutable, then we could theoretically create another image sharing
538     // our pixelRef. That doesn't work (without more invasive logic), because the image gets its
539     // gen ID from the bitmap, which gets it from the pixelRef.
540     SkPixmap pixmap = fBitmap.pixmap();
541     pixmap.setColorSpace(std::move(newCS));
542     return SkImage::MakeRasterCopy(pixmap);
543 }
544 
545 #if defined(SK_GANESH)
onAsView(GrRecordingContext * rContext,GrMipmapped mipmapped,GrImageTexGenPolicy policy) const546 std::tuple<GrSurfaceProxyView, GrColorType> SkImage_Raster::onAsView(
547         GrRecordingContext* rContext,
548         GrMipmapped mipmapped,
549         GrImageTexGenPolicy policy) const {
550     if (fPinnedView) {
551         // We ignore the mipmap request here. If the pinned view isn't mipmapped then we will
552         // fallback to bilinear. The pin API is used by Android Framework which does not expose
553         // mipmapping . Moreover, we're moving towards requiring that images be made with mip levels
554         // if mipmapping is desired (skbug.com/10411)
555         mipmapped = GrMipmapped::kNo;
556         if (policy != GrImageTexGenPolicy::kDraw) {
557             return {CopyView(rContext,
558                              fPinnedView,
559                              mipmapped,
560                              policy,
561                              /*label=*/"TextureForImageRasterWithPolicyNotEqualKDraw"),
562                     fPinnedColorType};
563         }
564         return {fPinnedView, fPinnedColorType};
565     }
566     if (policy == GrImageTexGenPolicy::kDraw) {
567         // If the draw doesn't require mipmaps but this SkImage has them go ahead and make a
568         // mipmapped texture. There are three reasons for this:
569         // 1) Avoiding another texture creation if a later draw requires mipmaps.
570         // 2) Ensuring we upload the bitmap's levels instead of generating on the GPU from the base.
571         if (this->hasMipmaps()) {
572             mipmapped = GrMipmapped::kYes;
573         }
574         return GrMakeCachedBitmapProxyView(rContext,
575                                            fBitmap,
576                                            /*label=*/"TextureForImageRasterWithPolicyEqualKDraw",
577                                            mipmapped);
578     }
579     auto budgeted = (policy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted)
580                             ? skgpu::Budgeted::kNo
581                             : skgpu::Budgeted::kYes;
582     return GrMakeUncachedBitmapProxyView(rContext,
583                                          fBitmap,
584                                          mipmapped,
585                                          SkBackingFit::kExact,
586                                          budgeted);
587 }
588 
onAsFragmentProcessor(GrRecordingContext * rContext,SkSamplingOptions sampling,const SkTileMode tileModes[2],const SkMatrix & m,const SkRect * subset,const SkRect * domain) const589 std::unique_ptr<GrFragmentProcessor> SkImage_Raster::onAsFragmentProcessor(
590         GrRecordingContext* rContext,
591         SkSamplingOptions sampling,
592         const SkTileMode tileModes[2],
593         const SkMatrix& m,
594         const SkRect* subset,
595         const SkRect* domain) const {
596     auto mm = sampling.mipmap == SkMipmapMode::kNone ? GrMipmapped::kNo : GrMipmapped::kYes;
597     return MakeFragmentProcessorFromView(rContext,
598                                          std::get<0>(this->asView(rContext, mm)),
599                                          this->alphaType(),
600                                          sampling,
601                                          tileModes,
602                                          m,
603                                          subset,
604                                          domain);
605 }
606 #endif
607 
608 #if defined(SK_GRAPHITE)
onMakeTextureImage(skgpu::graphite::Recorder * recorder,RequiredImageProperties requiredProps) const609 sk_sp<SkImage> SkImage_Raster::onMakeTextureImage(skgpu::graphite::Recorder* recorder,
610                                                   RequiredImageProperties requiredProps) const {
611     return skgpu::graphite::MakeFromBitmap(recorder,
612                                            this->imageInfo().colorInfo(),
613                                            fBitmap,
614                                            this->refMips(),
615                                            skgpu::Budgeted::kNo,
616                                            requiredProps);
617 }
618 
onMakeColorTypeAndColorSpace(SkColorType targetCT,sk_sp<SkColorSpace> targetCS,skgpu::graphite::Recorder * recorder,RequiredImageProperties requiredProps) const619 sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(
620         SkColorType targetCT,
621         sk_sp<SkColorSpace> targetCS,
622         skgpu::graphite::Recorder* recorder,
623         RequiredImageProperties requiredProps) const {
624     SkPixmap src;
625     SkAssertResult(fBitmap.peekPixels(&src));
626 
627     SkBitmap dst;
628     if (!dst.tryAllocPixels(fBitmap.info().makeColorType(targetCT).makeColorSpace(targetCS))) {
629         return nullptr;
630     }
631 
632     SkAssertResult(dst.writePixels(src));
633     dst.setImmutable();
634 
635     sk_sp<SkImage> tmp = dst.asImage();
636     if (recorder) {
637         return tmp->makeTextureImage(recorder, requiredProps);
638     } else {
639         return tmp;
640     }
641 }
642 
643 #endif
644