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