RecordedOp.h revision bcda2da5fe9ab9ee1fe765e1e80a49c12c86cdca
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 32class SkBitmap; 33class SkPaint; 34 35namespace android { 36namespace uirenderer { 37 38struct ClipBase; 39class OffscreenBuffer; 40class RenderNode; 41struct Vertex; 42 43namespace VectorDrawable { 44class 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(FunctorOp) \ 94 UNMERGEABLE_OP_FN(LinesOp) \ 95 UNMERGEABLE_OP_FN(OvalOp) \ 96 UNMERGEABLE_OP_FN(PathOp) \ 97 UNMERGEABLE_OP_FN(PointsOp) \ 98 UNMERGEABLE_OP_FN(RectOp) \ 99 UNMERGEABLE_OP_FN(RoundRectOp) \ 100 UNMERGEABLE_OP_FN(SimpleRectsOp) \ 101 UNMERGEABLE_OP_FN(TextOnPathOp) \ 102 UNMERGEABLE_OP_FN(TextureLayerOp) \ 103 \ 104 MERGEABLE_OP_FN(BitmapOp) \ 105 MERGEABLE_OP_FN(PatchOp) \ 106 MERGEABLE_OP_FN(TextOp) 107 108/** 109 * LUT generators, which will insert nullptr for unsupported ops 110 */ 111#define NULLPTR_OP_FN(Type) nullptr, 112 113#define BUILD_DEFERRABLE_OP_LUT(OP_FN) \ 114 { MAP_OPS_BASED_ON_TYPE(OP_FN, NULLPTR_OP_FN, OP_FN, OP_FN) } 115 116#define BUILD_MERGEABLE_OP_LUT(OP_FN) \ 117 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, NULLPTR_OP_FN, NULLPTR_OP_FN, OP_FN) } 118 119#define BUILD_RENDERABLE_OP_LUT(OP_FN) \ 120 { MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) } 121 122/** 123 * Op mapping functions, which skip unsupported ops. 124 * 125 * Note: Do not use for LUTS, since these do not preserve ID order. 126 */ 127#define NULL_OP_FN(Type) 128 129#define MAP_DEFERRABLE_OPS(OP_FN) \ 130 MAP_OPS_BASED_ON_TYPE(OP_FN, NULL_OP_FN, OP_FN, OP_FN) 131 132#define MAP_MERGEABLE_OPS(OP_FN) \ 133 MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, NULL_OP_FN, NULL_OP_FN, OP_FN) 134 135#define MAP_RENDERABLE_OPS(OP_FN) \ 136 MAP_OPS_BASED_ON_TYPE(NULL_OP_FN, OP_FN, OP_FN, OP_FN) 137 138// Generate OpId enum 139#define IDENTITY_FN(Type) Type, 140namespace RecordedOpId { 141 enum { 142 MAP_OPS_BASED_ON_TYPE(IDENTITY_FN, IDENTITY_FN, IDENTITY_FN, IDENTITY_FN) 143 Count, 144 }; 145} 146static_assert(RecordedOpId::RenderNodeOp == 0, 147 "First index must be zero for LUTs to work"); 148 149#define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint 150#define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const ClipBase* localClip 151#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, paint) 152#define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClip, nullptr) 153 154struct RecordedOp { 155 /* ID from RecordedOpId - generally used for jumping into function tables */ 156 const int opId; 157 158 /* bounds in *local* space, without accounting for DisplayList transformation, or stroke */ 159 const Rect unmappedBounds; 160 161 /* transform in recording space (vs DisplayList origin) */ 162 const Matrix4 localMatrix; 163 164 /* clip in recording space - nullptr if not clipped */ 165 const ClipBase* localClip; 166 167 /* optional paint, stored in base object to simplify merging logic */ 168 const SkPaint* paint; 169protected: 170 RecordedOp(unsigned int opId, BASE_PARAMS) 171 : opId(opId) 172 , unmappedBounds(unmappedBounds) 173 , localMatrix(localMatrix) 174 , localClip(localClip) 175 , paint(paint) {} 176}; 177 178struct RenderNodeOp : RecordedOp { 179 RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode) 180 : SUPER_PAINTLESS(RenderNodeOp) 181 , renderNode(renderNode) {} 182 RenderNode * renderNode; // not const, since drawing modifies it 183 184 /** 185 * Holds the transformation between the projection surface ViewGroup and this RenderNode 186 * drawing instance. Represents any translations / transformations done within the drawing of 187 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this 188 * DisplayList draw instance. 189 * 190 * Note: doesn't include transformation within the RenderNode, or its properties. 191 */ 192 Matrix4 transformFromCompositingAncestor; 193 bool skipInOrderDraw = false; 194}; 195 196//////////////////////////////////////////////////////////////////////////////////////////////////// 197// Standard Ops 198//////////////////////////////////////////////////////////////////////////////////////////////////// 199 200struct ArcOp : RecordedOp { 201 ArcOp(BASE_PARAMS, float startAngle, float sweepAngle, bool useCenter) 202 : SUPER(ArcOp) 203 , startAngle(startAngle) 204 , sweepAngle(sweepAngle) 205 , useCenter(useCenter) {} 206 const float startAngle; 207 const float sweepAngle; 208 const bool useCenter; 209}; 210 211struct BitmapOp : RecordedOp { 212 BitmapOp(BASE_PARAMS, const SkBitmap* bitmap) 213 : SUPER(BitmapOp) 214 , bitmap(bitmap) {} 215 const SkBitmap* bitmap; 216 // TODO: asset atlas/texture id lookup? 217}; 218 219struct BitmapMeshOp : RecordedOp { 220 BitmapMeshOp(BASE_PARAMS, const SkBitmap* bitmap, int meshWidth, int meshHeight, 221 const float* vertices, const int* colors) 222 : SUPER(BitmapMeshOp) 223 , bitmap(bitmap) 224 , meshWidth(meshWidth) 225 , meshHeight(meshHeight) 226 , vertices(vertices) 227 , colors(colors) {} 228 const SkBitmap* bitmap; 229 const int meshWidth; 230 const int meshHeight; 231 const float* vertices; 232 const int* colors; 233}; 234 235struct BitmapRectOp : RecordedOp { 236 BitmapRectOp(BASE_PARAMS, const SkBitmap* bitmap, const Rect& src) 237 : SUPER(BitmapRectOp) 238 , bitmap(bitmap) 239 , src(src) {} 240 const SkBitmap* bitmap; 241 const Rect src; 242}; 243 244struct CirclePropsOp : RecordedOp { 245 CirclePropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, 246 float* x, float* y, float* radius) 247 : RecordedOp(RecordedOpId::CirclePropsOp, Rect(), localMatrix, localClip, paint) 248 , x(x) 249 , y(y) 250 , radius(radius) {} 251 const float* x; 252 const float* y; 253 const float* radius; 254}; 255 256struct FunctorOp : RecordedOp { 257 FunctorOp(BASE_PARAMS_PAINTLESS, Functor* functor) 258 : SUPER_PAINTLESS(FunctorOp) 259 , functor(functor) {} 260 Functor* functor; 261}; 262 263struct LinesOp : RecordedOp { 264 LinesOp(BASE_PARAMS, const float* points, const int floatCount) 265 : SUPER(LinesOp) 266 , points(points) 267 , floatCount(floatCount) {} 268 const float* points; 269 const int floatCount; 270}; 271 272struct OvalOp : RecordedOp { 273 OvalOp(BASE_PARAMS) 274 : SUPER(OvalOp) {} 275}; 276 277struct PatchOp : RecordedOp { 278 PatchOp(BASE_PARAMS, const SkBitmap* bitmap, const Res_png_9patch* patch) 279 : SUPER(PatchOp) 280 , bitmap(bitmap) 281 , patch(patch) {} 282 const SkBitmap* bitmap; 283 const Res_png_9patch* patch; 284}; 285 286struct PathOp : RecordedOp { 287 PathOp(BASE_PARAMS, const SkPath* path) 288 : SUPER(PathOp) 289 , path(path) {} 290 const SkPath* path; 291}; 292 293struct PointsOp : RecordedOp { 294 PointsOp(BASE_PARAMS, const float* points, const int floatCount) 295 : SUPER(PointsOp) 296 , points(points) 297 , floatCount(floatCount) {} 298 const float* points; 299 const int floatCount; 300}; 301 302struct RectOp : RecordedOp { 303 RectOp(BASE_PARAMS) 304 : SUPER(RectOp) {} 305}; 306 307struct RoundRectOp : RecordedOp { 308 RoundRectOp(BASE_PARAMS, float rx, float ry) 309 : SUPER(RoundRectOp) 310 , rx(rx) 311 , ry(ry) {} 312 const float rx; 313 const float ry; 314}; 315 316struct RoundRectPropsOp : RecordedOp { 317 RoundRectPropsOp(const Matrix4& localMatrix, const ClipBase* localClip, const SkPaint* paint, 318 float* left, float* top, float* right, float* bottom, float *rx, float *ry) 319 : RecordedOp(RecordedOpId::RoundRectPropsOp, Rect(), localMatrix, localClip, paint) 320 , left(left) 321 , top(top) 322 , right(right) 323 , bottom(bottom) 324 , rx(rx) 325 , ry(ry) {} 326 const float* left; 327 const float* top; 328 const float* right; 329 const float* bottom; 330 const float* rx; 331 const float* ry; 332}; 333 334struct VectorDrawableOp : RecordedOp { 335 VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS) 336 : SUPER_PAINTLESS(VectorDrawableOp) 337 , vectorDrawable(tree) {} 338 VectorDrawable::Tree* vectorDrawable; 339}; 340 341/** 342 * Real-time, dynamic-lit shadow. 343 * 344 * Uses invalid/empty bounds and matrix since ShadowOp bounds aren't known at defer time, 345 * and are resolved dynamically, and transform isn't needed. 346 * 347 * State construction handles these properties specially, ignoring matrix/bounds. 348 */ 349struct ShadowOp : RecordedOp { 350 ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha) 351 : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr) 352 , shadowTask(shadowTask) 353 , casterAlpha(casterAlpha) { 354 }; 355 sp<TessellationCache::ShadowTask> shadowTask; 356 const float casterAlpha; 357}; 358 359struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?) 360 SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount) 361 : SUPER(SimpleRectsOp) 362 , vertices(vertices) 363 , vertexCount(vertexCount) {} 364 Vertex* vertices; 365 const size_t vertexCount; 366}; 367 368struct TextOp : RecordedOp { 369 TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount, 370 float x, float y) 371 : SUPER(TextOp) 372 , glyphs(glyphs) 373 , positions(positions) 374 , glyphCount(glyphCount) 375 , x(x) 376 , y(y) {} 377 const glyph_t* glyphs; 378 const float* positions; 379 const int glyphCount; 380 const float x; 381 const float y; 382}; 383 384struct TextOnPathOp : RecordedOp { 385 TextOnPathOp(BASE_PARAMS, const glyph_t* glyphs, int glyphCount, 386 const SkPath* path, float hOffset, float vOffset) 387 : SUPER(TextOnPathOp) 388 , glyphs(glyphs) 389 , glyphCount(glyphCount) 390 , path(path) 391 , hOffset(hOffset) 392 , vOffset(vOffset) {} 393 const glyph_t* glyphs; 394 const int glyphCount; 395 396 const SkPath* path; 397 const float hOffset; 398 const float vOffset; 399}; 400 401struct TextureLayerOp : RecordedOp { 402 TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer) 403 : SUPER_PAINTLESS(TextureLayerOp) 404 , layer(layer) {} 405 Layer* layer; 406}; 407 408//////////////////////////////////////////////////////////////////////////////////////////////////// 409// Layers 410//////////////////////////////////////////////////////////////////////////////////////////////////// 411 412/** 413 * Stateful operation! denotes the creation of an off-screen layer, 414 * and that commands following will render into it. 415 */ 416struct BeginLayerOp : RecordedOp { 417 BeginLayerOp(BASE_PARAMS) 418 : SUPER(BeginLayerOp) {} 419}; 420 421/** 422 * Stateful operation! Denotes end of off-screen layer, and that 423 * commands since last BeginLayerOp should be drawn into parent FBO. 424 * 425 * State in this op is empty, it just serves to signal that a layer has been finished. 426 */ 427struct EndLayerOp : RecordedOp { 428 EndLayerOp() 429 : RecordedOp(RecordedOpId::EndLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {} 430}; 431 432struct BeginUnclippedLayerOp : RecordedOp { 433 BeginUnclippedLayerOp(BASE_PARAMS) 434 : SUPER(BeginUnclippedLayerOp) {} 435}; 436 437struct EndUnclippedLayerOp : RecordedOp { 438 EndUnclippedLayerOp() 439 : RecordedOp(RecordedOpId::EndUnclippedLayerOp, Rect(), Matrix4::identity(), nullptr, nullptr) {} 440}; 441 442struct CopyToLayerOp : RecordedOp { 443 CopyToLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle) 444 : RecordedOp(RecordedOpId::CopyToLayerOp, 445 op.unmappedBounds, 446 op.localMatrix, 447 nullptr, // clip intentionally ignored 448 op.paint) 449 , layerHandle(layerHandle) {} 450 451 // Records a handle to the Layer object, since the Layer itself won't be 452 // constructed until after this operation is constructed. 453 OffscreenBuffer** layerHandle; 454}; 455 456 457// draw the parameter layer underneath 458struct CopyFromLayerOp : RecordedOp { 459 CopyFromLayerOp(const RecordedOp& op, OffscreenBuffer** layerHandle) 460 : RecordedOp(RecordedOpId::CopyFromLayerOp, 461 op.unmappedBounds, 462 op.localMatrix, 463 nullptr, // clip intentionally ignored 464 op.paint) 465 , layerHandle(layerHandle) {} 466 467 // Records a handle to the Layer object, since the Layer itself won't be 468 // constructed until after this operation is constructed. 469 OffscreenBuffer** layerHandle; 470}; 471 472/** 473 * Draws an OffscreenBuffer. 474 * 475 * Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated, 476 * when creating/tracking a SkPaint* during defer isn't worth the bother. 477 */ 478struct LayerOp : RecordedOp { 479 // Records a one-use (saveLayer) layer for drawing. Once drawn, the layer will be destroyed. 480 LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle) 481 : SUPER_PAINTLESS(LayerOp) 482 , layerHandle(layerHandle) 483 , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f) 484 , mode(PaintUtils::getXfermodeDirect(paint)) 485 , colorFilter(paint ? paint->getColorFilter() : nullptr) 486 , destroy(true) {} 487 488 LayerOp(RenderNode& node) 489 : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr) 490 , layerHandle(node.getLayerHandle()) 491 , alpha(node.properties().layerProperties().alpha() / 255.0f) 492 , mode(node.properties().layerProperties().xferMode()) 493 , colorFilter(node.properties().layerProperties().colorFilter()) 494 , destroy(false) {} 495 496 // Records a handle to the Layer object, since the Layer itself won't be 497 // constructed until after this operation is constructed. 498 OffscreenBuffer** layerHandle; 499 const float alpha; 500 const SkXfermode::Mode mode; 501 502 // pointer to object owned by either LayerProperties, or a recorded Paint object in a 503 // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used. 504 SkColorFilter* colorFilter; 505 506 // whether to destroy the layer, once rendered 507 const bool destroy; 508}; 509 510}; // namespace uirenderer 511}; // namespace android 512 513#endif // ANDROID_HWUI_RECORDED_OP_H 514