2 * Copyright (C) 2015 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "font/FontUtil.h"
23 #include "RenderNode.h"
24 #include "TessellationCache.h"
25 #include "utils/LinearAllocator.h"
26 #include "utils/PaintUtils.h"
29 #include <androidfw/ResourceTypes.h>
35 namespace uirenderer {
38 class OffscreenBuffer;
40 class DeferredLayerUpdater;
44 namespace VectorDrawable {
49 * Authoritative op list, used for generating the op ID enum, ID based LUTS, and
50 * the functions to which they dispatch. Parameter macros are executed for each op,
51 * in order, based on the op's type.
53 * There are 4 types of op, which defines dispatch/LUT capability:
55 * | DisplayList | Render | Merge |
56 * -------------|-------------|-------------|-------------|
57 * PRE RENDER | Yes | | |
58 * RENDER ONLY | | Yes | |
59 * UNMERGEABLE | Yes | Yes | |
60 * MERGEABLE | Yes | Yes | Yes |
62 * PRE RENDER - These ops are recorded into DisplayLists, but can't be directly rendered. This
63 * may be because they need to be transformed into other op types (e.g. CirclePropsOp),
64 * be traversed to access multiple renderable ops within (e.g. RenderNodeOp), or because they
65 * modify renderbuffer lifecycle, instead of directly rendering content (the various LayerOps).
67 * RENDER ONLY - These ops cannot be recorded into DisplayLists, and are instead implicitly
68 * constructed from other commands/RenderNode properties. They cannot be merged.
70 * UNMERGEABLE - These ops can be recorded into DisplayLists and rendered directly, but do not
71 * support merged rendering.
73 * MERGEABLE - These ops can be recorded into DisplayLists and rendered individually, or merged
74 * under certain circumstances.
76 #define MAP_OPS_BASED_ON_TYPE(PRE_RENDER_OP_FN, RENDER_ONLY_OP_FN, UNMERGEABLE_OP_FN, MERGEABLE_OP_FN) \
77 PRE_RENDER_OP_FN(RenderNodeOp) \
78 PRE_RENDER_OP_FN(CirclePropsOp) \
79 PRE_RENDER_OP_FN(RoundRectPropsOp) \
80 PRE_RENDER_OP_FN(BeginLayerOp) \
81 PRE_RENDER_OP_FN(EndLayerOp) \
82 PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \
83 PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
84 PRE_RENDER_OP_FN(VectorDrawableOp) \
86 RENDER_ONLY_OP_FN(ShadowOp) \
87 RENDER_ONLY_OP_FN(LayerOp) \
88 RENDER_ONLY_OP_FN(CopyToLayerOp) \
89 RENDER_ONLY_OP_FN(CopyFromLayerOp) \
91 UNMERGEABLE_OP_FN(ArcOp) \
92 UNMERGEABLE_OP_FN(BitmapMeshOp) \
93 UNMERGEABLE_OP_FN(BitmapRectOp) \
94 UNMERGEABLE_OP_FN(ColorOp) \
95 UNMERGEABLE_OP_FN(FunctorOp) \
96 UNMERGEABLE_OP_FN(LinesOp) \
97 UNMERGEABLE_OP_FN(OvalOp) \
98 UNMERGEABLE_OP_FN(PathOp) \
99 UNMERGEABLE_OP_FN(PointsOp) \
100 UNMERGEABLE_OP_FN(RectOp) \
101 UNMERGEABLE_OP_FN(RoundRectOp) \
102 UNMERGEABLE_OP_FN(SimpleRectsOp) \
103 UNMERGEABLE_OP_FN(TextOnPathOp) \
104 UNMERGEABLE_OP_FN(TextureLayerOp) \
106 MERGEABLE_OP_FN(BitmapOp) \
107 MERGEABLE_OP_FN(PatchOp) \
108 MERGEABLE_OP_FN(TextOp)
111 * LUT generators, which will insert nullptr for unsupported ops
113 #define NULLPTR_OP_FN(Type) nullptr,
115 #define BUILD_DEFERRABLE_OP_LUT(OP_FN) \
116 { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
118 #define BUILD_MERGEABLE_OP_LUT(OP_FN) \
119 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) }
121 #define BUILD_RENDERABLE_OP_LUT(OP_FN) \
122 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
124 #define BUILD_FULL_OP_LUT(OP_FN) \
125 { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
128 * Op mapping functions, which skip unsupported ops.
130 * Note: Do not use for LUTS, since these do not preserve ID order.
132 #define NULL_OP_FN(Type)
134 #define MAP_DEFERRABLE_OPS(OP_FN) \
135 MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
137 #define MAP_MERGEABLE_OPS(OP_FN) \
138 MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
140 #define MAP_RENDERABLE_OPS(OP_FN) \
141 MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
143 // Generate OpId enum
144 #define IDENTITY_FN(Type) Type,
145 namespace RecordedOpId {
147 MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN)
151 static_assert(RecordedOpId::RenderNodeOp == 0,
152 "First index must be zero for LUTs to work");
154 #define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint
155 #define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip
156 #define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint)
157 #define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr)
160 /* ID from RecordedOpId - generally used for jumping into function tables */
163 /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */
164 const Rect unmappedBounds;
166 /* transform in recording space (vs DisplayList origin) */
167 const Matrix4 localMatrix;
169 /* clip in recording space - nullptr if not clipped */
170 const ClipBase* localClip;
172 /* optional paint, stored in base object to simplify merging logic */
173 const SkPaint* paint;
175 RecordedOp(unsigned int opId, BASE_PARAMS)
177 , unmappedBounds(unmappedBounds)
178 , localMatrix(localMatrix)
179 , localClip(localClip)
183 struct RenderNodeOp : RecordedOp {
184 RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
185 : SUPER_PAINTLESS(RenderNodeOp)
186 , renderNode(renderNode) {}
187 RenderNode * renderNode; // not const, since drawing modifies it
190 * Holds the transformation between the projection surface ViewGroup and this RenderNode
191 * drawing instance. Represents any translations / transformations done within the drawing of
192 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
193 * DisplayList draw instance.
195 * Note: doesn't include transformation within the RenderNode, or its properties.
197 Matrix4 transformFromCompositingAncestor;
198 bool skipInOrderDraw = false;
201 ////////////////////////////////////////////////////////////////////////////////////////////////////
203 ////////////////////////////////////////////////////////////////////////////////////////////////////
205 struct ArcOp : RecordedOp {
206 ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter)
208 , startAngle(startAngle)
209 , sweepAngle(sweepAngle)
210 , useCenter(useCenter) {}
211 const float startAngle;
212 const float sweepAngle;
213 const bool useCenter;
216 struct BitmapOp : RecordedOp {
217 BitmapOp(BASE_PARAMS, Bitmap* bitmap)
223 struct BitmapMeshOp : RecordedOp {
224 BitmapMeshOp(BASE_PARAMS, Bitmap* bitmap, int meshWidth, int meshHeight,
225 const float* vertices, const int* colors)
226 : SUPER(BitmapMeshOp)
228 , meshWidth(meshWidth)
229 , meshHeight(meshHeight)
234 const int meshHeight;
235 const float* vertices;
239 struct BitmapRectOp : RecordedOp {
240 BitmapRectOp(BASE_PARAMS, Bitmap* bitmap, const Rect& src)
241 : SUPER(BitmapRectOp)
248 struct CirclePropsOp : RecordedOp {
249 CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
250 float* x, float* y, float* radius)
251 : RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint)
260 struct ColorOp : RecordedOp {
261 // Note: unbounded op that will fillclip, so no bounds/matrix needed
262 ColorOp(const ClipBase* localClip, int color, SkBlendMode mode)
263 : RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr)
267 const SkBlendMode mode;
270 struct FunctorOp : RecordedOp {
271 // Note: undefined record-time bounds, since this op fills the clip
272 // TODO: explicitly define bounds
273 FunctorOp(const Matrix4& localMatrix, const ClipBase* localClip, Functor* functor)
274 : RecordedOp(RecordedOpId::FunctorOp, Rect(), localMatrix, localClip, nullptr)
275 , functor(functor) {}
279 struct LinesOp : RecordedOp {
280 LinesOp(BASE_PARAMS, const float* points, const int floatCount)
283 , floatCount(floatCount) {}
285 const int floatCount;
288 struct OvalOp : RecordedOp {
293 struct PatchOp : RecordedOp {
294 PatchOp(BASE_PARAMS, Bitmap* bitmap, const Res_png_9patch* patch)
299 const Res_png_9patch* patch;
302 struct PathOp : RecordedOp {
303 PathOp(BASE_PARAMS, const SkPath* path)
309 struct PointsOp : RecordedOp {
310 PointsOp(BASE_PARAMS, const float* points, const int floatCount)
313 , floatCount(floatCount) {}
315 const int floatCount;
318 struct RectOp : RecordedOp {
323 struct RoundRectOp : RecordedOp {
324 RoundRectOp(BASE_PARAMS, float rx, float ry)
332 struct RoundRectPropsOp : RecordedOp {
333 RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
334 float* left, float* top, float* right, float* bottom, float *rx, float *ry)
335 : RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint)
350 struct VectorDrawableOp : RecordedOp {
351 VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS)
352 : SUPER_PAINTLESS(VectorDrawableOp)
353 , vectorDrawable(tree) {}
354 VectorDrawable::Tree* vectorDrawable;
358 * Real-time, dynamic-lit shadow.
360 * Uses invalid/empty bounds and matrix since ShadowOp bounds aren't known at defer time,
361 * and are resolved dynamically, and transform isn't needed.
363 * State construction handles these properties specially, ignoring matrix/bounds.
365 struct ShadowOp : RecordedOp {
366 ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha)
367 : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr)
368 , shadowTask(shadowTask)
369 , casterAlpha(casterAlpha) {
371 sp<TessellationCache::ShadowTask> shadowTask;
372 const float casterAlpha;
375 struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
376 SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
377 : SUPER(SimpleRectsOp)
379 , vertexCount(vertexCount) {}
381 const size_t vertexCount;
384 struct TextOp : RecordedOp {
385 TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount,
389 , positions(positions)
390 , glyphCount(glyphCount)
393 const glyph_t* glyphs;
394 const float* positions;
395 const int glyphCount;
400 struct TextOnPathOp : RecordedOp {
401 // TODO: explicitly define bounds
402 TextOnPathOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
403 const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset, float vOffset)
404 : RecordedOp(RecordedOpId::TextOnPathOp, Rect(), localMatrix, localClip, paint)
406 , glyphCount(glyphCount)
409 , vOffset(vOffset) {}
410 const glyph_t* glyphs;
411 const int glyphCount;
418 struct TextureLayerOp : RecordedOp {
419 TextureLayerOp(BASE_PARAMS_PAINTLESS, DeferredLayerUpdater* layer)
420 : SUPER_PAINTLESS(TextureLayerOp)
421 , layerHandle(layer) {}
423 // Copy an existing TextureLayerOp, replacing the underlying matrix
424 TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix)
425 : RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix,
426 op.localClip, op.paint)
427 , layerHandle(op.layerHandle) {
430 DeferredLayerUpdater* layerHandle;
433 ////////////////////////////////////////////////////////////////////////////////////////////////////
435 ////////////////////////////////////////////////////////////////////////////////////////////////////
438 * Stateful operation! denotes the creation of an off-screen layer,
439 * and that commands following will render into it.
441 struct BeginLayerOp : RecordedOp {
442 BeginLayerOp(BASE_PARAMS)
443 : SUPER(BeginLayerOp) {}
447 * Stateful operation! Denotes end of off-screen layer, and that
448 * commands since last BeginLayerOp should be drawn into parent FBO.
450 * State in this op is empty, it just serves to signal that a layer has been finished.
452 struct EndLayerOp : RecordedOp {
454 : RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
457 struct BeginUnclippedLayerOp : RecordedOp {
458 BeginUnclippedLayerOp(BASE_PARAMS)
459 : SUPER(BeginUnclippedLayerOp) {}
462 struct EndUnclippedLayerOp : RecordedOp {
463 EndUnclippedLayerOp()
464 : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
467 struct CopyToLayerOp : RecordedOp {
468 CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
469 : RecordedOp(RecordedOpId::CopyToLayerOp,
472 nullptr, // clip intentionally ignored
474 , layerHandle(layerHandle) {}
476 // Records a handle to the Layer object, since the Layer itself won't be
477 // constructed until after this operation is constructed.
478 OffscreenBuffer** layerHandle;
482 // draw the parameter layer underneath
483 struct CopyFromLayerOp : RecordedOp {
484 CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
485 : RecordedOp(RecordedOpId::CopyFromLayerOp,
488 nullptr, // clip intentionally ignored
490 , layerHandle(layerHandle) {}
492 // Records a handle to the Layer object, since the Layer itself won't be
493 // constructed until after this operation is constructed.
494 OffscreenBuffer** layerHandle;
498 * Draws an OffscreenBuffer.
500 * Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated,
501 * when creating/tracking a SkPaint* during defer isn't worth the bother.
503 struct LayerOp : RecordedOp {
504 // Records a one-use (saveLayer) layer for drawing.
505 LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
506 : SUPER_PAINTLESS(LayerOp)
507 , layerHandle(layerHandle)
508 , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f)
509 , mode(PaintUtils::getBlendModeDirect(paint))
510 , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
512 explicit LayerOp(RenderNode& node)
513 : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr)
514 , layerHandle(node.getLayerHandle())
515 , alpha(node.properties().layerProperties().alpha() / 255.0f)
516 , mode(node.properties().layerProperties().xferMode())
517 , colorFilter(node.properties().layerProperties().colorFilter()) {}
519 // Records a handle to the Layer object, since the Layer itself won't be
520 // constructed until after this operation is constructed.
521 OffscreenBuffer** layerHandle;
523 const SkBlendMode mode;
525 // pointer to object owned by either LayerProperties, or a recorded Paint object in a
526 // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
527 SkColorFilter* colorFilter;
530 }; // namespace uirenderer
531 }; // namespace android