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