| /* |
| * 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 |
| |
| Stencil::Stencil() |
| : mState(kDisabled) { |
| } |
| |
| uint8_t Stencil::getStencilSize() { |
| return STENCIL_BUFFER_SIZE; |
| } |
| |
| GLenum Stencil::getSmallestStencilFormat() { |
| #if !DEBUG_STENCIL |
| const Extensions& extensions = Caches::getInstance().extensions(); |
| if (extensions.has1BitStencil()) { |
| return GL_STENCIL_INDEX1_OES; |
| } else if (extensions.has4BitStencil()) { |
| return GL_STENCIL_INDEX4_OES; |
| } |
| #endif |
| return GL_STENCIL_INDEX8; |
| } |
| |
| void Stencil::clear() { |
| glClearStencil(0); |
| glClear(GL_STENCIL_BUFFER_BIT); |
| } |
| |
| void Stencil::enableTest(int incrementThreshold) { |
| if (mState != kTest) { |
| 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 = kTest; |
| } |
| } |
| |
| void Stencil::enableWrite(int incrementThreshold) { |
| if (mState != kWrite) { |
| 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 = kWrite; |
| } |
| } |
| |
| 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 = kTest; |
| } |
| |
| void Stencil::enableDebugWrite() { |
| if (mState != kWrite) { |
| 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 = kWrite; |
| } |
| } |
| |
| void Stencil::enable() { |
| if (mState == kDisabled) { |
| glEnable(GL_STENCIL_TEST); |
| } |
| } |
| |
| void Stencil::disable() { |
| if (mState != kDisabled) { |
| glDisable(GL_STENCIL_TEST); |
| mState = kDisabled; |
| } |
| } |
| |
| void Stencil::dump() { |
| ALOGD("Stencil: state %d", mState); |
| } |
| |
| }; // namespace uirenderer |
| }; // namespace android |