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 "SkSurface_Base.h"
9 #include "SkImagePriv.h"
10 #include "SkCanvas.h"
11 #include "SkDevice.h"
12 #include "SkMallocPixelRef.h"
13
14 static const size_t kIgnoreRowBytesValue = (size_t)~0;
15
16 class SkSurface_Raster : public SkSurface_Base {
17 public:
18 static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue);
19
20 SkSurface_Raster(const SkImageInfo&, void*, size_t rb,
21 void (*releaseProc)(void* pixels, void* context), void* context,
22 const SkSurfaceProps*);
23 SkSurface_Raster(SkPixelRef*, const SkSurfaceProps*);
24
25 SkCanvas* onNewCanvas() override;
26 SkSurface* onNewSurface(const SkImageInfo&) override;
27 SkImage* onNewImageSnapshot(SkBudgeted, ForceCopyMode) override;
28 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override;
29 void onCopyOnWrite(ContentChangeMode) override;
30 void onRestoreBackingMutability() override;
31
32 private:
33 SkBitmap fBitmap;
34 size_t fRowBytes;
35 bool fWeOwnThePixels;
36
37 typedef SkSurface_Base INHERITED;
38 };
39
40 ///////////////////////////////////////////////////////////////////////////////
41
Valid(const SkImageInfo & info,size_t rowBytes)42 bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
43 if (info.isEmpty()) {
44 return false;
45 }
46
47 static const size_t kMaxTotalSize = SK_MaxS32;
48
49 int shift = 0;
50 switch (info.colorType()) {
51 case kAlpha_8_SkColorType:
52 shift = 0;
53 break;
54 case kRGB_565_SkColorType:
55 shift = 1;
56 break;
57 case kN32_SkColorType:
58 shift = 2;
59 break;
60 case kRGBA_F16_SkColorType:
61 shift = 3;
62 break;
63 default:
64 return false;
65 }
66
67 if (kIgnoreRowBytesValue == rowBytes) {
68 return true;
69 }
70
71 uint64_t minRB = (uint64_t)info.width() << shift;
72 if (minRB > rowBytes) {
73 return false;
74 }
75
76 size_t alignedRowBytes = rowBytes >> shift << shift;
77 if (alignedRowBytes != rowBytes) {
78 return false;
79 }
80
81 uint64_t size = sk_64_mul(info.height(), rowBytes);
82 if (size > kMaxTotalSize) {
83 return false;
84 }
85
86 return true;
87 }
88
SkSurface_Raster(const SkImageInfo & info,void * pixels,size_t rb,void (* releaseProc)(void * pixels,void * context),void * context,const SkSurfaceProps * props)89 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb,
90 void (*releaseProc)(void* pixels, void* context), void* context,
91 const SkSurfaceProps* props)
92 : INHERITED(info, props)
93 {
94 fBitmap.installPixels(info, pixels, rb, nullptr, releaseProc, context);
95 fRowBytes = 0; // don't need to track the rowbytes
96 fWeOwnThePixels = false; // We are "Direct"
97 }
98
SkSurface_Raster(SkPixelRef * pr,const SkSurfaceProps * props)99 SkSurface_Raster::SkSurface_Raster(SkPixelRef* pr, const SkSurfaceProps* props)
100 : INHERITED(pr->info().width(), pr->info().height(), props)
101 {
102 const SkImageInfo& info = pr->info();
103
104 fBitmap.setInfo(info, pr->rowBytes());
105 fBitmap.setPixelRef(pr);
106 fRowBytes = pr->rowBytes(); // we track this, so that subsequent re-allocs will match
107 fWeOwnThePixels = true;
108 }
109
onNewCanvas()110 SkCanvas* SkSurface_Raster::onNewCanvas() { return new SkCanvas(fBitmap, this->props()); }
111
onNewSurface(const SkImageInfo & info)112 SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
113 return SkSurface::NewRaster(info, &this->props());
114 }
115
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)116 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
117 const SkPaint* paint) {
118 canvas->drawBitmap(fBitmap, x, y, paint);
119 }
120
onNewImageSnapshot(SkBudgeted,ForceCopyMode forceCopyMode)121 SkImage* SkSurface_Raster::onNewImageSnapshot(SkBudgeted, ForceCopyMode forceCopyMode) {
122 if (fWeOwnThePixels) {
123 // SkImage_raster requires these pixels are immutable for its full lifetime.
124 // We'll undo this via onRestoreBackingMutability() if we can avoid the COW.
125 if (SkPixelRef* pr = fBitmap.pixelRef()) {
126 pr->setTemporarilyImmutable();
127 }
128 } else {
129 forceCopyMode = kYes_ForceCopyMode;
130 }
131
132 // Our pixels are in memory, so read access on the snapshot SkImage could be cheap.
133 // Lock the shared pixel ref to ensure peekPixels() is usable.
134 return SkNewImageFromRasterBitmap(fBitmap, forceCopyMode);
135 }
136
onRestoreBackingMutability()137 void SkSurface_Raster::onRestoreBackingMutability() {
138 SkASSERT(!this->hasCachedImage()); // Shouldn't be any snapshots out there.
139 if (SkPixelRef* pr = fBitmap.pixelRef()) {
140 pr->restoreMutability();
141 }
142 }
143
onCopyOnWrite(ContentChangeMode mode)144 void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
145 // are we sharing pixelrefs with the image?
146 SkAutoTUnref<SkImage> cached(this->refCachedImage(SkBudgeted::kNo, kNo_ForceUnique));
147 SkASSERT(cached);
148 if (SkBitmapImageGetPixelRef(cached) == fBitmap.pixelRef()) {
149 SkASSERT(fWeOwnThePixels);
150 if (kDiscard_ContentChangeMode == mode) {
151 fBitmap.allocPixels();
152 } else {
153 SkBitmap prev(fBitmap);
154 fBitmap.allocPixels();
155 prev.lockPixels();
156 SkASSERT(prev.info() == fBitmap.info());
157 SkASSERT(prev.rowBytes() == fBitmap.rowBytes());
158 memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.getSafeSize());
159 }
160 SkASSERT(fBitmap.rowBytes() == fRowBytes); // be sure we always use the same value
161
162 // Now fBitmap is a deep copy of itself (and therefore different from
163 // what is being used by the image. Next we update the canvas to use
164 // this as its backend, so we can't modify the image's pixels anymore.
165 SkASSERT(this->getCachedCanvas());
166 this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
167 }
168 }
169
170 ///////////////////////////////////////////////////////////////////////////////
171
NewRasterDirectReleaseProc(const SkImageInfo & info,void * pixels,size_t rb,void (* releaseProc)(void * pixels,void * context),void * context,const SkSurfaceProps * props)172 SkSurface* SkSurface::NewRasterDirectReleaseProc(const SkImageInfo& info, void* pixels, size_t rb,
173 void (*releaseProc)(void* pixels, void* context),
174 void* context, const SkSurfaceProps* props) {
175 if (nullptr == releaseProc) {
176 context = nullptr;
177 }
178 if (!SkSurface_Raster::Valid(info, rb)) {
179 return nullptr;
180 }
181 if (nullptr == pixels) {
182 return nullptr;
183 }
184
185 return new SkSurface_Raster(info, pixels, rb, releaseProc, context, props);
186 }
187
NewRasterDirect(const SkImageInfo & info,void * pixels,size_t rowBytes,const SkSurfaceProps * props)188 SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes,
189 const SkSurfaceProps* props) {
190 return NewRasterDirectReleaseProc(info, pixels, rowBytes, nullptr, nullptr, props);
191 }
192
NewRaster(const SkImageInfo & info,size_t rowBytes,const SkSurfaceProps * props)193 SkSurface* SkSurface::NewRaster(const SkImageInfo& info, size_t rowBytes,
194 const SkSurfaceProps* props) {
195 if (!SkSurface_Raster::Valid(info)) {
196 return nullptr;
197 }
198
199 SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewZeroed(info, rowBytes, nullptr));
200 if (nullptr == pr.get()) {
201 return nullptr;
202 }
203 if (rowBytes) {
204 SkASSERT(pr->rowBytes() == rowBytes);
205 }
206 return new SkSurface_Raster(pr, props);
207 }
208
NewRaster(const SkImageInfo & info,const SkSurfaceProps * props)209 SkSurface* SkSurface::NewRaster(const SkImageInfo& info, const SkSurfaceProps* props) {
210 return NewRaster(info, 0, props);
211 }
212