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 "SkImage_Base.h"
9 #include "SkBitmap.h"
10 #include "SkBitmapProcShader.h"
11 #include "SkCanvas.h"
12 #include "SkColorSpaceXform_Base.h"
13 #include "SkColorSpaceXformPriv.h"
14 #include "SkColorTable.h"
15 #include "SkConvertPixels.h"
16 #include "SkData.h"
17 #include "SkImageInfoPriv.h"
18 #include "SkImagePriv.h"
19 #include "SkPixelRef.h"
20 #include "SkSurface.h"
21 #include "SkTLazy.h"
22 #include "SkUnPreMultiplyPriv.h"
23
24 #if SK_SUPPORT_GPU
25 #include "GrContext.h"
26 #include "GrTextureAdjuster.h"
27 #include "SkGr.h"
28 #endif
29
30 // fixes https://bug.skia.org/5096
is_not_subset(const SkBitmap & bm)31 static bool is_not_subset(const SkBitmap& bm) {
32 SkASSERT(bm.pixelRef());
33 SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
34 SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
35 return dim == bm.dimensions();
36 }
37
38 class SkImage_Raster : public SkImage_Base {
39 public:
ValidArgs(const Info & info,size_t rowBytes,size_t * minSize)40 static bool ValidArgs(const Info& info, size_t rowBytes, size_t* minSize) {
41 const int maxDimension = SK_MaxS32 >> 2;
42
43 if (info.width() <= 0 || info.height() <= 0) {
44 return false;
45 }
46 if (info.width() > maxDimension || info.height() > maxDimension) {
47 return false;
48 }
49 if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
50 return false;
51 }
52 if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
53 return false;
54 }
55
56 if (kUnknown_SkColorType == info.colorType()) {
57 return false;
58 }
59 if (!info.validRowBytes(rowBytes)) {
60 return false;
61 }
62
63 size_t size = info.computeByteSize(rowBytes);
64 if (SkImageInfo::ByteSizeOverflowed(size)) {
65 return false;
66 }
67
68 if (minSize) {
69 *minSize = size;
70 }
71 return true;
72 }
73
74 SkImage_Raster(const SkImageInfo&, sk_sp<SkData>, size_t rb,
75 uint32_t id = kNeedNewImageUniqueID);
76 ~SkImage_Raster() override;
77
onImageInfo() const78 SkImageInfo onImageInfo() const override {
79 return fBitmap.info();
80 }
onAlphaType() const81 SkAlphaType onAlphaType() const override {
82 return fBitmap.alphaType();
83 }
84
85 bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY, CachingHint) const override;
86 bool onPeekPixels(SkPixmap*) const override;
onPeekBitmap() const87 const SkBitmap* onPeekBitmap() const override { return &fBitmap; }
88
89 #if SK_SUPPORT_GPU
90 sk_sp<GrTextureProxy> asTextureProxyRef(GrContext*, const GrSamplerState&, SkColorSpace*,
91 sk_sp<SkColorSpace>*,
92 SkScalar scaleAdjust[2]) const override;
93 #endif
94
95 bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override;
96 sk_sp<SkImage> onMakeSubset(const SkIRect&) const override;
97
getPixelRef() const98 SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
99
100 bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const override;
101
SkImage_Raster(const SkBitmap & bm,bool bitmapMayBeMutable=false)102 SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable = false)
103 : INHERITED(bm.width(), bm.height(),
104 is_not_subset(bm) ? bm.getGenerationID()
105 : (uint32_t)kNeedNewImageUniqueID)
106 , fBitmap(bm)
107 {
108 SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
109 }
110
111 sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>, SkColorType,
112 SkTransferFunctionBehavior) const override;
113
onIsValid(GrContext * context) const114 bool onIsValid(GrContext* context) const override { return true; }
115
116 #if SK_SUPPORT_GPU
117 sk_sp<GrTextureProxy> refPinnedTextureProxy(uint32_t* uniqueID) const override;
118 bool onPinAsTexture(GrContext*) const override;
119 void onUnpinAsTexture(GrContext*) const override;
120 #endif
121
122 private:
123 SkBitmap fBitmap;
124
125 #if SK_SUPPORT_GPU
126 mutable sk_sp<GrTextureProxy> fPinnedProxy;
127 mutable int32_t fPinnedCount = 0;
128 mutable uint32_t fPinnedUniqueID = 0;
129 #endif
130
131 typedef SkImage_Base INHERITED;
132 };
133
134 ///////////////////////////////////////////////////////////////////////////////
135
release_data(void * addr,void * context)136 static void release_data(void* addr, void* context) {
137 SkData* data = static_cast<SkData*>(context);
138 data->unref();
139 }
140
SkImage_Raster(const Info & info,sk_sp<SkData> data,size_t rowBytes,uint32_t id)141 SkImage_Raster::SkImage_Raster(const Info& info, sk_sp<SkData> data, size_t rowBytes, uint32_t id)
142 : INHERITED(info.width(), info.height(), id)
143 {
144 void* addr = const_cast<void*>(data->data());
145
146 fBitmap.installPixels(info, addr, rowBytes, release_data, data.release());
147 fBitmap.setImmutable();
148 }
149
~SkImage_Raster()150 SkImage_Raster::~SkImage_Raster() {
151 #if SK_SUPPORT_GPU
152 SkASSERT(nullptr == fPinnedProxy.get()); // want the caller to have manually unpinned
153 #endif
154 }
155
onReadPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY,CachingHint) const156 bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
157 int srcX, int srcY, CachingHint) const {
158 SkBitmap shallowCopy(fBitmap);
159 return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
160 }
161
onPeekPixels(SkPixmap * pm) const162 bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
163 return fBitmap.peekPixels(pm);
164 }
165
getROPixels(SkBitmap * dst,SkColorSpace * dstColorSpace,CachingHint) const166 bool SkImage_Raster::getROPixels(SkBitmap* dst, SkColorSpace* dstColorSpace, CachingHint) const {
167 *dst = fBitmap;
168 return true;
169 }
170
171 #if SK_SUPPORT_GPU
asTextureProxyRef(GrContext * context,const GrSamplerState & params,SkColorSpace * dstColorSpace,sk_sp<SkColorSpace> * texColorSpace,SkScalar scaleAdjust[2]) const172 sk_sp<GrTextureProxy> SkImage_Raster::asTextureProxyRef(GrContext* context,
173 const GrSamplerState& params,
174 SkColorSpace* dstColorSpace,
175 sk_sp<SkColorSpace>* texColorSpace,
176 SkScalar scaleAdjust[2]) const {
177 if (!context) {
178 return nullptr;
179 }
180
181 if (texColorSpace) {
182 *texColorSpace = sk_ref_sp(fBitmap.colorSpace());
183 }
184
185 uint32_t uniqueID;
186 sk_sp<GrTextureProxy> tex = this->refPinnedTextureProxy(&uniqueID);
187 if (tex) {
188 GrTextureAdjuster adjuster(context, fPinnedProxy, fBitmap.alphaType(), fPinnedUniqueID,
189 fBitmap.colorSpace());
190 return adjuster.refTextureProxySafeForParams(params, scaleAdjust);
191 }
192
193 return GrRefCachedBitmapTextureProxy(context, fBitmap, params, scaleAdjust);
194 }
195 #endif
196
197 #if SK_SUPPORT_GPU
198
refPinnedTextureProxy(uint32_t * uniqueID) const199 sk_sp<GrTextureProxy> SkImage_Raster::refPinnedTextureProxy(uint32_t* uniqueID) const {
200 if (fPinnedProxy) {
201 SkASSERT(fPinnedCount > 0);
202 SkASSERT(fPinnedUniqueID != 0);
203 *uniqueID = fPinnedUniqueID;
204 return fPinnedProxy;
205 }
206 return nullptr;
207 }
208
onPinAsTexture(GrContext * ctx) const209 bool SkImage_Raster::onPinAsTexture(GrContext* ctx) const {
210 if (fPinnedProxy) {
211 SkASSERT(fPinnedCount > 0);
212 SkASSERT(fPinnedUniqueID != 0);
213 } else {
214 SkASSERT(fPinnedCount == 0);
215 SkASSERT(fPinnedUniqueID == 0);
216 fPinnedProxy = GrRefCachedBitmapTextureProxy(ctx, fBitmap, GrSamplerState::ClampNearest(),
217 nullptr);
218 if (!fPinnedProxy) {
219 return false;
220 }
221 fPinnedUniqueID = fBitmap.getGenerationID();
222 }
223 // Note: we only increment if the texture was successfully pinned
224 ++fPinnedCount;
225 return true;
226 }
227
onUnpinAsTexture(GrContext * ctx) const228 void SkImage_Raster::onUnpinAsTexture(GrContext* ctx) const {
229 // Note: we always decrement, even if fPinnedTexture is null
230 SkASSERT(fPinnedCount > 0);
231 SkASSERT(fPinnedUniqueID != 0);
232
233 if (0 == --fPinnedCount) {
234 fPinnedProxy.reset(nullptr);
235 fPinnedUniqueID = 0;
236 }
237 }
238 #endif
239
onMakeSubset(const SkIRect & subset) const240 sk_sp<SkImage> SkImage_Raster::onMakeSubset(const SkIRect& subset) const {
241 SkImageInfo info = fBitmap.info().makeWH(subset.width(), subset.height());
242 SkBitmap bitmap;
243 if (!bitmap.tryAllocPixels(info)) {
244 return nullptr;
245 }
246
247 void* dst = bitmap.getPixels();
248 void* src = fBitmap.getAddr(subset.x(), subset.y());
249 if (!dst || !src) {
250 SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
251 return nullptr;
252 }
253
254 SkRectMemcpy(dst, bitmap.rowBytes(), src, fBitmap.rowBytes(), bitmap.rowBytes(),
255 subset.height());
256
257 bitmap.setImmutable();
258 return MakeFromBitmap(bitmap);
259 }
260
261 ///////////////////////////////////////////////////////////////////////////////
262
MakeRasterCopyPriv(const SkPixmap & pmap,uint32_t id)263 sk_sp<SkImage> MakeRasterCopyPriv(const SkPixmap& pmap, uint32_t id) {
264 size_t size;
265 if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
266 return nullptr;
267 }
268
269 // Here we actually make a copy of the caller's pixel data
270 sk_sp<SkData> data(SkData::MakeWithCopy(pmap.addr(), size));
271 return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes(), id);
272 }
273
MakeRasterCopy(const SkPixmap & pmap)274 sk_sp<SkImage> SkImage::MakeRasterCopy(const SkPixmap& pmap) {
275 return MakeRasterCopyPriv(pmap, kNeedNewImageUniqueID);
276 }
277
MakeRasterData(const SkImageInfo & info,sk_sp<SkData> data,size_t rowBytes)278 sk_sp<SkImage> SkImage::MakeRasterData(const SkImageInfo& info, sk_sp<SkData> data,
279 size_t rowBytes) {
280 size_t size;
281 if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !data) {
282 return nullptr;
283 }
284
285 // did they give us enough data?
286 if (data->size() < size) {
287 return nullptr;
288 }
289
290 return sk_make_sp<SkImage_Raster>(info, std::move(data), rowBytes);
291 }
292
MakeFromRaster(const SkPixmap & pmap,RasterReleaseProc proc,ReleaseContext ctx)293 sk_sp<SkImage> SkImage::MakeFromRaster(const SkPixmap& pmap, RasterReleaseProc proc,
294 ReleaseContext ctx) {
295 size_t size;
296 if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), &size) || !pmap.addr()) {
297 return nullptr;
298 }
299
300 sk_sp<SkData> data(SkData::MakeWithProc(pmap.addr(), size, proc, ctx));
301 return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes());
302 }
303
SkMakeImageFromRasterBitmapPriv(const SkBitmap & bm,SkCopyPixelsMode cpm,uint32_t idForCopy)304 sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm,
305 uint32_t idForCopy) {
306 if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
307 SkPixmap pmap;
308 if (bm.peekPixels(&pmap)) {
309 return MakeRasterCopyPriv(pmap, idForCopy);
310 } else {
311 return sk_sp<SkImage>();
312 }
313 }
314
315 return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
316 }
317
SkMakeImageFromRasterBitmap(const SkBitmap & bm,SkCopyPixelsMode cpm)318 sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
319 if (!SkImageInfoIsValidAllowNumericalCS(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
320 return nullptr;
321 }
322
323 return SkMakeImageFromRasterBitmapPriv(bm, cpm, kNeedNewImageUniqueID);
324 }
325
SkBitmapImageGetPixelRef(const SkImage * image)326 const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
327 return ((const SkImage_Raster*)image)->getPixelRef();
328 }
329
onAsLegacyBitmap(SkBitmap * bitmap,LegacyBitmapMode mode) const330 bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const {
331 if (kRO_LegacyBitmapMode == mode) {
332 // When we're a snapshot from a surface, our bitmap may not be marked immutable
333 // even though logically always we are, but in that case we can't physically share our
334 // pixelref since the caller might call setImmutable() themselves
335 // (thus changing our state).
336 if (fBitmap.isImmutable()) {
337 SkIPoint origin = fBitmap.pixelRefOrigin();
338 bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
339 bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()), origin.x(), origin.y());
340 return true;
341 }
342 }
343 return this->INHERITED::onAsLegacyBitmap(bitmap, mode);
344 }
345
346 ///////////////////////////////////////////////////////////////////////////////
347
onMakeColorSpace(sk_sp<SkColorSpace> target,SkColorType targetColorType,SkTransferFunctionBehavior premulBehavior) const348 sk_sp<SkImage> SkImage_Raster::onMakeColorSpace(sk_sp<SkColorSpace> target,
349 SkColorType targetColorType,
350 SkTransferFunctionBehavior premulBehavior) const {
351 SkPixmap src;
352 SkAssertResult(fBitmap.peekPixels(&src));
353
354 // Treat nullptr srcs as sRGB.
355 if (!src.colorSpace()) {
356 if (target->isSRGB()) {
357 return sk_ref_sp(const_cast<SkImage*>((SkImage*)this));
358 }
359
360 src.setColorSpace(SkColorSpace::MakeSRGB());
361 }
362
363 SkImageInfo dstInfo = fBitmap.info().makeColorType(targetColorType).makeColorSpace(target);
364 SkBitmap dst;
365 dst.allocPixels(dstInfo);
366
367 SkAssertResult(dst.writePixels(src, 0, 0, premulBehavior));
368 dst.setImmutable();
369 return SkImage::MakeFromBitmap(dst);
370 }
371