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