home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / blend.cpp < prev    next >
C/C++ Source or Header  |  2002-10-24  |  13KB  |  461 lines

  1. /* $Id: blend.c,v 1.38 2002/10/24 23:57:19 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 "blend.h"
  30. #include "colormac.h"
  31. #include "context.h"
  32. #include "enums.h"
  33. #include "macros.h"
  34. #include "mtypes.h"
  35.  
  36.  
  37. void
  38. _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
  39. {
  40.  
  41.    GET_CURRENT_CONTEXT(ctx);
  42.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  43.  
  44.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  45.       _mesa_debug(ctx, "glBlendFunc %s %s\n",
  46.                   _mesa_lookup_enum_by_nr(sfactor),
  47.                   _mesa_lookup_enum_by_nr(dfactor));
  48.  
  49.    switch (sfactor) {
  50.       case GL_SRC_COLOR:
  51.       case GL_ONE_MINUS_SRC_COLOR:
  52.          if (!ctx->Extensions.NV_blend_square) {
  53.             _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
  54.             return;
  55.          }
  56.          /* fall-through */
  57.       case GL_ZERO:
  58.       case GL_ONE:
  59.       case GL_DST_COLOR:
  60.       case GL_ONE_MINUS_DST_COLOR:
  61.       case GL_SRC_ALPHA:
  62.       case GL_ONE_MINUS_SRC_ALPHA:
  63.       case GL_DST_ALPHA:
  64.       case GL_ONE_MINUS_DST_ALPHA:
  65.       case GL_SRC_ALPHA_SATURATE:
  66.       case GL_CONSTANT_COLOR:
  67.       case GL_ONE_MINUS_CONSTANT_COLOR:
  68.       case GL_CONSTANT_ALPHA:
  69.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  70.          break;
  71.       default:
  72.          _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
  73.          return;
  74.    }
  75.  
  76.    switch (dfactor) {
  77.       case GL_DST_COLOR:
  78.       case GL_ONE_MINUS_DST_COLOR:
  79.          if (!ctx->Extensions.NV_blend_square) {
  80.             _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
  81.             return;
  82.          }
  83.          /* fall-through */
  84.       case GL_ZERO:
  85.       case GL_ONE:
  86.       case GL_SRC_COLOR:
  87.       case GL_ONE_MINUS_SRC_COLOR:
  88.       case GL_SRC_ALPHA:
  89.       case GL_ONE_MINUS_SRC_ALPHA:
  90.       case GL_DST_ALPHA:
  91.       case GL_ONE_MINUS_DST_ALPHA:
  92.       case GL_CONSTANT_COLOR:
  93.       case GL_ONE_MINUS_CONSTANT_COLOR:
  94.       case GL_CONSTANT_ALPHA:
  95.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  96.          break;
  97.       default:
  98.          _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
  99.          return;
  100.    }
  101.  
  102.    if (ctx->Color.BlendDstRGB == dfactor &&
  103.        ctx->Color.BlendSrcRGB == sfactor &&
  104.        ctx->Color.BlendDstA == dfactor &&
  105.        ctx->Color.BlendSrcA == sfactor)
  106.       return;
  107.  
  108.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  109.    ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
  110.    ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
  111.  
  112.    if (ctx->Driver.BlendFunc)
  113.       ctx->Driver.BlendFunc( ctx, sfactor, dfactor );
  114. }
  115.  
  116.  
  117. /* GL_EXT_blend_func_separate */
  118. void
  119. _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
  120.                             GLenum sfactorA, GLenum dfactorA )
  121. {
  122.    GET_CURRENT_CONTEXT(ctx);
  123.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  124.  
  125.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  126.       _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
  127.                   _mesa_lookup_enum_by_nr(sfactorRGB),
  128.                   _mesa_lookup_enum_by_nr(dfactorRGB),
  129.                   _mesa_lookup_enum_by_nr(sfactorA),
  130.                   _mesa_lookup_enum_by_nr(dfactorA));
  131.  
  132.    switch (sfactorRGB) {
  133.       case GL_SRC_COLOR:
  134.       case GL_ONE_MINUS_SRC_COLOR:
  135.          if (!ctx->Extensions.NV_blend_square) {
  136.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
  137.             return;
  138.          }
  139.          /* fall-through */
  140.       case GL_ZERO:
  141.       case GL_ONE:
  142.       case GL_DST_COLOR:
  143.       case GL_ONE_MINUS_DST_COLOR:
  144.       case GL_SRC_ALPHA:
  145.       case GL_ONE_MINUS_SRC_ALPHA:
  146.       case GL_DST_ALPHA:
  147.       case GL_ONE_MINUS_DST_ALPHA:
  148.       case GL_SRC_ALPHA_SATURATE:
  149.       case GL_CONSTANT_COLOR:
  150.       case GL_ONE_MINUS_CONSTANT_COLOR:
  151.       case GL_CONSTANT_ALPHA:
  152.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  153.          break;
  154.       default:
  155.          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
  156.          return;
  157.    }
  158.  
  159.    switch (dfactorRGB) {
  160.       case GL_DST_COLOR:
  161.       case GL_ONE_MINUS_DST_COLOR:
  162.          if (!ctx->Extensions.NV_blend_square) {
  163.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
  164.             return;
  165.          }
  166.          /* fall-through */
  167.       case GL_ZERO:
  168.       case GL_ONE:
  169.       case GL_SRC_COLOR:
  170.       case GL_ONE_MINUS_SRC_COLOR:
  171.       case GL_SRC_ALPHA:
  172.       case GL_ONE_MINUS_SRC_ALPHA:
  173.       case GL_DST_ALPHA:
  174.       case GL_ONE_MINUS_DST_ALPHA:
  175.       case GL_CONSTANT_COLOR:
  176.       case GL_ONE_MINUS_CONSTANT_COLOR:
  177.       case GL_CONSTANT_ALPHA:
  178.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  179.          break;
  180.       default:
  181.          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
  182.          return;
  183.    }
  184.  
  185.    switch (sfactorA) {
  186.       case GL_SRC_COLOR:
  187.       case GL_ONE_MINUS_SRC_COLOR:
  188.          if (!ctx->Extensions.NV_blend_square) {
  189.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
  190.             return;
  191.          }
  192.          /* fall-through */
  193.       case GL_ZERO:
  194.       case GL_ONE:
  195.       case GL_DST_COLOR:
  196.       case GL_ONE_MINUS_DST_COLOR:
  197.       case GL_SRC_ALPHA:
  198.       case GL_ONE_MINUS_SRC_ALPHA:
  199.       case GL_DST_ALPHA:
  200.       case GL_ONE_MINUS_DST_ALPHA:
  201.       case GL_SRC_ALPHA_SATURATE:
  202.       case GL_CONSTANT_COLOR:
  203.       case GL_ONE_MINUS_CONSTANT_COLOR:
  204.       case GL_CONSTANT_ALPHA:
  205.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  206.          break;
  207.       default:
  208.          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
  209.          return;
  210.    }
  211.  
  212.    switch (dfactorA) {
  213.       case GL_DST_COLOR:
  214.       case GL_ONE_MINUS_DST_COLOR:
  215.          if (!ctx->Extensions.NV_blend_square) {
  216.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)");
  217.             return;
  218.          }
  219.          /* fall-through */
  220.       case GL_ZERO:
  221.       case GL_ONE:
  222.       case GL_SRC_COLOR:
  223.       case GL_ONE_MINUS_SRC_COLOR:
  224.       case GL_SRC_ALPHA:
  225.       case GL_ONE_MINUS_SRC_ALPHA:
  226.       case GL_DST_ALPHA:
  227.       case GL_ONE_MINUS_DST_ALPHA:
  228.       case GL_CONSTANT_COLOR:
  229.       case GL_ONE_MINUS_CONSTANT_COLOR:
  230.       case GL_CONSTANT_ALPHA:
  231.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  232.          break;
  233.       default:
  234.          _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
  235.          return;
  236.    }
  237.  
  238.    if (ctx->Color.BlendSrcRGB == sfactorRGB &&
  239.        ctx->Color.BlendDstRGB == dfactorRGB &&
  240.        ctx->Color.BlendSrcA == sfactorA &&
  241.        ctx->Color.BlendDstA == dfactorA)
  242.       return;
  243.  
  244.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  245.  
  246.    ctx->Color.BlendSrcRGB = sfactorRGB;
  247.    ctx->Color.BlendDstRGB = dfactorRGB;
  248.    ctx->Color.BlendSrcA = sfactorA;
  249.    ctx->Color.BlendDstA = dfactorA;
  250.  
  251.    if (ctx->Driver.BlendFuncSeparate) {
  252.       (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
  253.                     sfactorA, dfactorA );
  254.    }
  255. }
  256.  
  257.  
  258.  
  259. /* This is really an extension function! */
  260. void
  261. _mesa_BlendEquation( GLenum mode )
  262. {
  263.    GET_CURRENT_CONTEXT(ctx);
  264.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  265.  
  266.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  267.       _mesa_debug(ctx, "glBlendEquation %s\n",
  268.                   _mesa_lookup_enum_by_nr(mode));
  269.  
  270.    switch (mode) {
  271.       case GL_FUNC_ADD_EXT:
  272.          break;
  273.       case GL_MIN_EXT:
  274.       case GL_MAX_EXT:
  275.          if (!ctx->Extensions.EXT_blend_minmax &&
  276.              !ctx->Extensions.ARB_imaging) {
  277.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
  278.             return;
  279.          }
  280.          break;
  281.       case GL_LOGIC_OP:
  282.          if (!ctx->Extensions.EXT_blend_logic_op) {
  283.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
  284.             return;
  285.          }
  286.          break;
  287.       case GL_FUNC_SUBTRACT_EXT:
  288.       case GL_FUNC_REVERSE_SUBTRACT_EXT:
  289.          if (!ctx->Extensions.EXT_blend_subtract &&
  290.              !ctx->Extensions.ARB_imaging) {
  291.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
  292.             return;
  293.          }
  294.          break;
  295.       default:
  296.          _mesa_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
  297.          return;
  298.    }
  299.  
  300.    if (ctx->Color.BlendEquation == mode)
  301.       return;
  302.  
  303.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  304.    ctx->Color.BlendEquation = mode;
  305.  
  306.    /* This is needed to support 1.1's RGB logic ops AND
  307.     * 1.0's blending logicops.
  308.     */
  309.    ctx->Color.ColorLogicOpEnabled = (mode==GL_LOGIC_OP &&
  310.                      ctx->Color.BlendEnabled);
  311.  
  312.    if (ctx->Driver.BlendEquation)
  313.       (*ctx->Driver.BlendEquation)( ctx, mode );
  314. }
  315.  
  316.  
  317.  
  318. void
  319. _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
  320. {
  321.    GLfloat tmp[4];
  322.    GET_CURRENT_CONTEXT(ctx);
  323.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  324.  
  325.    tmp[0] = CLAMP( red,   0.0F, 1.0F );
  326.    tmp[1] = CLAMP( green, 0.0F, 1.0F );
  327.    tmp[2] = CLAMP( blue,  0.0F, 1.0F );
  328.    tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
  329.  
  330.    if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
  331.       return;
  332.  
  333.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  334.    COPY_4FV( ctx->Color.BlendColor, tmp );
  335.  
  336.    if (ctx->Driver.BlendColor)
  337.       (*ctx->Driver.BlendColor)(ctx, tmp);
  338. }
  339.  
  340.  
  341. void
  342. _mesa_AlphaFunc( GLenum func, GLclampf ref )
  343. {
  344.    GET_CURRENT_CONTEXT(ctx);
  345.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  346.  
  347.    switch (func) {
  348.    case GL_NEVER:
  349.    case GL_LESS:
  350.    case GL_EQUAL:
  351.    case GL_LEQUAL:
  352.    case GL_GREATER:
  353.    case GL_NOTEQUAL:
  354.    case GL_GEQUAL:
  355.    case GL_ALWAYS:
  356.       ref = CLAMP(ref, 0.0F, 1.0F);
  357.  
  358.       if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
  359.          return; /* no change */
  360.  
  361.       FLUSH_VERTICES(ctx, _NEW_COLOR);
  362.       ctx->Color.AlphaFunc = func;
  363.       ctx->Color.AlphaRef = ref;
  364.  
  365.       if (ctx->Driver.AlphaFunc)
  366.          ctx->Driver.AlphaFunc(ctx, func, ref);
  367.       return;
  368.  
  369.    default:
  370.       _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
  371.       return;
  372.    }
  373. }
  374.  
  375.  
  376. void
  377. _mesa_LogicOp( GLenum opcode )
  378. {
  379.    GET_CURRENT_CONTEXT(ctx);
  380.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  381.  
  382.    switch (opcode) {
  383.       case GL_CLEAR:
  384.       case GL_SET:
  385.       case GL_COPY:
  386.       case GL_COPY_INVERTED:
  387.       case GL_NOOP:
  388.       case GL_INVERT:
  389.       case GL_AND:
  390.       case GL_NAND:
  391.       case GL_OR:
  392.       case GL_NOR:
  393.       case GL_XOR:
  394.       case GL_EQUIV:
  395.       case GL_AND_REVERSE:
  396.       case GL_AND_INVERTED:
  397.       case GL_OR_REVERSE:
  398.       case GL_OR_INVERTED:
  399.      break;
  400.       default:
  401.          _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
  402.      return;
  403.    }
  404.  
  405.    if (ctx->Color.LogicOp == opcode)
  406.       return;
  407.  
  408.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  409.    ctx->Color.LogicOp = opcode;
  410.  
  411.    if (ctx->Driver.LogicOpcode)
  412.       ctx->Driver.LogicOpcode( ctx, opcode );
  413. }
  414.  
  415.  
  416. void
  417. _mesa_IndexMask( GLuint mask )
  418. {
  419.    GET_CURRENT_CONTEXT(ctx);
  420.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  421.  
  422.    if (ctx->Color.IndexMask == mask)
  423.       return;
  424.  
  425.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  426.    ctx->Color.IndexMask = mask;
  427.  
  428.    if (ctx->Driver.IndexMask)
  429.       ctx->Driver.IndexMask( ctx, mask );
  430. }
  431.  
  432.  
  433. void
  434. _mesa_ColorMask( GLboolean red, GLboolean green,
  435.                  GLboolean blue, GLboolean alpha )
  436. {
  437.    GET_CURRENT_CONTEXT(ctx);
  438.    GLubyte tmp[4];
  439.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  440.  
  441.    if (MESA_VERBOSE & VERBOSE_API)
  442.       _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
  443.  
  444.    /* Shouldn't have any information about channel depth in core mesa
  445.     * -- should probably store these as the native booleans:
  446.     */
  447.    tmp[RCOMP] = red    ? 0xff : 0x0;
  448.    tmp[GCOMP] = green  ? 0xff : 0x0;
  449.    tmp[BCOMP] = blue   ? 0xff : 0x0;
  450.    tmp[ACOMP] = alpha  ? 0xff : 0x0;
  451.  
  452.    if (TEST_EQ_4UBV(tmp, ctx->Color.ColorMask))
  453.       return;
  454.  
  455.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  456.    COPY_4UBV(ctx->Color.ColorMask, tmp);
  457.  
  458.    if (ctx->Driver.ColorMask)
  459.       ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
  460. }
  461.