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