/src/skia/src/image/SkSurface_Raster.cpp
Line | Count | Source (jump to first uncovered line) |
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, SkScalar, const SkSamplingOptions&, const SkPaint*) override; |
27 | | void onCopyOnWrite(ContentChangeMode) override; |
28 | | void onRestoreBackingMutability() override; |
29 | | |
30 | | private: |
31 | | SkBitmap fBitmap; |
32 | | bool fWeOwnThePixels; |
33 | | |
34 | | using INHERITED = SkSurface_Base; |
35 | | }; |
36 | | |
37 | | /////////////////////////////////////////////////////////////////////////////// |
38 | | |
39 | 75.7k | bool SkSurfaceValidateRasterInfo(const SkImageInfo& info, size_t rowBytes) { |
40 | 75.7k | if (!SkImageInfoIsValid(info)) { |
41 | 400 | return false; |
42 | 400 | } |
43 | | |
44 | 75.3k | if (kIgnoreRowBytesValue == rowBytes) { |
45 | 75.3k | return true; |
46 | 75.3k | } |
47 | | |
48 | 23 | if (!info.validRowBytes(rowBytes)) { |
49 | 0 | return false; |
50 | 0 | } |
51 | | |
52 | 23 | uint64_t size = sk_64_mul(info.height(), rowBytes); |
53 | 23 | static const size_t kMaxTotalSize = SK_MaxS32; |
54 | 23 | if (size > kMaxTotalSize) { |
55 | 0 | return false; |
56 | 0 | } |
57 | | |
58 | 23 | return true; |
59 | 23 | } |
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 | 23 | { |
66 | 23 | fBitmap.installPixels(info, pixels, rb, releaseProc, context); |
67 | 23 | fWeOwnThePixels = false; // We are "Direct" |
68 | 23 | } |
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 | 36.0k | { |
74 | 36.0k | fBitmap.setInfo(info, pr->rowBytes()); |
75 | 36.0k | fBitmap.setPixelRef(std::move(pr), 0, 0); |
76 | 36.0k | fWeOwnThePixels = true; |
77 | 36.0k | } |
78 | | |
79 | 35.0k | SkCanvas* SkSurface_Raster::onNewCanvas() { return new SkCanvas(fBitmap, this->props()); } |
80 | | |
81 | 0 | sk_sp<SkSurface> SkSurface_Raster::onNewSurface(const SkImageInfo& info) { |
82 | 0 | return SkSurface::MakeRaster(info, &this->props()); |
83 | 0 | } |
84 | | |
85 | | void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, |
86 | 0 | const SkSamplingOptions& sampling, const SkPaint* paint) { |
87 | 0 | canvas->drawImage(fBitmap.asImage().get(), x, y, sampling, paint); |
88 | 0 | } |
89 | | |
90 | 100 | sk_sp<SkImage> SkSurface_Raster::onNewImageSnapshot(const SkIRect* subset) { |
91 | 100 | if (subset) { |
92 | 0 | SkASSERT(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()).contains(*subset)); |
93 | 0 | SkBitmap dst; |
94 | 0 | dst.allocPixels(fBitmap.info().makeDimensions(subset->size())); |
95 | 0 | SkAssertResult(fBitmap.readPixels(dst.pixmap(), subset->left(), subset->top())); |
96 | 0 | dst.setImmutable(); // key, so MakeFromBitmap doesn't make a copy of the buffer |
97 | 0 | return dst.asImage(); |
98 | 0 | } |
99 | | |
100 | 100 | SkCopyPixelsMode cpm = kIfMutable_SkCopyPixelsMode; |
101 | 100 | 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 | 100 | if (SkPixelRef* pr = fBitmap.pixelRef()) { |
105 | 100 | pr->setTemporarilyImmutable(); |
106 | 100 | } |
107 | 0 | } else { |
108 | 0 | cpm = kAlways_SkCopyPixelsMode; |
109 | 0 | } |
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 | 100 | return SkMakeImageFromRasterBitmap(fBitmap, cpm); |
114 | 100 | } |
115 | | |
116 | 0 | void SkSurface_Raster::onWritePixels(const SkPixmap& src, int x, int y) { |
117 | 0 | fBitmap.writePixels(src, x, y); |
118 | 0 | } |
119 | | |
120 | 0 | void SkSurface_Raster::onRestoreBackingMutability() { |
121 | 0 | SkASSERT(!this->hasCachedImage()); // Shouldn't be any snapshots out there. |
122 | 0 | if (SkPixelRef* pr = fBitmap.pixelRef()) { |
123 | 0 | pr->restoreMutability(); |
124 | 0 | } |
125 | 0 | } Unexecuted instantiation: SkSurface_Raster::onRestoreBackingMutability() Unexecuted instantiation: SkSurface_Raster::onRestoreBackingMutability() |
126 | | |
127 | 0 | void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) { |
128 | | // are we sharing pixelrefs with the image? |
129 | 0 | sk_sp<SkImage> cached(this->refCachedImage()); |
130 | 0 | SkASSERT(cached); |
131 | 0 | if (SkBitmapImageGetPixelRef(cached.get()) == fBitmap.pixelRef()) { |
132 | 0 | SkASSERT(fWeOwnThePixels); |
133 | 0 | if (kDiscard_ContentChangeMode == mode) { |
134 | 0 | fBitmap.allocPixels(); |
135 | 0 | } else { |
136 | 0 | SkBitmap prev(fBitmap); |
137 | 0 | fBitmap.allocPixels(); |
138 | 0 | SkASSERT(prev.info() == fBitmap.info()); |
139 | 0 | SkASSERT(prev.rowBytes() == fBitmap.rowBytes()); |
140 | 0 | memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.computeByteSize()); |
141 | 0 | } |
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 | 0 | SkASSERT(this->getCachedCanvas()); |
147 | 0 | this->getCachedCanvas()->baseDevice()->replaceBitmapBackendForRasterSurface(fBitmap); |
148 | 0 | } |
149 | 0 | } Unexecuted instantiation: SkSurface_Raster::onCopyOnWrite(SkSurface::ContentChangeMode) Unexecuted instantiation: SkSurface_Raster::onCopyOnWrite(SkSurface::ContentChangeMode) |
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 | 23 | const SkSurfaceProps* props) { |
156 | 23 | if (nullptr == releaseProc) { |
157 | 23 | context = nullptr; |
158 | 23 | } |
159 | 23 | if (!SkSurfaceValidateRasterInfo(info, rb)) { |
160 | 0 | return nullptr; |
161 | 0 | } |
162 | 23 | if (nullptr == pixels) { |
163 | 0 | return nullptr; |
164 | 0 | } |
165 | | |
166 | 23 | return sk_make_sp<SkSurface_Raster>(info, pixels, rb, releaseProc, context, props); |
167 | 23 | } |
168 | | |
169 | | sk_sp<SkSurface> SkSurface::MakeRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes, |
170 | 23 | const SkSurfaceProps* props) { |
171 | 23 | return MakeRasterDirectReleaseProc(info, pixels, rowBytes, nullptr, nullptr, props); |
172 | 23 | } |
173 | | |
174 | | sk_sp<SkSurface> SkSurface::MakeRaster(const SkImageInfo& info, size_t rowBytes, |
175 | 36.2k | const SkSurfaceProps* props) { |
176 | 36.2k | if (!SkSurfaceValidateRasterInfo(info)) { |
177 | 248 | return nullptr; |
178 | 248 | } |
179 | | |
180 | 36.0k | sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, rowBytes); |
181 | 36.0k | if (!pr) { |
182 | 0 | return nullptr; |
183 | 0 | } |
184 | 36.0k | if (rowBytes) { |
185 | 0 | SkASSERT(pr->rowBytes() == rowBytes); |
186 | 0 | } |
187 | 36.0k | return sk_make_sp<SkSurface_Raster>(info, std::move(pr), props); |
188 | 36.0k | } |
189 | | |
190 | | sk_sp<SkSurface> SkSurface::MakeRasterN32Premul(int width, int height, |
191 | 35.9k | const SkSurfaceProps* surfaceProps) { |
192 | 35.9k | return MakeRaster(SkImageInfo::MakeN32Premul(width, height), surfaceProps); |
193 | 35.9k | } |