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 32 namespace android { 33 namespace 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 */ 44 class Snapshot: public LightRefBase<Snapshot> { 45 public: 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::kFlagFboTarget) { 74 flags |= Snapshot::kFlagFboTarget; 75 region = s->region; 76 } else { 77 region = NULL; 78 } 79 } 80 81 /** 82 * Various flags set on #flags. 83 */ 84 enum Flags { 85 /** 86 * Indicates that the clip region was modified. When this 87 * snapshot is restored so must the clip. 88 */ 89 kFlagClipSet = 0x1, 90 /** 91 * Indicates that this snapshot was created when saving 92 * a new layer. 93 */ 94 kFlagIsLayer = 0x2, 95 /** 96 * Indicates that this snapshot is a special type of layer 97 * backed by an FBO. This flag only makes sense when the 98 * flag kFlagIsLayer is also set. 99 */ 100 kFlagIsFboLayer = 0x4, 101 /** 102 * Indicates that this snapshot has changed the ortho matrix. 103 */ 104 kFlagDirtyOrtho = 0x8, 105 /** 106 * Indicates that this snapshot or an ancestor snapshot is 107 * an FBO layer. 108 */ 109 kFlagFboTarget = 0x10 110 }; 111 112 /** 113 * Modifies the current clip with the new clip rectangle and 114 * the specified operation. The specified rectangle is transformed 115 * by this snapshot's trasnformation. 116 */ 117 bool clip(float left, float top, float right, float bottom, 118 SkRegion::Op op = SkRegion::kIntersect_Op) { 119 Rect r(left, top, right, bottom); 120 transform->mapRect(r); 121 return clipTransformed(r, op); 122 } 123 124 /** 125 * Modifies the current clip with the new clip rectangle and 126 * the specified operation. The specified rectangle is considered 127 * already transformed. 128 */ 129 bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) { 130 bool clipped = false; 131 132 // NOTE: The unimplemented operations require support for regions 133 // Supporting regions would require using a stencil buffer instead 134 // of the scissor. The stencil buffer itself is not too expensive 135 // (memory cost excluded) but on fillrate limited devices, managing 136 // the stencil might have a negative impact on the framerate. 137 switch (op) { 138 case SkRegion::kDifference_Op: 139 break; 140 case SkRegion::kIntersect_Op: 141 clipped = clipRect->intersect(r); 142 if (!clipped) { 143 clipRect->setEmpty(); 144 clipped = true; 145 } 146 break; 147 case SkRegion::kUnion_Op: 148 clipped = clipRect->unionWith(r); 149 break; 150 case SkRegion::kXOR_Op: 151 break; 152 case SkRegion::kReverseDifference_Op: 153 break; 154 case SkRegion::kReplace_Op: 155 clipRect->set(r); 156 clipped = true; 157 break; 158 } 159 160 if (clipped) { 161 flags |= Snapshot::kFlagClipSet; 162 } 163 164 return clipped; 165 } 166 167 /** 168 * Sets the current clip. 169 */ 170 void setClip(float left, float top, float right, float bottom) { 171 clipRect->set(left, top, right, bottom); 172 flags |= Snapshot::kFlagClipSet; 173 } 174 175 const Rect& getLocalClip() { 176 mat4 inverse; 177 inverse.loadInverse(*transform); 178 179 mLocalClip.set(*clipRect); 180 inverse.mapRect(mLocalClip); 181 182 return mLocalClip; 183 } 184 185 void resetTransform(float x, float y, float z) { 186 transform = &mTransformRoot; 187 transform->loadTranslate(x, y, z); 188 } 189 190 void resetClip(float left, float top, float right, float bottom) { 191 clipRect = &mClipRectRoot; 192 clipRect->set(left, top, right, bottom); 193 flags |= Snapshot::kFlagClipSet; 194 } 195 196 bool isIgnored() const { 197 return invisible || empty; 198 } 199 200 /** 201 * Dirty flags. 202 */ 203 int flags; 204 205 /** 206 * Previous snapshot. 207 */ 208 sp<Snapshot> previous; 209 210 /** 211 * Only set when the flag kFlagIsLayer is set. 212 */ 213 Layer* layer; 214 215 /** 216 * Only set when the flag kFlagIsFboLayer is set. 217 */ 218 GLuint fbo; 219 220 /** 221 * Indicates that this snapshot is invisible and nothing should be drawn 222 * inside it. This flag is set only when the layer clips drawing to its 223 * bounds and is passed to subsequent snapshots. 224 */ 225 bool invisible; 226 227 /** 228 * If set to true, the layer will not be composited. This is similar to 229 * invisible but this flag is not passed to subsequent snapshots. 230 */ 231 bool empty; 232 233 /** 234 * Current viewport. 235 */ 236 Rect viewport; 237 238 /** 239 * Height of the framebuffer the snapshot is rendering into. 240 */ 241 int height; 242 243 /** 244 * Contains the previous ortho matrix. 245 */ 246 mat4 orthoMatrix; 247 248 /** 249 * Local transformation. Holds the current translation, scale and 250 * rotation values. 251 */ 252 mat4* transform; 253 254 /** 255 * Current clip region. The clip is stored in canvas-space coordinates, 256 * (screen-space coordinates in the regular case.) 257 */ 258 Rect* clipRect; 259 260 /** 261 * The ancestor layer's dirty region. 262 */ 263 Region* region; 264 265 private: 266 mat4 mTransformRoot; 267 Rect mClipRectRoot; 268 Rect mLocalClip; 269 270 }; // class Snapshot 271 272 }; // namespace uirenderer 273 }; // namespace android 274 275 #endif // ANDROID_HWUI_SNAPSHOT_H 276