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