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