/src/skia/src/gpu/ganesh/SurfaceContext.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2016 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 | | #ifndef SurfaceContext_DEFINED |
9 | | #define SurfaceContext_DEFINED |
10 | | |
11 | | #include "include/core/SkImage.h" |
12 | | #include "include/core/SkRect.h" |
13 | | #include "include/core/SkRefCnt.h" |
14 | | #include "include/core/SkSamplingOptions.h" |
15 | | #include "include/core/SkSurface.h" |
16 | | #include "src/gpu/ganesh/GrColorInfo.h" |
17 | | #include "src/gpu/ganesh/GrDataUtils.h" |
18 | | #include "src/gpu/ganesh/GrImageInfo.h" |
19 | | #include "src/gpu/ganesh/GrPixmap.h" |
20 | | #include "src/gpu/ganesh/GrRenderTargetProxy.h" |
21 | | #include "src/gpu/ganesh/GrRenderTask.h" |
22 | | #include "src/gpu/ganesh/GrSurfaceProxy.h" |
23 | | #include "src/gpu/ganesh/GrSurfaceProxyView.h" |
24 | | |
25 | | class GrDrawingManager; |
26 | | class GrRecordingContext; |
27 | | class GrRenderTargetProxy; |
28 | | class GrSurface; |
29 | | class GrSurfaceProxy; |
30 | | class GrTextureProxy; |
31 | | struct SkIPoint; |
32 | | struct SkIRect; |
33 | | |
34 | | namespace skgpu { |
35 | | class SingleOwner; |
36 | | } |
37 | | |
38 | | namespace skgpu::ganesh { |
39 | | |
40 | | class SurfaceFillContext; |
41 | | |
42 | | class SurfaceContext { |
43 | | public: |
44 | | // If it is known that the GrSurfaceProxy is not renderable, you can directly call the ctor |
45 | | // here to make a SurfaceContext on the stack. |
46 | | SurfaceContext(GrRecordingContext*, GrSurfaceProxyView readView, const GrColorInfo&); |
47 | | |
48 | 106k | virtual ~SurfaceContext() = default; |
49 | | |
50 | 112k | GrRecordingContext* recordingContext() const { return fContext; } |
51 | | |
52 | 700k | const GrColorInfo& colorInfo() const { return fColorInfo; } |
53 | 0 | GrImageInfo imageInfo() const { return {fColorInfo, fReadView.proxy()->dimensions()}; } |
54 | | |
55 | 103k | GrSurfaceOrigin origin() const { return fReadView.origin(); } |
56 | 17.9k | skgpu::Swizzle readSwizzle() const { return fReadView.swizzle(); } |
57 | | // TODO: See if it makes sense for this to return a const& instead and require the callers to |
58 | | // make a copy (which refs the proxy) if needed. |
59 | 122k | GrSurfaceProxyView readSurfaceView() { return fReadView; } |
60 | | |
61 | 386k | SkISize dimensions() const { return fReadView.dimensions(); } |
62 | 33.7k | int width() const { return fReadView.proxy()->width(); } |
63 | 33.7k | int height() const { return fReadView.proxy()->height(); } |
64 | | |
65 | 0 | skgpu::Mipmapped mipmapped() const { return fReadView.mipmapped(); } |
66 | | |
67 | | const GrCaps* caps() const; |
68 | | |
69 | | /** |
70 | | * Reads a rectangle of pixels from the surface context. |
71 | | * @param dContext The direct context to use |
72 | | * @param dst destination pixels for the read |
73 | | * @param srcPt offset w/in the surface context from which to read |
74 | | * is a GrDirectContext and fail otherwise. |
75 | | */ |
76 | | bool readPixels(GrDirectContext* dContext, GrPixmap dst, SkIPoint srcPt); |
77 | | |
78 | | using ReadPixelsCallback = SkImage::ReadPixelsCallback; |
79 | | using ReadPixelsContext = SkImage::ReadPixelsContext; |
80 | | using RescaleGamma = SkImage::RescaleGamma; |
81 | | using RescaleMode = SkImage::RescaleMode; |
82 | | |
83 | | // GPU implementation for SkImage:: and SkSurface::asyncRescaleAndReadPixels. |
84 | | void asyncRescaleAndReadPixels(GrDirectContext*, |
85 | | const SkImageInfo& info, |
86 | | const SkIRect& srcRect, |
87 | | RescaleGamma rescaleGamma, |
88 | | RescaleMode, |
89 | | ReadPixelsCallback callback, |
90 | | ReadPixelsContext callbackContext); |
91 | | |
92 | | // GPU implementation for SkImage:: and SkSurface::asyncRescaleAndReadPixelsYUV420. |
93 | | void asyncRescaleAndReadPixelsYUV420(GrDirectContext*, |
94 | | SkYUVColorSpace yuvColorSpace, |
95 | | bool readAlpha, |
96 | | sk_sp<SkColorSpace> dstColorSpace, |
97 | | const SkIRect& srcRect, |
98 | | SkISize dstSize, |
99 | | RescaleGamma rescaleGamma, |
100 | | RescaleMode, |
101 | | ReadPixelsCallback callback, |
102 | | ReadPixelsContext context); |
103 | | |
104 | | /** |
105 | | * Writes a rectangle of pixels from src into the surfaceDrawContext at the specified position. |
106 | | * @param dContext The direct context to use |
107 | | * @param src source for the write |
108 | | * @param dstPt offset w/in the surface context at which to write |
109 | | */ |
110 | | bool writePixels(GrDirectContext* dContext, |
111 | | GrCPixmap src, |
112 | | SkIPoint dstPt); |
113 | | |
114 | | /** |
115 | | * Fully populates either the base level or all MIP levels of the GrSurface with pixel data. |
116 | | * @param dContext The direct context to use |
117 | | * @param src Array of pixmaps |
118 | | * @param numLevels Number of pixmaps in src. To succeed this must be 1 or the total |
119 | | * number of MIP levels. |
120 | | */ |
121 | | bool writePixels(GrDirectContext* dContext, |
122 | | const GrCPixmap src[], |
123 | | int numLevels); |
124 | | |
125 | 727k | GrSurfaceProxy* asSurfaceProxy() { return fReadView.proxy(); } |
126 | 0 | const GrSurfaceProxy* asSurfaceProxy() const { return fReadView.proxy(); } |
127 | 74.5k | sk_sp<GrSurfaceProxy> asSurfaceProxyRef() { return fReadView.refProxy(); } |
128 | | |
129 | 10.7k | GrTextureProxy* asTextureProxy() { return fReadView.asTextureProxy(); } |
130 | 0 | const GrTextureProxy* asTextureProxy() const { return fReadView.asTextureProxy(); } |
131 | 0 | sk_sp<GrTextureProxy> asTextureProxyRef() { return fReadView.asTextureProxyRef(); } |
132 | | |
133 | 111k | GrRenderTargetProxy* asRenderTargetProxy() { return fReadView.asRenderTargetProxy(); } |
134 | 272k | const GrRenderTargetProxy* asRenderTargetProxy() const { |
135 | 272k | return fReadView.asRenderTargetProxy(); |
136 | 272k | } |
137 | 0 | sk_sp<GrRenderTargetProxy> asRenderTargetProxyRef() { |
138 | 0 | return fReadView.asRenderTargetProxyRef(); |
139 | 0 | } |
140 | | |
141 | 0 | virtual SurfaceFillContext* asFillContext() { return nullptr; } |
142 | | |
143 | | /** |
144 | | * Rescales the contents of srcRect. The gamma in which the rescaling occurs is controlled by |
145 | | * RescaleGamma. It is always in the original gamut. The result is converted to the color type |
146 | | * and color space of info after rescaling. Note: this currently requires that the info have a |
147 | | * different size than srcRect. Though, it could be relaxed to allow non-scaling color |
148 | | * conversions. |
149 | | */ |
150 | | std::unique_ptr<SurfaceFillContext> rescale(const GrImageInfo& info, |
151 | | GrSurfaceOrigin, |
152 | | SkIRect srcRect, |
153 | | SkImage::RescaleGamma, |
154 | | SkImage::RescaleMode); |
155 | | |
156 | | /** |
157 | | * Like the above but allows the caller ot specify a destination fill context and |
158 | | * rect within that context. The dst rect must be contained by the dst or this will fail. |
159 | | */ |
160 | | bool rescaleInto(SurfaceFillContext* dst, |
161 | | SkIRect dstRect, |
162 | | SkIRect srcRect, |
163 | | SkImage::RescaleGamma, |
164 | | SkImage::RescaleMode); |
165 | | |
166 | | #if defined(GR_TEST_UTILS) |
167 | 0 | bool testCopy(sk_sp<GrSurfaceProxy> src, const SkIRect& srcRect, const SkIPoint& dstPoint) { |
168 | 0 | return this->copy(std::move(src), srcRect, dstPoint) != nullptr; |
169 | 0 | } |
170 | | |
171 | 0 | bool testCopy(sk_sp<GrSurfaceProxy> src) { |
172 | 0 | auto rect = SkIRect::MakeSize(src->dimensions()); |
173 | 0 | return this->copy(std::move(src), rect, {0, 0}) != nullptr; |
174 | 0 | } |
175 | | #endif |
176 | | |
177 | | protected: |
178 | | GrDrawingManager* drawingManager(); |
179 | | const GrDrawingManager* drawingManager() const; |
180 | | |
181 | | SkDEBUGCODE(void validate() const;) |
182 | | |
183 | | SkDEBUGCODE(skgpu::SingleOwner* singleOwner() const;) |
184 | | |
185 | | GrRecordingContext* fContext; |
186 | | |
187 | | GrSurfaceProxyView fReadView; |
188 | | |
189 | | // Inserts a transfer, part of the implementation of asyncReadPixels and |
190 | | // asyncRescaleAndReadPixelsYUV420(). |
191 | | struct PixelTransferResult { |
192 | | using ConversionFn = void(void* dst, const void* mappedBuffer); |
193 | | // If null then the transfer could not be performed. Otherwise this buffer will contain |
194 | | // the pixel data when the transfer is complete. |
195 | | sk_sp<GrGpuBuffer> fTransferBuffer; |
196 | | // RowBytes for transfer buffer data |
197 | | size_t fRowBytes; |
198 | | // If this is null then the transfer buffer will contain the data in the requested |
199 | | // color type. Otherwise, when the transfer is done this must be called to convert |
200 | | // from the transfer buffer's color type to the requested color type. |
201 | | std::function<ConversionFn> fPixelConverter; |
202 | | }; |
203 | | PixelTransferResult transferPixels(GrColorType colorType, const SkIRect& rect); |
204 | | |
205 | | // The async read step of asyncRescaleAndReadPixels() |
206 | | void asyncReadPixels(GrDirectContext*, |
207 | | const SkIRect& srcRect, |
208 | | SkColorType, |
209 | | ReadPixelsCallback, |
210 | | ReadPixelsContext); |
211 | | |
212 | | private: |
213 | | friend class ::GrRecordingContextPriv; // for validate |
214 | | friend class ::GrSurfaceProxy; // for copy |
215 | | |
216 | | SkDEBUGCODE(virtual void onValidate() const {}) |
217 | | |
218 | | /** |
219 | | * Copy 'src' into the proxy backing this context. This call will not do any draw fallback. |
220 | | * Currently only writePixels and replaceRenderTarget call this directly. All other copies |
221 | | * should go through GrSurfaceProxy::Copy. |
222 | | * @param src src of pixels |
223 | | * @param dstPoint the origin of the 'srcRect' in the destination coordinate space |
224 | | * @return a task (that may be skippable by calling canSkip) if successful and |
225 | | * null otherwise. |
226 | | * |
227 | | * Note: Notionally, 'srcRect' is clipped to 'src's extent with 'dstPoint' being adjusted. |
228 | | * Then the 'srcRect' offset by 'dstPoint' is clipped against the dst's extent. |
229 | | * The end result is only valid src pixels and dst pixels will be touched but the copied |
230 | | * regions will not be shifted. The 'src' must have the same origin as the backing proxy |
231 | | * of fSurfaceContext. |
232 | | */ |
233 | | sk_sp<GrRenderTask> copy(sk_sp<GrSurfaceProxy> src, SkIRect srcRect, SkIPoint dstPoint); |
234 | | |
235 | | /** |
236 | | * Copy and scale 'src' into the proxy backing this context. This call will not do any draw |
237 | | * fallback. Currently only rescaleInto() calls this directly, which handles drawing fallback |
238 | | * automatically. |
239 | | * |
240 | | * @param src src of pixels |
241 | | * @param srcRect the subset of src that is copied to this proxy |
242 | | * @param dstRect the subset of dst that receives the copied data, possibly with different |
243 | | * dimensions than 'srcRect'. |
244 | | * @param filterMode the filter mode to apply when scaling src |
245 | | * @return a task (that may be skippable by calling canSkip) if successful and |
246 | | * null otherwise. |
247 | | * |
248 | | * Note: Unlike copy(rect,point), 'srcRect' and 'dstRect' are not adjusted to fit within the |
249 | | * surfaces. If they are not contained, then nullptr is returned. The 'src' must have the same |
250 | | * origin as the backing proxy of this context. |
251 | | */ |
252 | | sk_sp<GrRenderTask> copyScaled(sk_sp<GrSurfaceProxy> src, SkIRect srcRect, SkIRect dstRect, |
253 | | GrSamplerState::Filter filterMode); |
254 | | |
255 | | bool internalWritePixels(GrDirectContext* dContext, |
256 | | const GrCPixmap src[], |
257 | | int numLevels, |
258 | | SkIPoint); |
259 | | |
260 | | GrColorInfo fColorInfo; |
261 | | |
262 | | using INHERITED = SkRefCnt; |
263 | | }; |
264 | | |
265 | | } // namespace skgpu::ganesh |
266 | | |
267 | | #endif // SurfaceContext_DEFINED |