Snapshot.h revision f28daffda50042c1b7cbfeb34b4d47741c6e21a8
1/* 2 * Copyright (C) 2010 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_SNAPSHOT_H 18#define ANDROID_HWUI_SNAPSHOT_H 19 20#include <GLES2/gl2.h> 21#include <GLES2/gl2ext.h> 22 23#include <utils/RefBase.h> 24#include <ui/Region.h> 25 26#include <SkCanvas.h> 27 28#include "Layer.h" 29#include "Matrix.h" 30#include "Rect.h" 31 32namespace android { 33namespace uirenderer { 34 35/** 36 * A snapshot holds information about the current state of the rendering 37 * surface. A snapshot is usually created whenever the user calls save() 38 * and discarded when the user calls restore(). Once a snapshot is created, 39 * it can hold information for deferred rendering. 40 * 41 * Each snapshot has a link to a previous snapshot, indicating the previous 42 * state of the renderer. 43 */ 44class Snapshot: public LightRefBase<Snapshot> { 45public: 46 Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false), empty(false) { 47 transform = &mTransformRoot; 48 clipRect = &mClipRectRoot; 49 region = NULL; 50 } 51 52 /** 53 * Copies the specified snapshot/ The specified snapshot is stored as 54 * the previous snapshot. 55 */ 56 Snapshot(const sp<Snapshot>& s, int saveFlags): 57 flags(0), previous(s), layer(NULL), fbo(s->fbo), 58 invisible(s->invisible), empty(false), viewport(s->viewport), height(s->height) { 59 if (saveFlags & SkCanvas::kMatrix_SaveFlag) { 60 mTransformRoot.load(*s->transform); 61 transform = &mTransformRoot; 62 } else { 63 transform = s->transform; 64 } 65 66 if (saveFlags & SkCanvas::kClip_SaveFlag) { 67 mClipRectRoot.set(*s->clipRect); 68 clipRect = &mClipRectRoot; 69 } else { 70 clipRect = s->clipRect; 71 } 72 73 if ((s->flags & Snapshot::kFlagClipSet) && 74 !(s->flags & Snapshot::kFlagDirtyLocalClip)) { 75 mLocalClip.set(s->mLocalClip); 76 } else { 77 flags |= Snapshot::kFlagDirtyLocalClip; 78 } 79 80 if (s->flags & Snapshot::kFlagFboTarget) { 81 flags |= Snapshot::kFlagFboTarget; 82 region = s->region; 83 } else { 84 region = NULL; 85 } 86 } 87 88 /** 89 * Various flags set on #flags. 90 */ 91 enum Flags { 92 /** 93 * Indicates that the clip region was modified. When this 94 * snapshot is restored so must the clip. 95 */ 96 kFlagClipSet = 0x1, 97 /** 98 * Indicates that this snapshot was created when saving 99 * a new layer. 100 */ 101 kFlagIsLayer = 0x2, 102 /** 103 * Indicates that this snapshot is a special type of layer 104 * backed by an FBO. This flag only makes sense when the 105 * flag kFlagIsLayer is also set. 106 */ 107 kFlagIsFboLayer = 0x4, 108 /** 109 * Indicates that the local clip should be recomputed. 110 */ 111 kFlagDirtyLocalClip = 0x8, 112 /** 113 * Indicates that this snapshot has changed the ortho matrix. 114 */ 115 kFlagDirtyOrtho = 0x10, 116 /** 117 * Indicates that this snapshot or an ancestor snapshot is 118 * an FBO layer. 119 */ 120 kFlagFboTarget = 0x20 121 }; 122 123 /** 124 * Modifies the current clip with the new clip rectangle and 125 * the specified operation. The specified rectangle is transformed 126 * by this snapshot's trasnformation. 127 */ 128 bool clip(float left, float top, float right, float bottom, 129 SkRegion::Op op = SkRegion::kIntersect_Op) { 130 Rect r(left, top, right, bottom); 131 transform->mapRect(r); 132 return clipTransformed(r, op); 133 } 134 135 /** 136 * Modifies the current clip with the new clip rectangle and 137 * the specified operation. The specified rectangle is considered 138 * already transformed. 139 */ 140 bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) { 141 bool clipped = false; 142 143 // NOTE: The unimplemented operations require support for regions 144 // Supporting regions would require using a stencil buffer instead 145 // of the scissor. The stencil buffer itself is not too expensive 146 // (memory cost excluded) but on fillrate limited devices, managing 147 // the stencil might have a negative impact on the framerate. 148 switch (op) { 149 case SkRegion::kDifference_Op: 150 break; 151 case SkRegion::kIntersect_Op: 152 clipped = clipRect->intersect(r); 153 if (!clipped) { 154 clipRect->setEmpty(); 155 clipped = true; 156 } 157 break; 158 case SkRegion::kUnion_Op: 159 clipped = clipRect->unionWith(r); 160 break; 161 case SkRegion::kXOR_Op: 162 break; 163 case SkRegion::kReverseDifference_Op: 164 break; 165 case SkRegion::kReplace_Op: 166 clipRect->set(r); 167 clipped = true; 168 break; 169 } 170 171 if (clipped) { 172 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 173 } 174 175 return clipped; 176 } 177 178 /** 179 * Sets the current clip. 180 */ 181 void setClip(float left, float top, float right, float bottom) { 182 clipRect->set(left, top, right, bottom); 183 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 184 } 185 186 const Rect& getLocalClip() { 187 if (flags & Snapshot::kFlagDirtyLocalClip) { 188 mat4 inverse; 189 inverse.loadInverse(*transform); 190 191 mLocalClip.set(*clipRect); 192 inverse.mapRect(mLocalClip); 193 194 flags &= ~Snapshot::kFlagDirtyLocalClip; 195 } 196 return mLocalClip; 197 } 198 199 void resetTransform(float x, float y, float z) { 200 transform = &mTransformRoot; 201 transform->loadTranslate(x, y, z); 202 } 203 204 void resetClip(float left, float top, float right, float bottom) { 205 clipRect = &mClipRectRoot; 206 clipRect->set(left, top, right, bottom); 207 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 208 } 209 210 bool isIgnored() const { 211 return invisible || empty; 212 } 213 214 /** 215 * Dirty flags. 216 */ 217 int flags; 218 219 /** 220 * Previous snapshot. 221 */ 222 sp<Snapshot> previous; 223 224 /** 225 * Only set when the flag kFlagIsLayer is set. 226 */ 227 Layer* layer; 228 229 /** 230 * Only set when the flag kFlagIsFboLayer is set. 231 */ 232 GLuint fbo; 233 234 /** 235 * Indicates that this snapshot is invisible and nothing should be drawn 236 * inside it. This flag is set only when the layer clips drawing to its 237 * bounds and is passed to subsequent snapshots. 238 */ 239 bool invisible; 240 241 /** 242 * If set to true, the layer will not be composited. This is similar to 243 * invisible but this flag is not passed to subsequent snapshots. 244 */ 245 bool empty; 246 247 /** 248 * Current viewport. 249 */ 250 Rect viewport; 251 252 /** 253 * Height of the framebuffer the snapshot is rendering into. 254 */ 255 int height; 256 257 /** 258 * Contains the previous ortho matrix. 259 */ 260 mat4 orthoMatrix; 261 262 /** 263 * Local transformation. Holds the current translation, scale and 264 * rotation values. 265 */ 266 mat4* transform; 267 268 /** 269 * Current clip region. The clip is stored in canvas-space coordinates, 270 * (screen-space coordinates in the regular case.) 271 */ 272 Rect* clipRect; 273 274 /** 275 * The ancestor layer's dirty region. 276 */ 277 Region* region; 278 279private: 280 mat4 mTransformRoot; 281 Rect mClipRectRoot; 282 Rect mLocalClip; 283 284}; // class Snapshot 285 286}; // namespace uirenderer 287}; // namespace android 288 289#endif // ANDROID_HWUI_SNAPSHOT_H 290