stencil.c revision 01e04c3f
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/**
27 * \file stencil.c
28 * Stencil operations.
29 *
30 * Note: There's some conflict between GL_EXT_stencil_two_side and
31 * OpenGL 2.0's two-sided stencil feature.
32 *
33 * With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
34 * front OR back face state (as set by glActiveStencilFaceEXT) is set.
35 *
36 * But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
37 * front AND back state.
38 *
39 * Also, note that GL_ATI_separate_stencil is different as well:
40 * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...)  vs.
41 * glStencilFuncSeparate(GLenum face, GLenum func, ...).
42 *
43 * This problem is solved by keeping three sets of stencil state:
44 *  state[0] = GL_FRONT state.
45 *  state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
46 *  state[2] = GL_EXT_stencil_two_side GL_BACK state.
47 */
48
49
50#include "glheader.h"
51#include "imports.h"
52#include "context.h"
53#include "macros.h"
54#include "stencil.h"
55#include "mtypes.h"
56
57
58static GLboolean
59validate_stencil_op(struct gl_context *ctx, GLenum op)
60{
61   switch (op) {
62   case GL_KEEP:
63   case GL_ZERO:
64   case GL_REPLACE:
65   case GL_INCR:
66   case GL_DECR:
67   case GL_INVERT:
68   case GL_INCR_WRAP:
69   case GL_DECR_WRAP:
70      return GL_TRUE;
71   default:
72      return GL_FALSE;
73   }
74}
75
76
77static GLboolean
78validate_stencil_func(struct gl_context *ctx, GLenum func)
79{
80   switch (func) {
81   case GL_NEVER:
82   case GL_LESS:
83   case GL_LEQUAL:
84   case GL_GREATER:
85   case GL_GEQUAL:
86   case GL_EQUAL:
87   case GL_NOTEQUAL:
88   case GL_ALWAYS:
89      return GL_TRUE;
90   default:
91      return GL_FALSE;
92   }
93}
94
95
96/**
97 * Set the clear value for the stencil buffer.
98 *
99 * \param s clear value.
100 *
101 * \sa glClearStencil().
102 *
103 * Updates gl_stencil_attrib::Clear. On change
104 * flushes the vertices and notifies the driver via
105 * the dd_function_table::ClearStencil callback.
106 */
107void GLAPIENTRY
108_mesa_ClearStencil( GLint s )
109{
110   GET_CURRENT_CONTEXT(ctx);
111
112   if (MESA_VERBOSE & VERBOSE_API)
113      _mesa_debug(ctx, "glClearStencil(%d)\n", s);
114
115   ctx->Stencil.Clear = (GLuint) s;
116}
117
118
119/**
120 * Set the function and reference value for stencil testing.
121 *
122 * \param frontfunc front test function.
123 * \param backfunc back test function.
124 * \param ref front and back reference value.
125 * \param mask front and back bitmask.
126 *
127 * \sa glStencilFunc().
128 *
129 * Verifies the parameters and updates the respective values in
130 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
131 * the driver via the dd_function_table::StencilFunc callback.
132 */
133void GLAPIENTRY
134_mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask )
135{
136   GET_CURRENT_CONTEXT(ctx);
137
138   if (MESA_VERBOSE & VERBOSE_API)
139      _mesa_debug(ctx, "glStencilFuncSeparateATI()\n");
140
141   if (!validate_stencil_func(ctx, frontfunc)) {
142      _mesa_error(ctx, GL_INVALID_ENUM,
143                  "glStencilFuncSeparateATI(frontfunc)");
144      return;
145   }
146   if (!validate_stencil_func(ctx, backfunc)) {
147      _mesa_error(ctx, GL_INVALID_ENUM,
148                  "glStencilFuncSeparateATI(backfunc)");
149      return;
150   }
151
152   /* set both front and back state */
153   if (ctx->Stencil.Function[0] == frontfunc &&
154       ctx->Stencil.Function[1] == backfunc &&
155       ctx->Stencil.ValueMask[0] == mask &&
156       ctx->Stencil.ValueMask[1] == mask &&
157       ctx->Stencil.Ref[0] == ref &&
158       ctx->Stencil.Ref[1] == ref)
159      return;
160   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
161   ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
162   ctx->Stencil.Function[0]  = frontfunc;
163   ctx->Stencil.Function[1]  = backfunc;
164   ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
165   ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
166   if (ctx->Driver.StencilFuncSeparate) {
167      ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
168                                      frontfunc, ref, mask);
169      ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
170                                      backfunc, ref, mask);
171   }
172}
173
174
175/**
176 * Set the function and reference value for stencil testing.
177 *
178 * \param func test function.
179 * \param ref reference value.
180 * \param mask bitmask.
181 *
182 * \sa glStencilFunc().
183 *
184 * Verifies the parameters and updates the respective values in
185 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
186 * the driver via the dd_function_table::StencilFunc callback.
187 */
188static void
189stencil_func(struct gl_context *ctx, GLenum func, GLint ref, GLuint mask)
190{
191   const GLint face = ctx->Stencil.ActiveFace;
192
193   if (face != 0) {
194      if (ctx->Stencil.Function[face] == func &&
195          ctx->Stencil.ValueMask[face] == mask &&
196          ctx->Stencil.Ref[face] == ref)
197         return;
198      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
199      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
200      ctx->Stencil.Function[face] = func;
201      ctx->Stencil.Ref[face] = ref;
202      ctx->Stencil.ValueMask[face] = mask;
203
204      /* Only propagate the change to the driver if EXT_stencil_two_side
205       * is enabled.
206       */
207      if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
208         ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
209      }
210   }
211   else {
212      /* set both front and back state */
213      if (ctx->Stencil.Function[0] == func &&
214          ctx->Stencil.Function[1] == func &&
215          ctx->Stencil.ValueMask[0] == mask &&
216          ctx->Stencil.ValueMask[1] == mask &&
217          ctx->Stencil.Ref[0] == ref &&
218          ctx->Stencil.Ref[1] == ref)
219         return;
220      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
221      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
222      ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
223      ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
224      ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
225      if (ctx->Driver.StencilFuncSeparate) {
226         ctx->Driver.StencilFuncSeparate(ctx,
227					 ((ctx->Stencil.TestTwoSide)
228					  ? GL_FRONT : GL_FRONT_AND_BACK),
229                                         func, ref, mask);
230      }
231   }
232}
233
234
235void GLAPIENTRY
236_mesa_StencilFunc_no_error(GLenum func, GLint ref, GLuint mask)
237{
238   GET_CURRENT_CONTEXT(ctx);
239   stencil_func(ctx, func, ref, mask);
240}
241
242
243void GLAPIENTRY
244_mesa_StencilFunc(GLenum func, GLint ref, GLuint mask)
245{
246   GET_CURRENT_CONTEXT(ctx);
247
248   if (MESA_VERBOSE & VERBOSE_API)
249      _mesa_debug(ctx, "glStencilFunc()\n");
250
251   if (!validate_stencil_func(ctx, func)) {
252      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
253      return;
254   }
255
256   stencil_func(ctx, func, ref, mask);
257}
258
259
260/**
261 * Set the stencil writing mask.
262 *
263 * \param mask bit-mask to enable/disable writing of individual bits in the
264 * stencil planes.
265 *
266 * \sa glStencilMask().
267 *
268 * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
269 * notifies the driver via the dd_function_table::StencilMask callback.
270 */
271void GLAPIENTRY
272_mesa_StencilMask( GLuint mask )
273{
274   GET_CURRENT_CONTEXT(ctx);
275   const GLint face = ctx->Stencil.ActiveFace;
276
277   if (MESA_VERBOSE & VERBOSE_API)
278      _mesa_debug(ctx, "glStencilMask()\n");
279
280   if (face != 0) {
281      /* Only modify the EXT_stencil_two_side back-face state.
282       */
283      if (ctx->Stencil.WriteMask[face] == mask)
284         return;
285      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
286      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
287      ctx->Stencil.WriteMask[face] = mask;
288
289      /* Only propagate the change to the driver if EXT_stencil_two_side
290       * is enabled.
291       */
292      if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
293         ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
294      }
295   }
296   else {
297      /* set both front and back state */
298      if (ctx->Stencil.WriteMask[0] == mask &&
299          ctx->Stencil.WriteMask[1] == mask)
300         return;
301      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
302      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
303      ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
304      if (ctx->Driver.StencilMaskSeparate) {
305         ctx->Driver.StencilMaskSeparate(ctx,
306					 ((ctx->Stencil.TestTwoSide)
307					  ? GL_FRONT : GL_FRONT_AND_BACK),
308					  mask);
309      }
310   }
311}
312
313
314/**
315 * Set the stencil test actions.
316 *
317 * \param fail action to take when stencil test fails.
318 * \param zfail action to take when stencil test passes, but depth test fails.
319 * \param zpass action to take when stencil test passes and the depth test
320 * passes (or depth testing is not enabled).
321 *
322 * \sa glStencilOp().
323 *
324 * Verifies the parameters and updates the respective fields in
325 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
326 * the driver via the dd_function_table::StencilOp callback.
327 */
328static void
329stencil_op(struct gl_context *ctx, GLenum fail, GLenum zfail, GLenum zpass)
330{
331   const GLint face = ctx->Stencil.ActiveFace;
332
333   if (face != 0) {
334      /* only set active face state */
335      if (ctx->Stencil.ZFailFunc[face] == zfail &&
336          ctx->Stencil.ZPassFunc[face] == zpass &&
337          ctx->Stencil.FailFunc[face] == fail)
338         return;
339      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
340      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
341      ctx->Stencil.ZFailFunc[face] = zfail;
342      ctx->Stencil.ZPassFunc[face] = zpass;
343      ctx->Stencil.FailFunc[face] = fail;
344
345      /* Only propagate the change to the driver if EXT_stencil_two_side
346       * is enabled.
347       */
348      if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
349         ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
350      }
351   }
352   else {
353      /* set both front and back state */
354      if (ctx->Stencil.ZFailFunc[0] == zfail &&
355          ctx->Stencil.ZFailFunc[1] == zfail &&
356          ctx->Stencil.ZPassFunc[0] == zpass &&
357          ctx->Stencil.ZPassFunc[1] == zpass &&
358          ctx->Stencil.FailFunc[0] == fail &&
359          ctx->Stencil.FailFunc[1] == fail)
360         return;
361      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
362      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
363      ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
364      ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
365      ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
366      if (ctx->Driver.StencilOpSeparate) {
367         ctx->Driver.StencilOpSeparate(ctx,
368				       ((ctx->Stencil.TestTwoSide)
369					? GL_FRONT : GL_FRONT_AND_BACK),
370                                       fail, zfail, zpass);
371      }
372   }
373}
374
375
376void GLAPIENTRY
377_mesa_StencilOp_no_error(GLenum fail, GLenum zfail, GLenum zpass)
378{
379   GET_CURRENT_CONTEXT(ctx);
380   stencil_op(ctx, fail, zfail, zpass);
381}
382
383
384void GLAPIENTRY
385_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
386{
387   GET_CURRENT_CONTEXT(ctx);
388
389   if (MESA_VERBOSE & VERBOSE_API)
390      _mesa_debug(ctx, "glStencilOp()\n");
391
392   if (!validate_stencil_op(ctx, fail)) {
393      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
394      return;
395   }
396
397   if (!validate_stencil_op(ctx, zfail)) {
398      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
399      return;
400   }
401
402   if (!validate_stencil_op(ctx, zpass)) {
403      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
404      return;
405   }
406
407   stencil_op(ctx, fail, zfail, zpass);
408}
409
410
411/* GL_EXT_stencil_two_side */
412void GLAPIENTRY
413_mesa_ActiveStencilFaceEXT(GLenum face)
414{
415   GET_CURRENT_CONTEXT(ctx);
416
417   if (MESA_VERBOSE & VERBOSE_API)
418      _mesa_debug(ctx, "glActiveStencilFaceEXT()\n");
419
420   if (!ctx->Extensions.EXT_stencil_two_side) {
421      _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
422      return;
423   }
424
425   if (face == GL_FRONT || face == GL_BACK) {
426      ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
427   }
428   else {
429      _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
430   }
431}
432
433
434static void
435stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum sfail,
436                    GLenum zfail, GLenum zpass)
437{
438   GLboolean set = GL_FALSE;
439
440   if (face != GL_BACK) {
441      /* set front */
442      if (ctx->Stencil.ZFailFunc[0] != zfail ||
443          ctx->Stencil.ZPassFunc[0] != zpass ||
444          ctx->Stencil.FailFunc[0] != sfail){
445         FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
446         ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
447         ctx->Stencil.ZFailFunc[0] = zfail;
448         ctx->Stencil.ZPassFunc[0] = zpass;
449         ctx->Stencil.FailFunc[0] = sfail;
450         set = GL_TRUE;
451      }
452   }
453
454   if (face != GL_FRONT) {
455      /* set back */
456      if (ctx->Stencil.ZFailFunc[1] != zfail ||
457          ctx->Stencil.ZPassFunc[1] != zpass ||
458          ctx->Stencil.FailFunc[1] != sfail) {
459         FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
460         ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
461         ctx->Stencil.ZFailFunc[1] = zfail;
462         ctx->Stencil.ZPassFunc[1] = zpass;
463         ctx->Stencil.FailFunc[1] = sfail;
464         set = GL_TRUE;
465      }
466   }
467
468   if (set && ctx->Driver.StencilOpSeparate) {
469      ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
470   }
471}
472
473
474void GLAPIENTRY
475_mesa_StencilOpSeparate_no_error(GLenum face, GLenum sfail, GLenum zfail,
476                                 GLenum zpass)
477{
478   GET_CURRENT_CONTEXT(ctx);
479   stencil_op_separate(ctx, face, sfail, zfail, zpass);
480}
481
482
483void GLAPIENTRY
484_mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
485{
486   GET_CURRENT_CONTEXT(ctx);
487
488   if (MESA_VERBOSE & VERBOSE_API)
489      _mesa_debug(ctx, "glStencilOpSeparate()\n");
490
491   if (!validate_stencil_op(ctx, sfail)) {
492      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
493      return;
494   }
495
496   if (!validate_stencil_op(ctx, zfail)) {
497      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
498      return;
499   }
500
501   if (!validate_stencil_op(ctx, zpass)) {
502      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
503      return;
504   }
505
506   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
507      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
508      return;
509   }
510
511   stencil_op_separate(ctx, face, sfail, zfail, zpass);
512}
513
514
515static void
516stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func,
517                      GLint ref, GLuint mask)
518{
519   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
520   ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
521
522   if (face != GL_BACK) {
523      /* set front */
524      ctx->Stencil.Function[0] = func;
525      ctx->Stencil.Ref[0] = ref;
526      ctx->Stencil.ValueMask[0] = mask;
527   }
528
529   if (face != GL_FRONT) {
530      /* set back */
531      ctx->Stencil.Function[1] = func;
532      ctx->Stencil.Ref[1] = ref;
533      ctx->Stencil.ValueMask[1] = mask;
534   }
535
536   if (ctx->Driver.StencilFuncSeparate) {
537      ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
538   }
539}
540
541
542/* OpenGL 2.0 */
543void GLAPIENTRY
544_mesa_StencilFuncSeparate_no_error(GLenum face, GLenum func, GLint ref,
545                                   GLuint mask)
546{
547   GET_CURRENT_CONTEXT(ctx);
548   stencil_func_separate(ctx, face, func, ref, mask);
549}
550
551
552void GLAPIENTRY
553_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
554{
555   GET_CURRENT_CONTEXT(ctx);
556
557   if (MESA_VERBOSE & VERBOSE_API)
558      _mesa_debug(ctx, "glStencilFuncSeparate()\n");
559
560   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
561      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
562      return;
563   }
564
565   if (!validate_stencil_func(ctx, func)) {
566      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
567      return;
568   }
569
570   stencil_func_separate(ctx, face, func, ref, mask);
571}
572
573
574static void
575stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask)
576{
577   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
578   ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
579
580   if (face != GL_BACK) {
581      ctx->Stencil.WriteMask[0] = mask;
582   }
583
584   if (face != GL_FRONT) {
585      ctx->Stencil.WriteMask[1] = mask;
586   }
587
588   if (ctx->Driver.StencilMaskSeparate) {
589      ctx->Driver.StencilMaskSeparate(ctx, face, mask);
590   }
591}
592
593
594/* OpenGL 2.0 */
595void GLAPIENTRY
596_mesa_StencilMaskSeparate_no_error(GLenum face, GLuint mask)
597{
598   GET_CURRENT_CONTEXT(ctx);
599   stencil_mask_separate(ctx, face, mask);
600}
601
602
603void GLAPIENTRY
604_mesa_StencilMaskSeparate(GLenum face, GLuint mask)
605{
606   GET_CURRENT_CONTEXT(ctx);
607
608   if (MESA_VERBOSE & VERBOSE_API)
609      _mesa_debug(ctx, "glStencilMaskSeparate()\n");
610
611   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
612      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
613      return;
614   }
615
616   stencil_mask_separate(ctx, face, mask);
617}
618
619
620/**
621 * Initialize the context stipple state.
622 *
623 * \param ctx GL context.
624 *
625 * Initializes __struct gl_contextRec::Stencil attribute group.
626 */
627void
628_mesa_init_stencil(struct gl_context *ctx)
629{
630   ctx->Stencil.Enabled = GL_FALSE;
631   ctx->Stencil.TestTwoSide = GL_FALSE;
632   ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
633   ctx->Stencil.Function[0] = GL_ALWAYS;
634   ctx->Stencil.Function[1] = GL_ALWAYS;
635   ctx->Stencil.Function[2] = GL_ALWAYS;
636   ctx->Stencil.FailFunc[0] = GL_KEEP;
637   ctx->Stencil.FailFunc[1] = GL_KEEP;
638   ctx->Stencil.FailFunc[2] = GL_KEEP;
639   ctx->Stencil.ZPassFunc[0] = GL_KEEP;
640   ctx->Stencil.ZPassFunc[1] = GL_KEEP;
641   ctx->Stencil.ZPassFunc[2] = GL_KEEP;
642   ctx->Stencil.ZFailFunc[0] = GL_KEEP;
643   ctx->Stencil.ZFailFunc[1] = GL_KEEP;
644   ctx->Stencil.ZFailFunc[2] = GL_KEEP;
645   ctx->Stencil.Ref[0] = 0;
646   ctx->Stencil.Ref[1] = 0;
647   ctx->Stencil.Ref[2] = 0;
648
649   /* 4.1.4 Stencil Test section of the GL-ES 3.0 specification says:
650    *
651    *     "In the initial state, [...] the front and back stencil mask are both
652    *     set to the value 2^s − 1, where s is greater than or equal to the
653    *     number of bits in the deepest stencil buffer* supported by the GL
654    *     implementation."
655    *
656    * Since the maximum supported precision for stencil buffers is 8 bits,
657    * mask values should be initialized to 2^8 - 1 = 0xFF.
658    */
659   ctx->Stencil.ValueMask[0] = 0xFF;
660   ctx->Stencil.ValueMask[1] = 0xFF;
661   ctx->Stencil.ValueMask[2] = 0xFF;
662   ctx->Stencil.WriteMask[0] = 0xFF;
663   ctx->Stencil.WriteMask[1] = 0xFF;
664   ctx->Stencil.WriteMask[2] = 0xFF;
665
666   ctx->Stencil.Clear = 0;
667   ctx->Stencil._BackFace = 1;
668}
669