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