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