| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "renderstate/Stencil.h" |
| |
| #include "Caches.h" |
| #include "Debug.h" |
| #include "Extensions.h" |
| #include "Properties.h" |
| |
| #include <GLES2/gl2ext.h> |
| |
| namespace android { |
| namespace uirenderer { |
| |
| #if DEBUG_STENCIL |
| #define STENCIL_WRITE_VALUE 0xff |
| #define STENCIL_MASK_VALUE 0xff |
| #else |
| #define STENCIL_WRITE_VALUE 0x1 |
| #define STENCIL_MASK_VALUE 0x1 |
| #endif |
| |
| uint8_t Stencil::getStencilSize() { |
| return STENCIL_BUFFER_SIZE; |
| } |
| |
| /** |
| * This method will return either GL_STENCIL_INDEX4_OES if supported, |
| * GL_STENCIL_INDEX8 if not. |
| * |
| * Layers can't use a single bit stencil because multi-rect ClipArea needs a high enough |
| * stencil resolution to represent the summation of multiple intersecting rect geometries. |
| */ |
| GLenum Stencil::getLayerStencilFormat() { |
| #if !DEBUG_STENCIL |
| const Extensions& extensions = Caches::getInstance().extensions(); |
| if (extensions.has4BitStencil()) { |
| return GL_STENCIL_INDEX4_OES; |
| } |
| #endif |
| return GL_STENCIL_INDEX8; |
| } |
| |
| void Stencil::clear() { |
| glStencilMask(0xff); |
| glClearStencil(0); |
| glClear(GL_STENCIL_BUFFER_BIT); |
| |
| if (mState == StencilState::Test) { |
| // reset to test state, with immutable stencil |
| glStencilMask(0); |
| } |
| } |
| |
| void Stencil::enableTest(int incrementThreshold) { |
| if (mState != StencilState::Test) { |
| enable(); |
| if (incrementThreshold > 0) { |
| glStencilFunc(GL_EQUAL, incrementThreshold, 0xff); |
| } else { |
| glStencilFunc(GL_EQUAL, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE); |
| } |
| // We only want to test, let's keep everything |
| glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| glStencilMask(0); |
| mState = StencilState::Test; |
| } |
| } |
| |
| void Stencil::enableWrite(int incrementThreshold) { |
| if (mState != StencilState::Write) { |
| enable(); |
| if (incrementThreshold > 0) { |
| glStencilFunc(GL_ALWAYS, 1, 0xff); |
| // The test always passes so the first two values are meaningless |
| glStencilOp(GL_INCR, GL_INCR, GL_INCR); |
| } else { |
| glStencilFunc(GL_ALWAYS, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE); |
| // The test always passes so the first two values are meaningless |
| glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); |
| } |
| glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
| glStencilMask(0xff); |
| mState = StencilState::Write; |
| } |
| } |
| |
| void Stencil::enableDebugTest(GLint value, bool greater) { |
| enable(); |
| glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff); |
| // We only want to test, let's keep everything |
| glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); |
| mState = StencilState::Test; |
| glStencilMask(0); |
| } |
| |
| void Stencil::enableDebugWrite() { |
| enable(); |
| glStencilFunc(GL_ALWAYS, 0x1, 0xffffffff); |
| // The test always passes so the first two values are meaningless |
| glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| mState = StencilState::Write; |
| glStencilMask(0xff); |
| } |
| |
| void Stencil::enable() { |
| if (mState == StencilState::Disabled) { |
| glEnable(GL_STENCIL_TEST); |
| } |
| } |
| |
| void Stencil::disable() { |
| if (mState != StencilState::Disabled) { |
| glDisable(GL_STENCIL_TEST); |
| mState = StencilState::Disabled; |
| } |
| } |
| |
| void Stencil::dump() { |
| ALOGD("Stencil: state %d", mState); |
| } |
| |
| }; // namespace uirenderer |
| }; // namespace android |