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 "RecordedOp.h" 21 #include "font/FontUtil.h" 22 #include "Matrix.h" 23 #include "Rect.h" 24 #include "RenderNode.h" 25 #include "TessellationCache.h" 26 #include "utils/LinearAllocator.h" 27 #include "Vector.h" 28 29 #include <androidfw/ResourceTypes.h> 30 #include <SkXfermode.h> 31 32 class SkBitmap; 33 class SkPaint; 34 35 namespace android { 36 namespace uirenderer { 37 38 struct ClipBase; 39 class OffscreenBuffer; 40 class RenderNode; 41 struct Vertex; 42 43 namespace VectorDrawable { 44 class Tree; 45 } 46 47 /** 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. 51 * 52 * There are 4 types of op, which defines dispatch/LUT capability: 53 * 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. 74 */ 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) \ 81 PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \ 82 PRE_RENDER_OP_FN(EndUnclippedLayerOp) \ 83 PRE_RENDER_OP_FN(VectorDrawableOp) \ 84 \ 85 RENDER_ONLY_OP_FN(ShadowOp) \ 86 RENDER_ONLY_OP_FN(LayerOp) \ 87 RENDER_ONLY_OP_FN(CopyToLayerOp) \ 88 RENDER_ONLY_OP_FN(CopyFromLayerOp) \ 89 \ 90 UNMERGEABLE_OP_FN(ArcOp) \ 91 UNMERGEABLE_OP_FN(BitmapMeshOp) \ 92 UNMERGEABLE_OP_FN(BitmapRectOp) \ 93 UNMERGEABLE_OP_FN(ColorOp) \ 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) 108 109 /** 110 * LUT generators, which will insert nullptr for unsupported ops 111 */ 112 #define NULLPTR_OP_FN(Type) nullptr, 113 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 123 #define BUILD_FULL_OP_LUT(OP_FN) \ 124 { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) } 125 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 */ 131 #define NULL_OP_FN(Type) 132 133 #define MAP_DEFERRABLE_OPS(OP_FN) \ 134 MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN) 135 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 142 // Generate OpId enum 143 #define IDENTITY_FN(Type) Type, 144 namespace RecordedOpId { 145 enum { 146 MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN) 147 Count, 148 }; 149 } 150 static_assert(RecordedOpId::RenderNodeOp == 0, 151 "First index must be zero for LUTs to work"); 152 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) 157 158 struct RecordedOp { 159 /* ID from RecordedOpId - generally used for jumping into function tables */ 160 const int opId; 161 162 /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */ 163 const Rect unmappedBounds; 164 165 /* transform in recording space (vs DisplayList origin) */ 166 const Matrix4 localMatrix; 167 168 /* clip in recording space - nullptr if not clipped */ 169 const ClipBase* localClip; 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) 178 , localClip(localClip) 179 , paint(paint) {} 180 }; 181 182 struct RenderNodeOp : RecordedOp { 183 RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode) 184 : SUPER_PAINTLESS(RenderNodeOp) 185 , renderNode(renderNode) {} 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; 197 bool skipInOrderDraw = false; 198 }; 199 200 //////////////////////////////////////////////////////////////////////////////////////////////////// 201 // Standard Ops 202 //////////////////////////////////////////////////////////////////////////////////////////////////// 203 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 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 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 248 struct CirclePropsOp : RecordedOp { 249 CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, 250 float* x, float* y, float* radius) 251 : RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint) 252 , x(x) 253 , y(y) 254 , radius(radius) {} 255 const float* x; 256 const float* y; 257 const float* radius; 258 }; 259 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 270 struct FunctorOp : RecordedOp { 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) 275 , functor(functor) {} 276 Functor* functor; 277 }; 278 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 288 struct OvalOp : RecordedOp { 289 OvalOp(BASE_PARAMS) 290 : SUPER(OvalOp) {} 291 }; 292 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 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 318 struct RectOp : RecordedOp { 319 RectOp(BASE_PARAMS) 320 : SUPER(RectOp) {} 321 }; 322 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 332 struct RoundRectPropsOp : RecordedOp { 333 RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, 334 float* left, float* top, float* right, float* bottom, float *rx, float *ry) 335 : RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint) 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 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 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 * 363 * State construction handles these properties specially, ignoring matrix/bounds. 364 */ 365 struct ShadowOp : RecordedOp { 366 ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha) 367 : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr) 368 , shadowTask(shadowTask) 369 , casterAlpha(casterAlpha) { 370 }; 371 sp<TessellationCache::ShadowTask> shadowTask; 372 const float casterAlpha; 373 }; 374 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 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 400 struct TextOnPathOp : RecordedOp { 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) 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 418 struct TextureLayerOp : RecordedOp { 419 TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer) 420 : SUPER_PAINTLESS(TextureLayerOp) 421 , layer(layer) {} 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 } 430 Layer* layer; 431 }; 432 433 //////////////////////////////////////////////////////////////////////////////////////////////////// 434 // Layers 435 //////////////////////////////////////////////////////////////////////////////////////////////////// 436 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() 454 : RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {} 455 }; 456 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 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 */ 503 struct LayerOp : RecordedOp { 504 // Records a one-use (saveLayer) layer for drawing. 505 LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle) 506 : SUPER_PAINTLESS(LayerOp) 507 , layerHandle(layerHandle) 508 , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f) 509 , mode(PaintUtils::getXfermodeDirect(paint)) 510 , colorFilter(paint ? paint->getColorFilter() : nullptr) {} 511 512 LayerOp(RenderNode& node) 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()) 517 , colorFilter(node.properties().layerProperties().colorFilter()) {} 518 519 // Records a handle to the Layer object, since the Layer itself won't be 520 // constructed until after this operation is constructed. 521 OffscreenBuffer** layerHandle; 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; 528 }; 529 530 }; // namespace uirenderer 531 }; // namespace android 532 533 #endif // ANDROID_HWUI_RECORDED_OP_H 534