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