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