RecordedOp.h revision 15c3f19a445b8df575911a16e8a6dba755a084b5
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 "SkXfermode.h" 28 29class SkBitmap; 30class SkPaint; 31 32namespace android { 33namespace uirenderer { 34 35class OffscreenBuffer; 36class RenderNode; 37struct Vertex; 38 39/** 40 * On of the provided macros is executed for each op type in order. The first will be used for ops 41 * that cannot merge, and the second for those that can. 42 * 43 * This serves as the authoritative list of ops, used for generating ID enum, and ID based LUTs. 44 */ 45#define MAP_OPS_BASED_ON_MERGEABILITY(U_OP_FN, M_OP_FN) \ 46 M_OP_FN(BitmapOp) \ 47 U_OP_FN(LinesOp) \ 48 U_OP_FN(RectOp) \ 49 U_OP_FN(RenderNodeOp) \ 50 U_OP_FN(ShadowOp) \ 51 U_OP_FN(SimpleRectsOp) \ 52 M_OP_FN(TextOp) \ 53 U_OP_FN(BeginLayerOp) \ 54 U_OP_FN(EndLayerOp) \ 55 U_OP_FN(LayerOp) 56 57/** 58 * The provided macro is executed for each op type in order. This is used in cases where 59 * merge-ability of ops doesn't matter. 60 */ 61#define MAP_OPS(OP_FN) \ 62 MAP_OPS_BASED_ON_MERGEABILITY(OP_FN, OP_FN) 63 64#define NULL_OP_FN(Type) 65 66#define MAP_MERGED_OPS(OP_FN) \ 67 MAP_OPS_BASED_ON_MERGEABILITY(NULL_OP_FN, OP_FN) 68 69// Generate OpId enum 70#define IDENTITY_FN(Type) Type, 71namespace RecordedOpId { 72 enum { 73 MAP_OPS(IDENTITY_FN) 74 Count, 75 }; 76} 77static_assert(RecordedOpId::BitmapOp == 0, 78 "First index must be zero for LUTs to work"); 79 80#define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect, const SkPaint* paint 81#define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect 82#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, paint) 83#define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, nullptr) 84 85struct RecordedOp { 86 /* ID from RecordedOpId - generally used for jumping into function tables */ 87 const int opId; 88 89 /* bounds in *local* space, without accounting for DisplayList transformation */ 90 const Rect unmappedBounds; 91 92 /* transform in recording space (vs DisplayList origin) */ 93 const Matrix4 localMatrix; 94 95 /* clip in recording space */ 96 const Rect localClipRect; 97 98 /* optional paint, stored in base object to simplify merging logic */ 99 const SkPaint* paint; 100protected: 101 RecordedOp(unsigned int opId, BASE_PARAMS) 102 : opId(opId) 103 , unmappedBounds(unmappedBounds) 104 , localMatrix(localMatrix) 105 , localClipRect(localClipRect) 106 , paint(paint) {} 107}; 108 109struct RenderNodeOp : RecordedOp { 110 RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode) 111 : SUPER_PAINTLESS(RenderNodeOp) 112 , renderNode(renderNode) {} 113 RenderNode * renderNode; // not const, since drawing modifies it 114 115 /** 116 * Holds the transformation between the projection surface ViewGroup and this RenderNode 117 * drawing instance. Represents any translations / transformations done within the drawing of 118 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this 119 * DisplayList draw instance. 120 * 121 * Note: doesn't include transformation within the RenderNode, or its properties. 122 */ 123 Matrix4 transformFromCompositingAncestor; 124 bool skipInOrderDraw = false; 125}; 126 127//////////////////////////////////////////////////////////////////////////////////////////////////// 128// Standard Ops 129//////////////////////////////////////////////////////////////////////////////////////////////////// 130 131struct BitmapOp : RecordedOp { 132 BitmapOp(BASE_PARAMS, const SkBitmap* bitmap) 133 : SUPER(BitmapOp) 134 , bitmap(bitmap) {} 135 const SkBitmap* bitmap; 136 // TODO: asset atlas/texture id lookup? 137}; 138 139struct LinesOp : RecordedOp { 140 LinesOp(BASE_PARAMS, const float* points, const int floatCount) 141 : SUPER(LinesOp) 142 , points(points) 143 , floatCount(floatCount) {} 144 const float* points; 145 const int floatCount; 146}; 147 148struct RectOp : RecordedOp { 149 RectOp(BASE_PARAMS) 150 : SUPER(RectOp) {} 151}; 152 153/** 154 * Real-time, dynamic-lit shadow. 155 * 156 * Uses invalid/empty bounds and matrix since ShadowOp bounds aren't known at defer time, 157 * and are resolved dynamically, and transform isn't needed. 158 * 159 * State construction handles these properties specially, ignoring matrix/bounds. 160 */ 161struct ShadowOp : RecordedOp { 162 ShadowOp(const RenderNodeOp& casterOp, float casterAlpha, const SkPath* casterPath, 163 const Rect& clipRect, const Vector3& lightCenter) 164 : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), clipRect, nullptr) 165 , shadowMatrixXY(casterOp.localMatrix) 166 , shadowMatrixZ(casterOp.localMatrix) 167 , casterAlpha(casterAlpha) 168 , casterPath(casterPath) 169 , lightCenter(lightCenter) { 170 const RenderNode& node = *casterOp.renderNode; 171 node.applyViewPropertyTransforms(shadowMatrixXY, false); 172 node.applyViewPropertyTransforms(shadowMatrixZ, true); 173 }; 174 Matrix4 shadowMatrixXY; 175 Matrix4 shadowMatrixZ; 176 const float casterAlpha; 177 const SkPath* casterPath; 178 const Vector3 lightCenter; 179}; 180 181struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?) 182 SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount) 183 : SUPER(SimpleRectsOp) 184 , vertices(vertices) 185 , vertexCount(vertexCount) {} 186 Vertex* vertices; 187 const size_t vertexCount; 188}; 189 190struct TextOp : RecordedOp { 191 TextOp(BASE_PARAMS, const glyph_t* glyphs, const float* positions, int glyphCount, 192 float x, float y) 193 : SUPER(TextOp) 194 , glyphs(glyphs) 195 , positions(positions) 196 , glyphCount(glyphCount) 197 , x(x) 198 , y(y) {} 199 const glyph_t* glyphs; 200 const float* positions; 201 const int glyphCount; 202 const float x; 203 const float y; 204}; 205 206//////////////////////////////////////////////////////////////////////////////////////////////////// 207// Layers 208//////////////////////////////////////////////////////////////////////////////////////////////////// 209 210 211/** 212 * Stateful operation! denotes the creation of an off-screen layer, 213 * and that commands following will render into it. 214 */ 215struct BeginLayerOp : RecordedOp { 216 BeginLayerOp(BASE_PARAMS) 217 : SUPER(BeginLayerOp) {} 218}; 219 220/** 221 * Stateful operation! Denotes end of off-screen layer, and that 222 * commands since last BeginLayerOp should be drawn into parent FBO. 223 * 224 * State in this op is empty, it just serves to signal that a layer has been finished. 225 */ 226struct EndLayerOp : RecordedOp { 227 EndLayerOp() 228 : RecordedOp(RecordedOpId::EndLayerOp, Rect(0, 0), Matrix4::identity(), Rect(0, 0), nullptr) {} 229}; 230 231/** 232 * Draws an OffscreenBuffer. 233 * 234 * Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated, 235 * when creating/tracking a SkPaint* during defer isn't worth the bother. 236 */ 237struct LayerOp : RecordedOp { 238 // Records a one-use (saveLayer) layer for drawing. Once drawn, the layer will be destroyed. 239 LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle) 240 : SUPER_PAINTLESS(LayerOp) 241 , layerHandle(layerHandle) 242 , alpha(paint->getAlpha() / 255.0f) 243 , mode(PaintUtils::getXfermodeDirect(paint)) 244 , colorFilter(paint->getColorFilter()) 245 , destroy(true) {} 246 247 LayerOp(RenderNode& node) 248 : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), Rect(node.getWidth(), node.getHeight()), nullptr) 249 , layerHandle(node.getLayerHandle()) 250 , alpha(node.properties().layerProperties().alpha() / 255.0f) 251 , mode(node.properties().layerProperties().xferMode()) 252 , colorFilter(node.properties().layerProperties().colorFilter()) 253 , destroy(false) {} 254 255 // Records a handle to the Layer object, since the Layer itself won't be 256 // constructed until after this operation is constructed. 257 OffscreenBuffer** layerHandle; 258 const float alpha; 259 const SkXfermode::Mode mode; 260 261 // pointer to object owned by either LayerProperties, or a recorded Paint object in a 262 // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used. 263 SkColorFilter* colorFilter; 264 265 // whether to destroy the layer, once rendered 266 const bool destroy; 267}; 268 269}; // namespace uirenderer 270}; // namespace android 271 272#endif // ANDROID_HWUI_RECORDED_OP_H 273