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