1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "renderstate/Stencil.h" 18 19 #include "Caches.h" 20 #include "Debug.h" 21 #include "Extensions.h" 22 #include "Properties.h" 23 24 #include <GLES2/gl2ext.h> 25 26 namespace android { 27 namespace uirenderer { 28 29 #if DEBUG_STENCIL 30 #define STENCIL_WRITE_VALUE 0xff 31 #define STENCIL_MASK_VALUE 0xff 32 #else 33 #define STENCIL_WRITE_VALUE 0x1 34 #define STENCIL_MASK_VALUE 0x1 35 #endif 36 37 Stencil::Stencil() 38 : mState(kDisabled) { 39 } 40 41 uint8_t Stencil::getStencilSize() { 42 return STENCIL_BUFFER_SIZE; 43 } 44 45 /** 46 * This method will return either GL_STENCIL_INDEX4_OES if supported, 47 * GL_STENCIL_INDEX8 if not. 48 * 49 * Layers can't use a single bit stencil because multi-rect ClipArea needs a high enough 50 * stencil resolution to represent the summation of multiple intersecting rect geometries. 51 */ 52 GLenum Stencil::getLayerStencilFormat() { 53 #if !DEBUG_STENCIL 54 const Extensions& extensions = Caches::getInstance().extensions(); 55 if (extensions.has4BitStencil()) { 56 return GL_STENCIL_INDEX4_OES; 57 } 58 #endif 59 return GL_STENCIL_INDEX8; 60 } 61 62 void Stencil::clear() { 63 glStencilMask(0xff); 64 glClearStencil(0); 65 glClear(GL_STENCIL_BUFFER_BIT); 66 67 if (mState == kTest) { 68 // reset to test state, with immutable stencil 69 glStencilMask(0); 70 } 71 } 72 73 void Stencil::enableTest(int incrementThreshold) { 74 if (mState != kTest) { 75 enable(); 76 if (incrementThreshold > 0) { 77 glStencilFunc(GL_EQUAL, incrementThreshold, 0xff); 78 } else { 79 glStencilFunc(GL_EQUAL, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE); 80 } 81 // We only want to test, let's keep everything 82 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 83 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 84 glStencilMask(0); 85 mState = kTest; 86 } 87 } 88 89 void Stencil::enableWrite(int incrementThreshold) { 90 if (mState != kWrite) { 91 enable(); 92 if (incrementThreshold > 0) { 93 glStencilFunc(GL_ALWAYS, 1, 0xff); 94 // The test always passes so the first two values are meaningless 95 glStencilOp(GL_INCR, GL_INCR, GL_INCR); 96 } else { 97 glStencilFunc(GL_ALWAYS, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE); 98 // The test always passes so the first two values are meaningless 99 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 100 } 101 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 102 glStencilMask(0xff); 103 mState = kWrite; 104 } 105 } 106 107 void Stencil::enableDebugTest(GLint value, bool greater) { 108 enable(); 109 glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff); 110 // We only want to test, let's keep everything 111 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 112 mState = kTest; 113 glStencilMask(0); 114 } 115 116 void Stencil::enableDebugWrite() { 117 enable(); 118 glStencilFunc(GL_ALWAYS, 0x1, 0xffffffff); 119 // The test always passes so the first two values are meaningless 120 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); 121 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 122 mState = kWrite; 123 glStencilMask(0xff); 124 } 125 126 void Stencil::enable() { 127 if (mState == kDisabled) { 128 glEnable(GL_STENCIL_TEST); 129 } 130 } 131 132 void Stencil::disable() { 133 if (mState != kDisabled) { 134 glDisable(GL_STENCIL_TEST); 135 mState = kDisabled; 136 } 137 } 138 139 void Stencil::dump() { 140 ALOGD("Stencil: state %d", mState); 141 } 142 143 }; // namespace uirenderer 144 }; // namespace android 145