blob: 597d95ce79738aa96409d29a847bf6bbfbda772e [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)
Chris Craikd41c4d82015-01-05 15:51:13 -080032 , previous(nullptr)
33 , layer(nullptr)
Chris Craike4aa95e2014-05-08 13:57:05 -070034 , fbo(0)
35 , invisible(false)
36 , empty(false)
Chris Craikdeeda3d2014-05-05 19:09:33 -070037 , alpha(1.0f)
Rob Tsuk487a92c2015-01-06 13:22:54 -080038 , roundRectClipState(nullptr)
39 , mClipArea(&mClipAreaRoot) {
Romain Guyada4d532012-02-02 17:31:16 -080040 transform = &mTransformRoot;
Chris Craikd41c4d82015-01-05 15:51:13 -080041 region = nullptr;
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)
Chris Craikdeeda3d2014-05-05 19:09:33 -070056 , roundRectClipState(s->roundRectClipState)
Rob Tsuk487a92c2015-01-06 13:22:54 -080057 , mClipArea(nullptr)
Chris Craik69e5adf2014-08-14 13:34:01 -070058 , mViewportData(s->mViewportData)
59 , mRelativeLightCenter(s->mRelativeLightCenter) {
Romain Guyada4d532012-02-02 17:31:16 -080060 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) {
Rob Tsuk487a92c2015-01-06 13:22:54 -080068 mClipAreaRoot = s->getClipArea();
69 mClipArea = &mClipAreaRoot;
Romain Guyada4d532012-02-02 17:31:16 -080070 } else {
Rob Tsuk487a92c2015-01-06 13:22:54 -080071 mClipArea = s->mClipArea;
Romain Guyada4d532012-02-02 17:31:16 -080072 }
73
74 if (s->flags & Snapshot::kFlagFboTarget) {
75 flags |= Snapshot::kFlagFboTarget;
76 region = s->region;
77 } else {
Chris Craikd41c4d82015-01-05 15:51:13 -080078 region = nullptr;
Romain Guyada4d532012-02-02 17:31:16 -080079 }
80}
81
82///////////////////////////////////////////////////////////////////////////////
83// Clipping
84///////////////////////////////////////////////////////////////////////////////
85
Romain Guy8ce00302013-01-15 18:51:42 -080086bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
Romain Guy8ce00302013-01-15 18:51:42 -080087 flags |= Snapshot::kFlagClipSet;
Rob Tsuk487a92c2015-01-06 13:22:54 -080088 return mClipArea->clipRegion(region, op);
Romain Guy967e2bf2012-02-07 17:04:34 -080089}
90
Romain Guyada4d532012-02-02 17:31:16 -080091bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
Rob Tsuk487a92c2015-01-06 13:22:54 -080092 flags |= Snapshot::kFlagClipSet;
93 return mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op);
Romain Guyada4d532012-02-02 17:31:16 -080094}
95
Rob Tsuk487a92c2015-01-06 13:22:54 -080096bool Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
97 flags |= Snapshot::kFlagClipSet;
98 return mClipArea->clipPathWithTransform(path, transform, op);
Romain Guyada4d532012-02-02 17:31:16 -080099}
100
101void Snapshot::setClip(float left, float top, float right, float bottom) {
Rob Tsuk487a92c2015-01-06 13:22:54 -0800102 mClipArea->setClip(left, top, right, bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800103 flags |= Snapshot::kFlagClipSet;
104}
105
Romain Guya3dc55f2012-09-28 13:55:44 -0700106bool Snapshot::hasPerspectiveTransform() const {
107 return transform->isPerspective();
108}
109
Romain Guyada4d532012-02-02 17:31:16 -0800110const Rect& Snapshot::getLocalClip() {
111 mat4 inverse;
112 inverse.loadInverse(*transform);
113
Rob Tsuk487a92c2015-01-06 13:22:54 -0800114 mLocalClip.set(mClipArea->getClipRect());
Romain Guyada4d532012-02-02 17:31:16 -0800115 inverse.mapRect(mLocalClip);
116
117 return mLocalClip;
118}
119
120void Snapshot::resetClip(float left, float top, float right, float bottom) {
Romain Guy3bbacf22013-02-06 16:51:04 -0800121 // TODO: This is incorrect, when we start rendering into a new layer,
122 // we may have to modify the previous snapshot's clip rect and clip
123 // region if the previous restore() call did not restore the clip
Rob Tsuk487a92c2015-01-06 13:22:54 -0800124 mClipArea = &mClipAreaRoot;
Romain Guy967e2bf2012-02-07 17:04:34 -0800125 setClip(left, top, right, bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800126}
127
128///////////////////////////////////////////////////////////////////////////////
129// Transforms
130///////////////////////////////////////////////////////////////////////////////
131
132void Snapshot::resetTransform(float x, float y, float z) {
Chris Craik69e5adf2014-08-14 13:34:01 -0700133 // before resetting, map current light pos with inverse of current transform
134 Vector3 center = mRelativeLightCenter;
135 mat4 inverse;
136 inverse.loadInverse(*transform);
137 inverse.mapPoint3d(center);
138 mRelativeLightCenter = center;
139
Romain Guyada4d532012-02-02 17:31:16 -0800140 transform = &mTransformRoot;
141 transform->loadTranslate(x, y, z);
142}
143
144///////////////////////////////////////////////////////////////////////////////
Chris Craikaf4d04c2014-07-29 12:50:14 -0700145// Clipping round rect
Chris Craikdeeda3d2014-05-05 19:09:33 -0700146///////////////////////////////////////////////////////////////////////////////
147
Chris Craike83cbd42014-09-03 17:52:24 -0700148void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
149 float radius, bool highPriority) {
Chris Craikaf4d04c2014-07-29 12:50:14 -0700150 if (bounds.isEmpty()) {
Rob Tsuk487a92c2015-01-06 13:22:54 -0800151 mClipArea->setEmpty();
Chris Craikaf4d04c2014-07-29 12:50:14 -0700152 return;
153 }
Chris Craikdeeda3d2014-05-05 19:09:33 -0700154
Chris Craike83cbd42014-09-03 17:52:24 -0700155 if (roundRectClipState && roundRectClipState->highPriority) {
156 // ignore, don't replace, already have a high priority clip
157 return;
158 }
159
Chris Craikdeeda3d2014-05-05 19:09:33 -0700160 RoundRectClipState* state = new (allocator) RoundRectClipState;
161
Chris Craike83cbd42014-09-03 17:52:24 -0700162 state->highPriority = highPriority;
163
Chris Craikdeeda3d2014-05-05 19:09:33 -0700164 // store the inverse drawing matrix
Chris Craikaf4d04c2014-07-29 12:50:14 -0700165 Matrix4 roundRectDrawingMatrix;
166 roundRectDrawingMatrix.load(getOrthoMatrix());
167 roundRectDrawingMatrix.multiply(*transform);
168 state->matrix.loadInverse(roundRectDrawingMatrix);
Chris Craikdeeda3d2014-05-05 19:09:33 -0700169
170 // compute area under rounded corners - only draws overlapping these rects need to be clipped
171 for (int i = 0 ; i < 4; i++) {
172 state->dangerRects[i] = bounds;
173 }
174 state->dangerRects[0].bottom = state->dangerRects[1].bottom = bounds.top + radius;
175 state->dangerRects[0].right = state->dangerRects[2].right = bounds.left + radius;
176 state->dangerRects[1].left = state->dangerRects[3].left = bounds.right - radius;
177 state->dangerRects[2].top = state->dangerRects[3].top = bounds.bottom - radius;
178 for (int i = 0; i < 4; i++) {
179 transform->mapRect(state->dangerRects[i]);
180
181 // round danger rects out as though they are AA geometry (since they essentially are)
182 state->dangerRects[i].snapGeometryToPixelBoundaries(true);
183 }
184
185 // store RR area
Chris Craikaf4d04c2014-07-29 12:50:14 -0700186 state->innerRect = bounds;
187 state->innerRect.inset(radius);
188 state->radius = radius;
Chris Craikdeeda3d2014-05-05 19:09:33 -0700189
190 // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info
191 roundRectClipState = state;
192}
193
194///////////////////////////////////////////////////////////////////////////////
Romain Guyada4d532012-02-02 17:31:16 -0800195// Queries
196///////////////////////////////////////////////////////////////////////////////
197
198bool Snapshot::isIgnored() const {
199 return invisible || empty;
200}
201
Chris Craik5f803622013-03-21 14:39:04 -0700202void Snapshot::dump() const {
203 ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d",
Rob Tsuk487a92c2015-01-06 13:22:54 -0800204 this, flags, previous.get(), getViewportHeight(), isIgnored(), !mClipArea->isSimple());
205 const Rect& clipRect(mClipArea->getClipRect());
Chris Craik03188872015-02-02 18:39:33 -0800206 ALOGD(" ClipRect %.1f %.1f %.1f %.1f",
207 clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
Chris Craik5f803622013-03-21 14:39:04 -0700208 ALOGD(" Transform (at %p):", transform);
209 transform->dump();
210}
211
Romain Guyada4d532012-02-02 17:31:16 -0800212}; // namespace uirenderer
213}; // namespace android