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