Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Device.h
Go to the documentation of this file.
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
14#include "src/core/SkDevice.h"
21
22enum class SkBackingFit;
23class SkStrokeRec;
24
25namespace skgpu::graphite {
26
27class PathAtlas;
28class BoundsManager;
29class Clip;
30class Context;
31class DrawContext;
32enum class DstReadRequirement;
33class Geometry;
34class Image;
35enum class LoadOp : uint8_t;
36class PaintParams;
37class Recorder;
38class Renderer;
39class Shape;
40class StrokeStyle;
41class Task;
42class TextureProxy;
43class TextureProxyView;
44
45class Device final : public SkDevice {
46public:
47 ~Device() override;
48
49 // If 'registerWithRecorder' is false, it is meant to be a short-lived Device that is managed
50 // by the caller within a limited scope (such that it is guaranteed to go out of scope before
51 // the Recorder can be snapped).
54 SkISize deviceSize,
55 const SkColorInfo&,
56 const SkSurfaceProps&,
57 LoadOp initialLoadOp,
58 bool registerWithRecorder=true);
59 // Convenience factory to create the underlying TextureProxy based on the configuration provided
61 const SkImageInfo&,
65 const SkSurfaceProps&,
66 LoadOp initialLoadOp,
67 bool registerWithRecorder=true);
68
69 Device* asGraphiteDevice() override { return this; }
70
71 Recorder* recorder() const override { return fRecorder; }
72 // This call is triggered from the Recorder on its registered Devices. It is typically called
73 // when the Recorder is abandoned or deleted.
74 void abandonRecorder() { fRecorder = nullptr; }
75
76 // Ensures clip elements are drawn that will clip previous draw calls, snaps all pending work
77 // from the DrawContext as a RenderPassTask and records it in the Device's recorder.
78 // TODO(b/333073673): Optionally pass in the Recorder that triggered the flush for validation.
80
82
83 // Flushes any pending work to the recorder and then deregisters and abandons the recorder.
84 void setImmutable() override;
85
86 SkStrikeDeviceInfo strikeDeviceInfo() const override;
87
89 // May be null if target is not sampleable.
91 // Can succeed if target is readable but not sampleable. Assumes 'subset' is contained in bounds
93
94 // True if this Device represents an internal renderable surface that will go out of scope
95 // before the next Recorder snap.
96 // NOTE: Currently, there are two different notions of "scratch" that are being merged together.
97 // 1. Devices whose targets are not instantiated (Device::Make).
98 // 2. Devices that are not registered with the Recorder (Surface::MakeScratch).
99 //
100 // This function reflects notion #1, since the long-term plan will be that all Devices that are
101 // not instantiated will also not be registered with the Recorder. For the time being, due to
102 // shared atlas management, layer-backing Devices need to be registered with the Recorder but
103 // are otherwise the canonical scratch device.
104 //
105 // Existing uses of Surface::MakeScratch() will migrate to using un-instantiated Devices with
106 // the requirement that if the Device's target is being returned in a client-owned object
107 // (e.g. SkImages::MakeWithFilter), that it should then be explicitly instantiated. Once scratch
108 // tasks are fully organized in a graph and not automatically appended to the root task list,
109 // this explicit instantiation will be responsible for moving the scratch tasks to the root list
110 bool isScratchDevice() const;
111
112 // Only used for scratch devices.
114
115 // SkCanvas only uses drawCoverageMask w/o this staging flag, so only enable
116 // mask filters in clients that have finished migrating.
117#if !defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
118 bool useDrawCoverageMaskForMaskFilters() const override { return true; }
119#endif
120
121 // Clipping
122 void pushClipStack() override { fClip.save(); }
123 void popClipStack() override { fClip.restore(); }
124
125 bool isClipWideOpen() const override {
127 }
128 bool isClipEmpty() const override {
129 return fClip.clipState() == ClipStack::ClipState::kEmpty;
130 }
131 bool isClipRect() const override {
134 }
135
136 bool isClipAntiAliased() const override;
137 SkIRect devClipBounds() const override;
138 void android_utils_clipAsRgn(SkRegion*) const override;
139
140 void clipRect(const SkRect& rect, SkClipOp, bool aa) override;
141 void clipRRect(const SkRRect& rrect, SkClipOp, bool aa) override;
142 void clipPath(const SkPath& path, SkClipOp, bool aa) override;
143
144 void clipRegion(const SkRegion& globalRgn, SkClipOp) override;
145 void replaceClip(const SkIRect& rect) override;
146
147 // Drawing
148 void drawPaint(const SkPaint& paint) override;
149 void drawRect(const SkRect& r, const SkPaint& paint) override;
150 void drawOval(const SkRect& oval, const SkPaint& paint) override;
151 void drawRRect(const SkRRect& rr, const SkPaint& paint) override;
153 const SkPoint[], const SkPaint& paint) override;
154 void drawPath(const SkPath& path, const SkPaint& paint, bool pathIsMutable = false) override;
155
156 // No need to specialize drawDRRect, drawArc, drawRegion, drawPatch as the default impls all
157 // route to drawPath, drawRect, or drawVertices as desired.
158
159 void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
160 SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color,
161 SkBlendMode mode) override;
162
164 const SkPoint dstClips[], const SkMatrix preViewMatrices[],
165 const SkSamplingOptions&, const SkPaint&,
167
168 void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
169 const SkSamplingOptions&, const SkPaint&,
171
172 void drawVertices(const SkVertices*, sk_sp<SkBlender>, const SkPaint&, bool) override;
174 const SkImage*,
175 const SkRect* src,
176 const SkRect& dst,
177 const SkSamplingOptions&,
178 const SkPaint&,
180 // TODO: Implement these using per-edge AA quads and an inlined image shader program.
182 const SkRect& dst, SkFilterMode, const SkPaint&) override {}
183 void drawAtlas(const SkRSXform[], const SkRect[], const SkColor[], int count, sk_sp<SkBlender>,
184 const SkPaint&) override {}
185
186 void drawDrawable(SkCanvas*, SkDrawable*, const SkMatrix*) override {}
187 void drawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) override {}
188 void drawShadow(const SkPath&, const SkDrawShadowRec&) override {}
189
190 // Special images and layers
192
193 sk_sp<SkDevice> createDevice(const CreateInfo&, const SkPaint*) override;
194
195 sk_sp<SkSpecialImage> snapSpecial(const SkIRect& subset, bool forceCopy = false) override;
196
198 const SkSamplingOptions&, const SkPaint&,
201 const SkSamplingOptions&, const SkPaint&) override;
202
203 bool drawBlurredRRect(const SkRRect&, const SkPaint&, float deviceSigma) override;
204
205private:
206 class IntersectionTreeSet;
207
209
212
213 bool onReadPixels(const SkPixmap&, int x, int y) override;
214
215 bool onWritePixels(const SkPixmap&, int x, int y) override;
216
217 void onDrawGlyphRunList(SkCanvas*, const sktext::GlyphRunList&, const SkPaint&) override;
218
219 void onClipShader(sk_sp<SkShader> shader) override;
220
222 SkColorType colorType) const override;
223
224 // DrawFlags alters the effects used by drawGeometry.
225 //
226 // There is no kIgnoreMaskFilter flag because the Device always ignores the mask filter -- the
227 // mask filter should be handled by the SkCanvas, either with an auto mask filter layer or
228 // being converted to an analytic blur draw.
229 enum class DrawFlags : unsigned {
230 kNone = 0b000,
231
232 // Any SkPathEffect on the SkPaint passed into drawGeometry() is ignored.
233 // - drawPaint, drawImageLattice, drawImageRect, drawEdgeAAImageSet, drawVertices, drawAtlas
234 // - drawGeometry after it's applied the path effect.
235 kIgnorePathEffect = 0b001,
236 };
238
239 // Handles applying path effects, mask filters, stroke-and-fill styles, and hairlines.
240 // Ignores geometric style on the paint in favor of explicitly provided SkStrokeRec and flags.
241 // All overridden SkDevice::draw() functions should bottom-out with calls to drawGeometry().
242 void drawGeometry(const Transform&,
243 const Geometry&,
244 const SkPaint&,
245 const SkStrokeRec&,
246 SkEnumBitMask<DrawFlags> = DrawFlags::kNone,
247 sk_sp<SkBlender> primitiveBlender = nullptr,
248 bool skipColorXform = false);
249
250 // Like drawGeometry() but is Shape-only, depth-only, fill-only, and lets the ClipStack define
251 // the transform, clip, and DrawOrder (although Device still tracks stencil buffer usage).
252 void drawClipShape(const Transform&, const Shape&, const Clip&, DrawOrder);
253
254 sktext::gpu::AtlasDrawDelegate atlasDelegate();
255 // Handles primitive processing for atlas-based text
256 void drawAtlasSubRun(const sktext::gpu::AtlasSubRun*,
257 SkPoint drawOrigin,
258 const SkPaint& paint,
259 sk_sp<SkRefCnt> subRunStorage,
261
263 const SkPaint& paint) override;
264
265 void drawSlug(SkCanvas*, const sktext::gpu::Slug* slug, const SkPaint& paint) override;
266
267 // Returns the Renderer to draw the shape in the given style. If SkStrokeRec is a
268 // stroke-and-fill, this returns the Renderer used for the fill portion and it can be assumed
269 // that Renderer::TessellatedStrokes() will be used for the stroke portion.
270 //
271 // Depending on the preferred anti-aliasing quality and platform capabilities (such as compute
272 // shader support), an atlas handler for path rendering may be returned alongside the chosen
273 // Renderer. In that case, all fill, stroke, and stroke-and-fill styles should be rendered with
274 // a single recorded CoverageMask draw and the shape data should be added to the provided atlas
275 // handler to be scheduled for a coverage mask render.
276 //
277 // TODO: Renderers may have fallbacks (e.g. pre-chop large paths, or convert stroke to fill).
278 // Are those handled inside ChooseRenderer() where it can modify the shape, stroke? or does it
279 // return a retry error code? or does drawGeometry() handle all the fallbacks, knowing that
280 // a particular shape type needs to be pre-chopped?
281 // TODO: Move this into a RendererSelector object provided by the Context.
282 std::pair<const Renderer*, PathAtlas*> chooseRenderer(const Transform& localToDevice,
283 const Geometry&,
284 const SkStrokeRec&,
285 bool requireMSAA) const;
286
287 bool needsFlushBeforeDraw(int numNewDraws, DstReadRequirement) const;
288
289 // Flush internal work, such as pending clip draws and atlas uploads, into the Device's DrawTask
290 void internalFlush();
291
292 // TODO(b/333073673): Detect memory stomping over fRecorder to see if that's the cause of
293 // crashes; can be removed once the issue is resolved.
294 SkDEBUGCODE(const intptr_t fPreRecorderSentinel;)
295 Recorder* fRecorder;
296 SkDEBUGCODE(const intptr_t fPostRecorderSentinel;)
298 // Scratch devices hold on to their last snapped DrawTask so that they can be directly
299 // referenced when the device image is drawn into some other surface.
300 // NOTE: For now, this task is still added to the root task list when the Device is flushed, but
301 // in the long-term, these scratch draw tasks will only be executed if they are referenced by
302 // some other task chain that makes it to the root list.
303 sk_sp<Task> fLastTask;
304
305 ClipStack fClip;
306
307 // Tracks accumulated intersections for ordering dependent use of the color and depth attachment
308 // (i.e. depth-based clipping, and transparent blending)
309 std::unique_ptr<BoundsManager> fColorDepthBoundsManager;
310 // Tracks disjoint stencil indices for all recordered draws
311 std::unique_ptr<IntersectionTreeSet> fDisjointStencilSet;
312
313 // Lazily updated Transform constructed from localToDevice()'s SkM44
314 Transform fCachedLocalToDevice;
315
316 // The max depth value sent to the DrawContext, incremented so each draw has a unique value.
317 PaintersDepth fCurrentDepth;
318
319 // The DrawContext's target supports MSAA
320 bool fMSAASupported = false;
321
322 // TODO(b/330864257): Clean up once flushPendingWorkToRecorder() doesn't have to be re-entrant
323 bool fIsFlushing = false;
324
325 const sktext::gpu::SDFTControl fSDFTControl;
326
327#if defined(SK_DEBUG)
328 // When not 0, this Device is an unregistered scratch device that is intended to go out of
329 // scope before the Recorder is snapped. Assuming controlling code is valid, that means the
330 // Device's recorder's next recording ID should still be the the recording ID at the time the
331 // Device was created. If not, it means the Device lived too long and may not be flushing tasks
332 // in the expected order.
333 uint32_t fScopedRecordingID = 0;
334#endif
335
336 friend class ClipStack; // for recordDraw
337};
338
339SK_MAKE_BITMASK_OPS(Device::DrawFlags)
340
341} // namespace skgpu::graphite
342
343#endif // skgpu_graphite_Device_DEFINED
int count
SkColor4f color
SkBackingFit
SkBlendMode
Definition SkBlendMode.h:38
SkClipOp
Definition SkClipOp.h:13
SkColorType
Definition SkColorType.h:19
uint32_t SkColor
Definition SkColor.h:37
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
#define SK_DECL_BITMASK_OPS_FRIENDS(E)
#define SK_MAKE_BITMASK_OPS(E)
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
SkFilterMode
Shape
SrcRectConstraint
Definition SkCanvas.h:1541
sk_sp< SkSpecialImage > snapSpecial()
Definition SkDevice.cpp:321
const SkMatrix & localToDevice() const
Definition SkDevice.h:179
const SkSurfaceProps & surfaceProps() const
Definition SkDevice.h:131
sk_sp< SkDevice > createDevice(const CreateInfo &, const SkPaint *) override
Definition Device.cpp:385
TextureProxyView readSurfaceView() const
Definition Device.cpp:1643
bool useDrawCoverageMaskForMaskFilters() const override
Definition Device.h:118
static sk_sp< Device > Make(Recorder *recorder, sk_sp< TextureProxy >, SkISize deviceSize, const SkColorInfo &, const SkSurfaceProps &, LoadOp initialLoadOp, bool registerWithRecorder=true)
Definition Device.cpp:268
void drawRect(const SkRect &r, const SkPaint &paint) override
Definition Device.cpp:655
sk_sp< SkSurface > makeSurface(const SkImageInfo &, const SkSurfaceProps &) override
Definition Device.cpp:407
void drawOval(const SkRect &oval, const SkPaint &paint) override
Definition Device.cpp:716
void clipRRect(const SkRRect &rrect, SkClipOp, bool aa) override
Definition Device.cpp:564
void drawEdgeAAQuad(const SkRect &rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags, const SkColor4f &color, SkBlendMode mode) override
Definition Device.cpp:768
void drawAtlas(const SkRSXform[], const SkRect[], const SkColor[], int count, sk_sp< SkBlender >, const SkPaint &) override
Definition Device.h:183
Recorder * recorder() const override
Definition Device.h:71
void android_utils_clipAsRgn(SkRegion *) const override
Definition Device.cpp:539
void drawPaint(const SkPaint &paint) override
Definition Device.cpp:620
void drawImageLattice(const SkImage *, const SkCanvas::Lattice &, const SkRect &dst, SkFilterMode, const SkPaint &) override
Definition Device.h:181
void drawVertices(const SkVertices *, sk_sp< SkBlender >, const SkPaint &, bool) override
Definition Device.cpp:660
sk_sp< SkSpecialImage > makeSpecial(const SkBitmap &) override
Definition Device.cpp:1598
TextureProxy * target()
Definition Device.cpp:1641
void replaceClip(const SkIRect &rect) override
Definition Device.cpp:603
bool drawBlurredRRect(const SkRRect &, const SkPaint &, float deviceSigma) override
Definition Device.cpp:1672
void onDrawGlyphRunList(SkCanvas *, const sktext::GlyphRunList &, const SkPaint &) override
Definition Device.cpp:868
sk_sp< sktext::gpu::Slug > convertGlyphRunListToSlug(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint) override
Definition Device.cpp:1658
const Transform & localToDeviceTransform()
Definition Device.cpp:374
bool onReadPixels(const SkPixmap &, int x, int y) override
Definition Device.cpp:430
bool drawAsTiledImageRect(SkCanvas *, const SkImage *, const SkRect *src, const SkRect &dst, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
Definition Device.cpp:672
void drawRRect(const SkRRect &rr, const SkPaint &paint) override
Definition Device.cpp:730
void flushPendingWorkToRecorder(Recorder *recorder=nullptr)
Definition Device.cpp:1410
void drawSlug(SkCanvas *, const sktext::gpu::Slug *slug, const SkPaint &paint) override
Definition Device.cpp:1667
sk_sp< skif::Backend > createImageFilteringBackend(const SkSurfaceProps &surfaceProps, SkColorType colorType) const override
Definition Device.cpp:1636
void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
Definition Device.cpp:786
void drawSpecial(SkSpecialImage *, const SkMatrix &localToDevice, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
Definition Device.cpp:1520
void onClipShader(sk_sp< SkShader > shader) override
Definition Device.cpp:579
bool isClipAntiAliased() const override
Definition Device.cpp:520
void clipRegion(const SkRegion &globalRgn, SkClipOp) override
Definition Device.cpp:584
SkStrikeDeviceInfo strikeDeviceInfo() const override
Definition Device.cpp:381
void drawShadow(const SkPath &, const SkDrawShadowRec &) override
Definition Device.h:188
void drawPath(const SkPath &path, const SkPaint &paint, bool pathIsMutable=false) override
Definition Device.cpp:735
bool isScratchDevice() const
Definition Device.cpp:1645
void drawImageRect(const SkImage *, const SkRect *src, const SkRect &dst, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
Definition Device.cpp:847
Device * asGraphiteDevice() override
Definition Device.h:69
void drawMesh(const SkMesh &, sk_sp< SkBlender >, const SkPaint &) override
Definition Device.h:187
bool isClipRect() const override
Definition Device.h:131
void drawCoverageMask(const SkSpecialImage *, const SkMatrix &localToDevice, const SkSamplingOptions &, const SkPaint &) override
Definition Device.cpp:1552
friend class ClipStack
Definition Device.h:336
void clipRect(const SkRect &rect, SkClipOp, bool aa) override
Definition Device.cpp:558
void setImmutable() override
Definition Device.cpp:359
void drawDrawable(SkCanvas *, SkDrawable *, const SkMatrix *) override
Definition Device.h:186
sk_sp< Image > makeImageCopy(const SkIRect &subset, Budgeted, Mipmapped, SkBackingFit)
Definition Device.cpp:411
bool onWritePixels(const SkPixmap &, int x, int y) override
Definition Device.cpp:455
void popClipStack() override
Definition Device.h:123
SkIRect devClipBounds() const override
Definition Device.cpp:534
sk_sp< Task > lastDrawTask() const
Definition Device.cpp:1405
void drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint[], const SkPaint &paint) override
void pushClipStack() override
Definition Device.h:122
bool isClipWideOpen() const override
Definition Device.h:125
bool isClipEmpty() const override
Definition Device.h:128
void clipPath(const SkPath &path, SkClipOp, bool aa) override
Definition Device.cpp:571
const Paint & paint
double y
double x
CanvasImage Image
Definition dart_ui.cc:55
MonotonicValue< PaintersDepthSequence > PaintersDepth
Definition DrawOrder.h:86
Budgeted
Definition GpuTypes.h:35
Mipmapped
Definition GpuTypes.h:53
std::function< void(const sktext::gpu::AtlasSubRun *subRun, SkPoint drawOrigin, const SkPaint &paint, sk_sp< SkRefCnt > subRunStorage, sktext::gpu::RendererData)> AtlasDrawDelegate
Definition DM.cpp:1161