RecordedOp.h revision 15c3f19a445b8df575911a16e8a6dba755a084b5
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 "SkXfermode.h"
28
29class SkBitmap;
30class SkPaint;
31
32namespace android {
33namespace uirenderer {
34
35class OffscreenBuffer;
36class RenderNode;
37struct Vertex;
38
39/**
40 * On of the provided macros is executed for each op type in order. The first will be used for ops
41 * that cannot merge, and the second for those that can.
42 *
43 * This serves as the authoritative list of ops, used for generating ID enum, and ID based LUTs.
44 */
45#define MAP_OPS_BASED_ON_MERGEABILITY(U_OP_FN, M_OP_FN) \
46        M_OP_FN(BitmapOp) \
47        U_OP_FN(LinesOp) \
48        U_OP_FN(RectOp) \
49        U_OP_FN(RenderNodeOp) \
50        U_OP_FN(ShadowOp) \
51        U_OP_FN(SimpleRectsOp) \
52        M_OP_FN(TextOp) \
53        U_OP_FN(BeginLayerOp) \
54        U_OP_FN(EndLayerOp) \
55        U_OP_FN(LayerOp)
56
57/**
58 * The provided macro is executed for each op type in order. This is used in cases where
59 * merge-ability of ops doesn't matter.
60 */
61#define MAP_OPS(OP_FN) \
62        MAP_OPS_BASED_ON_MERGEABILITY(OP_FN, OP_FN)
63
64#define NULL_OP_FN(Type)
65
66#define MAP_MERGED_OPS(OP_FN) \
67        MAP_OPS_BASED_ON_MERGEABILITY(NULL_OP_FN, OP_FN)
68
69// Generate OpId enum
70#define IDENTITY_FN(Type) Type,
71namespace RecordedOpId {
72    enum {
73        MAP_OPS(IDENTITY_FN)
74        Count,
75    };
76}
77static_assert(RecordedOpId::BitmapOp == 0,
78        "First index must be zero for LUTs to work");
79
80#define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect, const SkPaint* paint
81#define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect
82#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, paint)
83#define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, nullptr)
84
85struct RecordedOp {
86    /* ID from RecordedOpId - generally used for jumping into function tables */
87    const int opId;
88
89    /* bounds in *local* space, without accounting for DisplayList transformation */
90    const Rect unmappedBounds;
91
92    /* transform in recording space (vs DisplayList origin) */
93    const Matrix4 localMatrix;
94
95    /* clip in recording space */
96    const Rect localClipRect;
97
98    /* optional paint, stored in base object to simplify merging logic */
99    const SkPaint* paint;
100protected:
101    RecordedOp(unsigned int opId, BASE_PARAMS)
102            : opId(opId)
103            , unmappedBounds(unmappedBounds)
104            , localMatrix(localMatrix)
105            , localClipRect(localClipRect)
106            , paint(paint) {}
107};
108
109struct RenderNodeOp : RecordedOp {
110    RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
111            : SUPER_PAINTLESS(RenderNodeOp)
112            , renderNode(renderNode) {}
113    RenderNode * renderNode; // not const, since drawing modifies it
114
115    /**
116     * Holds the transformation between the projection surface ViewGroup and this RenderNode
117     * drawing instance. Represents any translations / transformations done within the drawing of
118     * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
119     * DisplayList draw instance.
120     *
121     * Note: doesn't include transformation within the RenderNode, or its properties.
122     */
123    Matrix4 transformFromCompositingAncestor;
124    bool skipInOrderDraw = false;
125};
126
127////////////////////////////////////////////////////////////////////////////////////////////////////
128// Standard Ops
129////////////////////////////////////////////////////////////////////////////////////////////////////
130
131struct BitmapOp : RecordedOp {
132    BitmapOp(BASE_PARAMS, const SkBitmap* bitmap)
133            : SUPER(BitmapOp)
134            , bitmap(bitmap) {}
135    const SkBitmap* bitmap;
136    // TODO: asset atlas/texture id lookup?
137};
138
139struct LinesOp : RecordedOp {
140    LinesOp(BASE_PARAMS, const float* points, const int floatCount)
141            : SUPER(LinesOp)
142            , points(points)
143            , floatCount(floatCount) {}
144    const float* points;
145    const int floatCount;
146};
147
148struct RectOp : RecordedOp {
149    RectOp(BASE_PARAMS)
150            : SUPER(RectOp) {}
151};
152
153/**
154 * Real-time, dynamic-lit shadow.
155 *
156 * Uses invalid/empty bounds and matrix since ShadowOp bounds aren't known at defer time,
157 * and are resolved dynamically, and transform isn't needed.
158 *
159 * State construction handles these properties specially, ignoring matrix/bounds.
160 */
161struct ShadowOp : RecordedOp {
162    ShadowOp(const RenderNodeOp& casterOp, float casterAlpha, const SkPath* casterPath,
163            const Rect& clipRect, const Vector3& lightCenter)
164            : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), clipRect, nullptr)
165            , shadowMatrixXY(casterOp.localMatrix)
166            , shadowMatrixZ(casterOp.localMatrix)
167            , casterAlpha(casterAlpha)
168            , casterPath(casterPath)
169            , lightCenter(lightCenter) {
170        const RenderNode& node = *casterOp.renderNode;
171        node.applyViewPropertyTransforms(shadowMatrixXY, false);
172        node.applyViewPropertyTransforms(shadowMatrixZ, true);
173    };
174    Matrix4 shadowMatrixXY;
175    Matrix4 shadowMatrixZ;
176    const float casterAlpha;
177    const SkPath* casterPath;
178    const Vector3 lightCenter;
179};
180
181struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
182    SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
183            : SUPER(SimpleRectsOp)
184            , vertices(vertices)
185            , vertexCount(vertexCount) {}
186    Vertex* vertices;
187    const size_t vertexCount;
188};
189
190struct TextOp : RecordedOp {
191    TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount,
192            float x, float y)
193            : SUPER(TextOp)
194            , glyphs(glyphs)
195            , positions(positions)
196            , glyphCount(glyphCount)
197            , x(x)
198            , y(y) {}
199    const glyph_t* glyphs;
200    const float* positions;
201    const int glyphCount;
202    const float x;
203    const float y;
204};
205
206////////////////////////////////////////////////////////////////////////////////////////////////////
207// Layers
208////////////////////////////////////////////////////////////////////////////////////////////////////
209
210
211/**
212 * Stateful operation! denotes the creation of an off-screen layer,
213 * and that commands following will render into it.
214 */
215struct BeginLayerOp : RecordedOp {
216    BeginLayerOp(BASE_PARAMS)
217            : SUPER(BeginLayerOp) {}
218};
219
220/**
221 * Stateful operation! Denotes end of off-screen layer, and that
222 * commands since last BeginLayerOp should be drawn into parent FBO.
223 *
224 * State in this op is empty, it just serves to signal that a layer has been finished.
225 */
226struct EndLayerOp : RecordedOp {
227    EndLayerOp()
228            : RecordedOp(RecordedOpId::EndLayerOp, Rect(0, 0), Matrix4::identity(), Rect(0, 0), nullptr) {}
229};
230
231/**
232 * Draws an OffscreenBuffer.
233 *
234 * Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated,
235 * when creating/tracking a SkPaint* during defer isn't worth the bother.
236 */
237struct LayerOp : RecordedOp {
238    // Records a one-use (saveLayer) layer for drawing. Once drawn, the layer will be destroyed.
239    LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
240            : SUPER_PAINTLESS(LayerOp)
241            , layerHandle(layerHandle)
242            , alpha(paint->getAlpha() / 255.0f)
243            , mode(PaintUtils::getXfermodeDirect(paint))
244            , colorFilter(paint->getColorFilter())
245            , destroy(true) {}
246
247    LayerOp(RenderNode& node)
248        : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), Rect(node.getWidth(), node.getHeight()), nullptr)
249        , layerHandle(node.getLayerHandle())
250        , alpha(node.properties().layerProperties().alpha() / 255.0f)
251        , mode(node.properties().layerProperties().xferMode())
252        , colorFilter(node.properties().layerProperties().colorFilter())
253        , destroy(false) {}
254
255    // Records a handle to the Layer object, since the Layer itself won't be
256    // constructed until after this operation is constructed.
257    OffscreenBuffer** layerHandle;
258    const float alpha;
259    const SkXfermode::Mode mode;
260
261    // pointer to object owned by either LayerProperties, or a recorded Paint object in a
262    // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
263    SkColorFilter* colorFilter;
264
265    // whether to destroy the layer, once rendered
266    const bool destroy;
267};
268
269}; // namespace uirenderer
270}; // namespace android
271
272#endif // ANDROID_HWUI_RECORDED_OP_H
273