RecordedOp.h revision 766431aa57c16ece8842287a92b2e7208e3b8ac3
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
32class SkBitmap;
33class SkPaint;
34
35namespace android {
36namespace uirenderer {
37
38struct ClipBase;
39class OffscreenBuffer;
40class RenderNode;
41struct Vertex;
42
43namespace VectorDrawable {
44class 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(FunctorOp) \
94        UNMERGEABLE_OP_FN(LinesOp) \
95        UNMERGEABLE_OP_FN(OvalOp) \
96        UNMERGEABLE_OP_FN(PathOp) \
97        UNMERGEABLE_OP_FN(PointsOp) \
98        UNMERGEABLE_OP_FN(RectOp) \
99        UNMERGEABLE_OP_FN(RoundRectOp) \
100        UNMERGEABLE_OP_FN(SimpleRectsOp) \
101        UNMERGEABLE_OP_FN(TextOnPathOp) \
102        UNMERGEABLE_OP_FN(TextureLayerOp) \
103        \
104        MERGEABLE_OP_FN(BitmapOp) \
105        MERGEABLE_OP_FN(PatchOp) \
106        MERGEABLE_OP_FN(TextOp)
107
108/**
109 * LUT generators, which will insert nullptr for unsupported ops
110 */
111#define NULLPTR_OP_FN(Type) nullptr,
112
113#define BUILD_DEFERRABLE_OP_LUT(OP_FN) \
114        { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) }
115
116#define BUILD_MERGEABLE_OP_LUT(OP_FN) \
117        { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) }
118
119#define BUILD_RENDERABLE_OP_LUT(OP_FN) \
120        { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
121
122/**
123 * Op mapping functions, which skip unsupported ops.
124 *
125 * Note: Do not use for LUTS, since these do not preserve ID order.
126 */
127#define NULL_OP_FN(Type)
128
129#define MAP_DEFERRABLE_OPS(OP_FN) \
130        MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN)
131
132#define MAP_MERGEABLE_OPS(OP_FN) \
133        MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN)
134
135#define MAP_RENDERABLE_OPS(OP_FN) \
136        MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN)
137
138// Generate OpId enum
139#define IDENTITY_FN(Type) Type,
140namespace RecordedOpId {
141    enum {
142        MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN)
143        Count,
144    };
145}
146static_assert(RecordedOpId::RenderNodeOp == 0,
147        "First index must be zero for LUTs to work");
148
149#define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint
150#define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip
151#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint)
152#define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr)
153
154struct RecordedOp {
155    /* ID from RecordedOpId - generally used for jumping into function tables */
156    const int opId;
157
158    /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */
159    const Rect unmappedBounds;
160
161    /* transform in recording space (vs DisplayList origin) */
162    const Matrix4 localMatrix;
163
164    /* clip in recording space - nullptr if not clipped */
165    const ClipBase* localClip;
166
167    /* optional paint, stored in base object to simplify merging logic */
168    const SkPaint* paint;
169protected:
170    RecordedOp(unsigned int opId, BASE_PARAMS)
171            : opId(opId)
172            , unmappedBounds(unmappedBounds)
173            , localMatrix(localMatrix)
174            , localClip(localClip)
175            , paint(paint) {}
176};
177
178struct RenderNodeOp : RecordedOp {
179    RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
180            : SUPER_PAINTLESS(RenderNodeOp)
181            , renderNode(renderNode) {}
182    RenderNode * renderNode; // not const, since drawing modifies it
183
184    /**
185     * Holds the transformation between the projection surface ViewGroup and this RenderNode
186     * drawing instance. Represents any translations / transformations done within the drawing of
187     * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
188     * DisplayList draw instance.
189     *
190     * Note: doesn't include transformation within the RenderNode, or its properties.
191     */
192    Matrix4 transformFromCompositingAncestor;
193    bool skipInOrderDraw = false;
194};
195
196////////////////////////////////////////////////////////////////////////////////////////////////////
197// Standard Ops
198////////////////////////////////////////////////////////////////////////////////////////////////////
199
200struct ArcOp : RecordedOp {
201    ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter)
202            : SUPER(ArcOp)
203            , startAngle(startAngle)
204            , sweepAngle(sweepAngle)
205            , useCenter(useCenter) {}
206    const float startAngle;
207    const float sweepAngle;
208    const bool useCenter;
209};
210
211struct BitmapOp : RecordedOp {
212    BitmapOp(BASE_PARAMS, const SkBitmap* bitmap)
213            : SUPER(BitmapOp)
214            , bitmap(bitmap) {}
215    const SkBitmap* bitmap;
216    // TODO: asset atlas/texture id lookup?
217};
218
219struct BitmapMeshOp : RecordedOp {
220    BitmapMeshOp(BASE_PARAMS, const SkBitmap* bitmap, int meshWidth, int meshHeight,
221            const float* vertices, const int* colors)
222            : SUPER(BitmapMeshOp)
223            , bitmap(bitmap)
224            , meshWidth(meshWidth)
225            , meshHeight(meshHeight)
226            , vertices(vertices)
227            , colors(colors) {}
228    const SkBitmap* bitmap;
229    const int meshWidth;
230    const int meshHeight;
231    const float* vertices;
232    const int* colors;
233};
234
235struct BitmapRectOp : RecordedOp {
236    BitmapRectOp(BASE_PARAMS, const SkBitmap* bitmap, const Rect& src)
237            : SUPER(BitmapRectOp)
238            , bitmap(bitmap)
239            , src(src) {}
240    const SkBitmap* bitmap;
241    const Rect src;
242};
243
244struct CirclePropsOp : RecordedOp {
245    CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
246            float* x, float* y, float* radius)
247            : RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint)
248            , x(x)
249            , y(y)
250            , radius(radius) {}
251    const float* x;
252    const float* y;
253    const float* radius;
254};
255
256struct FunctorOp : RecordedOp {
257    FunctorOp(BASE_PARAMS_PAINTLESS, Functor* functor)
258            : SUPER_PAINTLESS(FunctorOp)
259            , functor(functor) {}
260    Functor* functor;
261};
262
263struct LinesOp : RecordedOp {
264    LinesOp(BASE_PARAMS, const float* points, const int floatCount)
265            : SUPER(LinesOp)
266            , points(points)
267            , floatCount(floatCount) {}
268    const float* points;
269    const int floatCount;
270};
271
272struct OvalOp : RecordedOp {
273    OvalOp(BASE_PARAMS)
274            : SUPER(OvalOp) {}
275};
276
277struct PatchOp : RecordedOp {
278    PatchOp(BASE_PARAMS, const SkBitmap* bitmap, const Res_png_9patch* patch)
279            : SUPER(PatchOp)
280            , bitmap(bitmap)
281            , patch(patch) {}
282    const SkBitmap* bitmap;
283    const Res_png_9patch* patch;
284};
285
286struct PathOp : RecordedOp {
287    PathOp(BASE_PARAMS, const SkPath* path)
288            : SUPER(PathOp)
289            , path(path) {}
290    const SkPath* path;
291};
292
293struct PointsOp : RecordedOp {
294    PointsOp(BASE_PARAMS, const float* points, const int floatCount)
295            : SUPER(PointsOp)
296            , points(points)
297            , floatCount(floatCount) {}
298    const float* points;
299    const int floatCount;
300};
301
302struct RectOp : RecordedOp {
303    RectOp(BASE_PARAMS)
304            : SUPER(RectOp) {}
305};
306
307struct RoundRectOp : RecordedOp {
308    RoundRectOp(BASE_PARAMS, float rx, float ry)
309            : SUPER(RoundRectOp)
310            , rx(rx)
311            , ry(ry) {}
312    const float rx;
313    const float ry;
314};
315
316struct RoundRectPropsOp : RecordedOp {
317    RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint,
318            float* left, float* top, float* right, float* bottom, float *rx, float *ry)
319            : RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint)
320            , left(left)
321            , top(top)
322            , right(right)
323            , bottom(bottom)
324            , rx(rx)
325            , ry(ry) {}
326    const float* left;
327    const float* top;
328    const float* right;
329    const float* bottom;
330    const float* rx;
331    const float* ry;
332};
333
334struct VectorDrawableOp : RecordedOp {
335    VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS)
336            : SUPER_PAINTLESS(VectorDrawableOp)
337            , vectorDrawable(tree) {}
338    VectorDrawable::Tree* vectorDrawable;
339};
340
341/**
342 * Real-time, dynamic-lit shadow.
343 *
344 * Uses invalid/empty bounds and matrix since ShadowOp bounds aren't known at defer time,
345 * and are resolved dynamically, and transform isn't needed.
346 *
347 * State construction handles these properties specially, ignoring matrix/bounds.
348 */
349struct ShadowOp : RecordedOp {
350    ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha)
351            : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr)
352            , shadowTask(shadowTask)
353            , casterAlpha(casterAlpha) {
354    };
355    sp<TessellationCache::ShadowTask> shadowTask;
356    const float casterAlpha;
357};
358
359struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
360    SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
361            : SUPER(SimpleRectsOp)
362            , vertices(vertices)
363            , vertexCount(vertexCount) {}
364    Vertex* vertices;
365    const size_t vertexCount;
366};
367
368struct TextOp : RecordedOp {
369    TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount,
370            float x, float y)
371            : SUPER(TextOp)
372            , glyphs(glyphs)
373            , positions(positions)
374            , glyphCount(glyphCount)
375            , x(x)
376            , y(y) {}
377    const glyph_t* glyphs;
378    const float* positions;
379    const int glyphCount;
380    const float x;
381    const float y;
382};
383
384struct TextOnPathOp : RecordedOp {
385    TextOnPathOp(BASE_PARAMS, const glyph_t* glyphs, int glyphCount,
386            const SkPath* path, float hOffset, float vOffset)
387            : SUPER(TextOnPathOp)
388            , glyphs(glyphs)
389            , glyphCount(glyphCount)
390            , path(path)
391            , hOffset(hOffset)
392            , vOffset(vOffset) {}
393    const glyph_t* glyphs;
394    const int glyphCount;
395
396    const SkPath* path;
397    const float hOffset;
398    const float vOffset;
399};
400
401struct TextureLayerOp : RecordedOp {
402    TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer)
403            : SUPER_PAINTLESS(TextureLayerOp)
404            , layer(layer) {}
405    Layer* layer;
406};
407
408////////////////////////////////////////////////////////////////////////////////////////////////////
409// Layers
410////////////////////////////////////////////////////////////////////////////////////////////////////
411
412/**
413 * Stateful operation! denotes the creation of an off-screen layer,
414 * and that commands following will render into it.
415 */
416struct BeginLayerOp : RecordedOp {
417    BeginLayerOp(BASE_PARAMS)
418            : SUPER(BeginLayerOp) {}
419};
420
421/**
422 * Stateful operation! Denotes end of off-screen layer, and that
423 * commands since last BeginLayerOp should be drawn into parent FBO.
424 *
425 * State in this op is empty, it just serves to signal that a layer has been finished.
426 */
427struct EndLayerOp : RecordedOp {
428    EndLayerOp()
429            : RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
430};
431
432struct BeginUnclippedLayerOp : RecordedOp {
433    BeginUnclippedLayerOp(BASE_PARAMS)
434            : SUPER(BeginUnclippedLayerOp) {}
435};
436
437struct EndUnclippedLayerOp : RecordedOp {
438    EndUnclippedLayerOp()
439            : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {}
440};
441
442struct CopyToLayerOp : RecordedOp {
443    CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
444            : RecordedOp(RecordedOpId::CopyToLayerOp,
445                    op.unmappedBounds,
446                    op.localMatrix,
447                    nullptr, // clip intentionally ignored
448                    op.paint)
449            , layerHandle(layerHandle) {}
450
451    // Records a handle to the Layer object, since the Layer itself won't be
452    // constructed until after this operation is constructed.
453    OffscreenBuffer** layerHandle;
454};
455
456
457// draw the parameter layer underneath
458struct CopyFromLayerOp : RecordedOp {
459    CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle)
460            : RecordedOp(RecordedOpId::CopyFromLayerOp,
461                    op.unmappedBounds,
462                    op.localMatrix,
463                    nullptr, // clip intentionally ignored
464                    op.paint)
465            , layerHandle(layerHandle) {}
466
467    // Records a handle to the Layer object, since the Layer itself won't be
468    // constructed until after this operation is constructed.
469    OffscreenBuffer** layerHandle;
470};
471
472/**
473 * Draws an OffscreenBuffer.
474 *
475 * Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated,
476 * when creating/tracking a SkPaint* during defer isn't worth the bother.
477 */
478struct LayerOp : RecordedOp {
479    // Records a one-use (saveLayer) layer for drawing. Once drawn, the layer will be destroyed.
480    LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
481            : SUPER_PAINTLESS(LayerOp)
482            , layerHandle(layerHandle)
483            , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f)
484            , mode(PaintUtils::getXfermodeDirect(paint))
485            , colorFilter(paint ? paint->getColorFilter() : nullptr)
486            , destroy(true) {}
487
488    LayerOp(RenderNode& node)
489            : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr)
490            , layerHandle(node.getLayerHandle())
491            , alpha(node.properties().layerProperties().alpha() / 255.0f)
492            , mode(node.properties().layerProperties().xferMode())
493            , colorFilter(node.properties().layerProperties().colorFilter())
494            , destroy(false) {}
495
496    // Records a handle to the Layer object, since the Layer itself won't be
497    // constructed until after this operation is constructed.
498    OffscreenBuffer** layerHandle;
499    const float alpha;
500    const SkXfermode::Mode mode;
501
502    // pointer to object owned by either LayerProperties, or a recorded Paint object in a
503    // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
504    SkColorFilter* colorFilter;
505
506    // whether to destroy the layer, once rendered
507    const bool destroy;
508};
509
510}; // namespace uirenderer
511}; // namespace android
512
513#endif // ANDROID_HWUI_RECORDED_OP_H
514