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