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