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