Snapshot.h revision 3b3e457c270a4bc5fe3047e815b5867d99b36f8a
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 // NOTE: The unimplemented operations require support for regions 120 // Supporting regions would require using a stencil buffer instead 121 // of the scissor. The stencil buffer itself is not too expensive 122 // (memory cost excluded) but on fillrate limited devices, managing 123 // the stencil might have a negative impact on the framerate. 124 switch (op) { 125 case SkRegion::kDifference_Op: 126 break; 127 case SkRegion::kIntersect_Op: 128 clipped = clipRect->intersect(r); 129 break; 130 case SkRegion::kUnion_Op: 131 clipped = clipRect->unionWith(r); 132 break; 133 case SkRegion::kXOR_Op: 134 break; 135 case SkRegion::kReverseDifference_Op: 136 break; 137 case SkRegion::kReplace_Op: 138 clipRect->set(r); 139 clipped = true; 140 break; 141 } 142 143 if (clipped) { 144 clipRect->snapToPixelBoundaries(); 145 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 146 } 147 148 return clipped; 149 } 150 151 /** 152 * Sets the current clip. 153 */ 154 void setClip(float left, float top, float right, float bottom) { 155 clipRect->set(left, top, right, bottom); 156 flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; 157 } 158 159 const Rect& getLocalClip() { 160 if (flags & Snapshot::kFlagDirtyLocalClip) { 161 mat4 inverse; 162 inverse.loadInverse(*transform); 163 164 mLocalClip.set(*clipRect); 165 inverse.mapRect(mLocalClip); 166 167 flags &= ~Snapshot::kFlagDirtyLocalClip; 168 } 169 return mLocalClip; 170 } 171 172 /** 173 * Dirty flags. 174 */ 175 int flags; 176 177 /** 178 * Previous snapshot. 179 */ 180 sp<Snapshot> previous; 181 182 /** 183 * Only set when the flag kFlagIsLayer is set. 184 */ 185 Layer* layer; 186 187 /** 188 * Local transformation. Holds the current translation, scale and 189 * rotation values. 190 */ 191 mat4* transform; 192 193 /** 194 * Current clip region. The clip is stored in canvas-space coordinates, 195 * (screen-space coordinates in the regular case.) 196 */ 197 Rect* clipRect; 198 199private: 200 mat4 mTransformRoot; 201 Rect mClipRectRoot; 202 Rect mLocalClip; 203 204}; // class Snapshot 205 206}; // namespace uirenderer 207}; // namespace android 208 209#endif // ANDROID_UI_SNAPSHOT_H 210