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
175f803623559aab395a29d575c37c4e39c23a4b4eChris Craik#define LOG_TAG "OpenGLRenderer"
185f803623559aab395a29d575c37c4e39c23a4b4eChris Craik
19ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy#include "Snapshot.h"
20ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
21ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy#include <SkCanvas.h>
22ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
23ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace android {
24ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace uirenderer {
25ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
26ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
27ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Constructors
28ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
29ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
30ada4d53d50dc869b8278573ad640dc44118d3bcfRomain GuySnapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
31db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase        invisible(false), empty(false), alpha(1.0f) {
32ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
33ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    transform = &mTransformRoot;
34ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    clipRect = &mClipRectRoot;
35ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    region = NULL;
368ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    clipRegion = &mClipRegionRoot;
37ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
38ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
39ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/**
40ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Copies the specified snapshot/ The specified snapshot is stored as
41ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * the previous snapshot.
42ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy */
43ada4d53d50dc869b8278573ad640dc44118d3bcfRomain GuySnapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
448ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy        flags(0), previous(s), layer(s->layer), fbo(s->fbo),
45ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        invisible(s->invisible), empty(false),
46db8c9a6a4d9bf8c39f834b25611926caf21380f6Chet Haase        viewport(s->viewport), height(s->height), alpha(s->alpha) {
47ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
48ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
49ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        mTransformRoot.load(*s->transform);
50ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        transform = &mTransformRoot;
51ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    } else {
52ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        transform = s->transform;
53ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
54ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
55ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    if (saveFlags & SkCanvas::kClip_SaveFlag) {
56ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        mClipRectRoot.set(*s->clipRect);
57ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        clipRect = &mClipRectRoot;
588ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy        if (!s->clipRegion->isEmpty()) {
590baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy            mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
60967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        }
618ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy        clipRegion = &mClipRegionRoot;
62ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    } else {
63ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        clipRect = s->clipRect;
64967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        clipRegion = s->clipRegion;
65ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
66ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
67ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    if (s->flags & Snapshot::kFlagFboTarget) {
68ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        flags |= Snapshot::kFlagFboTarget;
69ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        region = s->region;
70ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    } else {
71ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        region = NULL;
72ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
73ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
74ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
75ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
76ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Clipping
77ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
78ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
79967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guyvoid Snapshot::ensureClipRegion() {
808ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    if (clipRegion->isEmpty()) {
810baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
82967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    }
83967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy}
84967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy
85967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guyvoid Snapshot::copyClipRectFromRegion() {
86967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    if (!clipRegion->isEmpty()) {
870baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        const SkIRect& bounds = clipRegion->getBounds();
880baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
89967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy
90967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        if (clipRegion->isRect()) {
910baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy            clipRegion->setEmpty();
92967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        }
93967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    } else {
94967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        clipRect->setEmpty();
95967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    }
96967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy}
97967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy
980baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guybool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
990baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    SkIRect tmp;
1000baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    tmp.set(left, top, right, bottom);
1010baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    clipRegion->op(tmp, op);
102967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    copyClipRectFromRegion();
103967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    return true;
1048ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy}
1058ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy
1068ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guybool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
1078ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    ensureClipRegion();
1088ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    clipRegion->op(region, op);
1098ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    copyClipRectFromRegion();
1108ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    flags |= Snapshot::kFlagClipSet;
1118ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    return true;
112967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy}
113967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy
114ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guybool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
115ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    Rect r(left, top, right, bottom);
116ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    transform->mapRect(r);
117ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    return clipTransformed(r, op);
118ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
119ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
120ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guybool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
121ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    bool clipped = false;
122ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
123ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    switch (op) {
124967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        case SkRegion::kIntersect_Op: {
1258ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy            if (CC_UNLIKELY(!clipRegion->isEmpty())) {
126735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy                ensureClipRegion();
1270baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy                clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
128967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy            } else {
129967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy                clipped = clipRect->intersect(r);
130967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy                if (!clipped) {
131967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy                    clipRect->setEmpty();
132967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy                    clipped = true;
133967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy                }
134ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy            }
135ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy            break;
136967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        }
137967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        case SkRegion::kReplace_Op: {
138967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy            setClip(r.left, r.top, r.right, r.bottom);
139ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy            clipped = true;
140ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy            break;
141967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy        }
1420baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        default: {
1430baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy            ensureClipRegion();
1440baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy            clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op);
1450baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy            break;
1460baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        }
147ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
148ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
149ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    if (clipped) {
150ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy        flags |= Snapshot::kFlagClipSet;
151ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    }
152ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
153ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    return clipped;
154ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
155ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
156ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::setClip(float left, float top, float right, float bottom) {
157ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    clipRect->set(left, top, right, bottom);
1588ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy    if (!clipRegion->isEmpty()) {
1590baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        clipRegion->setEmpty();
160967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    }
161ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    flags |= Snapshot::kFlagClipSet;
162ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
163ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
164a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guybool Snapshot::hasPerspectiveTransform() const {
165a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy    return transform->isPerspective();
166a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy}
167a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy
168ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyconst Rect& Snapshot::getLocalClip() {
169ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    mat4 inverse;
170ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    inverse.loadInverse(*transform);
171ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
172ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    mLocalClip.set(*clipRect);
173ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    inverse.mapRect(mLocalClip);
174ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
175ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    return mLocalClip;
176ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
177ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
178ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::resetClip(float left, float top, float right, float bottom) {
1793bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    // TODO: This is incorrect, when we start rendering into a new layer,
1803bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    // we may have to modify the previous snapshot's clip rect and clip
1813bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    // region if the previous restore() call did not restore the clip
182ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    clipRect = &mClipRectRoot;
1833c099c42fd7ead1429076055990ae39b72c904f4Romain Guy    clipRegion = &mClipRegionRoot;
184967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy    setClip(left, top, right, bottom);
185ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
186ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
187ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
188ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Transforms
189ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
190ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
191ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::resetTransform(float x, float y, float z) {
192ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    transform = &mTransformRoot;
193ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    transform->loadTranslate(x, y, z);
194ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
195ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
196ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
197ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Queries
198ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy///////////////////////////////////////////////////////////////////////////////
199ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
200ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guybool Snapshot::isIgnored() const {
201ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy    return invisible || empty;
202ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}
203ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy
2045f803623559aab395a29d575c37c4e39c23a4b4eChris Craikvoid Snapshot::dump() const {
2055f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d",
2065f803623559aab395a29d575c37c4e39c23a4b4eChris Craik            this, flags, previous.get(), height, isIgnored(), clipRegion && !clipRegion->isEmpty());
2075f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    ALOGD("  ClipRect (at %p) %.1f %.1f %.1f %.1f",
2085f803623559aab395a29d575c37c4e39c23a4b4eChris Craik            clipRect, clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
2095f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    ALOGD("  Transform (at %p):", transform);
2105f803623559aab395a29d575c37c4e39c23a4b4eChris Craik    transform->dump();
2115f803623559aab395a29d575c37c4e39c23a4b4eChris Craik}
2125f803623559aab395a29d575c37c4e39c23a4b4eChris Craik
213ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace uirenderer
214ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace android
215