• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
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 skgpu_graphite_Device_DEFINED
9 #define skgpu_graphite_Device_DEFINED
10 
11 #include "include/gpu/GpuTypes.h"
12 #include "src/core/SkDevice.h"
13 #include "src/core/SkEnumBitMask.h"
14 #include "src/gpu/graphite/ClipStack_graphite.h"
15 #include "src/gpu/graphite/DrawOrder.h"
16 #include "src/gpu/graphite/geom/Rect.h"
17 #include "src/gpu/graphite/geom/Transform_graphite.h"
18 #include "src/text/gpu/SDFTControl.h"
19 #include "src/text/gpu/SubRunContainer.h"
20 
21 class SkStrokeRec;
22 
23 namespace sktext::gpu {
24 class AtlasSubRun;
25 enum class Budgeted : bool;
26 }  // namespace sktext::gpu
27 
28 namespace skgpu::graphite {
29 
30 class BoundsManager;
31 class Clip;
32 class Context;
33 class DrawContext;
34 class Geometry;
35 class PaintParams;
36 class Recorder;
37 class Renderer;
38 class Shape;
39 class StrokeStyle;
40 class TextureProxy;
41 class TextureProxyView;
42 
43 class Device final : public SkBaseDevice  {
44 public:
45     ~Device() override;
46 
47     static sk_sp<Device> Make(Recorder*,
48                               const SkImageInfo&,
49                               skgpu::Budgeted,
50                               Mipmapped,
51                               const SkSurfaceProps&,
52                               bool addInitialClear);
53     static sk_sp<Device> Make(Recorder*,
54                               sk_sp<TextureProxy>,
55                               const SkColorInfo&,
56                               const SkSurfaceProps&,
57                               bool addInitialClear);
58     static sk_sp<Device> Make(Recorder* recorder,
59                               sk_sp<TextureProxy>,
60                               SkISize deviceSize,
61                               const SkColorInfo&,
62                               const SkSurfaceProps&,
63                               bool addInitialClear);
64 
asGraphiteDevice()65     Device* asGraphiteDevice() override { return this; }
66 
recorder()67     Recorder* recorder() { return fRecorder; }
68     // This call is triggered from the Recorder on its registered Devices. It is typically called
69     // when the Recorder is abandoned or deleted.
70     void abandonRecorder();
71 
72     // Ensures clip elements are drawn that will clip previous draw calls, snaps all pending work
73     // from the DrawContext as a RenderPassTask and records it in the Device's recorder.
74     void flushPendingWorkToRecorder();
75 
76     TextureProxyView createCopy(const SkIRect* subset, Mipmapped);
77 
78     void asyncRescaleAndReadPixels(const SkImageInfo& info,
79                                    SkIRect srcRect,
80                                    SkImage::RescaleGamma rescaleGamma,
81                                    SkImage::RescaleMode rescaleMode,
82                                    SkImage::ReadPixelsCallback callback,
83                                    SkImage::ReadPixelsContext context);
84 
85     void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
86                                          sk_sp<SkColorSpace> dstColorSpace,
87                                          SkIRect srcRect,
88                                          SkISize dstSize,
89                                          SkImage::RescaleGamma rescaleGamma,
90                                          SkImage::RescaleMode,
91                                          SkImage::ReadPixelsCallback callback,
92                                          SkImage::ReadPixelsContext context);
93 
94     const Transform& localToDeviceTransform();
95 
96     SkStrikeDeviceInfo strikeDeviceInfo() const override;
97 
98     TextureProxy* target();
99     TextureProxyView readSurfaceView() const;
100 
101 private:
102     class IntersectionTreeSet;
103 
104     // Clipping
onSave()105     void onSave() override { fClip.save(); }
onRestore()106     void onRestore() override { fClip.restore(); }
107 
onClipIsWideOpen()108     bool onClipIsWideOpen() const override {
109         return fClip.clipState() == ClipStack::ClipState::kWideOpen;
110     }
111     bool onClipIsAA() const override;
112     ClipType onGetClipType() const override;
113     SkIRect onDevClipBounds() const override;
114     void onAsRgnClip(SkRegion*) const override;
115 
116     void onClipRect(const SkRect& rect, SkClipOp, bool aa) override;
117     void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override;
118     void onClipPath(const SkPath& path, SkClipOp, bool aa) override;
119 
120     void onClipShader(sk_sp<SkShader> shader) override;
121     void onClipRegion(const SkRegion& globalRgn, SkClipOp) override;
122     void onReplaceClip(const SkIRect& rect) override;
123 
124     // Drawing
125     void drawPaint(const SkPaint& paint) override;
126     void drawRect(const SkRect& r, const SkPaint& paint) override;
127     void drawOval(const SkRect& oval, const SkPaint& paint) override;
128     void drawRRect(const SkRRect& rr, const SkPaint& paint) override;
129     void drawPoints(SkCanvas::PointMode mode, size_t count,
130                     const SkPoint[], const SkPaint& paint) override;
131     void drawPath(const SkPath& path, const SkPaint& paint, bool pathIsMutable = false) override;
132 
133     // No need to specialize drawDRRect, drawArc, drawRegion, drawPatch as the default impls all
134     // route to drawPath, drawRect, or drawVertices as desired.
135 
136     // Pixel management
137     sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override;
138     SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
139 
140     bool onReadPixels(const SkPixmap&, int x, int y) override;
141 
142     bool onWritePixels(const SkPixmap&, int x, int y) override;
143 
144     void onDrawGlyphRunList(SkCanvas*, const sktext::GlyphRunList&,
145                             const SkPaint&, const SkPaint&) override;
146 
147     void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
148                         SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color,
149                         SkBlendMode mode) override;
150 
151     void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count,
152                             const SkPoint dstClips[], const SkMatrix preViewMatrices[],
153                             const SkSamplingOptions&, const SkPaint&,
154                             SkCanvas::SrcRectConstraint) override;
155 
156     void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
157                        const SkSamplingOptions&, const SkPaint&,
158                        SkCanvas::SrcRectConstraint) override;
159 
160     // TODO: Implement these using per-edge AA quads and an inlined image shader program.
drawImageLattice(const SkImage *,const SkCanvas::Lattice &,const SkRect & dst,SkFilterMode,const SkPaint &)161     void drawImageLattice(const SkImage*, const SkCanvas::Lattice&,
162                           const SkRect& dst, SkFilterMode, const SkPaint&) override {}
drawAtlas(const SkRSXform[],const SkRect[],const SkColor[],int count,sk_sp<SkBlender>,const SkPaint &)163     void drawAtlas(const SkRSXform[], const SkRect[], const SkColor[], int count, sk_sp<SkBlender>,
164                    const SkPaint&) override {}
165 
drawDrawable(SkCanvas *,SkDrawable *,const SkMatrix *)166     void drawDrawable(SkCanvas*, SkDrawable*, const SkMatrix*) override {}
167     void drawVertices(const SkVertices*, sk_sp<SkBlender>, const SkPaint&, bool) override;
drawMesh(const SkMesh &,sk_sp<SkBlender>,const SkPaint &)168     void drawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) override {}
drawShadow(const SkPath &,const SkDrawShadowRec &)169     void drawShadow(const SkPath&, const SkDrawShadowRec&) override {}
170 
171     void drawDevice(SkBaseDevice*, const SkSamplingOptions&, const SkPaint&) override;
172     void drawSpecial(SkSpecialImage*, const SkMatrix& localToDevice,
173                      const SkSamplingOptions&, const SkPaint&) override;
174 
175     sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
176     sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
177     sk_sp<SkSpecialImage> snapSpecial(const SkIRect& subset, bool forceCopy = false) override;
178 
179     // DrawFlags alters the effects used by drawShape.
180     enum class DrawFlags : unsigned {
181         kNone             = 0b000,
182 
183         // Any SkMaskFilter on the SkPaint passed into drawGeometry() is ignored.
184         // - drawPaint, drawVertices, drawAtlas
185         // - drawShape after it's applied the mask filter.
186         kIgnoreMaskFilter = 0b001,
187 
188         // Any SkPathEffect on the SkPaint passed into drawGeometry() is ignored.
189         // - drawPaint, drawImageLattice, drawImageRect, drawEdgeAAImageSet, drawVertices, drawAtlas
190         // - drawShape after it's applied the path effect.
191         kIgnorePathEffect = 0b010,
192     };
193     SK_DECL_BITMASK_OPS_FRIENDS(DrawFlags);
194 
195     Device(Recorder*, sk_sp<DrawContext>, bool addInitialClear);
196 
197     // Handles applying path effects, mask filters, stroke-and-fill styles, and hairlines.
198     // Ignores geometric style on the paint in favor of explicitly provided SkStrokeRec and flags.
199     // All overridden SkDevice::draw() functions should bottom-out with calls to drawGeometry().
200     void drawGeometry(const Transform&,
201                       const Geometry&,
202                       const SkPaint&,
203                       const SkStrokeRec&,
204                       SkEnumBitMask<DrawFlags> = DrawFlags::kNone,
205                       sk_sp<SkBlender> primitiveBlender = nullptr,
206                       bool skipColorXform = false);
207 
208     // Like drawGeometry() but is Shape-only, depth-only, fill-only, and lets the ClipStack define
209     // the transform, clip, and DrawOrder (although Device still tracks stencil buffer usage).
210     void drawClipShape(const Transform&, const Shape&, const Clip&, DrawOrder);
211 
212     // Handles primitive processing for atlas-based text
213     void drawAtlasSubRun(const sktext::gpu::AtlasSubRun*,
214                          SkPoint drawOrigin,
215                          const SkPaint& paint,
216                          sk_sp<SkRefCnt> subRunStorage);
217 
218     // Returns the Renderer to draw the shape in the given style. If SkStrokeRec is a
219     // stroke-and-fill, this returns the Renderer used for the fill portion and it can be assumed
220     // that Renderer::TessellatedStrokes() will be used for the stroke portion.
221     //
222     // TODO: Renderers may have fallbacks (e.g. pre-chop large paths, or convert stroke to fill).
223     // Are those handled inside ChooseRenderer() where it can modify the shape, stroke? or does it
224     // return a retry error code? or does drawGeometry() handle all the fallbacks, knowing that
225     // a particular shape type needs to be pre-chopped?
226     // TODO: Move this into a RendererSelector object provided by the Context.
227     const Renderer* chooseRenderer(const Geometry&,
228                                    const Clip&,
229                                    const SkStrokeRec&,
230                                    bool requireMSAA) const;
231 
232     bool needsFlushBeforeDraw(int numNewDraws) const;
233 
234     Recorder* fRecorder;
235     sk_sp<DrawContext> fDC;
236 
237     ClipStack fClip;
238 
239     // Tracks accumulated intersections for ordering dependent use of the color and depth attachment
240     // (i.e. depth-based clipping, and transparent blending)
241     std::unique_ptr<BoundsManager> fColorDepthBoundsManager;
242     // Tracks disjoint stencil indices for all recordered draws
243     std::unique_ptr<IntersectionTreeSet> fDisjointStencilSet;
244 
245     // Lazily updated Transform constructed from localToDevice()'s SkM44
246     Transform fCachedLocalToDevice;
247 
248     // The max depth value sent to the DrawContext, incremented so each draw has a unique value.
249     PaintersDepth fCurrentDepth;
250 
251     const sktext::gpu::SDFTControl fSDFTControl;
252 
253     bool fDrawsOverlap;
254 
255     friend class ClipStack; // for recordDraw
256     friend class sktext::gpu::AtlasSubRun; // for drawAtlasSubRun
257 };
258 
259 SK_MAKE_BITMASK_OPS(Device::DrawFlags)
260 
261 } // namespace skgpu::graphite
262 
263 #endif // skgpu_graphite_Device_DEFINED
264