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