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