Flutter Engine
 
Loading...
Searching...
No Matches
dl_op_receiver.h
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef FLUTTER_DISPLAY_LIST_DL_OP_RECEIVER_H_
6#define FLUTTER_DISPLAY_LIST_DL_OP_RECEIVER_H_
7
20#include "flutter/third_party/skia/include/core/SkTextBlob.h"
21
22namespace flutter {
23
24class DisplayList;
25class DlText;
26
27//------------------------------------------------------------------------------
28/// @brief Internal API for rendering recorded display lists to backends.
29///
30/// The |DisplayList| object will play back recorded operations in this format.
31/// Most developers should not need to deal with this interface unless they are
32/// writing a utility that needs to examine the contents of a display list.
33///
34/// Similar to |DlCanvas|, this interface carries clip and transform state
35/// which are saved and restored by the |save|, |saveLayer|, and |restore|
36/// calls.
37///
38/// Unlike DlCanvas, this interface has attribute state which is global across
39/// an entire DisplayList (not affected by save/restore).
40///
41/// DISPLAYLIST DEPTH TRACKING
42///
43/// Each rendering call in the DisplayList stream is assumed to have a "depth"
44/// value relative to the beginning of its DisplayList. The depth value is
45/// implicitly allocated during recording and only reported in 2 places so
46/// it is important for a dispatcher to perform the same internal allocations
47/// if it is to make sense of the information reported by the save/saveLayer
48/// calls. This depth value is maintained as follows:
49///
50/// - The absolute depth value is never reported, only the total depth
51/// size of the entire DisplayList or one of its save/restore pairs
52/// is reported. Since the DisplayList might be dispatched recursively
53/// due to embedded drawDisplayList calls, these depth size values
54/// will often be relative to things like:
55/// - the start of a given save/saveLayer group
56/// - the start of a DisplayList dispatch or recursion
57/// as such, only totals for groups of DisplayList dispatched calls
58/// will be reported. These totals will be reported in:
59/// - the `DisplayList::total_depth()` method reporting the total
60/// depth accumulated for every operation in the DisplayList
61/// - the save/saveLayer dispatch calls will report the total
62/// depth accumulated for every call until their corresponding
63/// restore call.
64/// - The depth value is incremented for every drawing operation, including:
65/// - all draw* calls (including drawDisplayList)
66/// - drawDisplayList will also accumulate the total_depth() of the
67/// DisplayList object it is drawing (in other words it will skip enough
68/// depth values for each drawing call in the child).
69/// This bump is in addition to the depth value it records for being
70/// a rendering operation. Some implementations may need to surround
71/// the actual drawDisplayList with a protective saveLayer, but others
72/// may not - so the implicit depth value assigned to the drawDisplayList
73/// call itself may go unused, but must be accounted for.
74/// - a saveLayer call will also increment the depth value just like a
75/// rendering call. This is in addition to the depth of its content.
76/// It is doing so to reserve a depth for the drawing operation that
77/// copies its layer back to the parent.
78/// - Each save() or saveLayer() call will report the total depth of all
79/// rendering calls within its content (recorded before the corresponding
80/// restore) and report this total during dispatch. This information might
81/// be needed to assign depths to the clip operations that occur within
82/// its content. As there is no enclosing saveLayer/restore pair around
83/// the root of a DisplayList, the total depth of the DisplayList can
84/// be used to determine the appropriate clip depths for any clip ops
85/// appearing before the first save/saveLayer or after the last restore.
86///
87/// @see DlSkCanvasDispatcher
88/// @see impeller::DlDispatcher
89/// @see DlOpSpy
91 public:
92 // MaxDrawPointsCount * sizeof(DlPoint) must be less than 1 << 32
93 static constexpr int kMaxDrawPointsCount = ((1 << 29) - 1);
94
95 // The following methods are nearly 1:1 with the methods on DlPaint and
96 // carry the same meanings. Each method sets a persistent value for the
97 // attribute for the rest of the display list or until it is reset by
98 // another method that changes the same attribute. The current set of
99 // attributes is not affected by |save| and |restore|.
100 virtual void setAntiAlias(bool aa) = 0;
101 virtual void setDrawStyle(DlDrawStyle style) = 0;
102 virtual void setColor(DlColor color) = 0;
103 virtual void setStrokeWidth(float width) = 0;
104 virtual void setStrokeMiter(float limit) = 0;
105 virtual void setStrokeCap(DlStrokeCap cap) = 0;
106 virtual void setStrokeJoin(DlStrokeJoin join) = 0;
107 virtual void setColorSource(const DlColorSource* source) = 0;
108 virtual void setColorFilter(const DlColorFilter* filter) = 0;
109 // setInvertColors is a quick way to set a ColorFilter that inverts the
110 // rgb values of all rendered colors.
111 // It is not reset by |setColorFilter|, but instead composed with that
112 // filter so that the color inversion happens after the ColorFilter.
113 virtual void setInvertColors(bool invert) = 0;
114 virtual void setBlendMode(DlBlendMode mode) = 0;
115 virtual void setMaskFilter(const DlMaskFilter* filter) = 0;
116 virtual void setImageFilter(const DlImageFilter* filter) = 0;
117
118 // All of the following methods are nearly 1:1 with their counterparts
119 // in |SkCanvas| and have the same behavior and output.
120 virtual void save() = 0;
121 // Optional variant of save() that passes the total depth count of
122 // all rendering operations that occur until the next restore() call.
123 virtual void save(uint32_t total_content_depth) { save(); }
124 // The |options| parameter can specify whether the existing rendering
125 // attributes will be applied to the save layer surface while rendering
126 // it back to the current surface. If the flag is false then this method
127 // is equivalent to |SkCanvas::saveLayer| with a null paint object.
128 //
129 // The |options| parameter can also specify whether the bounds came from
130 // the caller who recorded the operation, or whether they were calculated
131 // by the DisplayListBuilder.
132 //
133 // The |options| parameter may contain other options that indicate some
134 // specific optimizations may be made by the underlying implementation
135 // to avoid creating a temporary layer, these optimization options will
136 // be determined as the |DisplayList| is constructed and should not be
137 // specified in calling a |DisplayListBuilder| as they will be ignored.
138 // The |backdrop| filter, if not null, is used to initialize the new
139 // layer before further rendering happens.
140 virtual void saveLayer(const DlRect& bounds,
141 const SaveLayerOptions options,
142 const DlImageFilter* backdrop = nullptr,
143 std::optional<int64_t> backdrop_id = std::nullopt) = 0;
144 // Optional variant of saveLayer() that passes the total depth count of
145 // all rendering operations that occur until the next restore() call.
146 virtual void saveLayer(const DlRect& bounds,
147 const SaveLayerOptions& options,
148 uint32_t total_content_depth,
149 DlBlendMode max_content_blend_mode,
150 const DlImageFilter* backdrop = nullptr,
151 std::optional<int64_t> backdrop_id = std::nullopt) {
152 saveLayer(bounds, options, backdrop, backdrop_id);
153 }
154 virtual void restore() = 0;
155
156 // ---------------------------------------------------------------------
157 // Legacy helper method for older callers that use the null-ness of
158 // the bounds to indicate if they should be recorded or computed.
159 // This method will not be called on a |DlOpReceiver| that is passed
160 // to the |DisplayList::Dispatch()| method, so client receivers should
161 // ignore it for their implementation purposes.
162 //
163 // DlOpReceiver methods are generally meant to ONLY be output from a
164 // previously recorded DisplayList so this method is really only used
165 // from testing methods that bypass the public builder APIs for legacy
166 // convenience or for internal white-box testing of the DisplayList
167 // internals. Such methods should eventually be converted to using the
168 // public DisplayListBuilder/DlCanvas public interfaces where possible,
169 // as tracked in:
170 // https://github.com/flutter/flutter/issues/144070
171 virtual void saveLayer(
172 const DlRect* bounds,
173 const SaveLayerOptions options,
174 const DlImageFilter* backdrop = nullptr,
175 std::optional<int64_t> backdrop_id = std::nullopt) final {
176 if (bounds) {
177 saveLayer(*bounds, options.with_bounds_from_caller(), backdrop,
178 backdrop_id);
179 } else {
180 saveLayer(DlRect(), options.without_bounds_from_caller(), backdrop,
181 backdrop_id);
182 }
183 }
184 // ---------------------------------------------------------------------
185
186 virtual void translate(DlScalar tx, DlScalar ty) = 0;
187 virtual void scale(DlScalar sx, DlScalar sy) = 0;
188 virtual void rotate(DlScalar degrees) = 0;
189 virtual void skew(DlScalar sx, DlScalar sy) = 0;
190
191 // The transform methods all assume the following math for transforming
192 // an arbitrary 3D homogenous point (x, y, z, w).
193 // All coordinates in the rendering methods (and DlPoint and DlRect objects)
194 // represent a simplified coordinate (x, y, 0, 1).
195 // x' = x * mxx + y * mxy + z * mxz + w * mxt
196 // y' = x * myx + y * myy + z * myz + w * myt
197 // z' = x * mzx + y * mzy + z * mzz + w * mzt
198 // w' = x * mwx + y * mwy + z * mwz + w * mwt
199 // Note that for non-homogenous 2D coordinates, the last column in those
200 // equations is multiplied by 1 and is simply adding a translation and
201 // so is referred to with the final letter "t" here instead of "w".
202 //
203 // In 2D coordinates, z=0 and so the 3rd column always evaluates to 0.
204 //
205 // In non-perspective transforms, the 4th row has identity values
206 // and so w` = w. (i.e. w'=1 for 2d points transformed by a matrix
207 // with identity values in the last row).
208 //
209 // In affine 2D transforms, the 3rd and 4th row and 3rd column are all
210 // identity values and so z` = z (which is 0 for 2D coordinates) and
211 // the x` and y` equations don't see a contribution from a z coordinate
212 // and the w' ends up being the same as the w from the source coordinate
213 // (which is 1 for a 2D coordinate).
214 //
215 // Here is the math for transforming a 2D source coordinate and
216 // looking for the destination 2D coordinate (for a surface that
217 // does not have a Z buffer or track the Z coordinates in any way)
218 // Source coordinate = (x, y, 0, 1)
219 // x' = x * mxx + y * mxy + 0 * mxz + 1 * mxt
220 // y' = x * myx + y * myy + 0 * myz + 1 * myt
221 // z' = x * mzx + y * mzy + 0 * mzz + 1 * mzt
222 // w' = x * mwx + y * mwy + 0 * mwz + 1 * mwt
223 // Destination coordinate does not need z', so this reduces to:
224 // x' = x * mxx + y * mxy + mxt
225 // y' = x * myx + y * myy + myt
226 // w' = x * mwx + y * mwy + mwt
227 // Destination coordinate is (x' / w', y' / w', 0, 1)
228 // Note that these are the matrix values in SkMatrix which means that
229 // an SkMatrix contains enough data to transform a 2D source coordinate
230 // and place it on a 2D surface, but is otherwise not enough to continue
231 // concatenating with further matrices as its missing elements will not
232 // be able to model the interplay between the rows and columns that
233 // happens during a full 4x4 by 4x4 matrix multiplication.
234 //
235 // If the transform doesn't have any perspective parts (the last
236 // row is identity - 0, 0, 0, 1), then this further simplifies to:
237 // x' = x * mxx + y * mxy + mxt
238 // y' = x * myx + y * myy + myt
239 // w' = x * 0 + y * 0 + 1 = 1
240 //
241 // In short, while the full 4x4 set of matrix entries needs to be
242 // maintained for accumulating transform mutations accurately, the
243 // actual end work of transforming a single 2D coordinate (or, in
244 // the case of bounds transformations, 4 of them) can be accomplished
245 // with the 9 values from transform3x3 or SkMatrix.
246 //
247 // The only need for the w value here is for homogenous coordinates
248 // which only come up if the perspective elements (the 4th row) of
249 // a transform are non-identity. Otherwise the w always ends up
250 // being 1 in all calculations. If the matrix has perspecitve elements
251 // then the final transformed coordinates will have a w that is not 1
252 // and the actual coordinates are determined by dividing out that w
253 // factor resulting in a real-world point expressed as (x, y, z, 1).
254 //
255 // Because of the predominance of 2D affine transforms the
256 // 2x3 subset of the 4x4 transform matrix is special cased with
257 // its own dispatch method that omits the last 2 rows and the 3rd
258 // column. Even though a 3x3 subset is enough for transforming
259 // leaf coordinates as shown above, no method is provided for
260 // representing a 3x3 transform in the DisplayList since if there
261 // is perspective involved then a full 4x4 matrix should be provided
262 // for accurate concatenations. Providing a 3x3 method or record
263 // in the stream would encourage developers to prematurely subset
264 // a full perspective matrix.
265
266 // clang-format off
267
268 // |transform2DAffine| is equivalent to concatenating the internal
269 // 4x4 transform with the following row major transform matrix:
270 // [ mxx mxy 0 mxt ]
271 // [ myx myy 0 myt ]
272 // [ 0 0 1 0 ]
273 // [ 0 0 0 1 ]
274 virtual void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt,
275 DlScalar myx, DlScalar myy, DlScalar myt) = 0;
276 // |transformFullPerspective| is equivalent to concatenating the internal
277 // 4x4 transform with the following row major transform matrix:
278 // [ mxx mxy mxz mxt ]
279 // [ myx myy myz myt ]
280 // [ mzx mzy mzz mzt ]
281 // [ mwx mwy mwz mwt ]
283 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
284 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
285 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
286 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) = 0;
287 // clang-format on
288
289 // Clears the transformation stack.
290 virtual void transformReset() = 0;
291
292 virtual void clipRect(const DlRect& rect, DlClipOp clip_op, bool is_aa) = 0;
293 virtual void clipOval(const DlRect& bounds, DlClipOp clip_op, bool is_aa) = 0;
294 virtual void clipRoundRect(const DlRoundRect& rrect,
295 DlClipOp clip_op,
296 bool is_aa) = 0;
298 DlClipOp clip_op,
299 bool is_aa) = 0;
300 virtual void clipPath(const DlPath& path, DlClipOp clip_op, bool is_aa) = 0;
301
302 // The following rendering methods all take their rendering attributes
303 // from the last value set by the attribute methods above (regardless
304 // of any |save| or |restore| operations which do not affect attributes).
305 // In cases where a paint object may have been optional in the SkCanvas
306 // method, the methods here will generally offer a boolean parameter
307 // which specifies whether to honor the attributes of the display list
308 // stream, or assume default attributes.
309 virtual void drawColor(DlColor color, DlBlendMode mode) = 0;
310 virtual void drawPaint() = 0;
311 virtual void drawLine(const DlPoint& p0, const DlPoint& p1) = 0;
312 virtual void drawDashedLine(const DlPoint& p0,
313 const DlPoint& p1,
314 DlScalar on_length,
315 DlScalar off_length) = 0;
316 virtual void drawRect(const DlRect& rect) = 0;
317 virtual void drawOval(const DlRect& bounds) = 0;
318 virtual void drawCircle(const DlPoint& center, DlScalar radius) = 0;
319 virtual void drawRoundRect(const DlRoundRect& rrect) = 0;
320 virtual void drawDiffRoundRect(const DlRoundRect& outer,
321 const DlRoundRect& inner) = 0;
322 virtual void drawRoundSuperellipse(const DlRoundSuperellipse& rse) = 0;
323 virtual void drawPath(const DlPath& path) = 0;
324 virtual void drawArc(const DlRect& oval_bounds,
325 DlScalar start_degrees,
326 DlScalar sweep_degrees,
327 bool use_center) = 0;
328 virtual void drawPoints(DlPointMode mode,
329 uint32_t count,
330 const DlPoint points[]) = 0;
331 virtual void drawVertices(const std::shared_ptr<DlVertices>& vertices,
332 DlBlendMode mode) = 0;
333 virtual void drawImage(const sk_sp<DlImage> image,
334 const DlPoint& point,
335 DlImageSampling sampling,
336 bool render_with_attributes) = 0;
337 virtual void drawImageRect(
338 const sk_sp<DlImage> image,
339 const DlRect& src,
340 const DlRect& dst,
341 DlImageSampling sampling,
342 bool render_with_attributes,
344 virtual void drawImageNine(const sk_sp<DlImage> image,
345 const DlIRect& center,
346 const DlRect& dst,
347 DlFilterMode filter,
348 bool render_with_attributes) = 0;
349 virtual void drawAtlas(const sk_sp<DlImage> atlas,
350 const DlRSTransform xform[],
351 const DlRect tex[],
352 const DlColor colors[],
353 int count,
354 DlBlendMode mode,
355 DlImageSampling sampling,
356 const DlRect* cull_rect,
357 bool render_with_attributes) = 0;
358 virtual void drawDisplayList(const sk_sp<DisplayList> display_list,
359 DlScalar opacity = SK_Scalar1) = 0;
360 virtual void drawText(const std::shared_ptr<DlText>& text,
361 DlScalar x,
362 DlScalar y) = 0;
363 virtual void drawShadow(const DlPath& path,
364 const DlColor color,
365 const DlScalar elevation,
366 bool transparent_occluder,
367 DlScalar dpr) = 0;
368};
369
370} // namespace flutter
371
372#endif // FLUTTER_DISPLAY_LIST_DL_OP_RECEIVER_H_
Internal API for rendering recorded display lists to backends.
virtual void drawText(const std::shared_ptr< DlText > &text, DlScalar x, DlScalar y)=0
virtual void save()=0
virtual void save(uint32_t total_content_depth)
virtual void setStrokeMiter(float limit)=0
virtual void transformReset()=0
virtual void drawPath(const DlPath &path)=0
virtual void saveLayer(const DlRect *bounds, const SaveLayerOptions options, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) final
virtual void drawImageNine(const sk_sp< DlImage > image, const DlIRect &center, const DlRect &dst, DlFilterMode filter, bool render_with_attributes)=0
virtual void restore()=0
virtual void drawImageRect(const sk_sp< DlImage > image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, bool render_with_attributes, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast)=0
virtual void drawArc(const DlRect &oval_bounds, DlScalar start_degrees, DlScalar sweep_degrees, bool use_center)=0
virtual void translate(DlScalar tx, DlScalar ty)=0
virtual void drawImage(const sk_sp< DlImage > image, const DlPoint &point, DlImageSampling sampling, bool render_with_attributes)=0
virtual void scale(DlScalar sx, DlScalar sy)=0
virtual void setStrokeWidth(float width)=0
virtual void setMaskFilter(const DlMaskFilter *filter)=0
virtual void drawRoundSuperellipse(const DlRoundSuperellipse &rse)=0
virtual void drawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner)=0
virtual void setColorFilter(const DlColorFilter *filter)=0
virtual void rotate(DlScalar degrees)=0
virtual void drawVertices(const std::shared_ptr< DlVertices > &vertices, DlBlendMode mode)=0
virtual void setAntiAlias(bool aa)=0
virtual void drawLine(const DlPoint &p0, const DlPoint &p1)=0
virtual void drawCircle(const DlPoint &center, DlScalar radius)=0
static constexpr int kMaxDrawPointsCount
virtual void drawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity=SK_Scalar1)=0
virtual void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt)=0
virtual void drawShadow(const DlPath &path, const DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr)=0
virtual void saveLayer(const DlRect &bounds, const SaveLayerOptions &options, uint32_t total_content_depth, DlBlendMode max_content_blend_mode, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt)
virtual void drawPoints(DlPointMode mode, uint32_t count, const DlPoint points[])=0
virtual void clipRect(const DlRect &rect, DlClipOp clip_op, bool is_aa)=0
virtual void transformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt)=0
virtual void clipPath(const DlPath &path, DlClipOp clip_op, bool is_aa)=0
virtual void skew(DlScalar sx, DlScalar sy)=0
virtual void drawColor(DlColor color, DlBlendMode mode)=0
virtual void clipOval(const DlRect &bounds, DlClipOp clip_op, bool is_aa)=0
virtual void drawAtlas(const sk_sp< DlImage > atlas, const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const DlRect *cull_rect, bool render_with_attributes)=0
virtual void drawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length)=0
virtual void setStrokeJoin(DlStrokeJoin join)=0
virtual void clipRoundSuperellipse(const DlRoundSuperellipse &rse, DlClipOp clip_op, bool is_aa)=0
virtual void setImageFilter(const DlImageFilter *filter)=0
virtual void setColorSource(const DlColorSource *source)=0
virtual void drawPaint()=0
virtual void setDrawStyle(DlDrawStyle style)=0
virtual void setBlendMode(DlBlendMode mode)=0
virtual void setColor(DlColor color)=0
virtual void setInvertColors(bool invert)=0
virtual void drawRoundRect(const DlRoundRect &rrect)=0
virtual void drawRect(const DlRect &rect)=0
virtual void setStrokeCap(DlStrokeCap cap)=0
virtual void clipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op, bool is_aa)=0
virtual void saveLayer(const DlRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt)=0
virtual void drawOval(const DlRect &bounds)=0
int32_t x
FlutterVulkanImage * image
std::u16string text
double y
impeller::Scalar DlScalar
DlStrokeJoin
Definition dl_paint.h:37
DlStrokeCap
Definition dl_paint.h:28
impeller::Rect DlRect
DlPointMode
Definition dl_types.h:15
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
DlDrawStyle
Definition dl_paint.h:19
DlSrcRectConstraint
Definition dl_types.h:21
BlendMode
Definition color.h:58
flutter::DisplayList DisplayList
int32_t width
std::vector< Point > points