Snapshot.h revision af636ebf5feb2837683fbfe965040cb706b32ec1
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 break; 154 case SkRegion::kUnion_Op: 155 clipped = clipRect->unionWith(r); 156 break; 157 case SkRegion::kXOR_Op: 158 break; 159 case SkRegion::kReverseDifference_Op: 160 break; 161 case SkRegion::kReplace_Op: 162 clipRect->set(r); 163 clipped = true; 164 break; 165 } 166 167 if (clipped) { 168 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 169 } 170 171 return clipped; 172 } 173 174 /** 175 * Sets the current clip. 176 */ 177 void setClip(float left, float top, float right, float bottom) { 178 clipRect->set(left, top, right, bottom); 179 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 180 } 181 182 const Rect& getLocalClip() { 183 if (flags & Snapshot::kFlagDirtyLocalClip) { 184 mat4 inverse; 185 inverse.loadInverse(*transform); 186 187 mLocalClip.set(*clipRect); 188 inverse.mapRect(mLocalClip); 189 190 flags &= ~Snapshot::kFlagDirtyLocalClip; 191 } 192 return mLocalClip; 193 } 194 195 void resetTransform(float x, float y, float z) { 196 transform = &mTransformRoot; 197 transform->loadTranslate(x, y, z); 198 } 199 200 void resetClip(float left, float top, float right, float bottom) { 201 clipRect = &mClipRectRoot; 202 clipRect->set(left, top, right, bottom); 203 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 204 } 205 206 bool isIgnored() const { 207 return invisible || empty; 208 } 209 210 /** 211 * Dirty flags. 212 */ 213 int flags; 214 215 /** 216 * Previous snapshot. 217 */ 218 sp<Snapshot> previous; 219 220 /** 221 * Only set when the flag kFlagIsLayer is set. 222 */ 223 Layer* layer; 224 225 /** 226 * Only set when the flag kFlagIsFboLayer is set. 227 */ 228 GLuint fbo; 229 230 /** 231 * Indicates that this snapshot is invisible and nothing should be drawn 232 * inside it. This flag is set only when the layer clips drawing to its 233 * bounds and is passed to subsequent snapshots. 234 */ 235 bool invisible; 236 237 /** 238 * If set to true, the layer will not be composited. This is similar to 239 * invisible but this flag is not passed to subsequent snapshots. 240 */ 241 bool empty; 242 243 /** 244 * Current viewport. 245 */ 246 Rect viewport; 247 248 /** 249 * Height of the framebuffer the snapshot is rendering into. 250 */ 251 int height; 252 253 /** 254 * Contains the previous ortho matrix. 255 */ 256 mat4 orthoMatrix; 257 258 /** 259 * Local transformation. Holds the current translation, scale and 260 * rotation values. 261 */ 262 mat4* transform; 263 264 /** 265 * Current clip region. The clip is stored in canvas-space coordinates, 266 * (screen-space coordinates in the regular case.) 267 */ 268 Rect* clipRect; 269 270 /** 271 * The ancestor layer's dirty region.. 272 */ 273 Region* region; 274 275private: 276 mat4 mTransformRoot; 277 Rect mClipRectRoot; 278 Rect mLocalClip; 279 280}; // class Snapshot 281 282}; // namespace uirenderer 283}; // namespace android 284 285#endif // ANDROID_HWUI_SNAPSHOT_H 286