• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
18 
19 #include "font/FontUtil.h"
20 #include "GlLayer.h"
21 #include "Matrix.h"
22 #include "Rect.h"
23 #include "RenderNode.h"
24 #include "TessellationCache.h"
25 #include "utils/LinearAllocator.h"
26 #include "utils/PaintUtils.h"
27 #include "Vector.h"
28 
29 #include <androidfw/ResourceTypes.h>
30 
31 class SkBitmap;
32 class SkPaint;
33 
34 namespace android {
35 namespace uirenderer {
36 
37 struct ClipBase;
38 class OffscreenBuffer;
39 class RenderNode;
40 class DeferredLayerUpdater;
41 
42 struct Vertex;
43 
44 namespace VectorDrawable {
45 class Tree;
46 }
47 
48 /**
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.
52  *
53  * There are 4 types of op, which defines dispatch/LUT capability:
54  *
55  *              | DisplayList |   Render    |    Merge    |
56  * -------------|-------------|-------------|-------------|
57  * PRE RENDER   |     Yes     |             |             |
58  * RENDER ONLY  |             |     Yes     |             |
59  * UNMERGEABLE  |     Yes     |     Yes     |             |
60  * MERGEABLE    |     Yes     |     Yes     |     Yes     |
61  *
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).
66  *
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.
69  *
70  * UNMERGEABLE - These ops can be recorded into DisplayLists and rendered directly, but do not
71  *      support merged rendering.
72  *
73  * MERGEABLE - These ops can be recorded into DisplayLists and rendered individually, or merged
74  *      under certain circumstances.
75  */
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) \
85         \
86         RENDER_ONLY_OP_FN(ShadowOp) \
87         RENDER_ONLY_OP_FN(LayerOp) \
88         RENDER_ONLY_OP_FN(CopyToLayerOp) \
89         RENDER_ONLY_OP_FN(CopyFromLayerOp) \
90         \
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) \
105         \
106         MERGEABLE_OP_FN(BitmapOp) \
107         MERGEABLE_OP_FN(PatchOp) \
108         MERGEABLE_OP_FN(TextOp)
109 
110 /**
111  * LUT generators, which will insert nullptr for unsupported ops
112  */
113 #define NULLPTR_OP_FN(Type) nullptr,
114 
115 #define BUILD_DEFERRABLE_OP_LUT(OP_FN) \
116         { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
117 
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) }
120 
121 #define BUILD_RENDERABLE_OP_LUT(OP_FN) \
122         { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
123 
124 #define BUILD_FULL_OP_LUT(OP_FN) \
125         { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
126 
127 /**
128  * Op mapping functions, which skip unsupported ops.
129  *
130  * Note: Do not use for LUTS, since these do not preserve ID order.
131  */
132 #define NULL_OP_FN(Type)
133 
134 #define MAP_DEFERRABLE_OPS(OP_FN) \
135         MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
136 
137 #define MAP_MERGEABLE_OPS(OP_FN) \
138         MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
139 
140 #define MAP_RENDERABLE_OPS(OP_FN) \
141         MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
142 
143 // Generate OpId enum
144 #define IDENTITY_FN(Type) Type,
145 namespace RecordedOpId {
146     enum {
147         MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN)
148         Count,
149     };
150 }
151 static_assert(RecordedOpId::RenderNodeOp == 0,
152         "First index must be zero for LUTs to work");
153 
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)
158 
159 struct RecordedOp {
160     /* ID from RecordedOpId - generally used for jumping into function tables */
161     const int opId;
162 
163     /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */
164     const Rect unmappedBounds;
165 
166     /* transform in recording space (vs DisplayList origin) */
167     const Matrix4 localMatrix;
168 
169     /* clip in recording space - nullptr if not clipped */
170     const ClipBase* localClip;
171 
172     /* optional paint, stored in base object to simplify merging logic */
173     const SkPaint* paint;
174 protected:
RecordedOpRecordedOp175     RecordedOp(unsigned int opId, BASE_PARAMS)
176             : opId(opId)
177             , unmappedBounds(unmappedBounds)
178             , localMatrix(localMatrix)
179             , localClip(localClip)
180             , paint(paint) {}
181 };
182 
183 struct RenderNodeOp : RecordedOp {
RenderNodeOpRenderNodeOp184     RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
185             : SUPER_PAINTLESS(RenderNodeOp)
186             , renderNode(renderNode) {}
187     RenderNode * renderNode; // not const, since drawing modifies it
188 
189     /**
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.
194      *
195      * Note: doesn't include transformation within the RenderNode, or its properties.
196      */
197     Matrix4 transformFromCompositingAncestor;
198     bool skipInOrderDraw = false;
199 };
200 
201 ////////////////////////////////////////////////////////////////////////////////////////////////////
202 // Standard Ops
203 ////////////////////////////////////////////////////////////////////////////////////////////////////
204 
205 struct ArcOp : RecordedOp {
ArcOpArcOp206     ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter)
207             : SUPER(ArcOp)
208             , startAngle(startAngle)
209             , sweepAngle(sweepAngle)
210             , useCenter(useCenter) {}
211     const float startAngle;
212     const float sweepAngle;
213     const bool useCenter;
214 };
215 
216 struct BitmapOp : RecordedOp {
BitmapOpBitmapOp217     BitmapOp(BASE_PARAMS, Bitmap* bitmap)
218             : SUPER(BitmapOp)
219             , bitmap(bitmap) {}
220     Bitmap* bitmap;
221 };
222 
223 struct BitmapMeshOp : RecordedOp {
BitmapMeshOpBitmapMeshOp224     BitmapMeshOp(BASE_PARAMS, Bitmap* 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     Bitmap* 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, Bitmap* bitmap, const Rect& src)
241             : SUPER(BitmapRectOp)
242             , bitmap(bitmap)
243             , src(src) {}
244     Bitmap* 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, SkBlendMode mode)
263             : RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr)
264             , color(color)
265             , mode(mode) {}
266     const int color;
267     const SkBlendMode 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, Bitmap* bitmap, const Res_png_9patch* patch)
295             : SUPER(PatchOp)
296             , bitmap(bitmap)
297             , patch(patch) {}
298     Bitmap* 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, DeferredLayerUpdater* layer)
420             : SUPER_PAINTLESS(TextureLayerOp)
421             , layerHandle(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             , layerHandle(op.layerHandle) {
428 
429     }
430     DeferredLayerUpdater* layerHandle;
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::getBlendModeDirect(paint))
510             , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
511 
LayerOpLayerOp512     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()) {}
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 SkBlendMode 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