1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #ifndef ANDROID_HWUI_RECORDED_OP_H
18 #define ANDROID_HWUI_RECORDED_OP_H
19 
20 #include "RecordedOp.h"
21 #include "font/FontUtil.h"
22 #include "Matrix.h"
23 #include "Rect.h"
24 #include "RenderNode.h"
25 #include "TessellationCache.h"
26 #include "utils/LinearAllocator.h"
27 #include "Vector.h"
28 
29 #include <androidfw/ResourceTypes.h>
30 #include <SkXfermode.h>
31 
32 class SkBitmap;
33 class SkPaint;
34 
35 namespace android {
36 namespace uirenderer {
37 
38 struct ClipBase;
39 class OffscreenBuffer;
40 class RenderNode;
41 struct Vertex;
42 
43 namespace VectorDrawable {
44 class Tree;
45 }
46 
47 /**
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.
51  *
52  * There are 4 types of op, which defines dispatch/LUT capability:
53  *
54  *              | DisplayList |   Render    |    Merge    |
55  * -------------|-------------|-------------|-------------|
56  * PRE RENDER   |     Yes     |             |             |
57  * RENDER ONLY  |             |     Yes     |             |
58  * UNMERGEABLE  |     Yes     |     Yes     |             |
59  * MERGEABLE    |     Yes     |     Yes     |     Yes     |
60  *
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).
65  *
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.
68  *
69  * UNMERGEABLE - These ops can be recorded into DisplayLists and rendered directly, but do not
70  *      support merged rendering.
71  *
72  * MERGEABLE - These ops can be recorded into DisplayLists and rendered individually, or merged
73  *      under certain circumstances.
74  */
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) \
84         \
85         RENDER_ONLY_OP_FN(ShadowOp) \
86         RENDER_ONLY_OP_FN(LayerOp) \
87         RENDER_ONLY_OP_FN(CopyToLayerOp) \
88         RENDER_ONLY_OP_FN(CopyFromLayerOp) \
89         \
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) \
104         \
105         MERGEABLE_OP_FN(BitmapOp) \
106         MERGEABLE_OP_FN(PatchOp) \
107         MERGEABLE_OP_FN(TextOp)
108 
109 /**
110  * LUT generators, which will insert nullptr for unsupported ops
111  */
112 #define NULLPTR_OP_FN(Type) nullptr,
113 
114 #define BUILD_DEFERRABLE_OP_LUT(OP_FN) \
115         { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
116 
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) }
119 
120 #define BUILD_RENDERABLE_OP_LUT(OP_FN) \
121         { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
122 
123 #define BUILD_FULL_OP_LUT(OP_FN) \
124         { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
125 
126 /**
127  * Op mapping functions, which skip unsupported ops.
128  *
129  * Note: Do not use for LUTS, since these do not preserve ID order.
130  */
131 #define NULL_OP_FN(Type)
132 
133 #define MAP_DEFERRABLE_OPS(OP_FN) \
134         MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
135 
136 #define MAP_MERGEABLE_OPS(OP_FN) \
137         MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
138 
139 #define MAP_RENDERABLE_OPS(OP_FN) \
140         MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
141 
142 // Generate OpId enum
143 #define IDENTITY_FN(Type) Type,
144 namespace RecordedOpId {
145     enum {
146         MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN)
147         Count,
148     };
149 }
150 static_assert(RecordedOpId::RenderNodeOp == 0,
151         "First index must be zero for LUTs to work");
152 
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)
157 
158 struct RecordedOp {
159     /* ID from RecordedOpId - generally used for jumping into function tables */
160     const int opId;
161 
162     /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */
163     const Rect unmappedBounds;
164 
165     /* transform in recording space (vs DisplayList origin) */
166     const Matrix4 localMatrix;
167 
168     /* clip in recording space - nullptr if not clipped */
169     const ClipBase* localClip;
170 
171     /* optional paint, stored in base object to simplify merging logic */
172     const SkPaint* paint;
173 protected:
RecordedOpRecordedOp174     RecordedOp(unsigned int opId, BASE_PARAMS)
175             : opId(opId)
176             , unmappedBounds(unmappedBounds)
177             , localMatrix(localMatrix)
178             , localClip(localClip)
179             , paint(paint) {}
180 };
181 
182 struct RenderNodeOp : RecordedOp {
RenderNodeOpRenderNodeOp183     RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
184             : SUPER_PAINTLESS(RenderNodeOp)
185             , renderNode(renderNode) {}
186     RenderNode * renderNode; // not const, since drawing modifies it
187 
188     /**
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.
193      *
194      * Note: doesn't include transformation within the RenderNode, or its properties.
195      */
196     Matrix4 transformFromCompositingAncestor;
197     bool skipInOrderDraw = false;
198 };
199 
200 ////////////////////////////////////////////////////////////////////////////////////////////////////
201 // Standard Ops
202 ////////////////////////////////////////////////////////////////////////////////////////////////////
203 
204 struct ArcOp : RecordedOp {
ArcOpArcOp205     ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter)
206             : SUPER(ArcOp)
207             , startAngle(startAngle)
208             , sweepAngle(sweepAngle)
209             , useCenter(useCenter) {}
210     const float startAngle;
211     const float sweepAngle;
212     const bool useCenter;
213 };
214 
215 struct BitmapOp : RecordedOp {
BitmapOpBitmapOp216     BitmapOp(BASE_PARAMS, const SkBitmap* bitmap)
217             : SUPER(BitmapOp)
218             , bitmap(bitmap) {}
219     const SkBitmap* bitmap;
220     // TODO: asset atlas/texture id lookup?
221 };
222 
223 struct BitmapMeshOp : RecordedOp {
BitmapMeshOpBitmapMeshOp224     BitmapMeshOp(BASE_PARAMS, const SkBitmap* bitmap, int meshWidth, int meshHeight,
225             const float* vertices, const int* colors)
226             : SUPER(BitmapMeshOp)
227             , bitmap(bitmap)
228             , meshWidth(meshWidth)
229             , meshHeight(meshHeight)
230             , vertices(vertices)
231             , colors(colors) {}
232     const SkBitmap* bitmap;
233     const int meshWidth;
234     const int meshHeight;
235     const float* vertices;
236     const int* colors;
237 };
238 
239 struct BitmapRectOp : RecordedOp {
BitmapRectOpBitmapRectOp240     BitmapRectOp(BASE_PARAMS, const SkBitmap* bitmap, const Rect& src)
241             : SUPER(BitmapRectOp)
242             , bitmap(bitmap)
243             , src(src) {}
244     const SkBitmap* bitmap;
245     const Rect src;
246 };
247 
248 struct CirclePropsOp : RecordedOp {
CirclePropsOpCirclePropsOp249     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)
252             , x(x)
253             , y(y)
254             , radius(radius) {}
255     const float* x;
256     const float* y;
257     const float* radius;
258 };
259 
260 struct ColorOp : RecordedOp {
261     // Note: unbounded op that will fillclip, so no bounds/matrix needed
ColorOpColorOp262     ColorOp(const ClipBase* localClip, int color, SkXfermode::Mode mode)
263             : RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr)
264             , color(color)
265             , mode(mode) {}
266     const int color;
267     const SkXfermode::Mode mode;
268 };
269 
270 struct FunctorOp : RecordedOp {
271     // Note: undefined record-time bounds, since this op fills the clip
272     // TODO: explicitly define bounds
FunctorOpFunctorOp273     FunctorOp(const Matrix4& localMatrix, const ClipBase* localClip, Functor* functor)
274             : RecordedOp(RecordedOpId::FunctorOp, Rect(), localMatrix, localClip, nullptr)
275             , functor(functor) {}
276     Functor* functor;
277 };
278 
279 struct LinesOp : RecordedOp {
LinesOpLinesOp280     LinesOp(BASE_PARAMS, const float* points, const int floatCount)
281             : SUPER(LinesOp)
282             , points(points)
283             , floatCount(floatCount) {}
284     const float* points;
285     const int floatCount;
286 };
287 
288 struct OvalOp : RecordedOp {
OvalOpOvalOp289     OvalOp(BASE_PARAMS)
290             : SUPER(OvalOp) {}
291 };
292 
293 struct PatchOp : RecordedOp {
PatchOpPatchOp294     PatchOp(BASE_PARAMS, const SkBitmap* bitmap, const Res_png_9patch* patch)
295             : SUPER(PatchOp)
296             , bitmap(bitmap)
297             , patch(patch) {}
298     const SkBitmap* bitmap;
299     const Res_png_9patch* patch;
300 };
301 
302 struct PathOp : RecordedOp {
PathOpPathOp303     PathOp(BASE_PARAMS, const SkPath* path)
304             : SUPER(PathOp)
305             , path(path) {}
306     const SkPath* path;
307 };
308 
309 struct PointsOp : RecordedOp {
PointsOpPointsOp310     PointsOp(BASE_PARAMS, const float* points, const int floatCount)
311             : SUPER(PointsOp)
312             , points(points)
313             , floatCount(floatCount) {}
314     const float* points;
315     const int floatCount;
316 };
317 
318 struct RectOp : RecordedOp {
RectOpRectOp319     RectOp(BASE_PARAMS)
320             : SUPER(RectOp) {}
321 };
322 
323 struct RoundRectOp : RecordedOp {
RoundRectOpRoundRectOp324     RoundRectOp(BASE_PARAMS, float rx, float ry)
325             : SUPER(RoundRectOp)
326             , rx(rx)
327             , ry(ry) {}
328     const float rx;
329     const float ry;
330 };
331 
332 struct RoundRectPropsOp : RecordedOp {
RoundRectPropsOpRoundRectPropsOp333     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)
336             , left(left)
337             , top(top)
338             , right(right)
339             , bottom(bottom)
340             , rx(rx)
341             , ry(ry) {}
342     const float* left;
343     const float* top;
344     const float* right;
345     const float* bottom;
346     const float* rx;
347     const float* ry;
348 };
349 
350 struct VectorDrawableOp : RecordedOp {
VectorDrawableOpVectorDrawableOp351     VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS)
352             : SUPER_PAINTLESS(VectorDrawableOp)
353             , vectorDrawable(tree) {}
354     VectorDrawable::Tree* vectorDrawable;
355 };
356 
357 /**
358  * Real-time, dynamic-lit shadow.
359  *
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.
362  *
363  * State construction handles these properties specially, ignoring matrix/bounds.
364  */
365 struct ShadowOp : RecordedOp {
ShadowOpShadowOp366     ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha)
367             : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr)
368             , shadowTask(shadowTask)
369             , casterAlpha(casterAlpha) {
370     };
371     sp<TessellationCache::ShadowTask> shadowTask;
372     const float casterAlpha;
373 };
374 
375 struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
SimpleRectsOpSimpleRectsOp376     SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
377             : SUPER(SimpleRectsOp)
378             , vertices(vertices)
379             , vertexCount(vertexCount) {}
380     Vertex* vertices;
381     const size_t vertexCount;
382 };
383 
384 struct TextOp : RecordedOp {
TextOpTextOp385     TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount,
386             float x, float y)
387             : SUPER(TextOp)
388             , glyphs(glyphs)
389             , positions(positions)
390             , glyphCount(glyphCount)
391             , x(x)
392             , y(y) {}
393     const glyph_t* glyphs;
394     const float* positions;
395     const int glyphCount;
396     const float x;
397     const float y;
398 };
399 
400 struct TextOnPathOp : RecordedOp {
401     // TODO: explicitly define bounds
TextOnPathOpTextOnPathOp402     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)
405             , glyphs(glyphs)
406             , glyphCount(glyphCount)
407             , path(path)
408             , hOffset(hOffset)
409             , vOffset(vOffset) {}
410     const glyph_t* glyphs;
411     const int glyphCount;
412 
413     const SkPath* path;
414     const float hOffset;
415     const float vOffset;
416 };
417 
418 struct TextureLayerOp : RecordedOp {
TextureLayerOpTextureLayerOp419     TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer)
420             : SUPER_PAINTLESS(TextureLayerOp)
421             , layer(layer) {}
422 
423     // Copy an existing TextureLayerOp, replacing the underlying matrix
TextureLayerOpTextureLayerOp424     TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix)
425             : RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix,
426                     op.localClip, op.paint)
427             , layer(op.layer) {
428 
429     }
430     Layer* layer;
431 };
432 
433 ////////////////////////////////////////////////////////////////////////////////////////////////////
434 // Layers
435 ////////////////////////////////////////////////////////////////////////////////////////////////////
436 
437 /**
438  * Stateful operation! denotes the creation of an off-screen layer,
439  * and that commands following will render into it.
440  */
441 struct BeginLayerOp : RecordedOp {
BeginLayerOpBeginLayerOp442     BeginLayerOp(BASE_PARAMS)
443             : SUPER(BeginLayerOp) {}
444 };
445 
446 /**
447  * Stateful operation! Denotes end of off-screen layer, and that
448  * commands since last BeginLayerOp should be drawn into parent FBO.
449  *
450  * State in this op is empty, it just serves to signal that a layer has been finished.
451  */
452 struct EndLayerOp : RecordedOp {
EndLayerOpEndLayerOp453     EndLayerOp()
454             : RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
455 };
456 
457 struct BeginUnclippedLayerOp : RecordedOp {
BeginUnclippedLayerOpBeginUnclippedLayerOp458     BeginUnclippedLayerOp(BASE_PARAMS)
459             : SUPER(BeginUnclippedLayerOp) {}
460 };
461 
462 struct EndUnclippedLayerOp : RecordedOp {
EndUnclippedLayerOpEndUnclippedLayerOp463     EndUnclippedLayerOp()
464             : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
465 };
466 
467 struct CopyToLayerOp : RecordedOp {
CopyToLayerOpCopyToLayerOp468     CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
469             : RecordedOp(RecordedOpId::CopyToLayerOp,
470                     op.unmappedBounds,
471                     op.localMatrix,
472                     nullptr, // clip intentionally ignored
473                     op.paint)
474             , layerHandle(layerHandle) {}
475 
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;
479 };
480 
481 
482 // draw the parameter layer underneath
483 struct CopyFromLayerOp : RecordedOp {
CopyFromLayerOpCopyFromLayerOp484     CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
485             : RecordedOp(RecordedOpId::CopyFromLayerOp,
486                     op.unmappedBounds,
487                     op.localMatrix,
488                     nullptr, // clip intentionally ignored
489                     op.paint)
490             , layerHandle(layerHandle) {}
491 
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;
495 };
496 
497 /**
498  * Draws an OffscreenBuffer.
499  *
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.
502  */
503 struct LayerOp : RecordedOp {
504     // Records a one-use (saveLayer) layer for drawing.
LayerOpLayerOp505     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) {}
511 
LayerOpLayerOp512     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()) {}
518 
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;
522     const float alpha;
523     const SkXfermode::Mode mode;
524 
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;
528 };
529 
530 }; // namespace uirenderer
531 }; // namespace android
532 
533 #endif // ANDROID_HWUI_RECORDED_OP_H
534