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