• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
58 static GLboolean
validate_stencil_op(struct gl_context * ctx,GLenum op)59 validate_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 
77 static GLboolean
validate_stencil_func(struct gl_context * ctx,GLenum func)78 validate_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  */
107 void GLAPIENTRY
_mesa_ClearStencil(GLint s)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  */
133 void GLAPIENTRY
_mesa_StencilFuncSeparateATI(GLenum frontfunc,GLenum backfunc,GLint ref,GLuint mask)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, _NEW_STENCIL);
161    ctx->Stencil.Function[0]  = frontfunc;
162    ctx->Stencil.Function[1]  = backfunc;
163    ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
164    ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
165    if (ctx->Driver.StencilFuncSeparate) {
166       ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
167                                       frontfunc, ref, mask);
168       ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
169                                       backfunc, ref, mask);
170    }
171 }
172 
173 
174 /**
175  * Set the function and reference value for stencil testing.
176  *
177  * \param func test function.
178  * \param ref reference value.
179  * \param mask bitmask.
180  *
181  * \sa glStencilFunc().
182  *
183  * Verifies the parameters and updates the respective values in
184  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
185  * the driver via the dd_function_table::StencilFunc callback.
186  */
187 void GLAPIENTRY
_mesa_StencilFunc(GLenum func,GLint ref,GLuint mask)188 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
189 {
190    GET_CURRENT_CONTEXT(ctx);
191    const GLint face = ctx->Stencil.ActiveFace;
192 
193    if (MESA_VERBOSE & VERBOSE_API)
194       _mesa_debug(ctx, "glStencilFunc()\n");
195 
196    if (!validate_stencil_func(ctx, func)) {
197       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
198       return;
199    }
200 
201    if (face != 0) {
202       if (ctx->Stencil.Function[face] == func &&
203           ctx->Stencil.ValueMask[face] == mask &&
204           ctx->Stencil.Ref[face] == ref)
205          return;
206       FLUSH_VERTICES(ctx, _NEW_STENCIL);
207       ctx->Stencil.Function[face] = func;
208       ctx->Stencil.Ref[face] = ref;
209       ctx->Stencil.ValueMask[face] = mask;
210 
211       /* Only propagate the change to the driver if EXT_stencil_two_side
212        * is enabled.
213        */
214       if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
215          ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
216       }
217    }
218    else {
219       /* set both front and back state */
220       if (ctx->Stencil.Function[0] == func &&
221           ctx->Stencil.Function[1] == func &&
222           ctx->Stencil.ValueMask[0] == mask &&
223           ctx->Stencil.ValueMask[1] == mask &&
224           ctx->Stencil.Ref[0] == ref &&
225           ctx->Stencil.Ref[1] == ref)
226          return;
227       FLUSH_VERTICES(ctx, _NEW_STENCIL);
228       ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
229       ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
230       ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
231       if (ctx->Driver.StencilFuncSeparate) {
232          ctx->Driver.StencilFuncSeparate(ctx,
233 					 ((ctx->Stencil.TestTwoSide)
234 					  ? GL_FRONT : GL_FRONT_AND_BACK),
235                                          func, ref, mask);
236       }
237    }
238 }
239 
240 
241 /**
242  * Set the stencil writing mask.
243  *
244  * \param mask bit-mask to enable/disable writing of individual bits in the
245  * stencil planes.
246  *
247  * \sa glStencilMask().
248  *
249  * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
250  * notifies the driver via the dd_function_table::StencilMask callback.
251  */
252 void GLAPIENTRY
_mesa_StencilMask(GLuint mask)253 _mesa_StencilMask( GLuint mask )
254 {
255    GET_CURRENT_CONTEXT(ctx);
256    const GLint face = ctx->Stencil.ActiveFace;
257 
258    if (MESA_VERBOSE & VERBOSE_API)
259       _mesa_debug(ctx, "glStencilMask()\n");
260 
261    if (face != 0) {
262       /* Only modify the EXT_stencil_two_side back-face state.
263        */
264       if (ctx->Stencil.WriteMask[face] == mask)
265          return;
266       FLUSH_VERTICES(ctx, _NEW_STENCIL);
267       ctx->Stencil.WriteMask[face] = mask;
268 
269       /* Only propagate the change to the driver if EXT_stencil_two_side
270        * is enabled.
271        */
272       if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
273          ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
274       }
275    }
276    else {
277       /* set both front and back state */
278       if (ctx->Stencil.WriteMask[0] == mask &&
279           ctx->Stencil.WriteMask[1] == mask)
280          return;
281       FLUSH_VERTICES(ctx, _NEW_STENCIL);
282       ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
283       if (ctx->Driver.StencilMaskSeparate) {
284          ctx->Driver.StencilMaskSeparate(ctx,
285 					 ((ctx->Stencil.TestTwoSide)
286 					  ? GL_FRONT : GL_FRONT_AND_BACK),
287 					  mask);
288       }
289    }
290 }
291 
292 
293 /**
294  * Set the stencil test actions.
295  *
296  * \param fail action to take when stencil test fails.
297  * \param zfail action to take when stencil test passes, but depth test fails.
298  * \param zpass action to take when stencil test passes and the depth test
299  * passes (or depth testing is not enabled).
300  *
301  * \sa glStencilOp().
302  *
303  * Verifies the parameters and updates the respective fields in
304  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
305  * the driver via the dd_function_table::StencilOp callback.
306  */
307 void GLAPIENTRY
_mesa_StencilOp(GLenum fail,GLenum zfail,GLenum zpass)308 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
309 {
310    GET_CURRENT_CONTEXT(ctx);
311    const GLint face = ctx->Stencil.ActiveFace;
312 
313    if (MESA_VERBOSE & VERBOSE_API)
314       _mesa_debug(ctx, "glStencilOp()\n");
315 
316    if (!validate_stencil_op(ctx, fail)) {
317       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
318       return;
319    }
320    if (!validate_stencil_op(ctx, zfail)) {
321       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
322       return;
323    }
324    if (!validate_stencil_op(ctx, zpass)) {
325       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
326       return;
327    }
328 
329    if (face != 0) {
330       /* only set active face state */
331       if (ctx->Stencil.ZFailFunc[face] == zfail &&
332           ctx->Stencil.ZPassFunc[face] == zpass &&
333           ctx->Stencil.FailFunc[face] == fail)
334          return;
335       FLUSH_VERTICES(ctx, _NEW_STENCIL);
336       ctx->Stencil.ZFailFunc[face] = zfail;
337       ctx->Stencil.ZPassFunc[face] = zpass;
338       ctx->Stencil.FailFunc[face] = fail;
339 
340       /* Only propagate the change to the driver if EXT_stencil_two_side
341        * is enabled.
342        */
343       if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
344          ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
345       }
346    }
347    else {
348       /* set both front and back state */
349       if (ctx->Stencil.ZFailFunc[0] == zfail &&
350           ctx->Stencil.ZFailFunc[1] == zfail &&
351           ctx->Stencil.ZPassFunc[0] == zpass &&
352           ctx->Stencil.ZPassFunc[1] == zpass &&
353           ctx->Stencil.FailFunc[0] == fail &&
354           ctx->Stencil.FailFunc[1] == fail)
355          return;
356       FLUSH_VERTICES(ctx, _NEW_STENCIL);
357       ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
358       ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
359       ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
360       if (ctx->Driver.StencilOpSeparate) {
361          ctx->Driver.StencilOpSeparate(ctx,
362 				       ((ctx->Stencil.TestTwoSide)
363 					? GL_FRONT : GL_FRONT_AND_BACK),
364                                        fail, zfail, zpass);
365       }
366    }
367 }
368 
369 
370 
371 /* GL_EXT_stencil_two_side */
372 void GLAPIENTRY
_mesa_ActiveStencilFaceEXT(GLenum face)373 _mesa_ActiveStencilFaceEXT(GLenum face)
374 {
375    GET_CURRENT_CONTEXT(ctx);
376 
377    if (MESA_VERBOSE & VERBOSE_API)
378       _mesa_debug(ctx, "glActiveStencilFaceEXT()\n");
379 
380    if (!ctx->Extensions.EXT_stencil_two_side) {
381       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
382       return;
383    }
384 
385    if (face == GL_FRONT || face == GL_BACK) {
386       ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
387    }
388    else {
389       _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
390    }
391 }
392 
393 
394 
395 void GLAPIENTRY
_mesa_StencilOpSeparate(GLenum face,GLenum sfail,GLenum zfail,GLenum zpass)396 _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
397 {
398    GLboolean set = GL_FALSE;
399    GET_CURRENT_CONTEXT(ctx);
400 
401    if (MESA_VERBOSE & VERBOSE_API)
402       _mesa_debug(ctx, "glStencilOpSeparate()\n");
403 
404    if (!validate_stencil_op(ctx, sfail)) {
405       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
406       return;
407    }
408    if (!validate_stencil_op(ctx, zfail)) {
409       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
410       return;
411    }
412    if (!validate_stencil_op(ctx, zpass)) {
413       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
414       return;
415    }
416    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
417       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
418       return;
419    }
420 
421    if (face != GL_BACK) {
422       /* set front */
423       if (ctx->Stencil.ZFailFunc[0] != zfail ||
424           ctx->Stencil.ZPassFunc[0] != zpass ||
425           ctx->Stencil.FailFunc[0] != sfail){
426          FLUSH_VERTICES(ctx, _NEW_STENCIL);
427          ctx->Stencil.ZFailFunc[0] = zfail;
428          ctx->Stencil.ZPassFunc[0] = zpass;
429          ctx->Stencil.FailFunc[0] = sfail;
430          set = GL_TRUE;
431       }
432    }
433    if (face != GL_FRONT) {
434       /* set back */
435       if (ctx->Stencil.ZFailFunc[1] != zfail ||
436           ctx->Stencil.ZPassFunc[1] != zpass ||
437           ctx->Stencil.FailFunc[1] != sfail) {
438          FLUSH_VERTICES(ctx, _NEW_STENCIL);
439          ctx->Stencil.ZFailFunc[1] = zfail;
440          ctx->Stencil.ZPassFunc[1] = zpass;
441          ctx->Stencil.FailFunc[1] = sfail;
442          set = GL_TRUE;
443       }
444    }
445    if (set && ctx->Driver.StencilOpSeparate) {
446       ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
447    }
448 }
449 
450 
451 /* OpenGL 2.0 */
452 void GLAPIENTRY
_mesa_StencilFuncSeparate(GLenum face,GLenum func,GLint ref,GLuint mask)453 _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
454 {
455    GET_CURRENT_CONTEXT(ctx);
456 
457    if (MESA_VERBOSE & VERBOSE_API)
458       _mesa_debug(ctx, "glStencilFuncSeparate()\n");
459 
460    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
461       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
462       return;
463    }
464    if (!validate_stencil_func(ctx, func)) {
465       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
466       return;
467    }
468 
469    FLUSH_VERTICES(ctx, _NEW_STENCIL);
470 
471    if (face != GL_BACK) {
472       /* set front */
473       ctx->Stencil.Function[0] = func;
474       ctx->Stencil.Ref[0] = ref;
475       ctx->Stencil.ValueMask[0] = mask;
476    }
477    if (face != GL_FRONT) {
478       /* set back */
479       ctx->Stencil.Function[1] = func;
480       ctx->Stencil.Ref[1] = ref;
481       ctx->Stencil.ValueMask[1] = mask;
482    }
483    if (ctx->Driver.StencilFuncSeparate) {
484       ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
485    }
486 }
487 
488 
489 /* OpenGL 2.0 */
490 void GLAPIENTRY
_mesa_StencilMaskSeparate(GLenum face,GLuint mask)491 _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
492 {
493    GET_CURRENT_CONTEXT(ctx);
494 
495    if (MESA_VERBOSE & VERBOSE_API)
496       _mesa_debug(ctx, "glStencilMaskSeparate()\n");
497 
498    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
499       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
500       return;
501    }
502 
503    FLUSH_VERTICES(ctx, _NEW_STENCIL);
504 
505    if (face != GL_BACK) {
506       ctx->Stencil.WriteMask[0] = mask;
507    }
508    if (face != GL_FRONT) {
509       ctx->Stencil.WriteMask[1] = mask;
510    }
511    if (ctx->Driver.StencilMaskSeparate) {
512       ctx->Driver.StencilMaskSeparate(ctx, face, mask);
513    }
514 }
515 
516 
517 /**
518  * Update derived stencil state.
519  */
520 void
_mesa_update_stencil(struct gl_context * ctx)521 _mesa_update_stencil(struct gl_context *ctx)
522 {
523    const GLint face = ctx->Stencil._BackFace;
524 
525    ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
526                             ctx->DrawBuffer->Visual.stencilBits > 0);
527 
528     ctx->Stencil._TestTwoSide =
529        ctx->Stencil._Enabled &&
530        (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
531 	ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
532 	ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
533 	ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
534 	ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
535 	ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
536 	ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
537 
538    ctx->Stencil._WriteEnabled =
539       ctx->Stencil._Enabled &&
540       (ctx->Stencil.WriteMask[0] != 0 ||
541        (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[face] != 0));
542 }
543 
544 
545 /**
546  * Initialize the context stipple state.
547  *
548  * \param ctx GL context.
549  *
550  * Initializes __struct gl_contextRec::Stencil attribute group.
551  */
552 void
_mesa_init_stencil(struct gl_context * ctx)553 _mesa_init_stencil(struct gl_context *ctx)
554 {
555    ctx->Stencil.Enabled = GL_FALSE;
556    ctx->Stencil.TestTwoSide = GL_FALSE;
557    ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
558    ctx->Stencil.Function[0] = GL_ALWAYS;
559    ctx->Stencil.Function[1] = GL_ALWAYS;
560    ctx->Stencil.Function[2] = GL_ALWAYS;
561    ctx->Stencil.FailFunc[0] = GL_KEEP;
562    ctx->Stencil.FailFunc[1] = GL_KEEP;
563    ctx->Stencil.FailFunc[2] = GL_KEEP;
564    ctx->Stencil.ZPassFunc[0] = GL_KEEP;
565    ctx->Stencil.ZPassFunc[1] = GL_KEEP;
566    ctx->Stencil.ZPassFunc[2] = GL_KEEP;
567    ctx->Stencil.ZFailFunc[0] = GL_KEEP;
568    ctx->Stencil.ZFailFunc[1] = GL_KEEP;
569    ctx->Stencil.ZFailFunc[2] = GL_KEEP;
570    ctx->Stencil.Ref[0] = 0;
571    ctx->Stencil.Ref[1] = 0;
572    ctx->Stencil.Ref[2] = 0;
573 
574    /* 4.1.4 Stencil Test section of the GL-ES 3.0 specification says:
575     *
576     *     "In the initial state, [...] the front and back stencil mask are both
577     *     set to the value 2^s − 1, where s is greater than or equal to the
578     *     number of bits in the deepest stencil buffer* supported by the GL
579     *     implementation."
580     *
581     * Since the maximum supported precision for stencil buffers is 8 bits,
582     * mask values should be initialized to 2^8 - 1 = 0xFF.
583     */
584    ctx->Stencil.ValueMask[0] = 0xFF;
585    ctx->Stencil.ValueMask[1] = 0xFF;
586    ctx->Stencil.ValueMask[2] = 0xFF;
587    ctx->Stencil.WriteMask[0] = 0xFF;
588    ctx->Stencil.WriteMask[1] = 0xFF;
589    ctx->Stencil.WriteMask[2] = 0xFF;
590 
591    ctx->Stencil.Clear = 0;
592    ctx->Stencil._BackFace = 1;
593 }
594