Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 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 | |
Doris Liu | 766431a | 2016-02-04 22:17:11 +0000 | [diff] [blame] | 20 | #include "RecordedOp.h" |
Chris Craik | a171727 | 2015-11-19 13:02:43 -0800 | [diff] [blame] | 21 | #include "font/FontUtil.h" |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 22 | #include "Matrix.h" |
Chris Craik | 98787e6 | 2015-11-13 10:55:30 -0800 | [diff] [blame] | 23 | #include "Rect.h" |
Chris Craik | 0b7e824 | 2015-10-28 16:50:44 -0700 | [diff] [blame] | 24 | #include "RenderNode.h" |
Chris Craik | 6e068c01 | 2016-01-15 16:15:30 -0800 | [diff] [blame] | 25 | #include "TessellationCache.h" |
Chris Craik | 98787e6 | 2015-11-13 10:55:30 -0800 | [diff] [blame] | 26 | #include "utils/LinearAllocator.h" |
| 27 | #include "Vector.h" |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 28 | |
Chris Craik | f09ff5a | 2015-12-08 17:21:58 -0800 | [diff] [blame] | 29 | #include <androidfw/ResourceTypes.h> |
| 30 | #include <SkXfermode.h> |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 31 | |
| 32 | class SkBitmap; |
| 33 | class SkPaint; |
| 34 | |
| 35 | namespace android { |
| 36 | namespace uirenderer { |
| 37 | |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 38 | struct ClipBase; |
Chris Craik | 5854b34 | 2015-10-26 15:49:56 -0700 | [diff] [blame] | 39 | class OffscreenBuffer; |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 40 | class RenderNode; |
| 41 | struct Vertex; |
| 42 | |
Doris Liu | 766431a | 2016-02-04 22:17:11 +0000 | [diff] [blame] | 43 | namespace VectorDrawable { |
| 44 | class Tree; |
| 45 | } |
| 46 | |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 47 | /** |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 48 | * Authoritative op list, used for generating the op ID enum, ID based LUTS, and |
| 49 | * the functions to which they dispatch. Parameter macros are executed for each op, |
| 50 | * in order, based on the op's type. |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 51 | * |
Chris Craik | b87eadd | 2016-01-06 09:16:05 -0800 | [diff] [blame] | 52 | * There are 4 types of op, which defines dispatch/LUT capability: |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 53 | * |
Chris Craik | b87eadd | 2016-01-06 09:16:05 -0800 | [diff] [blame] | 54 | * | DisplayList | Render | Merge | |
| 55 | * -------------|-------------|-------------|-------------| |
| 56 | * PRE RENDER | Yes | | | |
| 57 | * RENDER ONLY | | Yes | | |
| 58 | * UNMERGEABLE | Yes | Yes | | |
| 59 | * MERGEABLE | Yes | Yes | Yes | |
| 60 | * |
| 61 | * PRE RENDER - These ops are recorded into DisplayLists, but can't be directly rendered. This |
| 62 | * may be because they need to be transformed into other op types (e.g. CirclePropsOp), |
| 63 | * be traversed to access multiple renderable ops within (e.g. RenderNodeOp), or because they |
| 64 | * modify renderbuffer lifecycle, instead of directly rendering content (the various LayerOps). |
| 65 | * |
| 66 | * RENDER ONLY - These ops cannot be recorded into DisplayLists, and are instead implicitly |
| 67 | * constructed from other commands/RenderNode properties. They cannot be merged. |
| 68 | * |
| 69 | * UNMERGEABLE - These ops can be recorded into DisplayLists and rendered directly, but do not |
| 70 | * support merged rendering. |
| 71 | * |
| 72 | * MERGEABLE - These ops can be recorded into DisplayLists and rendered individually, or merged |
| 73 | * under certain circumstances. |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 74 | */ |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 75 | #define MAP_OPS_BASED_ON_TYPE(PRE_RENDER_OP_FN, RENDER_ONLY_OP_FN, UNMERGEABLE_OP_FN, MERGEABLE_OP_FN) \ |
| 76 | PRE_RENDER_OP_FN(RenderNodeOp) \ |
| 77 | PRE_RENDER_OP_FN(CirclePropsOp) \ |
| 78 | PRE_RENDER_OP_FN(RoundRectPropsOp) \ |
| 79 | PRE_RENDER_OP_FN(BeginLayerOp) \ |
| 80 | PRE_RENDER_OP_FN(EndLayerOp) \ |
Chris Craik | b87eadd | 2016-01-06 09:16:05 -0800 | [diff] [blame] | 81 | PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \ |
| 82 | PRE_RENDER_OP_FN(EndUnclippedLayerOp) \ |
Doris Liu | 766431a | 2016-02-04 22:17:11 +0000 | [diff] [blame] | 83 | PRE_RENDER_OP_FN(VectorDrawableOp) \ |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 84 | \ |
| 85 | RENDER_ONLY_OP_FN(ShadowOp) \ |
| 86 | RENDER_ONLY_OP_FN(LayerOp) \ |
Chris Craik | b87eadd | 2016-01-06 09:16:05 -0800 | [diff] [blame] | 87 | RENDER_ONLY_OP_FN(CopyToLayerOp) \ |
| 88 | RENDER_ONLY_OP_FN(CopyFromLayerOp) \ |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 89 | \ |
| 90 | UNMERGEABLE_OP_FN(ArcOp) \ |
| 91 | UNMERGEABLE_OP_FN(BitmapMeshOp) \ |
| 92 | UNMERGEABLE_OP_FN(BitmapRectOp) \ |
Chris Craik | a204848 | 2016-03-25 14:17:49 -0700 | [diff] [blame] | 93 | UNMERGEABLE_OP_FN(ColorOp) \ |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 94 | UNMERGEABLE_OP_FN(FunctorOp) \ |
| 95 | UNMERGEABLE_OP_FN(LinesOp) \ |
| 96 | UNMERGEABLE_OP_FN(OvalOp) \ |
| 97 | UNMERGEABLE_OP_FN(PathOp) \ |
| 98 | UNMERGEABLE_OP_FN(PointsOp) \ |
| 99 | UNMERGEABLE_OP_FN(RectOp) \ |
| 100 | UNMERGEABLE_OP_FN(RoundRectOp) \ |
| 101 | UNMERGEABLE_OP_FN(SimpleRectsOp) \ |
| 102 | UNMERGEABLE_OP_FN(TextOnPathOp) \ |
| 103 | UNMERGEABLE_OP_FN(TextureLayerOp) \ |
| 104 | \ |
| 105 | MERGEABLE_OP_FN(BitmapOp) \ |
| 106 | MERGEABLE_OP_FN(PatchOp) \ |
| 107 | MERGEABLE_OP_FN(TextOp) |
Chris Craik | 15c3f19 | 2015-12-03 12:16:56 -0800 | [diff] [blame] | 108 | |
| 109 | /** |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 110 | * LUT generators, which will insert nullptr for unsupported ops |
Chris Craik | 15c3f19 | 2015-12-03 12:16:56 -0800 | [diff] [blame] | 111 | */ |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 112 | #define NULLPTR_OP_FN(Type) nullptr, |
Chris Craik | 15c3f19 | 2015-12-03 12:16:56 -0800 | [diff] [blame] | 113 | |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 114 | #define BUILD_DEFERRABLE_OP_LUT(OP_FN) \ |
| 115 | { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) } |
| 116 | |
| 117 | #define BUILD_MERGEABLE_OP_LUT(OP_FN) \ |
| 118 | { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) } |
| 119 | |
| 120 | #define BUILD_RENDERABLE_OP_LUT(OP_FN) \ |
| 121 | { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) } |
| 122 | |
Chris Craik | 91eff22 | 2016-02-22 13:39:33 -0800 | [diff] [blame] | 123 | #define BUILD_FULL_OP_LUT(OP_FN) \ |
| 124 | { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) } |
| 125 | |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 126 | /** |
| 127 | * Op mapping functions, which skip unsupported ops. |
| 128 | * |
| 129 | * Note: Do not use for LUTS, since these do not preserve ID order. |
| 130 | */ |
Chris Craik | 15c3f19 | 2015-12-03 12:16:56 -0800 | [diff] [blame] | 131 | #define NULL_OP_FN(Type) |
| 132 | |
Chris Craik | b87eadd | 2016-01-06 09:16:05 -0800 | [diff] [blame] | 133 | #define MAP_DEFERRABLE_OPS(OP_FN) \ |
| 134 | MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN) |
| 135 | |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 136 | #define MAP_MERGEABLE_OPS(OP_FN) \ |
| 137 | MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN) |
| 138 | |
| 139 | #define MAP_RENDERABLE_OPS(OP_FN) \ |
| 140 | MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN) |
| 141 | |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 142 | // Generate OpId enum |
| 143 | #define IDENTITY_FN(Type) Type, |
| 144 | namespace RecordedOpId { |
| 145 | enum { |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 146 | MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN) |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 147 | Count, |
| 148 | }; |
| 149 | } |
Chris Craik | 7cbf63d | 2016-01-06 13:46:52 -0800 | [diff] [blame] | 150 | static_assert(RecordedOpId::RenderNodeOp == 0, |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 151 | "First index must be zero for LUTs to work"); |
| 152 | |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 153 | #define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint |
| 154 | #define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip |
| 155 | #define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint) |
| 156 | #define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr) |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 157 | |
| 158 | struct RecordedOp { |
| 159 | /* ID from RecordedOpId - generally used for jumping into function tables */ |
| 160 | const int opId; |
| 161 | |
Chris Craik | 386aa03 | 2015-12-07 17:08:25 -0800 | [diff] [blame] | 162 | /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */ |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 163 | const Rect unmappedBounds; |
| 164 | |
| 165 | /* transform in recording space (vs DisplayList origin) */ |
| 166 | const Matrix4 localMatrix; |
| 167 | |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 168 | /* clip in recording space - nullptr if not clipped */ |
| 169 | const ClipBase* localClip; |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 170 | |
| 171 | /* optional paint, stored in base object to simplify merging logic */ |
| 172 | const SkPaint* paint; |
| 173 | protected: |
| 174 | RecordedOp(unsigned int opId, BASE_PARAMS) |
| 175 | : opId(opId) |
| 176 | , unmappedBounds(unmappedBounds) |
| 177 | , localMatrix(localMatrix) |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 178 | , localClip(localClip) |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 179 | , paint(paint) {} |
| 180 | }; |
| 181 | |
| 182 | struct RenderNodeOp : RecordedOp { |
| 183 | RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode) |
| 184 | : SUPER_PAINTLESS(RenderNodeOp) |
| 185 | , renderNode(renderNode) {} |
Chris Craik | 8d1f212 | 2015-11-24 16:40:09 -0800 | [diff] [blame] | 186 | RenderNode * renderNode; // not const, since drawing modifies it |
| 187 | |
| 188 | /** |
| 189 | * Holds the transformation between the projection surface ViewGroup and this RenderNode |
| 190 | * drawing instance. Represents any translations / transformations done within the drawing of |
| 191 | * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this |
| 192 | * DisplayList draw instance. |
| 193 | * |
| 194 | * Note: doesn't include transformation within the RenderNode, or its properties. |
| 195 | */ |
| 196 | Matrix4 transformFromCompositingAncestor; |
Chris Craik | 161f54b | 2015-11-05 11:08:52 -0800 | [diff] [blame] | 197 | bool skipInOrderDraw = false; |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 198 | }; |
| 199 | |
Chris Craik | a171727 | 2015-11-19 13:02:43 -0800 | [diff] [blame] | 200 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 201 | // Standard Ops |
| 202 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 203 | |
Chris Craik | 386aa03 | 2015-12-07 17:08:25 -0800 | [diff] [blame] | 204 | struct ArcOp : RecordedOp { |
| 205 | ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter) |
| 206 | : SUPER(ArcOp) |
| 207 | , startAngle(startAngle) |
| 208 | , sweepAngle(sweepAngle) |
| 209 | , useCenter(useCenter) {} |
| 210 | const float startAngle; |
| 211 | const float sweepAngle; |
| 212 | const bool useCenter; |
| 213 | }; |
| 214 | |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 215 | struct BitmapOp : RecordedOp { |
| 216 | BitmapOp(BASE_PARAMS, const SkBitmap* bitmap) |
| 217 | : SUPER(BitmapOp) |
| 218 | , bitmap(bitmap) {} |
| 219 | const SkBitmap* bitmap; |
| 220 | // TODO: asset atlas/texture id lookup? |
| 221 | }; |
| 222 | |
Chris Craik | f09ff5a | 2015-12-08 17:21:58 -0800 | [diff] [blame] | 223 | struct BitmapMeshOp : RecordedOp { |
| 224 | BitmapMeshOp(BASE_PARAMS, const SkBitmap* bitmap, int meshWidth, int meshHeight, |
| 225 | const float* vertices, const int* colors) |
| 226 | : SUPER(BitmapMeshOp) |
| 227 | , bitmap(bitmap) |
| 228 | , meshWidth(meshWidth) |
| 229 | , meshHeight(meshHeight) |
| 230 | , vertices(vertices) |
| 231 | , colors(colors) {} |
| 232 | const SkBitmap* bitmap; |
| 233 | const int meshWidth; |
| 234 | const int meshHeight; |
| 235 | const float* vertices; |
| 236 | const int* colors; |
| 237 | }; |
| 238 | |
| 239 | struct BitmapRectOp : RecordedOp { |
| 240 | BitmapRectOp(BASE_PARAMS, const SkBitmap* bitmap, const Rect& src) |
| 241 | : SUPER(BitmapRectOp) |
| 242 | , bitmap(bitmap) |
| 243 | , src(src) {} |
| 244 | const SkBitmap* bitmap; |
| 245 | const Rect src; |
| 246 | }; |
| 247 | |
Chris Craik | 268a9c0 | 2015-12-09 18:05:12 -0800 | [diff] [blame] | 248 | struct CirclePropsOp : RecordedOp { |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 249 | CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, |
Chris Craik | 268a9c0 | 2015-12-09 18:05:12 -0800 | [diff] [blame] | 250 | float* x, float* y, float* radius) |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 251 | : RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint) |
Chris Craik | 268a9c0 | 2015-12-09 18:05:12 -0800 | [diff] [blame] | 252 | , x(x) |
| 253 | , y(y) |
| 254 | , radius(radius) {} |
| 255 | const float* x; |
| 256 | const float* y; |
| 257 | const float* radius; |
| 258 | }; |
| 259 | |
Chris Craik | a204848 | 2016-03-25 14:17:49 -0700 | [diff] [blame] | 260 | struct ColorOp : RecordedOp { |
| 261 | // Note: unbounded op that will fillclip, so no bounds/matrix needed |
| 262 | ColorOp(const ClipBase* localClip, int color, SkXfermode::Mode mode) |
| 263 | : RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr) |
| 264 | , color(color) |
| 265 | , mode(mode) {} |
| 266 | const int color; |
| 267 | const SkXfermode::Mode mode; |
| 268 | }; |
| 269 | |
Chris Craik | e29ce6f | 2015-12-10 16:25:13 -0800 | [diff] [blame] | 270 | struct FunctorOp : RecordedOp { |
Chris Craik | 4c3980b | 2016-03-15 14:20:18 -0700 | [diff] [blame] | 271 | // Note: undefined record-time bounds, since this op fills the clip |
| 272 | // TODO: explicitly define bounds |
| 273 | FunctorOp(const Matrix4& localMatrix, const ClipBase* localClip, Functor* functor) |
| 274 | : RecordedOp(RecordedOpId::FunctorOp, Rect(), localMatrix, localClip, nullptr) |
Chris Craik | e29ce6f | 2015-12-10 16:25:13 -0800 | [diff] [blame] | 275 | , functor(functor) {} |
| 276 | Functor* functor; |
| 277 | }; |
| 278 | |
Chris Craik | a171727 | 2015-11-19 13:02:43 -0800 | [diff] [blame] | 279 | struct LinesOp : RecordedOp { |
| 280 | LinesOp(BASE_PARAMS, const float* points, const int floatCount) |
| 281 | : SUPER(LinesOp) |
| 282 | , points(points) |
| 283 | , floatCount(floatCount) {} |
| 284 | const float* points; |
| 285 | const int floatCount; |
| 286 | }; |
| 287 | |
Chris Craik | 386aa03 | 2015-12-07 17:08:25 -0800 | [diff] [blame] | 288 | struct OvalOp : RecordedOp { |
| 289 | OvalOp(BASE_PARAMS) |
| 290 | : SUPER(OvalOp) {} |
| 291 | }; |
| 292 | |
Chris Craik | f09ff5a | 2015-12-08 17:21:58 -0800 | [diff] [blame] | 293 | struct PatchOp : RecordedOp { |
| 294 | PatchOp(BASE_PARAMS, const SkBitmap* bitmap, const Res_png_9patch* patch) |
| 295 | : SUPER(PatchOp) |
| 296 | , bitmap(bitmap) |
| 297 | , patch(patch) {} |
| 298 | const SkBitmap* bitmap; |
| 299 | const Res_png_9patch* patch; |
| 300 | }; |
| 301 | |
Chris Craik | 386aa03 | 2015-12-07 17:08:25 -0800 | [diff] [blame] | 302 | struct PathOp : RecordedOp { |
| 303 | PathOp(BASE_PARAMS, const SkPath* path) |
| 304 | : SUPER(PathOp) |
| 305 | , path(path) {} |
| 306 | const SkPath* path; |
| 307 | }; |
| 308 | |
| 309 | struct PointsOp : RecordedOp { |
| 310 | PointsOp(BASE_PARAMS, const float* points, const int floatCount) |
| 311 | : SUPER(PointsOp) |
| 312 | , points(points) |
| 313 | , floatCount(floatCount) {} |
| 314 | const float* points; |
| 315 | const int floatCount; |
| 316 | }; |
| 317 | |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 318 | struct RectOp : RecordedOp { |
| 319 | RectOp(BASE_PARAMS) |
| 320 | : SUPER(RectOp) {} |
| 321 | }; |
| 322 | |
Chris Craik | 386aa03 | 2015-12-07 17:08:25 -0800 | [diff] [blame] | 323 | struct RoundRectOp : RecordedOp { |
| 324 | RoundRectOp(BASE_PARAMS, float rx, float ry) |
| 325 | : SUPER(RoundRectOp) |
| 326 | , rx(rx) |
| 327 | , ry(ry) {} |
| 328 | const float rx; |
| 329 | const float ry; |
| 330 | }; |
| 331 | |
Chris Craik | 268a9c0 | 2015-12-09 18:05:12 -0800 | [diff] [blame] | 332 | struct RoundRectPropsOp : RecordedOp { |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 333 | RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, |
Chris Craik | 268a9c0 | 2015-12-09 18:05:12 -0800 | [diff] [blame] | 334 | float* left, float* top, float* right, float* bottom, float *rx, float *ry) |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 335 | : RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint) |
Chris Craik | 268a9c0 | 2015-12-09 18:05:12 -0800 | [diff] [blame] | 336 | , left(left) |
| 337 | , top(top) |
| 338 | , right(right) |
| 339 | , bottom(bottom) |
| 340 | , rx(rx) |
| 341 | , ry(ry) {} |
| 342 | const float* left; |
| 343 | const float* top; |
| 344 | const float* right; |
| 345 | const float* bottom; |
| 346 | const float* rx; |
| 347 | const float* ry; |
| 348 | }; |
| 349 | |
Doris Liu | 766431a | 2016-02-04 22:17:11 +0000 | [diff] [blame] | 350 | struct VectorDrawableOp : RecordedOp { |
| 351 | VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS) |
| 352 | : SUPER_PAINTLESS(VectorDrawableOp) |
| 353 | , vectorDrawable(tree) {} |
| 354 | VectorDrawable::Tree* vectorDrawable; |
| 355 | }; |
| 356 | |
Chris Craik | d3daa31 | 2015-11-06 10:59:56 -0800 | [diff] [blame] | 357 | /** |
| 358 | * Real-time, dynamic-lit shadow. |
| 359 | * |
| 360 | * Uses invalid/empty bounds and matrix since ShadowOp bounds aren't known at defer time, |
| 361 | * and are resolved dynamically, and transform isn't needed. |
| 362 | * |
Chris Craik | 98787e6 | 2015-11-13 10:55:30 -0800 | [diff] [blame] | 363 | * State construction handles these properties specially, ignoring matrix/bounds. |
Chris Craik | d3daa31 | 2015-11-06 10:59:56 -0800 | [diff] [blame] | 364 | */ |
| 365 | struct ShadowOp : RecordedOp { |
Chris Craik | 6e068c01 | 2016-01-15 16:15:30 -0800 | [diff] [blame] | 366 | ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha) |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 367 | : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr) |
Chris Craik | 6e068c01 | 2016-01-15 16:15:30 -0800 | [diff] [blame] | 368 | , shadowTask(shadowTask) |
| 369 | , casterAlpha(casterAlpha) { |
Chris Craik | d3daa31 | 2015-11-06 10:59:56 -0800 | [diff] [blame] | 370 | }; |
Chris Craik | 6e068c01 | 2016-01-15 16:15:30 -0800 | [diff] [blame] | 371 | sp<TessellationCache::ShadowTask> shadowTask; |
Chris Craik | d3daa31 | 2015-11-06 10:59:56 -0800 | [diff] [blame] | 372 | const float casterAlpha; |
Chris Craik | d3daa31 | 2015-11-06 10:59:56 -0800 | [diff] [blame] | 373 | }; |
| 374 | |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 375 | struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?) |
| 376 | SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount) |
| 377 | : SUPER(SimpleRectsOp) |
| 378 | , vertices(vertices) |
| 379 | , vertexCount(vertexCount) {} |
| 380 | Vertex* vertices; |
| 381 | const size_t vertexCount; |
| 382 | }; |
| 383 | |
Chris Craik | a171727 | 2015-11-19 13:02:43 -0800 | [diff] [blame] | 384 | struct TextOp : RecordedOp { |
| 385 | TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount, |
| 386 | float x, float y) |
| 387 | : SUPER(TextOp) |
| 388 | , glyphs(glyphs) |
| 389 | , positions(positions) |
| 390 | , glyphCount(glyphCount) |
| 391 | , x(x) |
| 392 | , y(y) {} |
| 393 | const glyph_t* glyphs; |
| 394 | const float* positions; |
| 395 | const int glyphCount; |
| 396 | const float x; |
| 397 | const float y; |
| 398 | }; |
| 399 | |
Chris Craik | d7448e6 | 2015-12-15 10:34:36 -0800 | [diff] [blame] | 400 | struct TextOnPathOp : RecordedOp { |
Chris Craik | 4c3980b | 2016-03-15 14:20:18 -0700 | [diff] [blame] | 401 | // TODO: explicitly define bounds |
| 402 | TextOnPathOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, |
| 403 | const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset, float vOffset) |
| 404 | : RecordedOp(RecordedOpId::TextOnPathOp, Rect(), localMatrix, localClip, paint) |
Chris Craik | d7448e6 | 2015-12-15 10:34:36 -0800 | [diff] [blame] | 405 | , glyphs(glyphs) |
| 406 | , glyphCount(glyphCount) |
| 407 | , path(path) |
| 408 | , hOffset(hOffset) |
| 409 | , vOffset(vOffset) {} |
| 410 | const glyph_t* glyphs; |
| 411 | const int glyphCount; |
| 412 | |
| 413 | const SkPath* path; |
| 414 | const float hOffset; |
| 415 | const float vOffset; |
| 416 | }; |
| 417 | |
Chris Craik | d2dfd8f | 2015-12-16 14:27:20 -0800 | [diff] [blame] | 418 | struct TextureLayerOp : RecordedOp { |
| 419 | TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer) |
| 420 | : SUPER_PAINTLESS(TextureLayerOp) |
| 421 | , layer(layer) {} |
Chris Craik | aafb01d | 2016-03-25 18:34:11 -0700 | [diff] [blame] | 422 | |
| 423 | // Copy an existing TextureLayerOp, replacing the underlying matrix |
| 424 | TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix) |
| 425 | : RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix, |
| 426 | op.localClip, op.paint) |
| 427 | , layer(op.layer) { |
| 428 | |
| 429 | } |
Chris Craik | d2dfd8f | 2015-12-16 14:27:20 -0800 | [diff] [blame] | 430 | Layer* layer; |
| 431 | }; |
| 432 | |
Chris Craik | a171727 | 2015-11-19 13:02:43 -0800 | [diff] [blame] | 433 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 434 | // Layers |
| 435 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 436 | |
Chris Craik | 6fe991e5 | 2015-10-20 09:39:42 -0700 | [diff] [blame] | 437 | /** |
| 438 | * Stateful operation! denotes the creation of an off-screen layer, |
| 439 | * and that commands following will render into it. |
| 440 | */ |
| 441 | struct BeginLayerOp : RecordedOp { |
| 442 | BeginLayerOp(BASE_PARAMS) |
| 443 | : SUPER(BeginLayerOp) {} |
| 444 | }; |
| 445 | |
| 446 | /** |
| 447 | * Stateful operation! Denotes end of off-screen layer, and that |
| 448 | * commands since last BeginLayerOp should be drawn into parent FBO. |
| 449 | * |
| 450 | * State in this op is empty, it just serves to signal that a layer has been finished. |
| 451 | */ |
| 452 | struct EndLayerOp : RecordedOp { |
| 453 | EndLayerOp() |
Chris Craik | e4db79d | 2015-12-22 16:32:23 -0800 | [diff] [blame] | 454 | : RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {} |
Chris Craik | 6fe991e5 | 2015-10-20 09:39:42 -0700 | [diff] [blame] | 455 | }; |
| 456 | |
Chris Craik | b87eadd | 2016-01-06 09:16:05 -0800 | [diff] [blame] | 457 | struct BeginUnclippedLayerOp : RecordedOp { |
| 458 | BeginUnclippedLayerOp(BASE_PARAMS) |
| 459 | : SUPER(BeginUnclippedLayerOp) {} |
| 460 | }; |
| 461 | |
| 462 | struct EndUnclippedLayerOp : RecordedOp { |
| 463 | EndUnclippedLayerOp() |
| 464 | : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {} |
| 465 | }; |
| 466 | |
| 467 | struct CopyToLayerOp : RecordedOp { |
| 468 | CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle) |
| 469 | : RecordedOp(RecordedOpId::CopyToLayerOp, |
| 470 | op.unmappedBounds, |
| 471 | op.localMatrix, |
| 472 | nullptr, // clip intentionally ignored |
| 473 | op.paint) |
| 474 | , layerHandle(layerHandle) {} |
| 475 | |
| 476 | // Records a handle to the Layer object, since the Layer itself won't be |
| 477 | // constructed until after this operation is constructed. |
| 478 | OffscreenBuffer** layerHandle; |
| 479 | }; |
| 480 | |
| 481 | |
| 482 | // draw the parameter layer underneath |
| 483 | struct CopyFromLayerOp : RecordedOp { |
| 484 | CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle) |
| 485 | : RecordedOp(RecordedOpId::CopyFromLayerOp, |
| 486 | op.unmappedBounds, |
| 487 | op.localMatrix, |
| 488 | nullptr, // clip intentionally ignored |
| 489 | op.paint) |
| 490 | , layerHandle(layerHandle) {} |
| 491 | |
| 492 | // Records a handle to the Layer object, since the Layer itself won't be |
| 493 | // constructed until after this operation is constructed. |
| 494 | OffscreenBuffer** layerHandle; |
| 495 | }; |
| 496 | |
Chris Craik | 0b7e824 | 2015-10-28 16:50:44 -0700 | [diff] [blame] | 497 | /** |
| 498 | * Draws an OffscreenBuffer. |
| 499 | * |
| 500 | * Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated, |
| 501 | * when creating/tracking a SkPaint* during defer isn't worth the bother. |
| 502 | */ |
Chris Craik | 6fe991e5 | 2015-10-20 09:39:42 -0700 | [diff] [blame] | 503 | struct LayerOp : RecordedOp { |
Chris Craik | 74af6e2 | 2016-04-05 13:18:56 -0700 | [diff] [blame] | 504 | // Records a one-use (saveLayer) layer for drawing. |
Chris Craik | 5854b34 | 2015-10-26 15:49:56 -0700 | [diff] [blame] | 505 | LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle) |
Chris Craik | 0b7e824 | 2015-10-28 16:50:44 -0700 | [diff] [blame] | 506 | : SUPER_PAINTLESS(LayerOp) |
| 507 | , layerHandle(layerHandle) |
Chris Craik | e5b5019 | 2016-01-04 15:09:19 -0800 | [diff] [blame] | 508 | , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f) |
Chris Craik | 0b7e824 | 2015-10-28 16:50:44 -0700 | [diff] [blame] | 509 | , mode(PaintUtils::getXfermodeDirect(paint)) |
Chris Craik | 74af6e2 | 2016-04-05 13:18:56 -0700 | [diff] [blame] | 510 | , colorFilter(paint ? paint->getColorFilter() : nullptr) {} |
Chris Craik | 0b7e824 | 2015-10-28 16:50:44 -0700 | [diff] [blame] | 511 | |
Chih-Hung Hsieh | a619ec7 | 2016-08-29 14:52:43 -0700 | [diff] [blame] | 512 | explicit LayerOp(RenderNode& node) |
Chris Craik | b87eadd | 2016-01-06 09:16:05 -0800 | [diff] [blame] | 513 | : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr) |
| 514 | , layerHandle(node.getLayerHandle()) |
| 515 | , alpha(node.properties().layerProperties().alpha() / 255.0f) |
| 516 | , mode(node.properties().layerProperties().xferMode()) |
Chris Craik | 74af6e2 | 2016-04-05 13:18:56 -0700 | [diff] [blame] | 517 | , colorFilter(node.properties().layerProperties().colorFilter()) {} |
Chris Craik | 0b7e824 | 2015-10-28 16:50:44 -0700 | [diff] [blame] | 518 | |
Chris Craik | 818c9fb | 2015-10-23 14:33:42 -0700 | [diff] [blame] | 519 | // Records a handle to the Layer object, since the Layer itself won't be |
| 520 | // constructed until after this operation is constructed. |
Chris Craik | 5854b34 | 2015-10-26 15:49:56 -0700 | [diff] [blame] | 521 | OffscreenBuffer** layerHandle; |
Chris Craik | 0b7e824 | 2015-10-28 16:50:44 -0700 | [diff] [blame] | 522 | const float alpha; |
| 523 | const SkXfermode::Mode mode; |
| 524 | |
| 525 | // pointer to object owned by either LayerProperties, or a recorded Paint object in a |
| 526 | // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used. |
| 527 | SkColorFilter* colorFilter; |
Chris Craik | 6fe991e5 | 2015-10-20 09:39:42 -0700 | [diff] [blame] | 528 | }; |
| 529 | |
Chris Craik | b565df1 | 2015-10-05 13:00:52 -0700 | [diff] [blame] | 530 | }; // namespace uirenderer |
| 531 | }; // namespace android |
| 532 | |
| 533 | #endif // ANDROID_HWUI_RECORDED_OP_H |