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