ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

stencil.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 
00050 #include "glheader.h"
00051 #include "imports.h"
00052 #include "context.h"
00053 #include "macros.h"
00054 #include "stencil.h"
00055 #include "mtypes.h"
00056 
00057 
00058 static GLboolean
00059 validate_stencil_op(GLcontext *ctx, GLenum op)
00060 {
00061    switch (op) {
00062    case GL_KEEP:
00063    case GL_ZERO:
00064    case GL_REPLACE:
00065    case GL_INCR:
00066    case GL_DECR:
00067    case GL_INVERT:
00068       return GL_TRUE;
00069    case GL_INCR_WRAP_EXT:
00070    case GL_DECR_WRAP_EXT:
00071       if (ctx->Extensions.EXT_stencil_wrap) {
00072          return GL_TRUE;
00073       }
00074       /* FALL-THROUGH */
00075    default:
00076       return GL_FALSE;
00077    }
00078 }
00079 
00080 
00081 static GLboolean
00082 validate_stencil_func(GLcontext *ctx, GLenum func)
00083 {
00084    switch (func) {
00085    case GL_NEVER:
00086    case GL_LESS:
00087    case GL_LEQUAL:
00088    case GL_GREATER:
00089    case GL_GEQUAL:
00090    case GL_EQUAL:
00091    case GL_NOTEQUAL:
00092    case GL_ALWAYS:
00093       return GL_TRUE;
00094    default:
00095       return GL_FALSE;
00096    }
00097 }
00098 
00099 
00111 void GLAPIENTRY
00112 _mesa_ClearStencil( GLint s )
00113 {
00114    GET_CURRENT_CONTEXT(ctx);
00115    ASSERT_OUTSIDE_BEGIN_END(ctx);
00116 
00117    if (ctx->Stencil.Clear == (GLuint) s)
00118       return;
00119 
00120    FLUSH_VERTICES(ctx, _NEW_STENCIL);
00121    ctx->Stencil.Clear = (GLuint) s;
00122 
00123    if (ctx->Driver.ClearStencil) {
00124       ctx->Driver.ClearStencil( ctx, s );
00125    }
00126 }
00127 
00128 
00143 void GLAPIENTRY
00144 _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask )
00145 {
00146    GET_CURRENT_CONTEXT(ctx);
00147    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
00148    ASSERT_OUTSIDE_BEGIN_END(ctx);
00149 
00150    if (!validate_stencil_func(ctx, frontfunc)) {
00151       _mesa_error(ctx, GL_INVALID_ENUM,
00152                   "glStencilFuncSeparateATI(frontfunc)");
00153       return;
00154    }
00155    if (!validate_stencil_func(ctx, backfunc)) {
00156       _mesa_error(ctx, GL_INVALID_ENUM,
00157                   "glStencilFuncSeparateATI(backfunc)");
00158       return;
00159    }
00160 
00161    ref = CLAMP( ref, 0, stencilMax );
00162 
00163    /* set both front and back state */
00164    if (ctx->Stencil.Function[0] == frontfunc &&
00165        ctx->Stencil.Function[1] == backfunc &&
00166        ctx->Stencil.ValueMask[0] == mask &&
00167        ctx->Stencil.ValueMask[1] == mask &&
00168        ctx->Stencil.Ref[0] == ref &&
00169        ctx->Stencil.Ref[1] == ref)
00170       return;
00171    FLUSH_VERTICES(ctx, _NEW_STENCIL);
00172    ctx->Stencil.Function[0]  = frontfunc;
00173    ctx->Stencil.Function[1]  = backfunc;
00174    ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
00175    ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
00176    if (ctx->Driver.StencilFuncSeparate) {
00177       ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
00178                                       frontfunc, ref, mask);
00179       ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
00180                                       backfunc, ref, mask);
00181    }
00182 }
00183 
00184 
00198 void GLAPIENTRY
00199 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
00200 {
00201    GET_CURRENT_CONTEXT(ctx);
00202    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
00203    const GLint face = ctx->Stencil.ActiveFace;
00204    ASSERT_OUTSIDE_BEGIN_END(ctx);
00205 
00206    if (!validate_stencil_func(ctx, func)) {
00207       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
00208       return;
00209    }
00210 
00211    ref = CLAMP( ref, 0, stencilMax );
00212 
00213    if (face != 0) {
00214       if (ctx->Stencil.Function[face] == func &&
00215           ctx->Stencil.ValueMask[face] == mask &&
00216           ctx->Stencil.Ref[face] == ref)
00217          return;
00218       FLUSH_VERTICES(ctx, _NEW_STENCIL);
00219       ctx->Stencil.Function[face] = func;
00220       ctx->Stencil.Ref[face] = ref;
00221       ctx->Stencil.ValueMask[face] = mask;
00222 
00223       /* Only propagate the change to the driver if EXT_stencil_two_side
00224        * is enabled.
00225        */
00226       if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
00227          ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
00228       }
00229    }
00230    else {
00231       /* set both front and back state */
00232       if (ctx->Stencil.Function[0] == func &&
00233           ctx->Stencil.Function[1] == func &&
00234           ctx->Stencil.ValueMask[0] == mask &&
00235           ctx->Stencil.ValueMask[1] == mask &&
00236           ctx->Stencil.Ref[0] == ref &&
00237           ctx->Stencil.Ref[1] == ref)
00238          return;
00239       FLUSH_VERTICES(ctx, _NEW_STENCIL);
00240       ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
00241       ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
00242       ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
00243       if (ctx->Driver.StencilFuncSeparate) {
00244          ctx->Driver.StencilFuncSeparate(ctx,
00245                      ((ctx->Stencil.TestTwoSide)
00246                       ? GL_FRONT : GL_FRONT_AND_BACK),
00247                                          func, ref, mask);
00248       }
00249    }
00250 }
00251 
00252 
00264 void GLAPIENTRY
00265 _mesa_StencilMask( GLuint mask )
00266 {
00267    GET_CURRENT_CONTEXT(ctx);
00268    const GLint face = ctx->Stencil.ActiveFace;
00269 
00270    ASSERT_OUTSIDE_BEGIN_END(ctx);
00271 
00272    if (face != 0) {
00273       /* Only modify the EXT_stencil_two_side back-face state.
00274        */
00275       if (ctx->Stencil.WriteMask[face] == mask)
00276          return;
00277       FLUSH_VERTICES(ctx, _NEW_STENCIL);
00278       ctx->Stencil.WriteMask[face] = mask;
00279 
00280       /* Only propagate the change to the driver if EXT_stencil_two_side
00281        * is enabled.
00282        */
00283       if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
00284          ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
00285       }
00286    }
00287    else {
00288       /* set both front and back state */
00289       if (ctx->Stencil.WriteMask[0] == mask &&
00290           ctx->Stencil.WriteMask[1] == mask)
00291          return;
00292       FLUSH_VERTICES(ctx, _NEW_STENCIL);
00293       ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
00294       if (ctx->Driver.StencilMaskSeparate) {
00295          ctx->Driver.StencilMaskSeparate(ctx,
00296                      ((ctx->Stencil.TestTwoSide)
00297                       ? GL_FRONT : GL_FRONT_AND_BACK),
00298                       mask);
00299       }
00300    }
00301 }
00302 
00303 
00318 void GLAPIENTRY
00319 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
00320 {
00321    GET_CURRENT_CONTEXT(ctx);
00322    const GLint face = ctx->Stencil.ActiveFace;
00323 
00324    ASSERT_OUTSIDE_BEGIN_END(ctx);
00325 
00326    if (!validate_stencil_op(ctx, fail)) {
00327       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
00328       return;
00329    }
00330    if (!validate_stencil_op(ctx, zfail)) {
00331       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
00332       return;
00333    }
00334    if (!validate_stencil_op(ctx, zpass)) {
00335       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
00336       return;
00337    }
00338 
00339    if (face != 0) {
00340       /* only set active face state */
00341       if (ctx->Stencil.ZFailFunc[face] == zfail &&
00342           ctx->Stencil.ZPassFunc[face] == zpass &&
00343           ctx->Stencil.FailFunc[face] == fail)
00344          return;
00345       FLUSH_VERTICES(ctx, _NEW_STENCIL);
00346       ctx->Stencil.ZFailFunc[face] = zfail;
00347       ctx->Stencil.ZPassFunc[face] = zpass;
00348       ctx->Stencil.FailFunc[face] = fail;
00349 
00350       /* Only propagate the change to the driver if EXT_stencil_two_side
00351        * is enabled.
00352        */
00353       if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
00354          ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
00355       }
00356    }
00357    else {
00358       /* set both front and back state */
00359       if (ctx->Stencil.ZFailFunc[0] == zfail &&
00360           ctx->Stencil.ZFailFunc[1] == zfail &&
00361           ctx->Stencil.ZPassFunc[0] == zpass &&
00362           ctx->Stencil.ZPassFunc[1] == zpass &&
00363           ctx->Stencil.FailFunc[0] == fail &&
00364           ctx->Stencil.FailFunc[1] == fail)
00365          return;
00366       FLUSH_VERTICES(ctx, _NEW_STENCIL);
00367       ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
00368       ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
00369       ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
00370       if (ctx->Driver.StencilOpSeparate) {
00371          ctx->Driver.StencilOpSeparate(ctx,
00372                        ((ctx->Stencil.TestTwoSide)
00373                     ? GL_FRONT : GL_FRONT_AND_BACK),
00374                                        fail, zfail, zpass);
00375       }
00376    }
00377 }
00378 
00379 
00380 
00381 #if _HAVE_FULL_GL
00382 /* GL_EXT_stencil_two_side */
00383 void GLAPIENTRY
00384 _mesa_ActiveStencilFaceEXT(GLenum face)
00385 {
00386    GET_CURRENT_CONTEXT(ctx);
00387    ASSERT_OUTSIDE_BEGIN_END(ctx);
00388 
00389    if (!ctx->Extensions.EXT_stencil_two_side) {
00390       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
00391       return;
00392    }
00393 
00394    if (face == GL_FRONT || face == GL_BACK) {
00395       FLUSH_VERTICES(ctx, _NEW_STENCIL);
00396       ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
00397    }
00398    else {
00399       _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
00400    }
00401 }
00402 #endif
00403 
00404 
00405 
00412 void GLAPIENTRY
00413 _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
00414 {
00415    GLboolean set = GL_FALSE;
00416    GET_CURRENT_CONTEXT(ctx);
00417    ASSERT_OUTSIDE_BEGIN_END(ctx);
00418 
00419    if (!validate_stencil_op(ctx, sfail)) {
00420       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
00421       return;
00422    }
00423    if (!validate_stencil_op(ctx, zfail)) {
00424       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
00425       return;
00426    }
00427    if (!validate_stencil_op(ctx, zpass)) {
00428       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
00429       return;
00430    }
00431    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
00432       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
00433       return;
00434    }
00435 
00436    if (face != GL_BACK) {
00437       /* set front */
00438       if (ctx->Stencil.ZFailFunc[0] != zfail ||
00439           ctx->Stencil.ZPassFunc[0] != zpass ||
00440           ctx->Stencil.FailFunc[0] != sfail){
00441          FLUSH_VERTICES(ctx, _NEW_STENCIL);
00442          ctx->Stencil.ZFailFunc[0] = zfail;
00443          ctx->Stencil.ZPassFunc[0] = zpass;
00444          ctx->Stencil.FailFunc[0] = sfail;
00445          set = GL_TRUE;
00446       }
00447    }
00448    if (face != GL_FRONT) {
00449       /* set back */
00450       if (ctx->Stencil.ZFailFunc[1] != zfail ||
00451           ctx->Stencil.ZPassFunc[1] != zpass ||
00452           ctx->Stencil.FailFunc[1] != sfail) {
00453          FLUSH_VERTICES(ctx, _NEW_STENCIL);
00454          ctx->Stencil.ZFailFunc[1] = zfail;
00455          ctx->Stencil.ZPassFunc[1] = zpass;
00456          ctx->Stencil.FailFunc[1] = sfail;
00457          set = GL_TRUE;
00458       }
00459    }
00460    if (set && ctx->Driver.StencilOpSeparate) {
00461       ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
00462    }
00463 }
00464 
00465 
00466 /* OpenGL 2.0 */
00467 void GLAPIENTRY
00468 _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
00469 {
00470    GET_CURRENT_CONTEXT(ctx);
00471    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
00472    ASSERT_OUTSIDE_BEGIN_END(ctx);
00473 
00474    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
00475       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
00476       return;
00477    }
00478    if (!validate_stencil_func(ctx, func)) {
00479       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
00480       return;
00481    }
00482 
00483    ref = CLAMP(ref, 0, stencilMax);
00484 
00485    FLUSH_VERTICES(ctx, _NEW_STENCIL);
00486 
00487    if (face != GL_BACK) {
00488       /* set front */
00489       ctx->Stencil.Function[0] = func;
00490       ctx->Stencil.Ref[0] = ref;
00491       ctx->Stencil.ValueMask[0] = mask;
00492    }
00493    if (face != GL_FRONT) {
00494       /* set back */
00495       ctx->Stencil.Function[1] = func;
00496       ctx->Stencil.Ref[1] = ref;
00497       ctx->Stencil.ValueMask[1] = mask;
00498    }
00499    if (ctx->Driver.StencilFuncSeparate) {
00500       ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
00501    }
00502 }
00503 
00504 
00505 /* OpenGL 2.0 */
00506 void GLAPIENTRY
00507 _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
00508 {
00509    GET_CURRENT_CONTEXT(ctx);
00510    ASSERT_OUTSIDE_BEGIN_END(ctx);
00511 
00512    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
00513       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
00514       return;
00515    }
00516 
00517    FLUSH_VERTICES(ctx, _NEW_STENCIL);
00518 
00519    if (face != GL_BACK) {
00520       ctx->Stencil.WriteMask[0] = mask;
00521    }
00522    if (face != GL_FRONT) {
00523       ctx->Stencil.WriteMask[1] = mask;
00524    }
00525    if (ctx->Driver.StencilMaskSeparate) {
00526       ctx->Driver.StencilMaskSeparate(ctx, face, mask);
00527    }
00528 }
00529 
00530 
00534 void
00535 _mesa_update_stencil(GLcontext *ctx)
00536 {
00537    const GLint face = ctx->Stencil._BackFace;
00538 
00539    ctx->Stencil._TestTwoSide =
00540        (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
00541     ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
00542     ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
00543     ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
00544     ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
00545     ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
00546     ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
00547 }
00548 
00549 
00557 void
00558 _mesa_init_stencil(GLcontext *ctx)
00559 {
00560    ctx->Stencil.Enabled = GL_FALSE;
00561    ctx->Stencil.TestTwoSide = GL_FALSE;
00562    ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
00563    ctx->Stencil.Function[0] = GL_ALWAYS;
00564    ctx->Stencil.Function[1] = GL_ALWAYS;
00565    ctx->Stencil.Function[2] = GL_ALWAYS;
00566    ctx->Stencil.FailFunc[0] = GL_KEEP;
00567    ctx->Stencil.FailFunc[1] = GL_KEEP;
00568    ctx->Stencil.FailFunc[2] = GL_KEEP;
00569    ctx->Stencil.ZPassFunc[0] = GL_KEEP;
00570    ctx->Stencil.ZPassFunc[1] = GL_KEEP;
00571    ctx->Stencil.ZPassFunc[2] = GL_KEEP;
00572    ctx->Stencil.ZFailFunc[0] = GL_KEEP;
00573    ctx->Stencil.ZFailFunc[1] = GL_KEEP;
00574    ctx->Stencil.ZFailFunc[2] = GL_KEEP;
00575    ctx->Stencil.Ref[0] = 0;
00576    ctx->Stencil.Ref[1] = 0;
00577    ctx->Stencil.Ref[2] = 0;
00578    ctx->Stencil.ValueMask[0] = ~0U;
00579    ctx->Stencil.ValueMask[1] = ~0U;
00580    ctx->Stencil.ValueMask[2] = ~0U;
00581    ctx->Stencil.WriteMask[0] = ~0U;
00582    ctx->Stencil.WriteMask[1] = ~0U;
00583    ctx->Stencil.WriteMask[2] = ~0U;
00584    ctx->Stencil.Clear = 0;
00585    ctx->Stencil._BackFace = 1;
00586 }

Generated on Sun May 27 2012 04:20:29 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.