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