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/SkBitmap.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkCapabilities.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkMallocPixelRef.h"
13 #include "include/core/SkPixelRef.h"
14 #include "include/core/SkRect.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkSamplingOptions.h"
17 #include "include/core/SkScalar.h"
18 #include "include/core/SkSurface.h"
19 #include "include/private/base/SkAssert.h"
20 #include "include/private/base/SkMath.h"
21 #include "src/core/SkDevice.h"
22 #include "src/core/SkImageInfoPriv.h"
23 #include "src/core/SkImagePriv.h"
24 #include "src/core/SkSurfacePriv.h"
25 #include "src/image/SkSurface_Base.h"
26
27 #include <cstdint>
28 #include <cstring>
29 #include <utility>
30
31 class SkImage;
32 class SkPaint;
33 class SkPixmap;
34 class SkSurfaceProps;
35
36 class SkSurface_Raster : public SkSurface_Base {
37 public:
38 SkSurface_Raster(const SkImageInfo&, void*, size_t rb,
39 void (*releaseProc)(void* pixels, void* context), void* context,
40 const SkSurfaceProps*);
41 SkSurface_Raster(const SkImageInfo& info, sk_sp<SkPixelRef>, const SkSurfaceProps*);
42
imageInfo() const43 SkImageInfo imageInfo() const override { return fBitmap.info(); }
44
45 SkCanvas* onNewCanvas() override;
46 sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
47 sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset) override;
48 void onWritePixels(const SkPixmap&, int x, int y) override;
49 void onDraw(SkCanvas*, SkScalar, SkScalar, const SkSamplingOptions&, const SkPaint*) override;
50 bool onCopyOnWrite(ContentChangeMode) override;
51 void onRestoreBackingMutability() override;
52 sk_sp<const SkCapabilities> onCapabilities() override;
53
54 private:
55 SkBitmap fBitmap;
56 bool fWeOwnThePixels;
57
58 using INHERITED = SkSurface_Base;
59 };
60
61 ///////////////////////////////////////////////////////////////////////////////
62
SkSurfaceValidateRasterInfo(const SkImageInfo & info,size_t rowBytes)63 bool SkSurfaceValidateRasterInfo(const SkImageInfo& info, size_t rowBytes) {
64 if (!SkImageInfoIsValid(info)) {
65 return false;
66 }
67
68 if (kIgnoreRowBytesValue == rowBytes) {
69 return true;
70 }
71
72 if (!info.validRowBytes(rowBytes)) {
73 return false;
74 }
75
76 uint64_t size = sk_64_mul(info.height(), rowBytes);
77 static const size_t kMaxTotalSize = SK_MaxS32;
78 if (size > kMaxTotalSize) {
79 return false;
80 }
81
82 return true;
83 }
84
SkSurface_Raster(const SkImageInfo & info,void * pixels,size_t rb,void (* releaseProc)(void * pixels,void * context),void * context,const SkSurfaceProps * props)85 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb,
86 void (*releaseProc)(void* pixels, void* context), void* context,
87 const SkSurfaceProps* props)
88 : INHERITED(info, props)
89 {
90 fBitmap.installPixels(info, pixels, rb, releaseProc, context);
91 fWeOwnThePixels = false; // We are "Direct"
92 }
93
SkSurface_Raster(const SkImageInfo & info,sk_sp<SkPixelRef> pr,const SkSurfaceProps * props)94 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, sk_sp<SkPixelRef> pr,
95 const SkSurfaceProps* props)
96 : INHERITED(pr->width(), pr->height(), props)
97 {
98 fBitmap.setInfo(info, pr->rowBytes());
99 fBitmap.setPixelRef(std::move(pr), 0, 0);
100 fWeOwnThePixels = true;
101 }
102
onNewCanvas()103 SkCanvas* SkSurface_Raster::onNewCanvas() { return new SkCanvas(fBitmap, this->props()); }
104
onNewSurface(const SkImageInfo & info)105 sk_sp<SkSurface> SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
106 return SkSurface::MakeRaster(info, &this->props());
107 }
108
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkSamplingOptions & sampling,const SkPaint * paint)109 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
110 const SkSamplingOptions& sampling, const SkPaint* paint) {
111 canvas->drawImage(fBitmap.asImage().get(), x, y, sampling, paint);
112 }
113
onNewImageSnapshot(const SkIRect * subset)114 sk_sp<SkImage> SkSurface_Raster::onNewImageSnapshot(const SkIRect* subset) {
115 if (subset) {
116 SkASSERT(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()).contains(*subset));
117 SkBitmap dst;
118 dst.allocPixels(fBitmap.info().makeDimensions(subset->size()));
119 SkAssertResult(fBitmap.readPixels(dst.pixmap(), subset->left(), subset->top()));
120 dst.setImmutable(); // key, so MakeFromBitmap doesn't make a copy of the buffer
121 return dst.asImage();
122 }
123
124 SkCopyPixelsMode cpm = kIfMutable_SkCopyPixelsMode;
125 if (fWeOwnThePixels) {
126 // SkImage_raster requires these pixels are immutable for its full lifetime.
127 // We'll undo this via onRestoreBackingMutability() if we can avoid the COW.
128 if (SkPixelRef* pr = fBitmap.pixelRef()) {
129 pr->setTemporarilyImmutable();
130 }
131 } else {
132 cpm = kAlways_SkCopyPixelsMode;
133 }
134
135 // Our pixels are in memory, so read access on the snapshot SkImage could be cheap.
136 // Lock the shared pixel ref to ensure peekPixels() is usable.
137 return SkMakeImageFromRasterBitmap(fBitmap, cpm);
138 }
139
onWritePixels(const SkPixmap & src,int x,int y)140 void SkSurface_Raster::onWritePixels(const SkPixmap& src, int x, int y) {
141 fBitmap.writePixels(src, x, y);
142 }
143
onRestoreBackingMutability()144 void SkSurface_Raster::onRestoreBackingMutability() {
145 SkASSERT(!this->hasCachedImage()); // Shouldn't be any snapshots out there.
146 if (SkPixelRef* pr = fBitmap.pixelRef()) {
147 pr->restoreMutability();
148 }
149 }
150
onCopyOnWrite(ContentChangeMode mode)151 bool SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
152 // are we sharing pixelrefs with the image?
153 sk_sp<SkImage> cached(this->refCachedImage());
154 SkASSERT(cached);
155 if (SkBitmapImageGetPixelRef(cached.get()) == fBitmap.pixelRef()) {
156 SkASSERT(fWeOwnThePixels);
157 if (kDiscard_ContentChangeMode == mode) {
158 if (!fBitmap.tryAllocPixels()) {
159 return false;
160 }
161 } else {
162 SkBitmap prev(fBitmap);
163 if (!fBitmap.tryAllocPixels()) {
164 return false;
165 }
166 SkASSERT(prev.info() == fBitmap.info());
167 SkASSERT(prev.rowBytes() == fBitmap.rowBytes());
168 memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.computeByteSize());
169 }
170
171 // Now fBitmap is a deep copy of itself (and therefore different from
172 // what is being used by the image. Next we update the canvas to use
173 // this as its backend, so we can't modify the image's pixels anymore.
174 SkASSERT(this->getCachedCanvas());
175 this->getCachedCanvas()->baseDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
176 }
177 return true;
178 }
179
onCapabilities()180 sk_sp<const SkCapabilities> SkSurface_Raster::onCapabilities() {
181 return SkCapabilities::RasterBackend();
182 }
183
184 ///////////////////////////////////////////////////////////////////////////////
185
MakeRasterDirectReleaseProc(const SkImageInfo & info,void * pixels,size_t rb,void (* releaseProc)(void * pixels,void * context),void * context,const SkSurfaceProps * props)186 sk_sp<SkSurface> SkSurface::MakeRasterDirectReleaseProc(const SkImageInfo& info, void* pixels,
187 size_t rb, void (*releaseProc)(void* pixels, void* context), void* context,
188 const SkSurfaceProps* props) {
189 if (nullptr == releaseProc) {
190 context = nullptr;
191 }
192 if (!SkSurfaceValidateRasterInfo(info, rb)) {
193 return nullptr;
194 }
195 if (nullptr == pixels) {
196 return nullptr;
197 }
198
199 return sk_make_sp<SkSurface_Raster>(info, pixels, rb, releaseProc, context, props);
200 }
201
MakeRasterDirect(const SkImageInfo & info,void * pixels,size_t rowBytes,const SkSurfaceProps * props)202 sk_sp<SkSurface> SkSurface::MakeRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes,
203 const SkSurfaceProps* props) {
204 return MakeRasterDirectReleaseProc(info, pixels, rowBytes, nullptr, nullptr, props);
205 }
206
MakeRaster(const SkImageInfo & info,size_t rowBytes,const SkSurfaceProps * props)207 sk_sp<SkSurface> SkSurface::MakeRaster(const SkImageInfo& info, size_t rowBytes,
208 const SkSurfaceProps* props) {
209 if (!SkSurfaceValidateRasterInfo(info)) {
210 return nullptr;
211 }
212
213 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, rowBytes);
214 if (!pr) {
215 return nullptr;
216 }
217 if (rowBytes) {
218 SkASSERT(pr->rowBytes() == rowBytes);
219 }
220 return sk_make_sp<SkSurface_Raster>(info, std::move(pr), props);
221 }
222
MakeRasterN32Premul(int width,int height,const SkSurfaceProps * surfaceProps)223 sk_sp<SkSurface> SkSurface::MakeRasterN32Premul(int width, int height,
224 const SkSurfaceProps* surfaceProps) {
225 return MakeRaster(SkImageInfo::MakeN32Premul(width, height), surfaceProps);
226 }
227