blob: f1a1bef7c94e9bcd65c9509fc4101e176ff40cf9 [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
17#include "Snapshot.h"
18
sergeyvdccca442016-03-21 15:38:21 -070019#include "hwui/Canvas.h"
Romain Guyada4d532012-02-02 17:31:16 -080020
21namespace android {
22namespace uirenderer {
23
24///////////////////////////////////////////////////////////////////////////////
25// Constructors
26///////////////////////////////////////////////////////////////////////////////
27
Chris Craike4aa95e2014-05-08 13:57:05 -070028Snapshot::Snapshot()
29 : flags(0)
Chris Craikd41c4d82015-01-05 15:51:13 -080030 , previous(nullptr)
31 , layer(nullptr)
Chris Craike4aa95e2014-05-08 13:57:05 -070032 , fbo(0)
Chris Craikdeeda3d2014-05-05 19:09:33 -070033 , alpha(1.0f)
Rob Tsuk487a92c2015-01-06 13:22:54 -080034 , roundRectClipState(nullptr)
Chris Craikfca52b752015-04-28 11:45:59 -070035 , projectionPathMask(nullptr)
Rob Tsuk487a92c2015-01-06 13:22:54 -080036 , mClipArea(&mClipAreaRoot) {
Romain Guyada4d532012-02-02 17:31:16 -080037 transform = &mTransformRoot;
Keith Mokde89c2f2016-07-13 14:45:16 -070038 mRelativeLightCenter.x = mRelativeLightCenter.y = mRelativeLightCenter.z = 0;
Romain Guyada4d532012-02-02 17:31:16 -080039}
40
41/**
42 * Copies the specified snapshot/ The specified snapshot is stored as
43 * the previous snapshot.
44 */
John Reckd9ee5502015-10-06 10:06:37 -070045Snapshot::Snapshot(Snapshot* s, int saveFlags)
Chris Craike4aa95e2014-05-08 13:57:05 -070046 : flags(0)
47 , previous(s)
48 , layer(s->layer)
49 , fbo(s->fbo)
Chris Craika64a2be2014-05-14 14:17:01 -070050 , alpha(s->alpha)
Chris Craikdeeda3d2014-05-05 19:09:33 -070051 , roundRectClipState(s->roundRectClipState)
Chris Craikfca52b752015-04-28 11:45:59 -070052 , projectionPathMask(s->projectionPathMask)
Rob Tsuk487a92c2015-01-06 13:22:54 -080053 , mClipArea(nullptr)
Chris Craik69e5adf2014-08-14 13:34:01 -070054 , mViewportData(s->mViewportData)
55 , mRelativeLightCenter(s->mRelativeLightCenter) {
Florin Malitaeecff562015-12-21 10:43:01 -050056 if (saveFlags & SaveFlags::Matrix) {
Chris Craik7c85c542015-08-19 15:10:24 -070057 mTransformRoot = *s->transform;
Romain Guyada4d532012-02-02 17:31:16 -080058 transform = &mTransformRoot;
59 } else {
60 transform = s->transform;
61 }
62
Florin Malitaeecff562015-12-21 10:43:01 -050063 if (saveFlags & SaveFlags::Clip) {
Rob Tsuk487a92c2015-01-06 13:22:54 -080064 mClipAreaRoot = s->getClipArea();
65 mClipArea = &mClipAreaRoot;
Romain Guyada4d532012-02-02 17:31:16 -080066 } else {
Rob Tsuk487a92c2015-01-06 13:22:54 -080067 mClipArea = s->mClipArea;
Romain Guyada4d532012-02-02 17:31:16 -080068 }
Romain Guyada4d532012-02-02 17:31:16 -080069}
70
71///////////////////////////////////////////////////////////////////////////////
72// Clipping
73///////////////////////////////////////////////////////////////////////////////
74
Mike Reed6e49c9f2016-12-02 15:36:59 -050075void Snapshot::clip(const Rect& localClip, SkClipOp op) {
Rob Tsuk487a92c2015-01-06 13:22:54 -080076 flags |= Snapshot::kFlagClipSet;
Mike Reed6e49c9f2016-12-02 15:36:59 -050077 mClipArea->clipRectWithTransform(localClip, transform, static_cast<SkRegion::Op>(op));
Romain Guyada4d532012-02-02 17:31:16 -080078}
79
Mike Reed6e49c9f2016-12-02 15:36:59 -050080void Snapshot::clipPath(const SkPath& path, SkClipOp op) {
Rob Tsuk487a92c2015-01-06 13:22:54 -080081 flags |= Snapshot::kFlagClipSet;
Mike Reed6e49c9f2016-12-02 15:36:59 -050082 mClipArea->clipPathWithTransform(path, transform, static_cast<SkRegion::Op>(op));
Romain Guyada4d532012-02-02 17:31:16 -080083}
84
85void Snapshot::setClip(float left, float top, float right, float bottom) {
Romain Guyada4d532012-02-02 17:31:16 -080086 flags |= Snapshot::kFlagClipSet;
Chris Craik4d3e7042015-08-20 12:54:25 -070087 mClipArea->setClip(left, top, right, bottom);
Romain Guyada4d532012-02-02 17:31:16 -080088}
89
Romain Guya3dc55f2012-09-28 13:55:44 -070090bool Snapshot::hasPerspectiveTransform() const {
91 return transform->isPerspective();
92}
93
Romain Guyada4d532012-02-02 17:31:16 -080094const Rect& Snapshot::getLocalClip() {
95 mat4 inverse;
96 inverse.loadInverse(*transform);
97
Rob Tsuk487a92c2015-01-06 13:22:54 -080098 mLocalClip.set(mClipArea->getClipRect());
Romain Guyada4d532012-02-02 17:31:16 -080099 inverse.mapRect(mLocalClip);
100
101 return mLocalClip;
102}
103
104void Snapshot::resetClip(float left, float top, float right, float bottom) {
Romain Guy3bbacf22013-02-06 16:51:04 -0800105 // TODO: This is incorrect, when we start rendering into a new layer,
106 // we may have to modify the previous snapshot's clip rect and clip
107 // region if the previous restore() call did not restore the clip
Rob Tsuk487a92c2015-01-06 13:22:54 -0800108 mClipArea = &mClipAreaRoot;
Romain Guy967e2bf2012-02-07 17:04:34 -0800109 setClip(left, top, right, bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800110}
111
112///////////////////////////////////////////////////////////////////////////////
Chris Craikaf4d04c2014-07-29 12:50:14 -0700113// Clipping round rect
Chris Craikdeeda3d2014-05-05 19:09:33 -0700114///////////////////////////////////////////////////////////////////////////////
115
John Reck1bcacfd2017-11-03 10:12:19 -0700116void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius,
117 bool highPriority) {
Chris Craikaf4d04c2014-07-29 12:50:14 -0700118 if (bounds.isEmpty()) {
Rob Tsuk487a92c2015-01-06 13:22:54 -0800119 mClipArea->setEmpty();
Chris Craikaf4d04c2014-07-29 12:50:14 -0700120 return;
121 }
Chris Craikdeeda3d2014-05-05 19:09:33 -0700122
Chris Craike83cbd42014-09-03 17:52:24 -0700123 if (roundRectClipState && roundRectClipState->highPriority) {
124 // ignore, don't replace, already have a high priority clip
125 return;
126 }
127
Chris Craikdeeda3d2014-05-05 19:09:33 -0700128 RoundRectClipState* state = new (allocator) RoundRectClipState;
129
Chris Craike83cbd42014-09-03 17:52:24 -0700130 state->highPriority = highPriority;
131
Chris Craikdeeda3d2014-05-05 19:09:33 -0700132 // store the inverse drawing matrix
Chris Craik7c85c542015-08-19 15:10:24 -0700133 Matrix4 roundRectDrawingMatrix = getOrthoMatrix();
Chris Craikaf4d04c2014-07-29 12:50:14 -0700134 roundRectDrawingMatrix.multiply(*transform);
135 state->matrix.loadInverse(roundRectDrawingMatrix);
Chris Craikdeeda3d2014-05-05 19:09:33 -0700136
137 // compute area under rounded corners - only draws overlapping these rects need to be clipped
John Reck1bcacfd2017-11-03 10:12:19 -0700138 for (int i = 0; i < 4; i++) {
Chris Craikdeeda3d2014-05-05 19:09:33 -0700139 state->dangerRects[i] = bounds;
140 }
141 state->dangerRects[0].bottom = state->dangerRects[1].bottom = bounds.top + radius;
142 state->dangerRects[0].right = state->dangerRects[2].right = bounds.left + radius;
143 state->dangerRects[1].left = state->dangerRects[3].left = bounds.right - radius;
144 state->dangerRects[2].top = state->dangerRects[3].top = bounds.bottom - radius;
145 for (int i = 0; i < 4; i++) {
146 transform->mapRect(state->dangerRects[i]);
147
148 // round danger rects out as though they are AA geometry (since they essentially are)
149 state->dangerRects[i].snapGeometryToPixelBoundaries(true);
150 }
151
152 // store RR area
Chris Craikaf4d04c2014-07-29 12:50:14 -0700153 state->innerRect = bounds;
154 state->innerRect.inset(radius);
155 state->radius = radius;
Chris Craikdeeda3d2014-05-05 19:09:33 -0700156
157 // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info
158 roundRectClipState = state;
159}
160
Chris Craik5e00c7c2016-07-06 16:10:09 -0700161void Snapshot::setProjectionPathMask(const SkPath* path) {
Chris Craik678ff812016-03-01 13:27:54 -0800162 projectionPathMask = path;
Chris Craikfca52b752015-04-28 11:45:59 -0700163}
164
Chris Craik04d46eb2016-04-07 13:51:07 -0700165static Snapshot* getClipRoot(Snapshot* target) {
166 while (target->previous && target->previous->previous) {
167 target = target->previous;
168 }
169 return target;
170}
171
172const ClipBase* Snapshot::serializeIntersectedClip(LinearAllocator& allocator,
John Reck1bcacfd2017-11-03 10:12:19 -0700173 const ClipBase* recordedClip,
174 const Matrix4& recordedClipTransform) {
Chris Craik04d46eb2016-04-07 13:51:07 -0700175 auto target = this;
176 if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
177 // Clip must be intersected with root, instead of current clip.
178 target = getClipRoot(this);
179 }
180
John Reck1bcacfd2017-11-03 10:12:19 -0700181 return target->mClipArea->serializeIntersectedClip(allocator, recordedClip,
182 recordedClipTransform);
Chris Craik04d46eb2016-04-07 13:51:07 -0700183}
184
185void Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform) {
186 if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
187 // current clip is being replaced, but must intersect with clip root
188 *mClipArea = *(getClipRoot(this)->mClipArea);
189 }
190 mClipArea->applyClip(recordedClip, transform);
191}
192
Chris Craikdeeda3d2014-05-05 19:09:33 -0700193///////////////////////////////////////////////////////////////////////////////
Romain Guyada4d532012-02-02 17:31:16 -0800194// Queries
195///////////////////////////////////////////////////////////////////////////////
196
Chris Craik5f803622013-03-21 14:39:04 -0700197void Snapshot::dump() const {
John Reck1bcacfd2017-11-03 10:12:19 -0700198 ALOGD("Snapshot %p, flags %x, prev %p, height %d, hasComplexClip %d", this, flags, previous,
199 getViewportHeight(), !mClipArea->isSimple());
Rob Tsuk487a92c2015-01-06 13:22:54 -0800200 const Rect& clipRect(mClipArea->getClipRect());
John Reck1bcacfd2017-11-03 10:12:19 -0700201 ALOGD(" ClipRect %.1f %.1f %.1f %.1f, clip simple %d", clipRect.left, clipRect.top,
202 clipRect.right, clipRect.bottom, mClipArea->isSimple());
Chris Craike9c01a42015-04-06 10:47:23 -0700203
Chris Craik5f803622013-03-21 14:39:04 -0700204 ALOGD(" Transform (at %p):", transform);
205 transform->dump();
206}
207
John Reck1bcacfd2017-11-03 10:12:19 -0700208}; // namespace uirenderer
209}; // namespace android