blob: c3c1098a70de74bc2bbb1897f58e2650938438e1 [file] [log] [blame]
reed@google.com58b21ec2012-07-30 18:20:12 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkBitmap.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkData.h"
11#include "include/core/SkPixelRef.h"
12#include "include/core/SkSurface.h"
13#include "include/private/SkImageInfoPriv.h"
14#include "src/codec/SkColorTable.h"
Robert Phillips99dead92020-01-27 16:11:57 -050015#include "src/core/SkCompressedDataUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/core/SkConvertPixels.h"
17#include "src/core/SkImagePriv.h"
18#include "src/core/SkTLazy.h"
19#include "src/image/SkImage_Base.h"
20#include "src/shaders/SkBitmapProcShader.h"
reed@google.com58b21ec2012-07-30 18:20:12 +000021
reed746f31f2015-09-16 12:53:29 -070022#if SK_SUPPORT_GPU
Brian Salomond0924f32021-02-03 10:15:31 -050023#include "src/gpu/GrBitmapTextureMaker.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/gpu/GrTextureAdjuster.h"
25#include "src/gpu/SkGr.h"
reed746f31f2015-09-16 12:53:29 -070026#endif
27
halcanary8d3ad5a2016-03-24 09:18:14 -070028// fixes https://bug.skia.org/5096
29static bool is_not_subset(const SkBitmap& bm) {
30 SkASSERT(bm.pixelRef());
Matt Saretta6e976a2017-04-28 15:43:35 -040031 SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
halcanary8d3ad5a2016-03-24 09:18:14 -070032 SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
33 return dim == bm.dimensions();
34}
35
reed@google.com58b21ec2012-07-30 18:20:12 +000036class SkImage_Raster : public SkImage_Base {
37public:
Cary Clarkcc45cc72018-05-15 16:06:12 -040038 static bool ValidArgs(const SkImageInfo& info, size_t rowBytes, size_t* minSize) {
reed@google.com58b21ec2012-07-30 18:20:12 +000039 const int maxDimension = SK_MaxS32 >> 2;
reed@google.com58b21ec2012-07-30 18:20:12 +000040
Khushalb11ce192020-02-14 14:07:16 -080041 // TODO(mtklein): eliminate anything here that setInfo() has already checked.
42 SkBitmap dummy;
43 if (!dummy.setInfo(info, rowBytes)) {
44 return false;
45 }
46
reedb2497c22014-12-31 12:31:43 -080047 if (info.width() <= 0 || info.height() <= 0) {
reed@google.com58b21ec2012-07-30 18:20:12 +000048 return false;
49 }
reede5ea5002014-09-03 11:54:58 -070050 if (info.width() > maxDimension || info.height() > maxDimension) {
reed@google.com58b21ec2012-07-30 18:20:12 +000051 return false;
52 }
reede5ea5002014-09-03 11:54:58 -070053 if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
reed@google.com58b21ec2012-07-30 18:20:12 +000054 return false;
55 }
reede5ea5002014-09-03 11:54:58 -070056 if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
reed@google.com58b21ec2012-07-30 18:20:12 +000057 return false;
58 }
59
commit-bot@chromium.orga3264e52014-05-30 13:26:10 +000060 if (kUnknown_SkColorType == info.colorType()) {
reed@google.com58b21ec2012-07-30 18:20:12 +000061 return false;
62 }
Mike Reedf0ffb892017-10-03 14:47:21 -040063 if (!info.validRowBytes(rowBytes)) {
reed@google.com58b21ec2012-07-30 18:20:12 +000064 return false;
65 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000066
Mike Reedf0ffb892017-10-03 14:47:21 -040067 size_t size = info.computeByteSize(rowBytes);
Mike Reedc5eb97d2017-10-09 10:42:51 -040068 if (SkImageInfo::ByteSizeOverflowed(size)) {
reed@google.com58b21ec2012-07-30 18:20:12 +000069 return false;
70 }
reedde499882015-06-18 13:41:40 -070071
72 if (minSize) {
73 *minSize = size;
74 }
reed@google.com58b21ec2012-07-30 18:20:12 +000075 return true;
76 }
77
Mike Reed086a4272017-07-18 10:53:11 -040078 SkImage_Raster(const SkImageInfo&, sk_sp<SkData>, size_t rb,
Brian Osmane5312072017-06-20 09:35:51 -040079 uint32_t id = kNeedNewImageUniqueID);
Brian Salomond3b65972017-03-22 12:05:03 -040080 ~SkImage_Raster() override;
reed@google.com58b21ec2012-07-30 18:20:12 +000081
Adlai Hollerbcfc5542020-08-27 12:44:07 -040082 bool onReadPixels(GrDirectContext*, const SkImageInfo&, void*, size_t, int srcX, int srcY,
Greg Danielfebdedf2020-02-05 17:06:27 -050083 CachingHint) const override;
reed6ceeebd2016-03-09 14:26:26 -080084 bool onPeekPixels(SkPixmap*) const override;
reedf1ac1822016-08-01 11:24:14 -070085 const SkBitmap* onPeekBitmap() const override { return &fBitmap; }
86
Adlai Hollerbcfc5542020-08-27 12:44:07 -040087 bool getROPixels(GrDirectContext*, SkBitmap*, CachingHint) const override;
Adlai Holler872a32c2020-07-10 14:33:22 -040088 sk_sp<SkImage> onMakeSubset(const SkIRect&, GrDirectContext*) const override;
reed@google.com58b21ec2012-07-30 18:20:12 +000089
reed@google.com97af1a62012-08-28 12:19:02 +000090 SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
91
Adlai Hollerbcfc5542020-08-27 12:44:07 -040092 bool onAsLegacyBitmap(GrDirectContext*, SkBitmap*) const override;
piotaixrd2a35222014-08-19 14:29:02 -070093
reed2dad7692016-08-01 11:12:58 -070094 SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable = false)
Brian Salomon5ad6fd32019-03-21 15:30:08 -040095 : INHERITED(bm.info(),
96 is_not_subset(bm) ? bm.getGenerationID() : (uint32_t)kNeedNewImageUniqueID)
97 , fBitmap(bm) {
reed2dad7692016-08-01 11:12:58 -070098 SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
fmalita9a5d1ab2015-07-27 10:27:28 -070099 }
halcanaryea4673f2014-08-18 08:27:09 -0700100
Adlai Holler3a220172020-07-15 10:37:50 -0400101 sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
102 GrDirectContext*) const override;
Matt Sarett6de13102017-03-14 14:10:48 -0400103
Brian Osmand5148372019-08-14 16:14:51 -0400104 sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const override;
105
Robert Phillips4a3ebc22020-07-10 11:27:43 -0400106 bool onIsValid(GrRecordingContext* context) const override { return true; }
Brian Osman3a160732018-10-15 15:32:06 -0400107 void notifyAddedToRasterCache() const override {
108 // We explicitly DON'T want to call INHERITED::notifyAddedToRasterCache. That ties the
109 // lifetime of derived/cached resources to the image. In this case, we only want cached
110 // data (eg mips) tied to the lifetime of the underlying pixelRef.
111 SkASSERT(fBitmap.pixelRef());
112 fBitmap.pixelRef()->notifyAddedToCache();
113 }
Brian Osman5bbd0762017-05-08 11:07:42 -0400114
reed2d5b7142016-08-17 11:12:33 -0700115#if SK_SUPPORT_GPU
Adlai Holler29405382020-07-20 16:02:05 -0400116 bool onPinAsTexture(GrRecordingContext*) const override;
117 void onUnpinAsTexture(GrRecordingContext*) const override;
Brian Salomon490f1922021-02-01 13:14:37 -0500118 bool isPinnedOnContext(GrRecordingContext*) const override;
reed2d5b7142016-08-17 11:12:33 -0700119#endif
120
Brian Salomon7d2757f2021-01-26 17:46:50 -0500121 bool onHasMipmaps() const override { return SkToBool(fBitmap.fMips); }
122
Mike Reed13711eb2020-07-14 17:16:32 -0400123 SkMipmap* onPeekMips() const override { return fBitmap.fMips.get(); }
Mike Reed2fe15692020-07-14 11:29:38 -0400124
Mike Reed13711eb2020-07-14 17:16:32 -0400125 sk_sp<SkImage> onMakeWithMipmaps(sk_sp<SkMipmap> mips) const override {
Mike Reed2fe15692020-07-14 11:29:38 -0400126 auto img = new SkImage_Raster(fBitmap);
127 if (mips) {
128 img->fBitmap.fMips = std::move(mips);
129 } else {
Mike Reed13711eb2020-07-14 17:16:32 -0400130 img->fBitmap.fMips.reset(SkMipmap::Build(fBitmap.pixmap(), nullptr));
Mike Reed2fe15692020-07-14 11:29:38 -0400131 }
132 return sk_sp<SkImage>(img);
133 }
134
reed@google.com58b21ec2012-07-30 18:20:12 +0000135private:
Brian Salomond0924f32021-02-03 10:15:31 -0500136#if SK_SUPPORT_GPU
137 std::tuple<GrSurfaceProxyView, GrColorType> onAsView(GrRecordingContext*,
138 GrMipmapped,
139 GrImageTexGenPolicy) const override;
140#endif
141
reedaf3fbfc2015-10-04 11:28:36 -0700142 SkBitmap fBitmap;
reed@google.com58b21ec2012-07-30 18:20:12 +0000143
reed2d5b7142016-08-17 11:12:33 -0700144#if SK_SUPPORT_GPU
Greg Danielcc21d0c2020-02-05 16:58:40 -0500145 mutable GrSurfaceProxyView fPinnedView;
reed2d5b7142016-08-17 11:12:33 -0700146 mutable int32_t fPinnedCount = 0;
Brian Salomon490f1922021-02-01 13:14:37 -0500147 mutable uint32_t fPinnedUniqueID = SK_InvalidUniqueID;
148 mutable uint32_t fPinnedContextID = SK_InvalidUniqueID;
Brian Salomond0924f32021-02-03 10:15:31 -0500149 mutable GrColorType fPinnedColorType = GrColorType::kUnknown;
reed2d5b7142016-08-17 11:12:33 -0700150#endif
151
John Stiles7571f9e2020-09-02 22:42:33 -0400152 using INHERITED = SkImage_Base;
reed@google.com58b21ec2012-07-30 18:20:12 +0000153};
154
155///////////////////////////////////////////////////////////////////////////////
156
reed@google.com4f7c6152014-02-06 14:11:56 +0000157static void release_data(void* addr, void* context) {
158 SkData* data = static_cast<SkData*>(context);
159 data->unref();
160}
161
Cary Clarkcc45cc72018-05-15 16:06:12 -0400162SkImage_Raster::SkImage_Raster(const SkImageInfo& info, sk_sp<SkData> data, size_t rowBytes,
163 uint32_t id)
Brian Salomon5ad6fd32019-03-21 15:30:08 -0400164 : INHERITED(info, id) {
reed@google.com4f7c6152014-02-06 14:11:56 +0000165 void* addr = const_cast<void*>(data->data());
166
Mike Reed086a4272017-07-18 10:53:11 -0400167 fBitmap.installPixels(info, addr, rowBytes, release_data, data.release());
reed@google.com58b21ec2012-07-30 18:20:12 +0000168 fBitmap.setImmutable();
169}
170
reed2d5b7142016-08-17 11:12:33 -0700171SkImage_Raster::~SkImage_Raster() {
172#if SK_SUPPORT_GPU
Greg Danielcc21d0c2020-02-05 16:58:40 -0500173 SkASSERT(!fPinnedView); // want the caller to have manually unpinned
reed2d5b7142016-08-17 11:12:33 -0700174#endif
175}
reed@google.com58b21ec2012-07-30 18:20:12 +0000176
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400177bool SkImage_Raster::onReadPixels(GrDirectContext*,
178 const SkImageInfo& dstInfo,
179 void* dstPixels,
180 size_t dstRowBytes,
181 int srcX,
182 int srcY,
183 CachingHint) const {
reedb4f629c2014-12-25 13:55:08 -0800184 SkBitmap shallowCopy(fBitmap);
185 return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
reed@google.com4f7c6152014-02-06 14:11:56 +0000186}
187
reed6ceeebd2016-03-09 14:26:26 -0800188bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
189 return fBitmap.peekPixels(pm);
reed@google.com4f7c6152014-02-06 14:11:56 +0000190}
191
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400192bool SkImage_Raster::getROPixels(GrDirectContext*, SkBitmap* dst, CachingHint) const {
reed@google.com4b0757b2013-05-20 16:33:41 +0000193 *dst = fBitmap;
194 return true;
195}
196
Robert Phillipsb726d582017-03-09 16:36:32 -0500197#if SK_SUPPORT_GPU
Adlai Holler29405382020-07-20 16:02:05 -0400198bool SkImage_Raster::onPinAsTexture(GrRecordingContext* rContext) const {
Greg Danielcc21d0c2020-02-05 16:58:40 -0500199 if (fPinnedView) {
reed2d5b7142016-08-17 11:12:33 -0700200 SkASSERT(fPinnedCount > 0);
201 SkASSERT(fPinnedUniqueID != 0);
Brian Salomon490f1922021-02-01 13:14:37 -0500202 if (rContext->priv().contextID() != fPinnedContextID) {
203 return false;
204 }
reed2d5b7142016-08-17 11:12:33 -0700205 } else {
206 SkASSERT(fPinnedCount == 0);
207 SkASSERT(fPinnedUniqueID == 0);
Brian Salomond0924f32021-02-03 10:15:31 -0500208 GrBitmapTextureMaker maker(rContext, fBitmap, GrImageTexGenPolicy::kDraw);
209 fPinnedView = maker.view(GrMipmapped::kNo);
Greg Danielcc21d0c2020-02-05 16:58:40 -0500210 if (!fPinnedView) {
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500211 return false;
212 }
Greg Danielcc21d0c2020-02-05 16:58:40 -0500213 SkASSERT(fPinnedView.asTextureProxy());
reed2d5b7142016-08-17 11:12:33 -0700214 fPinnedUniqueID = fBitmap.getGenerationID();
Brian Salomon490f1922021-02-01 13:14:37 -0500215 fPinnedContextID = rContext->priv().contextID();
Brian Salomond0924f32021-02-03 10:15:31 -0500216 fPinnedColorType = maker.colorType();
reed2d5b7142016-08-17 11:12:33 -0700217 }
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500218 // Note: we only increment if the texture was successfully pinned
reed2d5b7142016-08-17 11:12:33 -0700219 ++fPinnedCount;
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500220 return true;
reed2d5b7142016-08-17 11:12:33 -0700221}
222
Brian Salomon490f1922021-02-01 13:14:37 -0500223void SkImage_Raster::onUnpinAsTexture(GrRecordingContext* rContext) const {
reed2d5b7142016-08-17 11:12:33 -0700224 // Note: we always decrement, even if fPinnedTexture is null
225 SkASSERT(fPinnedCount > 0);
226 SkASSERT(fPinnedUniqueID != 0);
Brian Salomon490f1922021-02-01 13:14:37 -0500227#if 0 // This would be better but Android currently calls with an already freed context ptr.
228 if (rContext->priv().contextID() != fPinnedContextID) {
229 return;
230 }
231#endif
reed2d5b7142016-08-17 11:12:33 -0700232
233 if (0 == --fPinnedCount) {
Greg Danielcc21d0c2020-02-05 16:58:40 -0500234 fPinnedView = GrSurfaceProxyView();
Brian Salomon490f1922021-02-01 13:14:37 -0500235 fPinnedUniqueID = SK_InvalidUniqueID;
236 fPinnedContextID = SK_InvalidUniqueID;
Brian Salomond0924f32021-02-03 10:15:31 -0500237 fPinnedColorType = GrColorType::kUnknown;
reed2d5b7142016-08-17 11:12:33 -0700238 }
239}
Brian Salomon490f1922021-02-01 13:14:37 -0500240
241bool SkImage_Raster::isPinnedOnContext(GrRecordingContext* rContext) const {
242 return fPinnedContextID == rContext->priv().contextID();
243}
reed2d5b7142016-08-17 11:12:33 -0700244#endif
245
Adlai Holler872a32c2020-07-10 14:33:22 -0400246sk_sp<SkImage> SkImage_Raster::onMakeSubset(const SkIRect& subset, GrDirectContext*) const {
Brian Salomon9241a6d2019-10-03 13:26:54 -0400247 SkImageInfo info = fBitmap.info().makeDimensions(subset.size());
Brian Osman73140932017-08-16 16:35:54 -0400248 SkBitmap bitmap;
249 if (!bitmap.tryAllocPixels(info)) {
reed7b6945b2015-09-24 00:50:58 -0700250 return nullptr;
251 }
Brian Osman73140932017-08-16 16:35:54 -0400252
253 void* dst = bitmap.getPixels();
254 void* src = fBitmap.getAddr(subset.x(), subset.y());
255 if (!dst || !src) {
256 SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
257 return nullptr;
258 }
259
260 SkRectMemcpy(dst, bitmap.rowBytes(), src, fBitmap.rowBytes(), bitmap.rowBytes(),
261 subset.height());
262
263 bitmap.setImmutable();
Mike Reeddc607e32020-12-23 11:50:36 -0500264 return bitmap.asImage();
reed7b6945b2015-09-24 00:50:58 -0700265}
266
reed@google.com58b21ec2012-07-30 18:20:12 +0000267///////////////////////////////////////////////////////////////////////////////
268
Brian Osmane5312072017-06-20 09:35:51 -0400269sk_sp<SkImage> MakeRasterCopyPriv(const SkPixmap& pmap, uint32_t id) {
reedde499882015-06-18 13:41:40 -0700270 size_t size;
Mike Reed086a4272017-07-18 10:53:11 -0400271 if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700272 return nullptr;
reed@google.com58b21ec2012-07-30 18:20:12 +0000273 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000274
reed@google.com58b21ec2012-07-30 18:20:12 +0000275 // Here we actually make a copy of the caller's pixel data
bungeman38d909e2016-08-02 14:40:46 -0700276 sk_sp<SkData> data(SkData::MakeWithCopy(pmap.addr(), size));
Mike Reed086a4272017-07-18 10:53:11 -0400277 return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes(), id);
reed@google.com58b21ec2012-07-30 18:20:12 +0000278}
279
Brian Osmane5312072017-06-20 09:35:51 -0400280sk_sp<SkImage> SkImage::MakeRasterCopy(const SkPixmap& pmap) {
281 return MakeRasterCopyPriv(pmap, kNeedNewImageUniqueID);
282}
reed@google.com58b21ec2012-07-30 18:20:12 +0000283
reed7fb4f8b2016-03-11 04:33:52 -0800284sk_sp<SkImage> SkImage::MakeRasterData(const SkImageInfo& info, sk_sp<SkData> data,
285 size_t rowBytes) {
reedde499882015-06-18 13:41:40 -0700286 size_t size;
Mike Reed086a4272017-07-18 10:53:11 -0400287 if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !data) {
halcanary96fcdcc2015-08-27 07:41:13 -0700288 return nullptr;
reed@google.com58b21ec2012-07-30 18:20:12 +0000289 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000290
reed@google.com58b21ec2012-07-30 18:20:12 +0000291 // did they give us enough data?
reed@google.com999da9c2014-02-06 13:43:07 +0000292 if (data->size() < size) {
halcanary96fcdcc2015-08-27 07:41:13 -0700293 return nullptr;
reed@google.com58b21ec2012-07-30 18:20:12 +0000294 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000295
Mike Reed086a4272017-07-18 10:53:11 -0400296 return sk_make_sp<SkImage_Raster>(info, std::move(data), rowBytes);
reed@google.com58b21ec2012-07-30 18:20:12 +0000297}
298
Robert Phillips99dead92020-01-27 16:11:57 -0500299// TODO: this could be improved to decode and make use of the mipmap
300// levels potentially present in the compressed data. For now, any
301// mipmap levels are discarded.
302sk_sp<SkImage> SkImage::MakeRasterFromCompressed(sk_sp<SkData> data,
303 int width, int height,
304 CompressionType type) {
305 size_t expectedSize = SkCompressedFormatDataSize(type, { width, height }, false);
306 if (!data || data->size() < expectedSize) {
307 return nullptr;
308 }
309
310 SkAlphaType at = SkCompressionTypeIsOpaque(type) ? kOpaque_SkAlphaType
311 : kPremul_SkAlphaType;
312
Robert Phillips162e04b2020-01-28 14:22:43 -0500313 SkImageInfo ii = SkImageInfo::MakeN32(width, height, at);
Robert Phillips99dead92020-01-27 16:11:57 -0500314
315 if (!SkImage_Raster::ValidArgs(ii, ii.minRowBytes(), nullptr)) {
316 return nullptr;
317 }
318
319 SkBitmap bitmap;
320 if (!bitmap.tryAllocPixels(ii)) {
321 return nullptr;
322 }
323
324 if (!SkDecompress(std::move(data), { width, height }, type, &bitmap)) {
325 return nullptr;
326 }
327
328 bitmap.setImmutable();
329 return MakeFromBitmap(bitmap);
330}
331
reed7fb4f8b2016-03-11 04:33:52 -0800332sk_sp<SkImage> SkImage::MakeFromRaster(const SkPixmap& pmap, RasterReleaseProc proc,
333 ReleaseContext ctx) {
reedde499882015-06-18 13:41:40 -0700334 size_t size;
Mike Reed086a4272017-07-18 10:53:11 -0400335 if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700336 return nullptr;
reedde499882015-06-18 13:41:40 -0700337 }
338
bungeman38d909e2016-08-02 14:40:46 -0700339 sk_sp<SkData> data(SkData::MakeWithProc(pmap.addr(), size, proc, ctx));
Mike Reed086a4272017-07-18 10:53:11 -0400340 return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes());
reedde499882015-06-18 13:41:40 -0700341}
342
Brian Osmane5312072017-06-20 09:35:51 -0400343sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm,
344 uint32_t idForCopy) {
Matt Sarettb6759dd2017-06-12 13:46:11 -0400345 if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
346 SkPixmap pmap;
347 if (bm.peekPixels(&pmap)) {
Brian Osmane5312072017-06-20 09:35:51 -0400348 return MakeRasterCopyPriv(pmap, idForCopy);
Matt Sarettb6759dd2017-06-12 13:46:11 -0400349 } else {
350 return sk_sp<SkImage>();
351 }
halcanaryc56c6ef2015-09-28 11:55:28 -0700352 }
353
Matt Sarettb6759dd2017-06-12 13:46:11 -0400354 return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
355}
356
357sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
Brian Osmane1adc3a2018-06-04 09:21:17 -0400358 if (!SkImageInfoIsValid(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700359 return nullptr;
kkinnunen73953e72015-02-23 22:12:12 -0800360 }
361
Brian Osmane5312072017-06-20 09:35:51 -0400362 return SkMakeImageFromRasterBitmapPriv(bm, cpm, kNeedNewImageUniqueID);
reed@google.com58b21ec2012-07-30 18:20:12 +0000363}
364
piotaixr65151752014-10-16 11:58:39 -0700365const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
366 return ((const SkImage_Raster*)image)->getPixelRef();
reed@google.com97af1a62012-08-28 12:19:02 +0000367}
piotaixrd2a35222014-08-19 14:29:02 -0700368
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400369bool SkImage_Raster::onAsLegacyBitmap(GrDirectContext*, SkBitmap* bitmap) const {
Cary Clark4f5a79c2018-02-07 15:51:00 -0500370 // When we're a snapshot from a surface, our bitmap may not be marked immutable
371 // even though logically always we are, but in that case we can't physically share our
372 // pixelref since the caller might call setImmutable() themselves
373 // (thus changing our state).
374 if (fBitmap.isImmutable()) {
375 SkIPoint origin = fBitmap.pixelRefOrigin();
376 bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
377 bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()), origin.x(), origin.y());
378 return true;
reed3c065112015-07-08 12:46:22 -0700379 }
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400380 return this->INHERITED::onAsLegacyBitmap(nullptr, bitmap);
reed3c065112015-07-08 12:46:22 -0700381}
Matt Sarett6de13102017-03-14 14:10:48 -0400382
Matt Sarett5b1dba82017-04-03 11:42:52 -0400383///////////////////////////////////////////////////////////////////////////////
384
Adlai Holler3a220172020-07-15 10:37:50 -0400385sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(SkColorType targetCT,
386 sk_sp<SkColorSpace> targetCS,
387 GrDirectContext*) const {
Matt Sarett6de13102017-03-14 14:10:48 -0400388 SkPixmap src;
Matt Sarett9f3dcb32017-05-04 08:53:32 -0400389 SkAssertResult(fBitmap.peekPixels(&src));
Matt Sarett6de13102017-03-14 14:10:48 -0400390
Matt Sarettd3df9ec2017-06-05 10:45:30 -0400391 SkBitmap dst;
Brian Osmanf48c9962019-01-14 11:15:50 -0500392 dst.allocPixels(fBitmap.info().makeColorType(targetCT).makeColorSpace(targetCS));
Matt Sarettd3df9ec2017-06-05 10:45:30 -0400393
Brian Osmanbe686f02018-10-12 11:18:02 -0400394 SkAssertResult(dst.writePixels(src));
Matt Sarett6de13102017-03-14 14:10:48 -0400395 dst.setImmutable();
Mike Reeddc607e32020-12-23 11:50:36 -0500396 return dst.asImage();
Matt Sarett6de13102017-03-14 14:10:48 -0400397}
Brian Osmand5148372019-08-14 16:14:51 -0400398
399sk_sp<SkImage> SkImage_Raster::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
400 // TODO: If our bitmap is immutable, then we could theoretically create another image sharing
401 // our pixelRef. That doesn't work (without more invasive logic), because the image gets its
402 // gen ID from the bitmap, which gets it from the pixelRef.
403 SkPixmap pixmap = fBitmap.pixmap();
404 pixmap.setColorSpace(std::move(newCS));
405 return SkImage::MakeRasterCopy(pixmap);
406}
Brian Salomond0924f32021-02-03 10:15:31 -0500407
408#if SK_SUPPORT_GPU
409std::tuple<GrSurfaceProxyView, GrColorType> SkImage_Raster::onAsView(
410 GrRecordingContext* context,
411 GrMipmapped mipmapped,
412 GrImageTexGenPolicy policy) const {
413 if (fPinnedView) {
414 if (policy != GrImageTexGenPolicy::kDraw) {
415 return {CopyView(context, fPinnedView, mipmapped, policy), fPinnedColorType};
416 }
417 GrColorInfo colorInfo(fPinnedColorType, this->alphaType(), this->refColorSpace());
418 GrTextureAdjuster adjuster(context, fPinnedView, colorInfo, fPinnedUniqueID);
419 return {adjuster.view(mipmapped), adjuster.colorType()};
420 }
421
422 GrBitmapTextureMaker maker(context, fBitmap, policy);
423 return {maker.view(mipmapped), maker.colorType()};
424}
425#endif