Snapshot.cpp revision e4aa95e3627226bcb0d8cc3e42dca6e4df8f421c
1/* 2 * Copyright (C) 2012 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#define LOG_TAG "OpenGLRenderer" 18 19#include "Snapshot.h" 20 21#include <SkCanvas.h> 22 23namespace android { 24namespace uirenderer { 25 26/////////////////////////////////////////////////////////////////////////////// 27// Constructors 28/////////////////////////////////////////////////////////////////////////////// 29 30Snapshot::Snapshot() 31 : flags(0) 32 , previous(NULL) 33 , layer(NULL) 34 , fbo(0) 35 , invisible(false) 36 , empty(false) 37 , height(0) 38 , alpha(1.0f) { 39 transform = &mTransformRoot; 40 clipRect = &mClipRectRoot; 41 region = NULL; 42 clipRegion = &mClipRegionRoot; 43} 44 45/** 46 * Copies the specified snapshot/ The specified snapshot is stored as 47 * the previous snapshot. 48 */ 49Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags) 50 : flags(0) 51 , previous(s) 52 , layer(s->layer) 53 , fbo(s->fbo) 54 , invisible(s->invisible) 55 , empty(false) 56 , viewport(s->viewport) 57 , height(s->height) 58 , alpha(s->alpha) { 59 60 if (saveFlags & SkCanvas::kMatrix_SaveFlag) { 61 mTransformRoot.load(*s->transform); 62 transform = &mTransformRoot; 63 } else { 64 transform = s->transform; 65 } 66 67 if (saveFlags & SkCanvas::kClip_SaveFlag) { 68 mClipRectRoot.set(*s->clipRect); 69 clipRect = &mClipRectRoot; 70 if (!s->clipRegion->isEmpty()) { 71 mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op); 72 } 73 clipRegion = &mClipRegionRoot; 74 } else { 75 clipRect = s->clipRect; 76 clipRegion = s->clipRegion; 77 } 78 79 if (s->flags & Snapshot::kFlagFboTarget) { 80 flags |= Snapshot::kFlagFboTarget; 81 region = s->region; 82 } else { 83 region = NULL; 84 } 85} 86 87/////////////////////////////////////////////////////////////////////////////// 88// Clipping 89/////////////////////////////////////////////////////////////////////////////// 90 91void Snapshot::ensureClipRegion() { 92 if (clipRegion->isEmpty()) { 93 clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); 94 } 95} 96 97void Snapshot::copyClipRectFromRegion() { 98 if (!clipRegion->isEmpty()) { 99 const SkIRect& bounds = clipRegion->getBounds(); 100 clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 101 102 if (clipRegion->isRect()) { 103 clipRegion->setEmpty(); 104 } 105 } else { 106 clipRect->setEmpty(); 107 } 108} 109 110bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) { 111 SkIRect tmp; 112 tmp.set(left, top, right, bottom); 113 clipRegion->op(tmp, op); 114 copyClipRectFromRegion(); 115 return true; 116} 117 118bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) { 119 ensureClipRegion(); 120 clipRegion->op(region, op); 121 copyClipRectFromRegion(); 122 flags |= Snapshot::kFlagClipSet; 123 return true; 124} 125 126bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) { 127 Rect r(left, top, right, bottom); 128 transform->mapRect(r); 129 return clipTransformed(r, op); 130} 131 132bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) { 133 bool clipped = false; 134 135 switch (op) { 136 case SkRegion::kIntersect_Op: { 137 if (CC_UNLIKELY(!clipRegion->isEmpty())) { 138 ensureClipRegion(); 139 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op); 140 } else { 141 clipped = clipRect->intersect(r); 142 if (!clipped) { 143 clipRect->setEmpty(); 144 clipped = true; 145 } 146 } 147 break; 148 } 149 case SkRegion::kReplace_Op: { 150 setClip(r.left, r.top, r.right, r.bottom); 151 clipped = true; 152 break; 153 } 154 default: { 155 ensureClipRegion(); 156 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op); 157 break; 158 } 159 } 160 161 if (clipped) { 162 flags |= Snapshot::kFlagClipSet; 163 } 164 165 return clipped; 166} 167 168void Snapshot::setClip(float left, float top, float right, float bottom) { 169 clipRect->set(left, top, right, bottom); 170 if (!clipRegion->isEmpty()) { 171 clipRegion->setEmpty(); 172 } 173 flags |= Snapshot::kFlagClipSet; 174} 175 176bool Snapshot::hasPerspectiveTransform() const { 177 return transform->isPerspective(); 178} 179 180const Rect& Snapshot::getLocalClip() { 181 mat4 inverse; 182 inverse.loadInverse(*transform); 183 184 mLocalClip.set(*clipRect); 185 inverse.mapRect(mLocalClip); 186 187 return mLocalClip; 188} 189 190void Snapshot::resetClip(float left, float top, float right, float bottom) { 191 // TODO: This is incorrect, when we start rendering into a new layer, 192 // we may have to modify the previous snapshot's clip rect and clip 193 // region if the previous restore() call did not restore the clip 194 clipRect = &mClipRectRoot; 195 clipRegion = &mClipRegionRoot; 196 setClip(left, top, right, bottom); 197} 198 199/////////////////////////////////////////////////////////////////////////////// 200// Transforms 201/////////////////////////////////////////////////////////////////////////////// 202 203void Snapshot::resetTransform(float x, float y, float z) { 204 transform = &mTransformRoot; 205 transform->loadTranslate(x, y, z); 206} 207 208/////////////////////////////////////////////////////////////////////////////// 209// Queries 210/////////////////////////////////////////////////////////////////////////////// 211 212bool Snapshot::isIgnored() const { 213 return invisible || empty; 214} 215 216void Snapshot::dump() const { 217 ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d", 218 this, flags, previous.get(), height, isIgnored(), clipRegion && !clipRegion->isEmpty()); 219 ALOGD(" ClipRect (at %p) %.1f %.1f %.1f %.1f", 220 clipRect, clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); 221 ALOGD(" Transform (at %p):", transform); 222 transform->dump(); 223} 224 225}; // namespace uirenderer 226}; // namespace android 227