stencil.c revision cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290
1/* $Id: stencil.c,v 1.24 2000/12/26 05:09:29 keithw Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2000  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#ifdef PC_HEADER
29#include "all.h"
30#else
31#include "glheader.h"
32#include "context.h"
33#include "depth.h"
34#include "macros.h"
35#include "mem.h"
36#include "stencil.h"
37#include "mtypes.h"
38#include "enable.h"
39#endif
40
41
42
43
44void
45_mesa_ClearStencil( GLint s )
46{
47   GET_CURRENT_CONTEXT(ctx);
48   ASSERT_OUTSIDE_BEGIN_END(ctx);
49
50   if (ctx->Stencil.Clear == (GLstencil) s)
51      return;
52
53   FLUSH_VERTICES(ctx, _NEW_STENCIL);
54   ctx->Stencil.Clear = (GLstencil) s;
55
56   if (ctx->Driver.ClearStencil) {
57      (*ctx->Driver.ClearStencil)( ctx, s );
58   }
59}
60
61
62
63void
64_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
65{
66   GET_CURRENT_CONTEXT(ctx);
67   GLint maxref;
68   ASSERT_OUTSIDE_BEGIN_END(ctx);
69
70   switch (func) {
71      case GL_NEVER:
72      case GL_LESS:
73      case GL_LEQUAL:
74      case GL_GREATER:
75      case GL_GEQUAL:
76      case GL_EQUAL:
77      case GL_NOTEQUAL:
78      case GL_ALWAYS:
79         break;
80      default:
81         gl_error( ctx, GL_INVALID_ENUM, "glStencilFunc" );
82         return;
83   }
84
85   maxref = (1 << STENCIL_BITS) - 1;
86   ref = (GLstencil) CLAMP( ref, 0, maxref );
87
88   if (ctx->Stencil.Function == func &&
89       ctx->Stencil.ValueMask == (GLstencil) mask &&
90       ctx->Stencil.Ref == ref)
91      return;
92
93   FLUSH_VERTICES(ctx, _NEW_STENCIL);
94   ctx->Stencil.Function = func;
95   ctx->Stencil.Ref = ref;
96   ctx->Stencil.ValueMask = (GLstencil) mask;
97
98   if (ctx->Driver.StencilFunc) {
99      (*ctx->Driver.StencilFunc)( ctx, func, ctx->Stencil.Ref, mask );
100   }
101}
102
103
104
105void
106_mesa_StencilMask( GLuint mask )
107{
108   GET_CURRENT_CONTEXT(ctx);
109   ASSERT_OUTSIDE_BEGIN_END(ctx);
110
111   if (ctx->Stencil.WriteMask == (GLstencil) mask)
112	 return;
113
114   FLUSH_VERTICES(ctx, _NEW_STENCIL);
115   ctx->Stencil.WriteMask = (GLstencil) mask;
116
117   if (ctx->Driver.StencilMask) {
118      (*ctx->Driver.StencilMask)( ctx, mask );
119   }
120}
121
122
123
124void
125_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
126{
127   GET_CURRENT_CONTEXT(ctx);
128   ASSERT_OUTSIDE_BEGIN_END(ctx);
129
130   switch (fail) {
131      case GL_KEEP:
132      case GL_ZERO:
133      case GL_REPLACE:
134      case GL_INCR:
135      case GL_DECR:
136      case GL_INVERT:
137         ctx->Stencil.FailFunc = fail;
138         break;
139      case GL_INCR_WRAP_EXT:
140      case GL_DECR_WRAP_EXT:
141         if (!ctx->Extensions.EXT_stencil_wrap) {
142            break;
143         }
144         /* FALL-THROUGH */
145      default:
146         gl_error(ctx, GL_INVALID_ENUM, "glStencilOp");
147         return;
148   }
149   switch (zfail) {
150      case GL_KEEP:
151      case GL_ZERO:
152      case GL_REPLACE:
153      case GL_INCR:
154      case GL_DECR:
155      case GL_INVERT:
156         break;
157      case GL_INCR_WRAP_EXT:
158      case GL_DECR_WRAP_EXT:
159         if (ctx->Extensions.EXT_stencil_wrap) {
160            break;
161         }
162         /* FALL-THROUGH */
163      default:
164         gl_error(ctx, GL_INVALID_ENUM, "glStencilOp");
165         return;
166   }
167   switch (zpass) {
168      case GL_KEEP:
169      case GL_ZERO:
170      case GL_REPLACE:
171      case GL_INCR:
172      case GL_DECR:
173      case GL_INVERT:
174         break;
175      case GL_INCR_WRAP_EXT:
176      case GL_DECR_WRAP_EXT:
177         if (ctx->Extensions.EXT_stencil_wrap) {
178            break;
179         }
180         /* FALL-THROUGH */
181      default:
182         gl_error(ctx, GL_INVALID_ENUM, "glStencilOp");
183         return;
184   }
185
186   if (ctx->Stencil.ZFailFunc == zfail &&
187       ctx->Stencil.ZPassFunc == zpass &&
188       ctx->Stencil.FailFunc == fail)
189      return;
190
191   FLUSH_VERTICES(ctx, _NEW_STENCIL);
192   ctx->Stencil.ZFailFunc = zfail;
193   ctx->Stencil.ZPassFunc = zpass;
194   ctx->Stencil.FailFunc = fail;
195
196   if (ctx->Driver.StencilOp) {
197      (*ctx->Driver.StencilOp)(ctx, fail, zfail, zpass);
198   }
199}
200
201