1ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/*
2ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Copyright (C) 2012 The Android Open Source Project
3ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy *
4ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * you may not use this file except in compliance with the License.
6ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * You may obtain a copy of the License at
7ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy *
8ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy *
10ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Unless required by applicable law or agreed to in writing, software
11ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * See the License for the specific language governing permissions and
14ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * limitations under the License.
15ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy */
16ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
17ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy#include "Snapshot.h"
18ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
19dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "hwui/Canvas.h"
20ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
21ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace android {
22ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace uirenderer {
23ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
24ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
25ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Constructors
26ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
27ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
28e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris CraikSnapshot::Snapshot()
29e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        : flags(0)
30d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        , previous(nullptr)
31d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        , layer(nullptr)
32e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , fbo(0)
33e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , invisible(false)
34e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , empty(false)
35deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        , alpha(1.0f)
36487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        , roundRectClipState(nullptr)
37fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        , projectionPathMask(nullptr)
38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        , mClipArea(&mClipAreaRoot) {
39ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    transform = &mTransformRoot;
40d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    region = nullptr;
41ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
42ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
43ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/**
44ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Copies the specified snapshot/ The specified snapshot is stored as
45ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * the previous snapshot.
46ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy */
47d9ee550888011a64fa3f35e666360ec8278597d8John ReckSnapshot::Snapshot(Snapshot* s, int saveFlags)
48e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        : flags(0)
49e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , previous(s)
50e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , layer(s->layer)
51e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , fbo(s->fbo)
52e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , invisible(s->invisible)
53e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik        , empty(false)
54a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik        , alpha(s->alpha)
55deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        , roundRectClipState(s->roundRectClipState)
56fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        , projectionPathMask(s->projectionPathMask)
57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        , mClipArea(nullptr)
5869e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik        , mViewportData(s->mViewportData)
5969e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik        , mRelativeLightCenter(s->mRelativeLightCenter) {
60eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    if (saveFlags & SaveFlags::Matrix) {
617c85c54499994c687a833644f7f213e747fadb98Chris Craik        mTransformRoot = *s->transform;
62ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        transform = &mTransformRoot;
63ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    } else {
64ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        transform = s->transform;
65ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
66ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
67eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    if (saveFlags & SaveFlags::Clip) {
68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        mClipAreaRoot = s->getClipArea();
69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        mClipArea = &mClipAreaRoot;
70ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    } else {
71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        mClipArea = s->mClipArea;
72ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
73ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
74ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    if (s->flags & Snapshot::kFlagFboTarget) {
75ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        flags |= Snapshot::kFlagFboTarget;
76ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        region = s->region;
77ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    } else {
78d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        region = nullptr;
79ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
80ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
81ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
82ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
83ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Clipping
84ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
85ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
864d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
878ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    flags |= Snapshot::kFlagClipSet;
884d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mClipArea->clipRegion(region, op);
89967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy}
90967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy
91a2a70723b8cbda4354d23f901f995623e819012cChris Craikvoid Snapshot::clip(const Rect& localClip, SkRegion::Op op) {
92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    flags |= Snapshot::kFlagClipSet;
93a2a70723b8cbda4354d23f901f995623e819012cChris Craik    mClipArea->clipRectWithTransform(localClip, transform, op);
94ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
95ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
964d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    flags |= Snapshot::kFlagClipSet;
984d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mClipArea->clipPathWithTransform(path, transform, op);
99ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
100ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
101ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::setClip(float left, float top, float right, float bottom) {
102ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    flags |= Snapshot::kFlagClipSet;
1034d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mClipArea->setClip(left, top, right, bottom);
104ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
105ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
106a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guybool Snapshot::hasPerspectiveTransform() const {
107a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy    return transform->isPerspective();
108a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy}
109a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy
110ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyconst Rect& Snapshot::getLocalClip() {
111ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    mat4 inverse;
112ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    inverse.loadInverse(*transform);
113ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
114487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    mLocalClip.set(mClipArea->getClipRect());
115ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    inverse.mapRect(mLocalClip);
116ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
117ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    return mLocalClip;
118ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
119ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
120ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::resetClip(float left, float top, float right, float bottom) {
1213bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    // TODO: This is incorrect, when we start rendering into a new layer,
1223bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    // we may have to modify the previous snapshot's clip rect and clip
1233bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    // region if the previous restore() call did not restore the clip
124487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    mClipArea = &mClipAreaRoot;
125967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    setClip(left, top, right, bottom);
126ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
127ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
128ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
129ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Transforms
130ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
131ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
132ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::resetTransform(float x, float y, float z) {
13398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#if HWUI_NEW_OPS
13498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    LOG_ALWAYS_FATAL("not supported - light center managed differently");
13598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#else
13669e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    // before resetting, map current light pos with inverse of current transform
13769e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    Vector3 center = mRelativeLightCenter;
13869e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    mat4 inverse;
13969e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    inverse.loadInverse(*transform);
14069e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    inverse.mapPoint3d(center);
14169e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    mRelativeLightCenter = center;
14269e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik
143ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    transform = &mTransformRoot;
144ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    transform->loadTranslate(x, y, z);
14598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#endif
146ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
147ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
148fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craikvoid Snapshot::buildScreenSpaceTransform(Matrix4* outTransform) const {
149678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik#if HWUI_NEW_OPS
150678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    LOG_ALWAYS_FATAL("not supported - not needed by new ops");
151678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik#else
152fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    // build (reverse ordered) list of the stack of snapshots, terminated with a NULL
153fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    Vector<const Snapshot*> snapshotList;
154fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    snapshotList.push(nullptr);
155fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    const Snapshot* current = this;
156fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    do {
157fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        snapshotList.push(current);
158d9ee550888011a64fa3f35e666360ec8278597d8John Reck        current = current->previous;
159fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    } while (current);
160fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik
161fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    // traverse the list, adding in each transform that contributes to the total transform
162fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    outTransform->loadIdentity();
163fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    for (size_t i = snapshotList.size() - 1; i > 0; i--) {
164fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        // iterate down the stack
165fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        const Snapshot* current = snapshotList[i];
166fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        const Snapshot* next = snapshotList[i - 1];
167fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        if (current->flags & kFlagIsFboLayer) {
168fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik            // if we've hit a layer, translate by the layer's draw offset
169fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik            outTransform->translate(current->layer->layer.left, current->layer->layer.top);
170fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        }
171fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        if (!next || (next->flags & kFlagIsFboLayer)) {
172fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik            // if this snapshot is last, or if this snapshot is last before an
173fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik            // FBO layer (which reset the transform), apply it
174fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik            outTransform->multiply(*(current->transform));
175fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        }
176fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    }
177678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik#endif
178fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik}
179fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik
180ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
181af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik// Clipping round rect
182deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik///////////////////////////////////////////////////////////////////////////////
183deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
184e83cbd451868a734bfac07ccd680d5617080b579Chris Craikvoid Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
185e83cbd451868a734bfac07ccd680d5617080b579Chris Craik        float radius, bool highPriority) {
186af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    if (bounds.isEmpty()) {
187487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        mClipArea->setEmpty();
188af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik        return;
189af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    }
190deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
191e83cbd451868a734bfac07ccd680d5617080b579Chris Craik    if (roundRectClipState && roundRectClipState->highPriority) {
192e83cbd451868a734bfac07ccd680d5617080b579Chris Craik        // ignore, don't replace, already have a high priority clip
193e83cbd451868a734bfac07ccd680d5617080b579Chris Craik        return;
194e83cbd451868a734bfac07ccd680d5617080b579Chris Craik    }
195e83cbd451868a734bfac07ccd680d5617080b579Chris Craik
196deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    RoundRectClipState* state = new (allocator) RoundRectClipState;
197deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
198e83cbd451868a734bfac07ccd680d5617080b579Chris Craik    state->highPriority = highPriority;
199e83cbd451868a734bfac07ccd680d5617080b579Chris Craik
200deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    // store the inverse drawing matrix
2017c85c54499994c687a833644f7f213e747fadb98Chris Craik    Matrix4 roundRectDrawingMatrix = getOrthoMatrix();
202af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    roundRectDrawingMatrix.multiply(*transform);
203af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    state->matrix.loadInverse(roundRectDrawingMatrix);
204deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
205deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    // compute area under rounded corners - only draws overlapping these rects need to be clipped
206deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    for (int i = 0 ; i < 4; i++) {
207deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        state->dangerRects[i] = bounds;
208deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
209deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    state->dangerRects[0].bottom = state->dangerRects[1].bottom = bounds.top + radius;
210deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    state->dangerRects[0].right = state->dangerRects[2].right = bounds.left + radius;
211deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    state->dangerRects[1].left = state->dangerRects[3].left = bounds.right - radius;
212deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    state->dangerRects[2].top = state->dangerRects[3].top = bounds.bottom - radius;
213deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    for (int i = 0; i < 4; i++) {
214deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        transform->mapRect(state->dangerRects[i]);
215deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
216deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        // round danger rects out as though they are AA geometry (since they essentially are)
217deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        state->dangerRects[i].snapGeometryToPixelBoundaries(true);
218deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
219deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
220deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    // store RR area
221af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    state->innerRect = bounds;
222af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    state->innerRect.inset(radius);
223af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    state->radius = radius;
224deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
225deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info
226deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    roundRectClipState = state;
227deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik}
228deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
229fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craikvoid Snapshot::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
230678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik#if HWUI_NEW_OPS
231678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    // TODO: remove allocator param for HWUI_NEW_OPS
232678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    projectionPathMask = path;
233678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik#else
234fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    if (path) {
235fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        ProjectionPathMask* mask = new (allocator) ProjectionPathMask;
236fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        mask->projectionMask = path;
237fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        buildScreenSpaceTransform(&(mask->projectionMaskTransform));
238fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        projectionPathMask = mask;
239fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    } else {
240fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik        projectionPathMask = nullptr;
241fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    }
242678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik#endif
243fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik}
244fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik
24504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craikstatic Snapshot* getClipRoot(Snapshot* target) {
24604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    while (target->previous && target->previous->previous) {
24704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        target = target->previous;
24804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    }
24904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    return target;
25004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik}
25104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
25204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craikconst ClipBase* Snapshot::serializeIntersectedClip(LinearAllocator& allocator,
25304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        const ClipBase* recordedClip, const Matrix4& recordedClipTransform) {
25404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    auto target = this;
25504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
25604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        // Clip must be intersected with root, instead of current clip.
25704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        target = getClipRoot(this);
25804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    }
25904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
26004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    return target->mClipArea->serializeIntersectedClip(allocator,
26104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            recordedClip, recordedClipTransform);
26204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik}
26304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
26404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craikvoid Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform) {
26504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
26604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        // current clip is being replaced, but must intersect with clip root
26704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        *mClipArea = *(getClipRoot(this)->mClipArea);
26804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    }
26904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    mClipArea->applyClip(recordedClip, transform);
27004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik}
27104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
272deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik///////////////////////////////////////////////////////////////////////////////
273ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Queries
274ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
275ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
276ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guybool Snapshot::isIgnored() const {
277ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    return invisible || empty;
278ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
279ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
2805f803623559aab395a29d575c37c4e39c23a4b4eChris Craikvoid Snapshot::dump() const {
2815f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d",
282d9ee550888011a64fa3f35e666360ec8278597d8John Reck            this, flags, previous, getViewportHeight(), isIgnored(), !mClipArea->isSimple());
283487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    const Rect& clipRect(mClipArea->getClipRect());
284e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik    ALOGD("  ClipRect %.1f %.1f %.1f %.1f, clip simple %d",
285e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik            clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, mClipArea->isSimple());
286e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik
2875f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    ALOGD("  Transform (at %p):", transform);
2885f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    transform->dump();
2895f803623559aab395a29d575c37c4e39c23a4b4eChris Craik}
2905f803623559aab395a29d575c37c4e39c23a4b4eChris Craik
291ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace uirenderer
292ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace android
293