Stencil.cpp revision 117bdbcfa3e8306dad21e7e01fa71b00cdfa7265
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
37487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukStencil::Stencil()
38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        : mState(kDisabled) {
390baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
400baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
4123b797ab5151eb2474f3bdd679f2f07bfd723042John Reckuint8_t Stencil::getStencilSize() {
420baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    return STENCIL_BUFFER_SIZE;
430baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
440baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
453bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain GuyGLenum Stencil::getSmallestStencilFormat() {
463bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#if !DEBUG_STENCIL
47117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    const Extensions& extensions = Caches::getInstance().extensions();
483bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    if (extensions.has1BitStencil()) {
493bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        return GL_STENCIL_INDEX1_OES;
503bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    } else if (extensions.has4BitStencil()) {
513bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        return GL_STENCIL_INDEX4_OES;
523bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    }
533bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy#endif
543bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    return GL_STENCIL_INDEX8;
553bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy}
563bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
570baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guyvoid Stencil::clear() {
580baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    glClearStencil(0);
590baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    glClear(GL_STENCIL_BUFFER_BIT);
600baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
610baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
62487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid Stencil::enableTest(int incrementThreshold) {
630baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    if (mState != kTest) {
640baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        enable();
65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        if (incrementThreshold > 0) {
66487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_EQUAL, incrementThreshold, 0xff);
67487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        } else {
68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_EQUAL, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE);
69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        }
700baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        // We only want to test, let's keep everything
710baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
72f7e52d92b41adf460089625ea47bfea2ed7e6296Romain Guy        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        glStencilMask(0);
740baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        mState = kTest;
750baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
760baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
770baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
78487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid Stencil::enableWrite(int incrementThreshold) {
790baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    if (mState != kWrite) {
800baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        enable();
81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        if (incrementThreshold > 0) {
82487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_ALWAYS, 1, 0xff);
83487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            // The test always passes so the first two values are meaningless
84487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilOp(GL_INCR, GL_INCR, GL_INCR);
85487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        } else {
86487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilFunc(GL_ALWAYS, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE);
87487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            // The test always passes so the first two values are meaningless
88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
89487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        }
90f7e52d92b41adf460089625ea47bfea2ed7e6296Romain Guy        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        glStencilMask(0xff);
920baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        mState = kWrite;
930baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
940baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
950baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
967c450aaa3caac2a05fcb20a177483d0e92378426Romain Guyvoid Stencil::enableDebugTest(GLint value, bool greater) {
977c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    enable();
987c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff);
997c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    // We only want to test, let's keep everything
1007c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1017c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    mState = kTest;
1027c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy}
1037c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
1047c450aaa3caac2a05fcb20a177483d0e92378426Romain Guyvoid Stencil::enableDebugWrite() {
1057c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    if (mState != kWrite) {
1067c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        enable();
1077c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        glStencilFunc(GL_ALWAYS, 0x1, 0xffffffff);
1087c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        // The test always passes so the first two values are meaningless
1097c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
1107c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1117c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        mState = kWrite;
1127c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    }
1137c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy}
1147c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
1150baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guyvoid Stencil::enable() {
1167c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    if (mState == kDisabled) {
1170baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        glEnable(GL_STENCIL_TEST);
1180baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
1190baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
1200baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
1210baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guyvoid Stencil::disable() {
1220baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    if (mState != kDisabled) {
1230baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        glDisable(GL_STENCIL_TEST);
1240baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy        mState = kDisabled;
1250baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy    }
1260baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}
1270baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy
128117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craikvoid Stencil::dump() {
129117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    ALOGD("Stencil: state %d", mState);
130117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik}
131117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
1320baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}; // namespace uirenderer
1330baaac5e9adf3ee280ae1239e2e58754a9d2b099Romain Guy}; // namespace android
134