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.
17 #ifndef ANDROID_HWUI_RECORDED_OP_H
18 #define ANDROID_HWUI_RECORDED_OP_H
20 #include "RecordedOp.h"
21 #include "font/FontUtil.h"
24 #include "RenderNode.h"
25 #include "TessellationCache.h"
26 #include "utils/LinearAllocator.h"
29 #include <androidfw/ResourceTypes.h>
30 #include <SkXfermode.h>
36 namespace uirenderer {
39 class OffscreenBuffer;
43 namespace VectorDrawable {
48 * Authoritative op list, used for generating the op ID enum, ID based LUTS, and
49 * the functions to which they dispatch. Parameter macros are executed for each op,
50 * in order, based on the op's type.
52 * There are 4 types of op, which defines dispatch/LUT capability:
54 * | DisplayList | Render | Merge |
55 * -------------|-------------|-------------|-------------|
56 * PRE RENDER | Yes | | |
57 * RENDER ONLY | | Yes | |
58 * UNMERGEABLE | Yes | Yes | |
59 * MERGEABLE | Yes | Yes | Yes |
61 * PRE RENDER - These ops are recorded into DisplayLists, but can't be directly rendered. This
62 * may be because they need to be transformed into other op types (e.g. CirclePropsOp),
63 * be traversed to access multiple renderable ops within (e.g. RenderNodeOp), or because they
64 * modify renderbuffer lifecycle, instead of directly rendering content (the various LayerOps).
66 * RENDER ONLY - These ops cannot be recorded into DisplayLists, and are instead implicitly
67 * constructed from other commands/RenderNode properties. They cannot be merged.
69 * UNMERGEABLE - These ops can be recorded into DisplayLists and rendered directly, but do not
70 * support merged rendering.
72 * MERGEABLE - These ops can be recorded into DisplayLists and rendered individually, or merged
73 * under certain circumstances.
75 #define MAP_OPS_BASED_ON_TYPE(PRE_RENDER_OP_FN, RENDER_ONLY_OP_FN, UNMERGEABLE_OP_FN, MERGEABLE_OP_FN) \
76 PRE_RENDER_OP_FN(RenderNodeOp) \
77 PRE_RENDER_OP_FN(CirclePropsOp) \
78 PRE_RENDER_OP_FN(RoundRectPropsOp) \
79 PRE_RENDER_OP_FN(BeginLayerOp) \
80 PRE_RENDER_OP_FN(EndLayerOp) \
81 PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \
82 PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
83 PRE_RENDER_OP_FN(VectorDrawableOp) \
85 RENDER_ONLY_OP_FN(ShadowOp) \
86 RENDER_ONLY_OP_FN(LayerOp) \
87 RENDER_ONLY_OP_FN(CopyToLayerOp) \
88 RENDER_ONLY_OP_FN(CopyFromLayerOp) \
90 UNMERGEABLE_OP_FN(ArcOp) \
91 UNMERGEABLE_OP_FN(BitmapMeshOp) \
92 UNMERGEABLE_OP_FN(BitmapRectOp) \
93 UNMERGEABLE_OP_FN(ColorOp) \
94 UNMERGEABLE_OP_FN(FunctorOp) \
95 UNMERGEABLE_OP_FN(LinesOp) \
96 UNMERGEABLE_OP_FN(OvalOp) \
97 UNMERGEABLE_OP_FN(PathOp) \
98 UNMERGEABLE_OP_FN(PointsOp) \
99 UNMERGEABLE_OP_FN(RectOp) \
100 UNMERGEABLE_OP_FN(RoundRectOp) \
101 UNMERGEABLE_OP_FN(SimpleRectsOp) \
102 UNMERGEABLE_OP_FN(TextOnPathOp) \
103 UNMERGEABLE_OP_FN(TextureLayerOp) \
105 MERGEABLE_OP_FN(BitmapOp) \
106 MERGEABLE_OP_FN(PatchOp) \
107 MERGEABLE_OP_FN(TextOp)
110 * LUT generators, which will insert nullptr for unsupported ops
112 #define NULLPTR_OP_FN(Type) nullptr,
114 #define BUILD_DEFERRABLE_OP_LUT(OP_FN) \
115 { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
117 #define BUILD_MERGEABLE_OP_LUT(OP_FN) \
118 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) }
120 #define BUILD_RENDERABLE_OP_LUT(OP_FN) \
121 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
123 #define BUILD_FULL_OP_LUT(OP_FN) \
124 { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
127 * Op mapping functions, which skip unsupported ops.
129 * Note: Do not use for LUTS, since these do not preserve ID order.
131 #define NULL_OP_FN(Type)
133 #define MAP_DEFERRABLE_OPS(OP_FN) \
134 MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
136 #define MAP_MERGEABLE_OPS(OP_FN) \
137 MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
139 #define MAP_RENDERABLE_OPS(OP_FN) \
140 MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
142 // Generate OpId enum
143 #define IDENTITY_FN(Type) Type,
144 namespace RecordedOpId {
146 MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN)
150 static_assert(RecordedOpId::RenderNodeOp == 0,
151 "First index must be zero for LUTs to work");
153 #define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint
154 #define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip
155 #define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint)
156 #define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr)
159 /* ID from RecordedOpId - generally used for jumping into function tables */
162 /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */
163 const Rect unmappedBounds;
165 /* transform in recording space (vs DisplayList origin) */
166 const Matrix4 localMatrix;
168 /* clip in recording space - nullptr if not clipped */
169 const ClipBase* localClip;
171 /* optional paint, stored in base object to simplify merging logic */
172 const SkPaint* paint;
174 RecordedOp(unsigned int opId, BASE_PARAMS)
176 , unmappedBounds(unmappedBounds)
177 , localMatrix(localMatrix)
178 , localClip(localClip)
182 struct RenderNodeOp : RecordedOp {
183 RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
184 : SUPER_PAINTLESS(RenderNodeOp)
185 , renderNode(renderNode) {}
186 RenderNode * renderNode; // not const, since drawing modifies it
189 * Holds the transformation between the projection surface ViewGroup and this RenderNode
190 * drawing instance. Represents any translations / transformations done within the drawing of
191 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
192 * DisplayList draw instance.
194 * Note: doesn't include transformation within the RenderNode, or its properties.
196 Matrix4 transformFromCompositingAncestor;
197 bool skipInOrderDraw = false;
200 ////////////////////////////////////////////////////////////////////////////////////////////////////
202 ////////////////////////////////////////////////////////////////////////////////////////////////////
204 struct ArcOp : RecordedOp {
205 ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter)
207 , startAngle(startAngle)
208 , sweepAngle(sweepAngle)
209 , useCenter(useCenter) {}
210 const float startAngle;
211 const float sweepAngle;
212 const bool useCenter;
215 struct BitmapOp : RecordedOp {
216 BitmapOp(BASE_PARAMS, const SkBitmap* bitmap)
219 const SkBitmap* bitmap;
220 // TODO: asset atlas/texture id lookup?
223 struct BitmapMeshOp : RecordedOp {
224 BitmapMeshOp(BASE_PARAMS, const SkBitmap* bitmap, int meshWidth, int meshHeight,
225 const float* vertices, const int* colors)
226 : SUPER(BitmapMeshOp)
228 , meshWidth(meshWidth)
229 , meshHeight(meshHeight)
232 const SkBitmap* bitmap;
234 const int meshHeight;
235 const float* vertices;
239 struct BitmapRectOp : RecordedOp {
240 BitmapRectOp(BASE_PARAMS, const SkBitmap* bitmap, const Rect& src)
241 : SUPER(BitmapRectOp)
244 const SkBitmap* bitmap;
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, SkXfermode::Mode mode)
263 : RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr)
267 const SkXfermode::Mode 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, const SkBitmap* bitmap, const Res_png_9patch* patch)
298 const SkBitmap* bitmap;
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, Layer* layer)
420 : SUPER_PAINTLESS(TextureLayerOp)
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)
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::getXfermodeDirect(paint))
510 , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
512 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 SkXfermode::Mode 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
533 #endif // ANDROID_HWUI_RECORDED_OP_H