Snapshot.h revision f607bdc167f66b3e7003acaa4736ae46d78c1492
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_UI_SNAPSHOT_H 18#define ANDROID_UI_SNAPSHOT_H 19 20#include <GLES2/gl2.h> 21#include <GLES2/gl2ext.h> 22 23#include <utils/RefBase.h> 24 25#include <SkCanvas.h> 26#include <SkRegion.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) { 47 transform = &mTransformRoot; 48 clipRect = &mClipRectRoot; 49 } 50 51 /** 52 * Copies the specified snapshot/ The specified snapshot is stored as 53 * the previous snapshot. 54 */ 55 Snapshot(const sp<Snapshot>& s, int saveFlags): 56 flags(0), previous(s), layer(NULL) { 57 if (saveFlags & SkCanvas::kMatrix_SaveFlag) { 58 mTransformRoot.load(*s->transform); 59 transform = &mTransformRoot; 60 } else { 61 transform = s->transform; 62 } 63 64 if (saveFlags & SkCanvas::kClip_SaveFlag) { 65 mClipRectRoot.set(*s->clipRect); 66 clipRect = &mClipRectRoot; 67 } else { 68 clipRect = s->clipRect; 69 } 70 71 if ((s->flags & Snapshot::kFlagClipSet) && 72 !(s->flags & Snapshot::kFlagDirtyLocalClip)) { 73 mLocalClip.set(s->mLocalClip); 74 } else { 75 flags |= Snapshot::kFlagDirtyLocalClip; 76 } 77 } 78 79 /** 80 * Various flags set on #flags. 81 */ 82 enum Flags { 83 /** 84 * Indicates that the clip region was modified. When this 85 * snapshot is restored so must the clip. 86 */ 87 kFlagClipSet = 0x1, 88 /** 89 * Indicates that this snapshot was created when saving 90 * a new layer. 91 */ 92 kFlagIsLayer = 0x2, 93 /** 94 * Indicates that the local clip should be recomputed. 95 */ 96 kFlagDirtyLocalClip = 0x4, 97 }; 98 99 /** 100 * Modifies the current clip with the new clip rectangle and 101 * the specified operation. The specified rectangle is transformed 102 * by this snapshot's trasnformation. 103 */ 104 bool clip(float left, float top, float right, float bottom, 105 SkRegion::Op op = SkRegion::kIntersect_Op) { 106 Rect r(left, top, right, bottom); 107 transform->mapRect(r); 108 return clipTransformed(r, op); 109 } 110 111 /** 112 * Modifies the current clip with the new clip rectangle and 113 * the specified operation. The specified rectangle is considered 114 * already transformed. 115 */ 116 bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) { 117 bool clipped = false; 118 119 switch (op) { 120 case SkRegion::kDifference_Op: 121 break; 122 case SkRegion::kIntersect_Op: 123 clipped = clipRect->intersect(r); 124 break; 125 case SkRegion::kUnion_Op: 126 clipped = clipRect->unionWith(r); 127 break; 128 case SkRegion::kXOR_Op: 129 break; 130 case SkRegion::kReverseDifference_Op: 131 break; 132 case SkRegion::kReplace_Op: 133 clipRect->set(r); 134 clipped = true; 135 break; 136 } 137 138 if (clipped) { 139 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 140 } 141 142 return clipped; 143 } 144 145 /** 146 * Sets the current clip. 147 */ 148 void setClip(float left, float top, float right, float bottom) { 149 clipRect->set(left, top, right, bottom); 150 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 151 } 152 153 const Rect& getLocalClip() { 154 if (flags & Snapshot::kFlagDirtyLocalClip) { 155 mat4 inverse; 156 inverse.loadInverse(*transform); 157 158 mLocalClip.set(*clipRect); 159 inverse.mapRect(mLocalClip); 160 161 flags &= ~Snapshot::kFlagDirtyLocalClip; 162 } 163 return mLocalClip; 164 } 165 166 /** 167 * Dirty flags. 168 */ 169 int flags; 170 171 /** 172 * Previous snapshot. 173 */ 174 sp<Snapshot> previous; 175 176 /** 177 * Only set when the flag kFlagIsLayer is set. 178 */ 179 Layer* layer; 180 181 /** 182 * Local transformation. Holds the current translation, scale and 183 * rotation values. 184 */ 185 mat4* transform; 186 187 /** 188 * Current clip region. The clip is stored in canvas-space coordinates, 189 * (screen-space coordinates in the regular case.) 190 */ 191 Rect* clipRect; 192 193private: 194 mat4 mTransformRoot; 195 Rect mClipRectRoot; 196 Rect mLocalClip; 197 198}; // class Snapshot 199 200}; // namespace uirenderer 201}; // namespace android 202 203#endif // ANDROID_UI_SNAPSHOT_H 204