10baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy/*
20baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * Copyright (C) 2012 The Android Open Source Project
30baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy *
40baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
50baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * you may not use this file except in compliance with the License.
60baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * You may obtain a copy of the License at
70baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy *
80baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
90baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy *
100baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * Unless required by applicable law or agreed to in writing, software
110baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
120baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * See the License for the specific language governing permissions and
140baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy * limitations under the License.
150baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy */
160baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
17117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik#include "renderstate/Stencil.h"
18117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
19117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik#include "Caches.h"
20b7b93e00893f5c690a96bd3e0e10583bc5721f83Romain Guy#include "Debug.h"
213bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#include "Extensions.h"
220baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy#include "Properties.h"
230baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
243bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#include <GLES2/gl2ext.h>
253bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
260baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guynamespace android {
270baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guynamespace uirenderer {
280baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
293bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#if DEBUG_STENCIL
303bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#define STENCIL_WRITE_VALUE 0xff
313bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#define STENCIL_MASK_VALUE 0xff
323bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#else
333bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#define STENCIL_WRITE_VALUE 0x1
343bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#define STENCIL_MASK_VALUE 0x1
353bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#endif
363bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
3723b797ab5151eb2474f3bdd679f2f07bfd723042John Reckuint8_t Stencil::getStencilSize() {
380baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    return STENCIL_BUFFER_SIZE;
390baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
400baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
41e145013153b562d0b1bcac3e88095411874f1c25Chris Craik/**
42e145013153b562d0b1bcac3e88095411874f1c25Chris Craik * This method will return either GL_STENCIL_INDEX4_OES if supported,
43e145013153b562d0b1bcac3e88095411874f1c25Chris Craik * GL_STENCIL_INDEX8 if not.
44e145013153b562d0b1bcac3e88095411874f1c25Chris Craik *
45e145013153b562d0b1bcac3e88095411874f1c25Chris Craik * Layers can't use a single bit stencil because multi-rect ClipArea needs a high enough
46e145013153b562d0b1bcac3e88095411874f1c25Chris Craik * stencil resolution to represent the summation of multiple intersecting rect geometries.
47e145013153b562d0b1bcac3e88095411874f1c25Chris Craik */
48e145013153b562d0b1bcac3e88095411874f1c25Chris CraikGLenum Stencil::getLayerStencilFormat() {
493bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#if !DEBUG_STENCIL
50117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    const Extensions& extensions = Caches::getInstance().extensions();
51e145013153b562d0b1bcac3e88095411874f1c25Chris Craik    if (extensions.has4BitStencil()) {
523bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        return GL_STENCIL_INDEX4_OES;
533bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    }
543bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#endif
553bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    return GL_STENCIL_INDEX8;
563bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy}
573bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
580baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guyvoid Stencil::clear() {
59fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    glStencilMask(0xff);
600baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    glClearStencil(0);
610baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    glClear(GL_STENCIL_BUFFER_BIT);
62fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik
63b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    if (mState == StencilState::Test) {
64fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik        // reset to test state, with immutable stencil
65fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik        glStencilMask(0);
66fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    }
670baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
680baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid Stencil::enableTest(int incrementThreshold) {
70b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    if (mState != StencilState::Test) {
710baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        enable();
72487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        if (incrementThreshold > 0) {
73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_EQUAL, incrementThreshold, 0xff);
74487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        } else {
75487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_EQUAL, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE);
76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        }
770baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        // We only want to test, let's keep everything
780baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
79f7e52d92b41adf460089625ea47bfea2ed7e6296Romain Guy        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
80487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        glStencilMask(0);
81b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mState = StencilState::Test;
820baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
830baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
840baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
85487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid Stencil::enableWrite(int incrementThreshold) {
86b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    if (mState != StencilState::Write) {
870baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        enable();
88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        if (incrementThreshold > 0) {
89487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_ALWAYS, 1, 0xff);
90487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            // The test always passes so the first two values are meaningless
91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilOp(GL_INCR, GL_INCR, GL_INCR);
92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        } else {
93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_ALWAYS, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE);
94487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            // The test always passes so the first two values are meaningless
95487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        }
97f7e52d92b41adf460089625ea47bfea2ed7e6296Romain Guy        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        glStencilMask(0xff);
99b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mState = StencilState::Write;
1000baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
1010baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
1020baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
1037c450aaa3caac2a05fcb20a177483d0e92378426Romain Guyvoid Stencil::enableDebugTest(GLint value, bool greater) {
1047c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    enable();
1057c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff);
1067c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    // We only want to test, let's keep everything
1077c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
108b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    mState = StencilState::Test;
109fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    glStencilMask(0);
1107c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy}
1117c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
1127c450aaa3caac2a05fcb20a177483d0e92378426Romain Guyvoid Stencil::enableDebugWrite() {
113fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    enable();
114fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    glStencilFunc(GL_ALWAYS, 0x1, 0xffffffff);
115fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    // The test always passes so the first two values are meaningless
116fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
117fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
118b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    mState = StencilState::Write;
119fa51a0e1ceb496e57f6c234800a3f5e9a2d89142Chris Craik    glStencilMask(0xff);
1207c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy}
1217c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
1220baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guyvoid Stencil::enable() {
123b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    if (mState == StencilState::Disabled) {
1240baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        glEnable(GL_STENCIL_TEST);
1250baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
1260baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
1270baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
1280baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guyvoid Stencil::disable() {
129b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    if (mState != StencilState::Disabled) {
1300baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        glDisable(GL_STENCIL_TEST);
131b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mState = StencilState::Disabled;
1320baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
1330baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
1340baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
135117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craikvoid Stencil::dump() {
136117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    ALOGD("Stencil: state %d", mState);
137117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik}
138117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
1390baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}; // namespace uirenderer
1400baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}; // namespace android
141