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/SkSurface.h"
9
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkCapabilities.h" // IWYU pragma: keep
13 #include "include/core/SkColorSpace.h"
14 #include "include/core/SkImage.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkPixmap.h"
17 #include "include/core/SkRect.h"
18 #include "include/core/SkRefCnt.h"
19 #include "include/core/SkScalar.h"
20 #include "include/core/SkSize.h"
21 #include "include/core/SkSurfaceProps.h"
22 #include "include/private/base/SkTemplates.h"
23 #include "src/core/SkImageInfoPriv.h"
24 #include "src/core/SkSurfacePriv.h"
25 #include "src/image/SkSurface_Base.h"
26
27 #include <cstddef>
28 #include <cstdint>
29 #include <utility>
30
31 class GrBackendSemaphore;
32 class GrRecordingContext; // IWYU pragma: keep
33 class SkPaint;
34 class GrSurfaceCharacterization;
35 namespace skgpu { namespace graphite { class Recorder; } }
36
SkSurfaceProps()37 SkSurfaceProps::SkSurfaceProps()
38 : fFlags(0)
39 , fPixelGeometry(kUnknown_SkPixelGeometry)
40 , fTextContrast(SK_GAMMA_CONTRAST)
41 , fTextGamma(SK_GAMMA_EXPONENT) {}
42
SkSurfaceProps(uint32_t flags,SkPixelGeometry pg)43 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
44 : fFlags(flags)
45 , fPixelGeometry(pg)
46 , fTextContrast(SK_GAMMA_CONTRAST)
47 , fTextGamma(SK_GAMMA_EXPONENT) {}
48
SkSurfaceProps(uint32_t flags,SkPixelGeometry pg,SkScalar textContrast,SkScalar textGamma)49 SkSurfaceProps::SkSurfaceProps(uint32_t flags,
50 SkPixelGeometry pg,
51 SkScalar textContrast,
52 SkScalar textGamma)
53 : fFlags(flags), fPixelGeometry(pg), fTextContrast(textContrast), fTextGamma(textGamma) {}
54
SkSurface(int width,int height,const SkSurfaceProps * props)55 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
56 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
57 {
58 SkASSERT(fWidth > 0);
59 SkASSERT(fHeight > 0);
60 fGenerationID = 0;
61 }
62
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)63 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
64 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
65 {
66 SkASSERT(fWidth > 0);
67 SkASSERT(fHeight > 0);
68 fGenerationID = 0;
69 }
70
generationID()71 uint32_t SkSurface::generationID() {
72 if (0 == fGenerationID) {
73 fGenerationID = asSB(this)->newGenerationID();
74 }
75 return fGenerationID;
76 }
77
notifyContentWillChange(ContentChangeMode mode)78 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
79 sk_ignore_unused_variable(asSB(this)->aboutToDraw(mode));
80 }
81
getCanvas()82 SkCanvas* SkSurface::getCanvas() {
83 return asSB(this)->getCachedCanvas();
84 }
85
capabilities()86 sk_sp<const SkCapabilities> SkSurface::capabilities() {
87 return asSB(this)->onCapabilities();
88 }
89
makeImageSnapshot()90 sk_sp<SkImage> SkSurface::makeImageSnapshot() {
91 return asSB(this)->refCachedImage();
92 }
93
makeImageSnapshot(const SkIRect & srcBounds)94 sk_sp<SkImage> SkSurface::makeImageSnapshot(const SkIRect& srcBounds) {
95 const SkIRect surfBounds = { 0, 0, fWidth, fHeight };
96 SkIRect bounds = srcBounds;
97 if (!bounds.intersect(surfBounds)) {
98 return nullptr;
99 }
100 SkASSERT(!bounds.isEmpty());
101 if (bounds == surfBounds) {
102 return this->makeImageSnapshot();
103 } else {
104 return asSB(this)->onNewImageSnapshot(&bounds);
105 }
106 }
107
makeSurface(const SkImageInfo & info)108 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
109 return asSB(this)->onNewSurface(info);
110 }
111
makeSurface(int width,int height)112 sk_sp<SkSurface> SkSurface::makeSurface(int width, int height) {
113 return this->makeSurface(this->imageInfo().makeWH(width, height));
114 }
115
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkSamplingOptions & sampling,const SkPaint * paint)116 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkSamplingOptions& sampling,
117 const SkPaint* paint) {
118 asSB(this)->onDraw(canvas, x, y, sampling, paint);
119 }
120
peekPixels(SkPixmap * pmap)121 bool SkSurface::peekPixels(SkPixmap* pmap) {
122 return this->getCanvas()->peekPixels(pmap);
123 }
124
readPixels(const SkPixmap & pm,int srcX,int srcY)125 bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
126 return this->getCanvas()->readPixels(pm, srcX, srcY);
127 }
128
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)129 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
130 int srcX, int srcY) {
131 return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
132 }
133
readPixels(const SkBitmap & bitmap,int srcX,int srcY)134 bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
135 SkPixmap pm;
136 return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
137 }
138
asyncRescaleAndReadPixels(const SkImageInfo & info,const SkIRect & srcRect,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)139 void SkSurface::asyncRescaleAndReadPixels(const SkImageInfo& info,
140 const SkIRect& srcRect,
141 RescaleGamma rescaleGamma,
142 RescaleMode rescaleMode,
143 ReadPixelsCallback callback,
144 ReadPixelsContext context) {
145 if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) ||
146 !SkImageInfoIsValid(info)) {
147 callback(context, nullptr);
148 return;
149 }
150 asSB(this)->onAsyncRescaleAndReadPixels(
151 info, srcRect, rescaleGamma, rescaleMode, callback, context);
152 }
153
asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,const SkISize & dstSize,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)154 void SkSurface::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
155 sk_sp<SkColorSpace> dstColorSpace,
156 const SkIRect& srcRect,
157 const SkISize& dstSize,
158 RescaleGamma rescaleGamma,
159 RescaleMode rescaleMode,
160 ReadPixelsCallback callback,
161 ReadPixelsContext context) {
162 if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || dstSize.isZero() ||
163 (dstSize.width() & 0b1) || (dstSize.height() & 0b1)) {
164 callback(context, nullptr);
165 return;
166 }
167 asSB(this)->onAsyncRescaleAndReadPixelsYUV420(yuvColorSpace,
168 /*readAlpha=*/false,
169 std::move(dstColorSpace),
170 srcRect,
171 dstSize,
172 rescaleGamma,
173 rescaleMode,
174 callback,
175 context);
176 }
177
asyncRescaleAndReadPixelsYUVA420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,const SkISize & dstSize,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)178 void SkSurface::asyncRescaleAndReadPixelsYUVA420(SkYUVColorSpace yuvColorSpace,
179 sk_sp<SkColorSpace> dstColorSpace,
180 const SkIRect& srcRect,
181 const SkISize& dstSize,
182 RescaleGamma rescaleGamma,
183 RescaleMode rescaleMode,
184 ReadPixelsCallback callback,
185 ReadPixelsContext context) {
186 if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || dstSize.isZero() ||
187 (dstSize.width() & 0b1) || (dstSize.height() & 0b1)) {
188 callback(context, nullptr);
189 return;
190 }
191 asSB(this)->onAsyncRescaleAndReadPixelsYUV420(yuvColorSpace,
192 /*readAlpha=*/true,
193 std::move(dstColorSpace),
194 srcRect,
195 dstSize,
196 rescaleGamma,
197 rescaleMode,
198 callback,
199 context);
200 }
201
writePixels(const SkPixmap & pmap,int x,int y)202 void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
203 if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
204 return;
205 }
206
207 const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
208 const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
209 if (SkIRect::Intersects(srcR, dstR)) {
210 ContentChangeMode mode = kRetain_ContentChangeMode;
211 if (srcR.contains(dstR)) {
212 mode = kDiscard_ContentChangeMode;
213 }
214 if (!asSB(this)->aboutToDraw(mode)) {
215 return;
216 }
217 asSB(this)->onWritePixels(pmap, x, y);
218 }
219 }
220
writePixels(const SkBitmap & src,int x,int y)221 void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
222 SkPixmap pm;
223 if (src.peekPixels(&pm)) {
224 this->writePixels(pm, x, y);
225 }
226 }
227
recordingContext() const228 GrRecordingContext* SkSurface::recordingContext() const {
229 return asConstSB(this)->onGetRecordingContext();
230 }
231
recorder() const232 skgpu::graphite::Recorder* SkSurface::recorder() const { return asConstSB(this)->onGetRecorder(); }
233
wait(int numSemaphores,const GrBackendSemaphore * waitSemaphores,bool deleteSemaphoresAfterWait)234 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
235 bool deleteSemaphoresAfterWait) {
236 return asSB(this)->onWait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
237 }
238
characterize(GrSurfaceCharacterization * characterization) const239 bool SkSurface::characterize(GrSurfaceCharacterization* characterization) const {
240 return asConstSB(this)->onCharacterize(characterization);
241 }
242
isCompatible(const GrSurfaceCharacterization & characterization) const243 bool SkSurface::isCompatible(const GrSurfaceCharacterization& characterization) const {
244 return asConstSB(this)->onIsCompatible(characterization);
245 }
246