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