Removed all RCS / CVS tags (Id, Header, Date, etc.) from everything.
[mesa.git] / src / mesa / main / stencil.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 4.1
5 *
6 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 #include "glheader.h"
28 #include "imports.h"
29 #include "context.h"
30 #include "depth.h"
31 #include "macros.h"
32 #include "stencil.h"
33 #include "mtypes.h"
34 #include "enable.h"
35
36
37 void
38 _mesa_ClearStencil( GLint s )
39 {
40 GET_CURRENT_CONTEXT(ctx);
41 ASSERT_OUTSIDE_BEGIN_END(ctx);
42
43 if (ctx->Stencil.Clear == (GLstencil) s)
44 return;
45
46 FLUSH_VERTICES(ctx, _NEW_STENCIL);
47 ctx->Stencil.Clear = (GLstencil) s;
48
49 if (ctx->Driver.ClearStencil) {
50 (*ctx->Driver.ClearStencil)( ctx, s );
51 }
52 }
53
54
55
56 void
57 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
58 {
59 GET_CURRENT_CONTEXT(ctx);
60 const GLint face = ctx->Stencil.ActiveFace;
61 GLint maxref;
62 ASSERT_OUTSIDE_BEGIN_END(ctx);
63
64 switch (func) {
65 case GL_NEVER:
66 case GL_LESS:
67 case GL_LEQUAL:
68 case GL_GREATER:
69 case GL_GEQUAL:
70 case GL_EQUAL:
71 case GL_NOTEQUAL:
72 case GL_ALWAYS:
73 break;
74 default:
75 _mesa_error( ctx, GL_INVALID_ENUM, "glStencilFunc" );
76 return;
77 }
78
79 maxref = (1 << STENCIL_BITS) - 1;
80 ref = (GLstencil) CLAMP( ref, 0, maxref );
81
82 if (ctx->Stencil.Function[face] == func &&
83 ctx->Stencil.ValueMask[face] == (GLstencil) mask &&
84 ctx->Stencil.Ref[face] == ref)
85 return;
86
87 FLUSH_VERTICES(ctx, _NEW_STENCIL);
88 ctx->Stencil.Function[face] = func;
89 ctx->Stencil.Ref[face] = ref;
90 ctx->Stencil.ValueMask[face] = (GLstencil) mask;
91
92 if (ctx->Driver.StencilFunc) {
93 (*ctx->Driver.StencilFunc)( ctx, func, ref, mask );
94 }
95 }
96
97
98
99 void
100 _mesa_StencilMask( GLuint mask )
101 {
102 GET_CURRENT_CONTEXT(ctx);
103 const GLint face = ctx->Stencil.ActiveFace;
104 ASSERT_OUTSIDE_BEGIN_END(ctx);
105
106 if (ctx->Stencil.WriteMask[face] == (GLstencil) mask)
107 return;
108
109 FLUSH_VERTICES(ctx, _NEW_STENCIL);
110 ctx->Stencil.WriteMask[face] = (GLstencil) mask;
111
112 if (ctx->Driver.StencilMask) {
113 (*ctx->Driver.StencilMask)( ctx, mask );
114 }
115 }
116
117
118
119 void
120 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
121 {
122 GET_CURRENT_CONTEXT(ctx);
123 const GLint face = ctx->Stencil.ActiveFace;
124 ASSERT_OUTSIDE_BEGIN_END(ctx);
125
126 switch (fail) {
127 case GL_KEEP:
128 case GL_ZERO:
129 case GL_REPLACE:
130 case GL_INCR:
131 case GL_DECR:
132 case GL_INVERT:
133 break;
134 case GL_INCR_WRAP_EXT:
135 case GL_DECR_WRAP_EXT:
136 if (ctx->Extensions.EXT_stencil_wrap) {
137 break;
138 }
139 /* FALL-THROUGH */
140 default:
141 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp");
142 return;
143 }
144 switch (zfail) {
145 case GL_KEEP:
146 case GL_ZERO:
147 case GL_REPLACE:
148 case GL_INCR:
149 case GL_DECR:
150 case GL_INVERT:
151 break;
152 case GL_INCR_WRAP_EXT:
153 case GL_DECR_WRAP_EXT:
154 if (ctx->Extensions.EXT_stencil_wrap) {
155 break;
156 }
157 /* FALL-THROUGH */
158 default:
159 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp");
160 return;
161 }
162 switch (zpass) {
163 case GL_KEEP:
164 case GL_ZERO:
165 case GL_REPLACE:
166 case GL_INCR:
167 case GL_DECR:
168 case GL_INVERT:
169 break;
170 case GL_INCR_WRAP_EXT:
171 case GL_DECR_WRAP_EXT:
172 if (ctx->Extensions.EXT_stencil_wrap) {
173 break;
174 }
175 /* FALL-THROUGH */
176 default:
177 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp");
178 return;
179 }
180
181 if (ctx->Stencil.ZFailFunc[face] == zfail &&
182 ctx->Stencil.ZPassFunc[face] == zpass &&
183 ctx->Stencil.FailFunc[face] == fail)
184 return;
185
186 FLUSH_VERTICES(ctx, _NEW_STENCIL);
187 ctx->Stencil.ZFailFunc[face] = zfail;
188 ctx->Stencil.ZPassFunc[face] = zpass;
189 ctx->Stencil.FailFunc[face] = fail;
190
191 if (ctx->Driver.StencilOp) {
192 (*ctx->Driver.StencilOp)(ctx, fail, zfail, zpass);
193 }
194 }
195
196
197 /* GL_EXT_stencil_two_side */
198 void
199 _mesa_ActiveStencilFaceEXT(GLenum face)
200 {
201 GET_CURRENT_CONTEXT(ctx);
202 ASSERT_OUTSIDE_BEGIN_END(ctx);
203
204 if (face == GL_FRONT || face == GL_BACK) {
205 FLUSH_VERTICES(ctx, _NEW_STENCIL);
206 ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 1;
207 }
208
209 if (ctx->Driver.ActiveStencilFace) {
210 (*ctx->Driver.ActiveStencilFace)( ctx, (GLuint) ctx->Stencil.ActiveFace );
211 }
212 }
213