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