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