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