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 #pragma once 18 19 #include "GlLayer.h" 20 #include "Matrix.h" 21 #include "Rect.h" 22 #include "RenderNode.h" 23 #include "TessellationCache.h" 24 #include "Vector.h" 25 #include "font/FontUtil.h" 26 #include "utils/LinearAllocator.h" 27 #include "utils/PaintUtils.h" 28 29 #include <androidfw/ResourceTypes.h> 30 31 class SkBitmap; 32 class SkPaint; 33 34 namespace android { 35 namespace uirenderer { 36 37 struct ClipBase; 38 class OffscreenBuffer; 39 class RenderNode; 40 class DeferredLayerUpdater; 41 42 struct Vertex; 43 44 namespace VectorDrawable { 45 class Tree; 46 } 47 48 /** 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. 52 * 53 * There are 4 types of op, which defines dispatch/LUT capability: 54 * 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. 75 */ 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) 110 111 /** 112 * LUT generators, which will insert nullptr for unsupported ops 113 */ 114 #define NULLPTR_OP_FN(Type) nullptr, 115 116 #define BUILD_DEFERRABLE_OP_LUT(OP_FN) \ 117 { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) } 118 119 #define BUILD_MERGEABLE_OP_LUT(OP_FN) \ 120 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) } 121 122 #define BUILD_RENDERABLE_OP_LUT(OP_FN) \ 123 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) } 124 125 #define BUILD_FULL_OP_LUT(OP_FN) \ 126 { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) } 127 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 */ 133 #define NULL_OP_FN(Type) 134 135 #define MAP_DEFERRABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN) 136 137 #define MAP_MERGEABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN) 138 139 #define MAP_RENDERABLE_OPS(OP_FN) MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN) 140 141 // Generate OpId enum 142 #define IDENTITY_FN(Type) Type, 143 namespace RecordedOpId { 144 enum { 145 MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN) Count, 146 }; 147 } 148 static_assert(RecordedOpId::RenderNodeOp == 0, "First index must be zero for LUTs to work"); 149 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 155 #define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint) 156 #define SUPER_PAINTLESS(Type) \ 157 RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr) 158 159 struct RecordedOp { 160 /* ID from RecordedOpId - generally used for jumping into function tables */ 161 const int opId; 162 163 /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */ 164 const Rect unmappedBounds; 165 166 /* transform in recording space (vs DisplayList origin) */ 167 const Matrix4 localMatrix; 168 169 /* clip in recording space - nullptr if not clipped */ 170 const ClipBase* localClip; 171 172 /* optional paint, stored in base object to simplify merging logic */ 173 const SkPaint* paint; 174 175 protected: RecordedOpRecordedOp176 RecordedOp(unsigned int opId, BASE_PARAMS) 177 : opId(opId) 178 , unmappedBounds(unmappedBounds) 179 , localMatrix(localMatrix) 180 , localClip(localClip) 181 , paint(paint) {} 182 }; 183 184 struct RenderNodeOp : RecordedOp { RenderNodeOpRenderNodeOp185 RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode) 186 : SUPER_PAINTLESS(RenderNodeOp), renderNode(renderNode) {} 187 RenderNode* renderNode; // not const, since drawing modifies it 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; 198 bool skipInOrderDraw = false; 199 }; 200 201 //////////////////////////////////////////////////////////////////////////////////////////////////// 202 // Standard Ops 203 //////////////////////////////////////////////////////////////////////////////////////////////////// 204 205 struct ArcOp : RecordedOp { ArcOpArcOp206 ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter) 207 : SUPER(ArcOp), startAngle(startAngle), sweepAngle(sweepAngle), useCenter(useCenter) {} 208 const float startAngle; 209 const float sweepAngle; 210 const bool useCenter; 211 }; 212 213 struct BitmapOp : RecordedOp { BitmapOpBitmapOp214 BitmapOp(BASE_PARAMS, Bitmap* bitmap) : SUPER(BitmapOp), bitmap(bitmap) {} 215 Bitmap* bitmap; 216 }; 217 218 struct BitmapMeshOp : RecordedOp { BitmapMeshOpBitmapMeshOp219 BitmapMeshOp(BASE_PARAMS, Bitmap* bitmap, int meshWidth, int meshHeight, const float* vertices, 220 const int* colors) 221 : SUPER(BitmapMeshOp) 222 , bitmap(bitmap) 223 , meshWidth(meshWidth) 224 , meshHeight(meshHeight) 225 , vertices(vertices) 226 , colors(colors) {} 227 Bitmap* bitmap; 228 const int meshWidth; 229 const int meshHeight; 230 const float* vertices; 231 const int* colors; 232 }; 233 234 struct BitmapRectOp : RecordedOp { BitmapRectOpBitmapRectOp235 BitmapRectOp(BASE_PARAMS, Bitmap* bitmap, const Rect& src) 236 : SUPER(BitmapRectOp), bitmap(bitmap), src(src) {} 237 Bitmap* bitmap; 238 const Rect src; 239 }; 240 241 struct CirclePropsOp : RecordedOp { CirclePropsOpCirclePropsOp242 CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, 243 float* x, float* y, float* radius) 244 : RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint) 245 , x(x) 246 , y(y) 247 , radius(radius) {} 248 const float* x; 249 const float* y; 250 const float* radius; 251 }; 252 253 struct ColorOp : RecordedOp { 254 // Note: unbounded op that will fillclip, so no bounds/matrix needed ColorOpColorOp255 ColorOp(const ClipBase* localClip, int color, SkBlendMode mode) 256 : RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr) 257 , color(color) 258 , mode(mode) {} 259 const int color; 260 const SkBlendMode mode; 261 }; 262 263 struct FunctorOp : RecordedOp { 264 // Note: undefined record-time bounds, since this op fills the clip 265 // TODO: explicitly define bounds FunctorOpFunctorOp266 FunctorOp(const Matrix4& localMatrix, const ClipBase* localClip, Functor* functor) 267 : RecordedOp(RecordedOpId::FunctorOp, Rect(), localMatrix, localClip, nullptr) 268 , functor(functor) {} 269 Functor* functor; 270 }; 271 272 struct LinesOp : RecordedOp { LinesOpLinesOp273 LinesOp(BASE_PARAMS, const float* points, const int floatCount) 274 : SUPER(LinesOp), points(points), floatCount(floatCount) {} 275 const float* points; 276 const int floatCount; 277 }; 278 279 struct OvalOp : RecordedOp { OvalOpOvalOp280 OvalOp(BASE_PARAMS) : SUPER(OvalOp) {} 281 }; 282 283 struct PatchOp : RecordedOp { PatchOpPatchOp284 PatchOp(BASE_PARAMS, Bitmap* bitmap, const Res_png_9patch* patch) 285 : SUPER(PatchOp), bitmap(bitmap), patch(patch) {} 286 Bitmap* bitmap; 287 const Res_png_9patch* patch; 288 }; 289 290 struct PathOp : RecordedOp { PathOpPathOp291 PathOp(BASE_PARAMS, const SkPath* path) : SUPER(PathOp), path(path) {} 292 const SkPath* path; 293 }; 294 295 struct PointsOp : RecordedOp { PointsOpPointsOp296 PointsOp(BASE_PARAMS, const float* points, const int floatCount) 297 : SUPER(PointsOp), points(points), floatCount(floatCount) {} 298 const float* points; 299 const int floatCount; 300 }; 301 302 struct RectOp : RecordedOp { RectOpRectOp303 RectOp(BASE_PARAMS) : SUPER(RectOp) {} 304 }; 305 306 struct RoundRectOp : RecordedOp { RoundRectOpRoundRectOp307 RoundRectOp(BASE_PARAMS, float rx, float ry) : SUPER(RoundRectOp), rx(rx), ry(ry) {} 308 const float rx; 309 const float ry; 310 }; 311 312 struct RoundRectPropsOp : RecordedOp { RoundRectPropsOpRoundRectPropsOp313 RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, 314 float* left, float* top, float* right, float* bottom, float* rx, float* ry) 315 : RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint) 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 330 struct VectorDrawableOp : RecordedOp { VectorDrawableOpVectorDrawableOp331 VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS) 332 : SUPER_PAINTLESS(VectorDrawableOp), vectorDrawable(tree) {} 333 VectorDrawable::Tree* vectorDrawable; 334 }; 335 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 * 342 * State construction handles these properties specially, ignoring matrix/bounds. 343 */ 344 struct ShadowOp : RecordedOp { ShadowOpShadowOp345 ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha) 346 : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr) 347 , shadowTask(shadowTask) 348 , casterAlpha(casterAlpha){}; 349 sp<TessellationCache::ShadowTask> shadowTask; 350 const float casterAlpha; 351 }; 352 353 struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?) SimpleRectsOpSimpleRectsOp354 SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount) 355 : SUPER(SimpleRectsOp), vertices(vertices), vertexCount(vertexCount) {} 356 Vertex* vertices; 357 const size_t vertexCount; 358 }; 359 360 struct TextOp : RecordedOp { TextOpTextOp361 TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount, float x, 362 float y) 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 376 struct TextOnPathOp : RecordedOp { 377 // TODO: explicitly define bounds TextOnPathOpTextOnPathOp378 TextOnPathOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, 379 const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset, 380 float vOffset) 381 : RecordedOp(RecordedOpId::TextOnPathOp, Rect(), localMatrix, localClip, paint) 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 395 struct TextureLayerOp : RecordedOp { TextureLayerOpTextureLayerOp396 TextureLayerOp(BASE_PARAMS_PAINTLESS, DeferredLayerUpdater* layer) 397 : SUPER_PAINTLESS(TextureLayerOp), layerHandle(layer) {} 398 399 // Copy an existing TextureLayerOp, replacing the underlying matrix TextureLayerOpTextureLayerOp400 TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix) 401 : RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix, 402 op.localClip, op.paint) 403 , layerHandle(op.layerHandle) {} 404 DeferredLayerUpdater* layerHandle; 405 }; 406 407 //////////////////////////////////////////////////////////////////////////////////////////////////// 408 // Layers 409 //////////////////////////////////////////////////////////////////////////////////////////////////// 410 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 { BeginLayerOpBeginLayerOp416 BeginLayerOp(BASE_PARAMS) : SUPER(BeginLayerOp) {} 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 { EndLayerOpEndLayerOp426 EndLayerOp() 427 : RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {} 428 }; 429 430 struct BeginUnclippedLayerOp : RecordedOp { BeginUnclippedLayerOpBeginUnclippedLayerOp431 BeginUnclippedLayerOp(BASE_PARAMS) : SUPER(BeginUnclippedLayerOp) {} 432 }; 433 434 struct EndUnclippedLayerOp : RecordedOp { EndUnclippedLayerOpEndUnclippedLayerOp435 EndUnclippedLayerOp() 436 : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr, 437 nullptr) {} 438 }; 439 440 struct CopyToLayerOp : RecordedOp { CopyToLayerOpCopyToLayerOp441 CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle) 442 : RecordedOp(RecordedOpId::CopyToLayerOp, op.unmappedBounds, op.localMatrix, 443 nullptr, // clip intentionally ignored 444 op.paint) 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 452 // draw the parameter layer underneath 453 struct CopyFromLayerOp : RecordedOp { CopyFromLayerOpCopyFromLayerOp454 CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle) 455 : RecordedOp(RecordedOpId::CopyFromLayerOp, op.unmappedBounds, op.localMatrix, 456 nullptr, // clip intentionally ignored 457 op.paint) 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 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 */ 471 struct LayerOp : RecordedOp { 472 // Records a one-use (saveLayer) layer for drawing. LayerOpLayerOp473 LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle) 474 : SUPER_PAINTLESS(LayerOp) 475 , layerHandle(layerHandle) 476 , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f) 477 , mode(PaintUtils::getBlendModeDirect(paint)) 478 , colorFilter(paint ? paint->getColorFilter() : nullptr) {} 479 LayerOpLayerOp480 explicit LayerOp(RenderNode& node) 481 : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), 482 Matrix4::identity(), nullptr, nullptr) 483 , layerHandle(node.getLayerHandle()) 484 , alpha(node.properties().layerProperties().alpha() / 255.0f) 485 , mode(node.properties().layerProperties().xferMode()) 486 , colorFilter(node.properties().layerProperties().colorFilter()) {} 487 488 // Records a handle to the Layer object, since the Layer itself won't be 489 // constructed until after this operation is constructed. 490 OffscreenBuffer** layerHandle; 491 const float alpha; 492 const SkBlendMode mode; 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; 497 }; 498 499 }; // namespace uirenderer 500 }; // namespace android 501