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