Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /**
  2.  * \file blend.c
  3.  * Blending operations.
  4.  */
  5.  
  6. /*
  7.  * Mesa 3-D graphics library
  8.  * Version:  6.5.1
  9.  *
  10.  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  11.  *
  12.  * Permission is hereby granted, free of charge, to any person obtaining a
  13.  * copy of this software and associated documentation files (the "Software"),
  14.  * to deal in the Software without restriction, including without limitation
  15.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  16.  * and/or sell copies of the Software, and to permit persons to whom the
  17.  * Software is furnished to do so, subject to the following conditions:
  18.  *
  19.  * The above copyright notice and this permission notice shall be included
  20.  * in all copies or substantial portions of the Software.
  21.  *
  22.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  23.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  25.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  26.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  27.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28.  */
  29.  
  30.  
  31.  
  32. #include "glheader.h"
  33. #include "blend.h"
  34. #include "context.h"
  35. #include "enums.h"
  36. #include "macros.h"
  37. #include "mtypes.h"
  38.  
  39.  
  40. /**
  41.  * Specify the blending operation.
  42.  *
  43.  * \param sfactor source factor operator.
  44.  * \param dfactor destination factor operator.
  45.  *
  46.  * \sa glBlendFunc, glBlendFuncSeparateEXT
  47.  */
  48. void GLAPIENTRY
  49. _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
  50. {
  51.    _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
  52. }
  53.  
  54.  
  55. /**
  56.  * Process GL_EXT_blend_func_separate().
  57.  *
  58.  * \param sfactorRGB RGB source factor operator.
  59.  * \param dfactorRGB RGB destination factor operator.
  60.  * \param sfactorA alpha source factor operator.
  61.  * \param dfactorA alpha destination factor operator.
  62.  *
  63.  * Verifies the parameters and updates gl_colorbuffer_attrib.
  64.  * On a change, flush the vertices and notify the driver via
  65.  * dd_function_table::BlendFuncSeparate.
  66.  */
  67. void GLAPIENTRY
  68. _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
  69.                             GLenum sfactorA, GLenum dfactorA )
  70. {
  71.    GET_CURRENT_CONTEXT(ctx);
  72.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  73.  
  74.    if (MESA_VERBOSE & VERBOSE_API)
  75.       _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
  76.                   _mesa_lookup_enum_by_nr(sfactorRGB),
  77.                   _mesa_lookup_enum_by_nr(dfactorRGB),
  78.                   _mesa_lookup_enum_by_nr(sfactorA),
  79.                   _mesa_lookup_enum_by_nr(dfactorA));
  80.  
  81.    switch (sfactorRGB) {
  82.       case GL_SRC_COLOR:
  83.       case GL_ONE_MINUS_SRC_COLOR:
  84.          if (!ctx->Extensions.NV_blend_square) {
  85.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
  86.             return;
  87.          }
  88.          /* fall-through */
  89.       case GL_ZERO:
  90.       case GL_ONE:
  91.       case GL_DST_COLOR:
  92.       case GL_ONE_MINUS_DST_COLOR:
  93.       case GL_SRC_ALPHA:
  94.       case GL_ONE_MINUS_SRC_ALPHA:
  95.       case GL_DST_ALPHA:
  96.       case GL_ONE_MINUS_DST_ALPHA:
  97.       case GL_SRC_ALPHA_SATURATE:
  98.       case GL_CONSTANT_COLOR:
  99.       case GL_ONE_MINUS_CONSTANT_COLOR:
  100.       case GL_CONSTANT_ALPHA:
  101.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  102.          break;
  103.       default:
  104.          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
  105.          return;
  106.    }
  107.  
  108.    switch (dfactorRGB) {
  109.       case GL_DST_COLOR:
  110.       case GL_ONE_MINUS_DST_COLOR:
  111.          if (!ctx->Extensions.NV_blend_square) {
  112.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
  113.             return;
  114.          }
  115.          /* fall-through */
  116.       case GL_ZERO:
  117.       case GL_ONE:
  118.       case GL_SRC_COLOR:
  119.       case GL_ONE_MINUS_SRC_COLOR:
  120.       case GL_SRC_ALPHA:
  121.       case GL_ONE_MINUS_SRC_ALPHA:
  122.       case GL_DST_ALPHA:
  123.       case GL_ONE_MINUS_DST_ALPHA:
  124.       case GL_CONSTANT_COLOR:
  125.       case GL_ONE_MINUS_CONSTANT_COLOR:
  126.       case GL_CONSTANT_ALPHA:
  127.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  128.          break;
  129.       default:
  130.          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
  131.          return;
  132.    }
  133.  
  134.    switch (sfactorA) {
  135.       case GL_SRC_COLOR:
  136.       case GL_ONE_MINUS_SRC_COLOR:
  137.          if (!ctx->Extensions.NV_blend_square) {
  138.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
  139.             return;
  140.          }
  141.          /* fall-through */
  142.       case GL_ZERO:
  143.       case GL_ONE:
  144.       case GL_DST_COLOR:
  145.       case GL_ONE_MINUS_DST_COLOR:
  146.       case GL_SRC_ALPHA:
  147.       case GL_ONE_MINUS_SRC_ALPHA:
  148.       case GL_DST_ALPHA:
  149.       case GL_ONE_MINUS_DST_ALPHA:
  150.       case GL_SRC_ALPHA_SATURATE:
  151.       case GL_CONSTANT_COLOR:
  152.       case GL_ONE_MINUS_CONSTANT_COLOR:
  153.       case GL_CONSTANT_ALPHA:
  154.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  155.          break;
  156.       default:
  157.          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
  158.          return;
  159.    }
  160.  
  161.    switch (dfactorA) {
  162.       case GL_DST_COLOR:
  163.       case GL_ONE_MINUS_DST_COLOR:
  164.          if (!ctx->Extensions.NV_blend_square) {
  165.             _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)");
  166.             return;
  167.          }
  168.          /* fall-through */
  169.       case GL_ZERO:
  170.       case GL_ONE:
  171.       case GL_SRC_COLOR:
  172.       case GL_ONE_MINUS_SRC_COLOR:
  173.       case GL_SRC_ALPHA:
  174.       case GL_ONE_MINUS_SRC_ALPHA:
  175.       case GL_DST_ALPHA:
  176.       case GL_ONE_MINUS_DST_ALPHA:
  177.       case GL_CONSTANT_COLOR:
  178.       case GL_ONE_MINUS_CONSTANT_COLOR:
  179.       case GL_CONSTANT_ALPHA:
  180.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  181.          break;
  182.       default:
  183.          _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)" );
  184.          return;
  185.    }
  186.  
  187.    if (ctx->Color.BlendSrcRGB == sfactorRGB &&
  188.        ctx->Color.BlendDstRGB == dfactorRGB &&
  189.        ctx->Color.BlendSrcA == sfactorA &&
  190.        ctx->Color.BlendDstA == dfactorA)
  191.       return;
  192.  
  193.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  194.  
  195.    ctx->Color.BlendSrcRGB = sfactorRGB;
  196.    ctx->Color.BlendDstRGB = dfactorRGB;
  197.    ctx->Color.BlendSrcA = sfactorA;
  198.    ctx->Color.BlendDstA = dfactorA;
  199.  
  200.    if (ctx->Driver.BlendFuncSeparate) {
  201.       (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
  202.                                         sfactorA, dfactorA );
  203.    }
  204. }
  205.  
  206.  
  207. #if _HAVE_FULL_GL
  208.  
  209. static GLboolean
  210. _mesa_validate_blend_equation( struct gl_context *ctx,
  211.                                GLenum mode, GLboolean is_separate )
  212. {
  213.    switch (mode) {
  214.       case GL_FUNC_ADD:
  215.          break;
  216.       case GL_MIN:
  217.       case GL_MAX:
  218.          if (!ctx->Extensions.EXT_blend_minmax) {
  219.             return GL_FALSE;
  220.          }
  221.          break;
  222.       /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
  223.        */
  224.       case GL_LOGIC_OP:
  225.          if (!ctx->Extensions.EXT_blend_logic_op || is_separate) {
  226.             return GL_FALSE;
  227.          }
  228.          break;
  229.       case GL_FUNC_SUBTRACT:
  230.       case GL_FUNC_REVERSE_SUBTRACT:
  231.          if (!ctx->Extensions.EXT_blend_subtract) {
  232.             return GL_FALSE;
  233.          }
  234.          break;
  235.       default:
  236.          return GL_FALSE;
  237.    }
  238.  
  239.    return GL_TRUE;
  240. }
  241.  
  242.  
  243. /* This is really an extension function! */
  244. void GLAPIENTRY
  245. _mesa_BlendEquation( GLenum mode )
  246. {
  247.    GET_CURRENT_CONTEXT(ctx);
  248.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  249.  
  250.    if (MESA_VERBOSE & VERBOSE_API)
  251.       _mesa_debug(ctx, "glBlendEquation %s\n",
  252.                   _mesa_lookup_enum_by_nr(mode));
  253.  
  254.    if ( ! _mesa_validate_blend_equation( ctx, mode, GL_FALSE ) ) {
  255.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
  256.       return;
  257.    }
  258.  
  259.    if ( (ctx->Color.BlendEquationRGB == mode) &&
  260.         (ctx->Color.BlendEquationA == mode) )
  261.       return;
  262.  
  263.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  264.    ctx->Color.BlendEquationRGB = mode;
  265.    ctx->Color.BlendEquationA = mode;
  266.  
  267.    if (ctx->Driver.BlendEquationSeparate)
  268.       (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
  269. }
  270.  
  271.  
  272. void GLAPIENTRY
  273. _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
  274. {
  275.    GET_CURRENT_CONTEXT(ctx);
  276.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  277.  
  278.    if (MESA_VERBOSE & VERBOSE_API)
  279.       _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n",
  280.                   _mesa_lookup_enum_by_nr(modeRGB),
  281.                   _mesa_lookup_enum_by_nr(modeA));
  282.  
  283.    if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
  284.       _mesa_error(ctx, GL_INVALID_OPERATION,
  285.                   "glBlendEquationSeparateEXT not supported by driver");
  286.       return;
  287.    }
  288.  
  289.    if ( ! _mesa_validate_blend_equation( ctx, modeRGB, GL_TRUE ) ) {
  290.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
  291.       return;
  292.    }
  293.  
  294.    if ( ! _mesa_validate_blend_equation( ctx, modeA, GL_TRUE ) ) {
  295.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
  296.       return;
  297.    }
  298.  
  299.  
  300.    if ( (ctx->Color.BlendEquationRGB == modeRGB) &&
  301.         (ctx->Color.BlendEquationA == modeA) )
  302.       return;
  303.  
  304.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  305.    ctx->Color.BlendEquationRGB = modeRGB;
  306.    ctx->Color.BlendEquationA = modeA;
  307.  
  308.    if (ctx->Driver.BlendEquationSeparate)
  309.       (*ctx->Driver.BlendEquationSeparate)( ctx, modeRGB, modeA );
  310. }
  311. #endif
  312.  
  313.  
  314. /**
  315.  * Set the blending color.
  316.  *
  317.  * \param red red color component.
  318.  * \param green green color component.
  319.  * \param blue blue color component.
  320.  * \param alpha alpha color component.
  321.  *
  322.  * \sa glBlendColor().
  323.  *
  324.  * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor.  On a
  325.  * change, flushes the vertices and notifies the driver via
  326.  * dd_function_table::BlendColor callback.
  327.  */
  328. void GLAPIENTRY
  329. _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
  330. {
  331.    GLfloat tmp[4];
  332.    GET_CURRENT_CONTEXT(ctx);
  333.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  334.  
  335.    tmp[0] = CLAMP( red,   0.0F, 1.0F );
  336.    tmp[1] = CLAMP( green, 0.0F, 1.0F );
  337.    tmp[2] = CLAMP( blue,  0.0F, 1.0F );
  338.    tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
  339.  
  340.    if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
  341.       return;
  342.  
  343.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  344.    COPY_4FV( ctx->Color.BlendColor, tmp );
  345.  
  346.    if (ctx->Driver.BlendColor)
  347.       (*ctx->Driver.BlendColor)(ctx, tmp);
  348. }
  349.  
  350.  
  351. /**
  352.  * Specify the alpha test function.
  353.  *
  354.  * \param func alpha comparison function.
  355.  * \param ref reference value.
  356.  *
  357.  * Verifies the parameters and updates gl_colorbuffer_attrib.
  358.  * On a change, flushes the vertices and notifies the driver via
  359.  * dd_function_table::AlphaFunc callback.
  360.  */
  361. void GLAPIENTRY
  362. _mesa_AlphaFunc( GLenum func, GLclampf ref )
  363. {
  364.    GET_CURRENT_CONTEXT(ctx);
  365.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  366.  
  367.    switch (func) {
  368.    case GL_NEVER:
  369.    case GL_LESS:
  370.    case GL_EQUAL:
  371.    case GL_LEQUAL:
  372.    case GL_GREATER:
  373.    case GL_NOTEQUAL:
  374.    case GL_GEQUAL:
  375.    case GL_ALWAYS:
  376.       ref = CLAMP(ref, 0.0F, 1.0F);
  377.  
  378.       if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
  379.          return; /* no change */
  380.  
  381.       FLUSH_VERTICES(ctx, _NEW_COLOR);
  382.       ctx->Color.AlphaFunc = func;
  383.       ctx->Color.AlphaRef = ref;
  384.  
  385.       if (ctx->Driver.AlphaFunc)
  386.          ctx->Driver.AlphaFunc(ctx, func, ref);
  387.       return;
  388.  
  389.    default:
  390.       _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
  391.       return;
  392.    }
  393. }
  394.  
  395.  
  396. /**
  397.  * Specify a logic pixel operation for color index rendering.
  398.  *
  399.  * \param opcode operation.
  400.  *
  401.  * Verifies that \p opcode is a valid enum and updates
  402. gl_colorbuffer_attrib::LogicOp.
  403.  * On a change, flushes the vertices and notifies the driver via the
  404.  * dd_function_table::LogicOpcode callback.
  405.  */
  406. void GLAPIENTRY
  407. _mesa_LogicOp( GLenum opcode )
  408. {
  409.    GET_CURRENT_CONTEXT(ctx);
  410.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  411.  
  412.    switch (opcode) {
  413.       case GL_CLEAR:
  414.       case GL_SET:
  415.       case GL_COPY:
  416.       case GL_COPY_INVERTED:
  417.       case GL_NOOP:
  418.       case GL_INVERT:
  419.       case GL_AND:
  420.       case GL_NAND:
  421.       case GL_OR:
  422.       case GL_NOR:
  423.       case GL_XOR:
  424.       case GL_EQUIV:
  425.       case GL_AND_REVERSE:
  426.       case GL_AND_INVERTED:
  427.       case GL_OR_REVERSE:
  428.       case GL_OR_INVERTED:
  429.          break;
  430.       default:
  431.          _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
  432.          return;
  433.    }
  434.  
  435.    if (ctx->Color.LogicOp == opcode)
  436.       return;
  437.  
  438.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  439.    ctx->Color.LogicOp = opcode;
  440.  
  441.    if (ctx->Driver.LogicOpcode)
  442.       ctx->Driver.LogicOpcode( ctx, opcode );
  443. }
  444.  
  445. #if _HAVE_FULL_GL
  446. void GLAPIENTRY
  447. _mesa_IndexMask( GLuint mask )
  448. {
  449.    GET_CURRENT_CONTEXT(ctx);
  450.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  451.  
  452.    if (ctx->Color.IndexMask == mask)
  453.       return;
  454.  
  455.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  456.    ctx->Color.IndexMask = mask;
  457. }
  458. #endif
  459.  
  460.  
  461. /**
  462.  * Enable or disable writing of frame buffer color components.
  463.  *
  464.  * \param red whether to mask writing of the red color component.
  465.  * \param green whether to mask writing of the green color component.
  466.  * \param blue whether to mask writing of the blue color component.
  467.  * \param alpha whether to mask writing of the alpha color component.
  468.  *
  469.  * \sa glColorMask().
  470.  *
  471.  * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask.  On a
  472.  * change, flushes the vertices and notifies the driver via the
  473.  * dd_function_table::ColorMask callback.
  474.  */
  475. void GLAPIENTRY
  476. _mesa_ColorMask( GLboolean red, GLboolean green,
  477.                  GLboolean blue, GLboolean alpha )
  478. {
  479.    GET_CURRENT_CONTEXT(ctx);
  480.    GLubyte tmp[4];
  481.    GLuint i;
  482.    GLboolean flushed;
  483.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  484.  
  485.    if (MESA_VERBOSE & VERBOSE_API)
  486.       _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
  487.  
  488.    /* Shouldn't have any information about channel depth in core mesa
  489.     * -- should probably store these as the native booleans:
  490.     */
  491.    tmp[RCOMP] = red    ? 0xff : 0x0;
  492.    tmp[GCOMP] = green  ? 0xff : 0x0;
  493.    tmp[BCOMP] = blue   ? 0xff : 0x0;
  494.    tmp[ACOMP] = alpha  ? 0xff : 0x0;
  495.  
  496.    flushed = GL_FALSE;
  497.    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
  498.       if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
  499.          if (!flushed) {
  500.             FLUSH_VERTICES(ctx, _NEW_COLOR);
  501.          }
  502.          flushed = GL_TRUE;
  503.          COPY_4UBV(ctx->Color.ColorMask[i], tmp);
  504.       }
  505.    }
  506.  
  507.    if (ctx->Driver.ColorMask)
  508.       ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
  509. }
  510.  
  511.  
  512. /**
  513.  * For GL_EXT_draw_buffers2 and GL3
  514.  */
  515. void GLAPIENTRY
  516. _mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
  517.                         GLboolean blue, GLboolean alpha )
  518. {
  519.    GLubyte tmp[4];
  520.    GET_CURRENT_CONTEXT(ctx);
  521.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  522.  
  523.    if (MESA_VERBOSE & VERBOSE_API)
  524.       _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
  525.                   buf, red, green, blue, alpha);
  526.  
  527.    if (buf >= ctx->Const.MaxDrawBuffers) {
  528.       _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
  529.       return;
  530.    }
  531.  
  532.    /* Shouldn't have any information about channel depth in core mesa
  533.     * -- should probably store these as the native booleans:
  534.     */
  535.    tmp[RCOMP] = red    ? 0xff : 0x0;
  536.    tmp[GCOMP] = green  ? 0xff : 0x0;
  537.    tmp[BCOMP] = blue   ? 0xff : 0x0;
  538.    tmp[ACOMP] = alpha  ? 0xff : 0x0;
  539.  
  540.    if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
  541.       return;
  542.  
  543.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  544.    COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
  545.  
  546.    if (ctx->Driver.ColorMaskIndexed)
  547.       ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
  548. }
  549.  
  550.  
  551. extern void GLAPIENTRY
  552. _mesa_ClampColorARB(GLenum target, GLenum clamp)
  553. {
  554.    GET_CURRENT_CONTEXT(ctx);
  555.  
  556.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  557.  
  558.    if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
  559.       _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
  560.       return;
  561.    }
  562.  
  563.    switch (target) {
  564.    case GL_CLAMP_VERTEX_COLOR_ARB:
  565.       ctx->Light.ClampVertexColor = clamp;
  566.       break;
  567.    case GL_CLAMP_FRAGMENT_COLOR_ARB:
  568.       ctx->Color.ClampFragmentColor = clamp;
  569.       break;
  570.    case GL_CLAMP_READ_COLOR_ARB:
  571.       ctx->Color.ClampReadColor = clamp;
  572.       break;
  573.    default:
  574.       _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
  575.       return;
  576.    }
  577. }
  578.  
  579.  
  580.  
  581.  
  582. /**********************************************************************/
  583. /** \name Initialization */
  584. /*@{*/
  585.  
  586. /**
  587.  * Initialization of the context's Color attribute group.
  588.  *
  589.  * \param ctx GL context.
  590.  *
  591.  * Initializes the related fields in the context color attribute group,
  592.  * __struct gl_contextRec::Color.
  593.  */
  594. void _mesa_init_color( struct gl_context * ctx )
  595. {
  596.    /* Color buffer group */
  597.    ctx->Color.IndexMask = ~0u;
  598.    memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
  599.    ctx->Color.ClearIndex = 0;
  600.    ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
  601.    ctx->Color.AlphaEnabled = GL_FALSE;
  602.    ctx->Color.AlphaFunc = GL_ALWAYS;
  603.    ctx->Color.AlphaRef = 0;
  604.    ctx->Color.BlendEnabled = 0x0;
  605.    ctx->Color.BlendSrcRGB = GL_ONE;
  606.    ctx->Color.BlendDstRGB = GL_ZERO;
  607.    ctx->Color.BlendSrcA = GL_ONE;
  608.    ctx->Color.BlendDstA = GL_ZERO;
  609.    ctx->Color.BlendEquationRGB = GL_FUNC_ADD;
  610.    ctx->Color.BlendEquationA = GL_FUNC_ADD;
  611.    ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
  612.    ctx->Color.IndexLogicOpEnabled = GL_FALSE;
  613.    ctx->Color.ColorLogicOpEnabled = GL_FALSE;
  614.    ctx->Color._LogicOpEnabled = GL_FALSE;
  615.    ctx->Color.LogicOp = GL_COPY;
  616.    ctx->Color.DitherFlag = GL_TRUE;
  617.  
  618.    if (ctx->Visual.doubleBufferMode) {
  619.       ctx->Color.DrawBuffer[0] = GL_BACK;
  620.    }
  621.    else {
  622.       ctx->Color.DrawBuffer[0] = GL_FRONT;
  623.    }
  624.  
  625.    ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
  626.    ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
  627. }
  628.  
  629. /*@}*/
  630.