blob: 029b56d6ae0091d689c32c8b99f3aa941a14410b [file] [log] [blame]
Romain Guyada4d532012-02-02 17:31:16 -08001/*
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
Chris Craik5f803622013-03-21 14:39:04 -070017#define LOG_TAG "OpenGLRenderer"
18
Romain Guyada4d532012-02-02 17:31:16 -080019#include "Snapshot.h"
20
21#include <SkCanvas.h>
22
23namespace android {
24namespace uirenderer {
25
26///////////////////////////////////////////////////////////////////////////////
27// Constructors
28///////////////////////////////////////////////////////////////////////////////
29
Chris Craike4aa95e2014-05-08 13:57:05 -070030Snapshot::Snapshot()
31 : flags(0)
32 , previous(NULL)
33 , layer(NULL)
34 , fbo(0)
35 , invisible(false)
36 , empty(false)
Chris Craike4aa95e2014-05-08 13:57:05 -070037 , alpha(1.0f) {
Romain Guyada4d532012-02-02 17:31:16 -080038 transform = &mTransformRoot;
39 clipRect = &mClipRectRoot;
40 region = NULL;
Romain Guy8ce00302013-01-15 18:51:42 -080041 clipRegion = &mClipRegionRoot;
Romain Guyada4d532012-02-02 17:31:16 -080042}
43
44/**
45 * Copies the specified snapshot/ The specified snapshot is stored as
46 * the previous snapshot.
47 */
Chris Craike4aa95e2014-05-08 13:57:05 -070048Snapshot::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)
Chris Craika64a2be2014-05-14 14:17:01 -070055 , alpha(s->alpha)
56 , mViewportData(s->mViewportData) {
Romain Guyada4d532012-02-02 17:31:16 -080057
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;
Romain Guy8ce00302013-01-15 18:51:42 -080068 if (!s->clipRegion->isEmpty()) {
Romain Guy0baaac52012-08-31 20:31:01 -070069 mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
Romain Guy967e2bf2012-02-07 17:04:34 -080070 }
Romain Guy8ce00302013-01-15 18:51:42 -080071 clipRegion = &mClipRegionRoot;
Romain Guyada4d532012-02-02 17:31:16 -080072 } else {
73 clipRect = s->clipRect;
Romain Guy967e2bf2012-02-07 17:04:34 -080074 clipRegion = s->clipRegion;
Romain Guyada4d532012-02-02 17:31:16 -080075 }
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
Romain Guy967e2bf2012-02-07 17:04:34 -080089void Snapshot::ensureClipRegion() {
Romain Guy8ce00302013-01-15 18:51:42 -080090 if (clipRegion->isEmpty()) {
Romain Guy0baaac52012-08-31 20:31:01 -070091 clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
Romain Guy967e2bf2012-02-07 17:04:34 -080092 }
Romain Guy967e2bf2012-02-07 17:04:34 -080093}
94
95void Snapshot::copyClipRectFromRegion() {
Romain Guy967e2bf2012-02-07 17:04:34 -080096 if (!clipRegion->isEmpty()) {
Romain Guy0baaac52012-08-31 20:31:01 -070097 const SkIRect& bounds = clipRegion->getBounds();
98 clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Romain Guy967e2bf2012-02-07 17:04:34 -080099
100 if (clipRegion->isRect()) {
Romain Guy0baaac52012-08-31 20:31:01 -0700101 clipRegion->setEmpty();
Romain Guy967e2bf2012-02-07 17:04:34 -0800102 }
103 } else {
104 clipRect->setEmpty();
Romain Guy967e2bf2012-02-07 17:04:34 -0800105 }
Romain Guy967e2bf2012-02-07 17:04:34 -0800106}
107
Romain Guy0baaac52012-08-31 20:31:01 -0700108bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
Romain Guy0baaac52012-08-31 20:31:01 -0700109 SkIRect tmp;
110 tmp.set(left, top, right, bottom);
111 clipRegion->op(tmp, op);
Romain Guy967e2bf2012-02-07 17:04:34 -0800112 copyClipRectFromRegion();
113 return true;
Romain Guy8ce00302013-01-15 18:51:42 -0800114}
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;
Romain Guy967e2bf2012-02-07 17:04:34 -0800122}
123
Romain Guyada4d532012-02-02 17:31:16 -0800124bool 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
Romain Guyada4d532012-02-02 17:31:16 -0800133 switch (op) {
Romain Guy967e2bf2012-02-07 17:04:34 -0800134 case SkRegion::kIntersect_Op: {
Romain Guy8ce00302013-01-15 18:51:42 -0800135 if (CC_UNLIKELY(!clipRegion->isEmpty())) {
Romain Guy735738c2012-12-03 12:34:51 -0800136 ensureClipRegion();
Romain Guy0baaac52012-08-31 20:31:01 -0700137 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
Romain Guy967e2bf2012-02-07 17:04:34 -0800138 } else {
139 clipped = clipRect->intersect(r);
140 if (!clipped) {
141 clipRect->setEmpty();
142 clipped = true;
143 }
Romain Guyada4d532012-02-02 17:31:16 -0800144 }
145 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800146 }
Romain Guy967e2bf2012-02-07 17:04:34 -0800147 case SkRegion::kReplace_Op: {
148 setClip(r.left, r.top, r.right, r.bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800149 clipped = true;
150 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800151 }
Romain Guy0baaac52012-08-31 20:31:01 -0700152 default: {
153 ensureClipRegion();
154 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op);
155 break;
156 }
Romain Guyada4d532012-02-02 17:31:16 -0800157 }
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);
Romain Guy8ce00302013-01-15 18:51:42 -0800168 if (!clipRegion->isEmpty()) {
Romain Guy0baaac52012-08-31 20:31:01 -0700169 clipRegion->setEmpty();
Romain Guy967e2bf2012-02-07 17:04:34 -0800170 }
Romain Guyada4d532012-02-02 17:31:16 -0800171 flags |= Snapshot::kFlagClipSet;
172}
173
Romain Guya3dc55f2012-09-28 13:55:44 -0700174bool Snapshot::hasPerspectiveTransform() const {
175 return transform->isPerspective();
176}
177
Romain Guyada4d532012-02-02 17:31:16 -0800178const 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) {
Romain Guy3bbacf22013-02-06 16:51:04 -0800189 // 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
Romain Guyada4d532012-02-02 17:31:16 -0800192 clipRect = &mClipRectRoot;
Romain Guy3c099c42013-02-06 15:28:04 -0800193 clipRegion = &mClipRegionRoot;
Romain Guy967e2bf2012-02-07 17:04:34 -0800194 setClip(left, top, right, bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800195}
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
Chris Craik5f803622013-03-21 14:39:04 -0700214void Snapshot::dump() const {
215 ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d",
Chris Craika64a2be2014-05-14 14:17:01 -0700216 this, flags, previous.get(), getViewportHeight(), isIgnored(), clipRegion && !clipRegion->isEmpty());
Chris Craik5f803622013-03-21 14:39:04 -0700217 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
Romain Guyada4d532012-02-02 17:31:16 -0800223}; // namespace uirenderer
224}; // namespace android