Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**
  2.  * \file blend.c
  3.  * Blending operations.
  4.  */
  5.  
  6. /*
  7.  * Mesa 3-D graphics library
  8.  *
  9.  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  10.  *
  11.  * Permission is hereby granted, free of charge, to any person obtaining a
  12.  * copy of this software and associated documentation files (the "Software"),
  13.  * to deal in the Software without restriction, including without limitation
  14.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15.  * and/or sell copies of the Software, and to permit persons to whom the
  16.  * Software is furnished to do so, subject to the following conditions:
  17.  *
  18.  * The above copyright notice and this permission notice shall be included
  19.  * in all copies or substantial portions of the Software.
  20.  *
  21.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  22.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  24.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  25.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  26.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  27.  * 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. /**
  42.  * Check if given blend source factor is legal.
  43.  * \return GL_TRUE if legal, GL_FALSE otherwise.
  44.  */
  45. static GLboolean
  46. legal_src_factor(const struct gl_context *ctx, GLenum factor)
  47. {
  48.    switch (factor) {
  49.    case GL_SRC_COLOR:
  50.    case GL_ONE_MINUS_SRC_COLOR:
  51.    case GL_ZERO:
  52.    case GL_ONE:
  53.    case GL_DST_COLOR:
  54.    case GL_ONE_MINUS_DST_COLOR:
  55.    case GL_SRC_ALPHA:
  56.    case GL_ONE_MINUS_SRC_ALPHA:
  57.    case GL_DST_ALPHA:
  58.    case GL_ONE_MINUS_DST_ALPHA:
  59.    case GL_SRC_ALPHA_SATURATE:
  60.       return GL_TRUE;
  61.    case GL_CONSTANT_COLOR:
  62.    case GL_ONE_MINUS_CONSTANT_COLOR:
  63.    case GL_CONSTANT_ALPHA:
  64.    case GL_ONE_MINUS_CONSTANT_ALPHA:
  65.       return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2;
  66.    case GL_SRC1_COLOR:
  67.    case GL_SRC1_ALPHA:
  68.    case GL_ONE_MINUS_SRC1_COLOR:
  69.    case GL_ONE_MINUS_SRC1_ALPHA:
  70.       return _mesa_is_desktop_gl(ctx)
  71.          && ctx->Extensions.ARB_blend_func_extended;
  72.    default:
  73.       return GL_FALSE;
  74.    }
  75. }
  76.  
  77.  
  78. /**
  79.  * Check if given blend destination factor is legal.
  80.  * \return GL_TRUE if legal, GL_FALSE otherwise.
  81.  */
  82. static GLboolean
  83. legal_dst_factor(const struct gl_context *ctx, GLenum factor)
  84. {
  85.    switch (factor) {
  86.    case GL_DST_COLOR:
  87.    case GL_ONE_MINUS_DST_COLOR:
  88.    case GL_ZERO:
  89.    case GL_ONE:
  90.    case GL_SRC_COLOR:
  91.    case GL_ONE_MINUS_SRC_COLOR:
  92.    case GL_SRC_ALPHA:
  93.    case GL_ONE_MINUS_SRC_ALPHA:
  94.    case GL_DST_ALPHA:
  95.    case GL_ONE_MINUS_DST_ALPHA:
  96.       return GL_TRUE;
  97.    case GL_CONSTANT_COLOR:
  98.    case GL_ONE_MINUS_CONSTANT_COLOR:
  99.    case GL_CONSTANT_ALPHA:
  100.    case GL_ONE_MINUS_CONSTANT_ALPHA:
  101.       return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2;
  102.    case GL_SRC_ALPHA_SATURATE:
  103.       return (_mesa_is_desktop_gl(ctx)
  104.               && ctx->Extensions.ARB_blend_func_extended)
  105.          || _mesa_is_gles3(ctx);
  106.    case GL_SRC1_COLOR:
  107.    case GL_SRC1_ALPHA:
  108.    case GL_ONE_MINUS_SRC1_COLOR:
  109.    case GL_ONE_MINUS_SRC1_ALPHA:
  110.       return _mesa_is_desktop_gl(ctx)
  111.          && ctx->Extensions.ARB_blend_func_extended;
  112.    default:
  113.       return GL_FALSE;
  114.    }
  115. }
  116.  
  117.  
  118. /**
  119.  * Check if src/dest RGB/A blend factors are legal.  If not generate
  120.  * a GL error.
  121.  * \return GL_TRUE if factors are legal, GL_FALSE otherwise.
  122.  */
  123. static GLboolean
  124. validate_blend_factors(struct gl_context *ctx, const char *func,
  125.                        GLenum sfactorRGB, GLenum dfactorRGB,
  126.                        GLenum sfactorA, GLenum dfactorA)
  127. {
  128.    if (!legal_src_factor(ctx, sfactorRGB)) {
  129.       _mesa_error(ctx, GL_INVALID_ENUM,
  130.                   "%s(sfactorRGB = %s)", func,
  131.                   _mesa_lookup_enum_by_nr(sfactorRGB));
  132.       return GL_FALSE;
  133.    }
  134.  
  135.    if (!legal_dst_factor(ctx, dfactorRGB)) {
  136.       _mesa_error(ctx, GL_INVALID_ENUM,
  137.                   "%s(dfactorRGB = %s)", func,
  138.                   _mesa_lookup_enum_by_nr(dfactorRGB));
  139.       return GL_FALSE;
  140.    }
  141.  
  142.    if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) {
  143.       _mesa_error(ctx, GL_INVALID_ENUM,
  144.                   "%s(sfactorA = %s)", func,
  145.                   _mesa_lookup_enum_by_nr(sfactorA));
  146.       return GL_FALSE;
  147.    }
  148.  
  149.    if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) {
  150.       _mesa_error(ctx, GL_INVALID_ENUM,
  151.                   "%s(dfactorA = %s)", func,
  152.                   _mesa_lookup_enum_by_nr(dfactorA));
  153.       return GL_FALSE;
  154.    }
  155.  
  156.    return GL_TRUE;
  157. }
  158.  
  159.  
  160. /**
  161.  * Specify the blending operation.
  162.  *
  163.  * \param sfactor source factor operator.
  164.  * \param dfactor destination factor operator.
  165.  *
  166.  * \sa glBlendFunc, glBlendFuncSeparateEXT
  167.  */
  168. void GLAPIENTRY
  169. _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
  170. {
  171.    _mesa_BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
  172. }
  173.  
  174. static GLboolean
  175. blend_factor_is_dual_src(GLenum factor)
  176. {
  177.    return (factor == GL_SRC1_COLOR ||
  178.            factor == GL_SRC1_ALPHA ||
  179.            factor == GL_ONE_MINUS_SRC1_COLOR ||
  180.            factor == GL_ONE_MINUS_SRC1_ALPHA);
  181. }
  182.  
  183. static void
  184. update_uses_dual_src(struct gl_context *ctx, int buf)
  185. {
  186.    ctx->Color.Blend[buf]._UsesDualSrc =
  187.       (blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcRGB) ||
  188.        blend_factor_is_dual_src(ctx->Color.Blend[buf].DstRGB) ||
  189.        blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcA) ||
  190.        blend_factor_is_dual_src(ctx->Color.Blend[buf].DstA));
  191. }
  192.  
  193. /**
  194.  * Set the separate blend source/dest factors for all draw buffers.
  195.  *
  196.  * \param sfactorRGB RGB source factor operator.
  197.  * \param dfactorRGB RGB destination factor operator.
  198.  * \param sfactorA alpha source factor operator.
  199.  * \param dfactorA alpha destination factor operator.
  200.  */
  201. void GLAPIENTRY
  202. _mesa_BlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB,
  203.                             GLenum sfactorA, GLenum dfactorA )
  204. {
  205.    GLuint buf, numBuffers;
  206.    GLboolean changed;
  207.    GET_CURRENT_CONTEXT(ctx);
  208.  
  209.    if (MESA_VERBOSE & VERBOSE_API)
  210.       _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
  211.                   _mesa_lookup_enum_by_nr(sfactorRGB),
  212.                   _mesa_lookup_enum_by_nr(dfactorRGB),
  213.                   _mesa_lookup_enum_by_nr(sfactorA),
  214.                   _mesa_lookup_enum_by_nr(dfactorA));
  215.  
  216.    if (!validate_blend_factors(ctx, "glBlendFuncSeparate",
  217.                                sfactorRGB, dfactorRGB,
  218.                                sfactorA, dfactorA)) {
  219.       return;
  220.    }
  221.  
  222.    numBuffers = ctx->Extensions.ARB_draw_buffers_blend
  223.       ? ctx->Const.MaxDrawBuffers : 1;
  224.  
  225.    changed = GL_FALSE;
  226.    for (buf = 0; buf < numBuffers; buf++) {
  227.       if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB ||
  228.           ctx->Color.Blend[buf].DstRGB != dfactorRGB ||
  229.           ctx->Color.Blend[buf].SrcA != sfactorA ||
  230.           ctx->Color.Blend[buf].DstA != dfactorA) {
  231.          changed = GL_TRUE;
  232.          break;
  233.       }
  234.    }
  235.    if (!changed)
  236.       return;
  237.  
  238.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  239.  
  240.    for (buf = 0; buf < numBuffers; buf++) {
  241.       ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
  242.       ctx->Color.Blend[buf].DstRGB = dfactorRGB;
  243.       ctx->Color.Blend[buf].SrcA = sfactorA;
  244.       ctx->Color.Blend[buf].DstA = dfactorA;
  245.       update_uses_dual_src(ctx, buf);
  246.    }
  247.    ctx->Color._BlendFuncPerBuffer = GL_FALSE;
  248.  
  249.    if (ctx->Driver.BlendFuncSeparate) {
  250.       ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB,
  251.                                     sfactorA, dfactorA);
  252.    }
  253. }
  254.  
  255.  
  256. /**
  257.  * Set blend source/dest factors for one color buffer/target.
  258.  */
  259. void GLAPIENTRY
  260. _mesa_BlendFunciARB(GLuint buf, GLenum sfactor, GLenum dfactor)
  261. {
  262.    _mesa_BlendFuncSeparateiARB(buf, sfactor, dfactor, sfactor, dfactor);
  263. }
  264.  
  265.  
  266. /**
  267.  * Set separate blend source/dest factors for one color buffer/target.
  268.  */
  269. void GLAPIENTRY
  270. _mesa_BlendFuncSeparateiARB(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
  271.                          GLenum sfactorA, GLenum dfactorA)
  272. {
  273.    GET_CURRENT_CONTEXT(ctx);
  274.  
  275.    if (!ctx->Extensions.ARB_draw_buffers_blend) {
  276.       _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
  277.       return;
  278.    }
  279.  
  280.    if (buf >= ctx->Const.MaxDrawBuffers) {
  281.       _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
  282.                   buf);
  283.       return;
  284.    }
  285.  
  286.    if (!validate_blend_factors(ctx, "glBlendFuncSeparatei",
  287.                                sfactorRGB, dfactorRGB,
  288.                                sfactorA, dfactorA)) {
  289.       return;
  290.    }
  291.  
  292.    if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB &&
  293.        ctx->Color.Blend[buf].DstRGB == dfactorRGB &&
  294.        ctx->Color.Blend[buf].SrcA == sfactorA &&
  295.        ctx->Color.Blend[buf].DstA == dfactorA)
  296.       return; /* no change */
  297.  
  298.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  299.  
  300.    ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
  301.    ctx->Color.Blend[buf].DstRGB = dfactorRGB;
  302.    ctx->Color.Blend[buf].SrcA = sfactorA;
  303.    ctx->Color.Blend[buf].DstA = dfactorA;
  304.    update_uses_dual_src(ctx, buf);
  305.    ctx->Color._BlendFuncPerBuffer = GL_TRUE;
  306.  
  307.    if (ctx->Driver.BlendFuncSeparatei) {
  308.       ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB,
  309.                                      sfactorA, dfactorA);
  310.    }
  311. }
  312.  
  313.  
  314. /**
  315.  * Check if given blend equation is legal.
  316.  * \return GL_TRUE if legal, GL_FALSE otherwise.
  317.  */
  318. static GLboolean
  319. legal_blend_equation(const struct gl_context *ctx, GLenum mode)
  320. {
  321.    switch (mode) {
  322.    case GL_FUNC_ADD:
  323.    case GL_FUNC_SUBTRACT:
  324.    case GL_FUNC_REVERSE_SUBTRACT:
  325.       return GL_TRUE;
  326.    case GL_MIN:
  327.    case GL_MAX:
  328.       return ctx->Extensions.EXT_blend_minmax;
  329.    default:
  330.       return GL_FALSE;
  331.    }
  332. }
  333.  
  334.  
  335. /* This is really an extension function! */
  336. void GLAPIENTRY
  337. _mesa_BlendEquation( GLenum mode )
  338. {
  339.    GLuint buf, numBuffers;
  340.    GLboolean changed;
  341.    GET_CURRENT_CONTEXT(ctx);
  342.  
  343.    if (MESA_VERBOSE & VERBOSE_API)
  344.       _mesa_debug(ctx, "glBlendEquation(%s)\n",
  345.                   _mesa_lookup_enum_by_nr(mode));
  346.  
  347.    if (!legal_blend_equation(ctx, mode)) {
  348.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
  349.       return;
  350.    }
  351.  
  352.    numBuffers = ctx->Extensions.ARB_draw_buffers_blend
  353.       ? ctx->Const.MaxDrawBuffers : 1;
  354.  
  355.    changed = GL_FALSE;
  356.    for (buf = 0; buf < numBuffers; buf++) {
  357.       if (ctx->Color.Blend[buf].EquationRGB != mode ||
  358.           ctx->Color.Blend[buf].EquationA != mode) {
  359.          changed = GL_TRUE;
  360.          break;
  361.       }
  362.    }
  363.    if (!changed)
  364.       return;
  365.  
  366.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  367.    for (buf = 0; buf < numBuffers; buf++) {
  368.       ctx->Color.Blend[buf].EquationRGB = mode;
  369.       ctx->Color.Blend[buf].EquationA = mode;
  370.    }
  371.    ctx->Color._BlendEquationPerBuffer = GL_FALSE;
  372.  
  373.    if (ctx->Driver.BlendEquationSeparate)
  374.       (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
  375. }
  376.  
  377.  
  378. /**
  379.  * Set blend equation for one color buffer/target.
  380.  */
  381. void GLAPIENTRY
  382. _mesa_BlendEquationiARB(GLuint buf, GLenum mode)
  383. {
  384.    GET_CURRENT_CONTEXT(ctx);
  385.  
  386.    if (MESA_VERBOSE & VERBOSE_API)
  387.       _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
  388.                   buf, _mesa_lookup_enum_by_nr(mode));
  389.  
  390.    if (buf >= ctx->Const.MaxDrawBuffers) {
  391.       _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
  392.                   buf);
  393.       return;
  394.    }
  395.  
  396.    if (!legal_blend_equation(ctx, mode)) {
  397.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi");
  398.       return;
  399.    }
  400.  
  401.    if (ctx->Color.Blend[buf].EquationRGB == mode &&
  402.        ctx->Color.Blend[buf].EquationA == mode)
  403.       return;  /* no change */
  404.  
  405.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  406.    ctx->Color.Blend[buf].EquationRGB = mode;
  407.    ctx->Color.Blend[buf].EquationA = mode;
  408.    ctx->Color._BlendEquationPerBuffer = GL_TRUE;
  409.  
  410.    if (ctx->Driver.BlendEquationSeparatei)
  411.       ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode);
  412. }
  413.  
  414.  
  415. void GLAPIENTRY
  416. _mesa_BlendEquationSeparate( GLenum modeRGB, GLenum modeA )
  417. {
  418.    GLuint buf, numBuffers;
  419.    GLboolean changed;
  420.    GET_CURRENT_CONTEXT(ctx);
  421.  
  422.    if (MESA_VERBOSE & VERBOSE_API)
  423.       _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
  424.                   _mesa_lookup_enum_by_nr(modeRGB),
  425.                   _mesa_lookup_enum_by_nr(modeA));
  426.  
  427.    if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
  428.       _mesa_error(ctx, GL_INVALID_OPERATION,
  429.                   "glBlendEquationSeparateEXT not supported by driver");
  430.       return;
  431.    }
  432.  
  433.    if (!legal_blend_equation(ctx, modeRGB)) {
  434.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
  435.       return;
  436.    }
  437.  
  438.    if (!legal_blend_equation(ctx, modeA)) {
  439.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
  440.       return;
  441.    }
  442.  
  443.    numBuffers = ctx->Extensions.ARB_draw_buffers_blend
  444.       ? ctx->Const.MaxDrawBuffers : 1;
  445.  
  446.    changed = GL_FALSE;
  447.    for (buf = 0; buf < numBuffers; buf++) {
  448.       if (ctx->Color.Blend[buf].EquationRGB != modeRGB ||
  449.           ctx->Color.Blend[buf].EquationA != modeA) {
  450.          changed = GL_TRUE;
  451.          break;
  452.       }
  453.    }
  454.    if (!changed)
  455.       return;
  456.  
  457.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  458.    for (buf = 0; buf < numBuffers; buf++) {
  459.       ctx->Color.Blend[buf].EquationRGB = modeRGB;
  460.       ctx->Color.Blend[buf].EquationA = modeA;
  461.    }
  462.    ctx->Color._BlendEquationPerBuffer = GL_FALSE;
  463.  
  464.    if (ctx->Driver.BlendEquationSeparate)
  465.       ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
  466. }
  467.  
  468.  
  469. /**
  470.  * Set separate blend equations for one color buffer/target.
  471.  */
  472. void GLAPIENTRY
  473. _mesa_BlendEquationSeparateiARB(GLuint buf, GLenum modeRGB, GLenum modeA)
  474. {
  475.    GET_CURRENT_CONTEXT(ctx);
  476.  
  477.    if (MESA_VERBOSE & VERBOSE_API)
  478.       _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
  479.                   _mesa_lookup_enum_by_nr(modeRGB),
  480.                   _mesa_lookup_enum_by_nr(modeA));
  481.  
  482.    if (buf >= ctx->Const.MaxDrawBuffers) {
  483.       _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)",
  484.                   buf);
  485.       return;
  486.    }
  487.  
  488.    if (!legal_blend_equation(ctx, modeRGB)) {
  489.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)");
  490.       return;
  491.    }
  492.  
  493.    if (!legal_blend_equation(ctx, modeA)) {
  494.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)");
  495.       return;
  496.    }
  497.  
  498.    if (ctx->Color.Blend[buf].EquationRGB == modeRGB &&
  499.        ctx->Color.Blend[buf].EquationA == modeA)
  500.       return;  /* no change */
  501.  
  502.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  503.    ctx->Color.Blend[buf].EquationRGB = modeRGB;
  504.    ctx->Color.Blend[buf].EquationA = modeA;
  505.    ctx->Color._BlendEquationPerBuffer = GL_TRUE;
  506.  
  507.    if (ctx->Driver.BlendEquationSeparatei)
  508.       ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA);
  509. }
  510.  
  511.  
  512. /**
  513.  * Set the blending color.
  514.  *
  515.  * \param red red color component.
  516.  * \param green green color component.
  517.  * \param blue blue color component.
  518.  * \param alpha alpha color component.
  519.  *
  520.  * \sa glBlendColor().
  521.  *
  522.  * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor.  On a
  523.  * change, flushes the vertices and notifies the driver via
  524.  * dd_function_table::BlendColor callback.
  525.  */
  526. void GLAPIENTRY
  527. _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
  528. {
  529.    GLfloat tmp[4];
  530.    GET_CURRENT_CONTEXT(ctx);
  531.  
  532.    tmp[0] = red;
  533.    tmp[1] = green;
  534.    tmp[2] = blue;
  535.    tmp[3] = alpha;
  536.  
  537.    if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped))
  538.       return;
  539.  
  540.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  541.    COPY_4FV( ctx->Color.BlendColorUnclamped, tmp );
  542.  
  543.    ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
  544.    ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
  545.    ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
  546.    ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
  547.  
  548.    if (ctx->Driver.BlendColor)
  549.       (*ctx->Driver.BlendColor)(ctx, ctx->Color.BlendColor);
  550. }
  551.  
  552.  
  553. /**
  554.  * Specify the alpha test function.
  555.  *
  556.  * \param func alpha comparison function.
  557.  * \param ref reference value.
  558.  *
  559.  * Verifies the parameters and updates gl_colorbuffer_attrib.
  560.  * On a change, flushes the vertices and notifies the driver via
  561.  * dd_function_table::AlphaFunc callback.
  562.  */
  563. void GLAPIENTRY
  564. _mesa_AlphaFunc( GLenum func, GLclampf ref )
  565. {
  566.    GET_CURRENT_CONTEXT(ctx);
  567.  
  568.    if (MESA_VERBOSE & VERBOSE_API)
  569.       _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
  570.                   _mesa_lookup_enum_by_nr(func), ref);
  571.  
  572.    switch (func) {
  573.    case GL_NEVER:
  574.    case GL_LESS:
  575.    case GL_EQUAL:
  576.    case GL_LEQUAL:
  577.    case GL_GREATER:
  578.    case GL_NOTEQUAL:
  579.    case GL_GEQUAL:
  580.    case GL_ALWAYS:
  581.       if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref)
  582.          return; /* no change */
  583.  
  584.       FLUSH_VERTICES(ctx, _NEW_COLOR);
  585.       ctx->Color.AlphaFunc = func;
  586.       ctx->Color.AlphaRefUnclamped = ref;
  587.       ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F);
  588.  
  589.       if (ctx->Driver.AlphaFunc)
  590.          ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef);
  591.       return;
  592.  
  593.    default:
  594.       _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
  595.       return;
  596.    }
  597. }
  598.  
  599.  
  600. /**
  601.  * Specify a logic pixel operation for color index rendering.
  602.  *
  603.  * \param opcode operation.
  604.  *
  605.  * Verifies that \p opcode is a valid enum and updates
  606. gl_colorbuffer_attrib::LogicOp.
  607.  * On a change, flushes the vertices and notifies the driver via the
  608.  * dd_function_table::LogicOpcode callback.
  609.  */
  610. void GLAPIENTRY
  611. _mesa_LogicOp( GLenum opcode )
  612. {
  613.    GET_CURRENT_CONTEXT(ctx);
  614.  
  615.    if (MESA_VERBOSE & VERBOSE_API)
  616.       _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode));
  617.  
  618.    switch (opcode) {
  619.       case GL_CLEAR:
  620.       case GL_SET:
  621.       case GL_COPY:
  622.       case GL_COPY_INVERTED:
  623.       case GL_NOOP:
  624.       case GL_INVERT:
  625.       case GL_AND:
  626.       case GL_NAND:
  627.       case GL_OR:
  628.       case GL_NOR:
  629.       case GL_XOR:
  630.       case GL_EQUIV:
  631.       case GL_AND_REVERSE:
  632.       case GL_AND_INVERTED:
  633.       case GL_OR_REVERSE:
  634.       case GL_OR_INVERTED:
  635.          break;
  636.       default:
  637.          _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
  638.          return;
  639.    }
  640.  
  641.    if (ctx->Color.LogicOp == opcode)
  642.       return;
  643.  
  644.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  645.    ctx->Color.LogicOp = opcode;
  646.  
  647.    if (ctx->Driver.LogicOpcode)
  648.       ctx->Driver.LogicOpcode( ctx, opcode );
  649. }
  650.  
  651.  
  652. void GLAPIENTRY
  653. _mesa_IndexMask( GLuint mask )
  654. {
  655.    GET_CURRENT_CONTEXT(ctx);
  656.  
  657.    if (ctx->Color.IndexMask == mask)
  658.       return;
  659.  
  660.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  661.    ctx->Color.IndexMask = mask;
  662. }
  663.  
  664.  
  665. /**
  666.  * Enable or disable writing of frame buffer color components.
  667.  *
  668.  * \param red whether to mask writing of the red color component.
  669.  * \param green whether to mask writing of the green color component.
  670.  * \param blue whether to mask writing of the blue color component.
  671.  * \param alpha whether to mask writing of the alpha color component.
  672.  *
  673.  * \sa glColorMask().
  674.  *
  675.  * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask.  On a
  676.  * change, flushes the vertices and notifies the driver via the
  677.  * dd_function_table::ColorMask callback.
  678.  */
  679. void GLAPIENTRY
  680. _mesa_ColorMask( GLboolean red, GLboolean green,
  681.                  GLboolean blue, GLboolean alpha )
  682. {
  683.    GET_CURRENT_CONTEXT(ctx);
  684.    GLubyte tmp[4];
  685.    GLuint i;
  686.    GLboolean flushed;
  687.  
  688.    if (MESA_VERBOSE & VERBOSE_API)
  689.       _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
  690.                   red, green, blue, alpha);
  691.  
  692.    /* Shouldn't have any information about channel depth in core mesa
  693.     * -- should probably store these as the native booleans:
  694.     */
  695.    tmp[RCOMP] = red    ? 0xff : 0x0;
  696.    tmp[GCOMP] = green  ? 0xff : 0x0;
  697.    tmp[BCOMP] = blue   ? 0xff : 0x0;
  698.    tmp[ACOMP] = alpha  ? 0xff : 0x0;
  699.  
  700.    flushed = GL_FALSE;
  701.    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
  702.       if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
  703.          if (!flushed) {
  704.             FLUSH_VERTICES(ctx, _NEW_COLOR);
  705.          }
  706.          flushed = GL_TRUE;
  707.          COPY_4UBV(ctx->Color.ColorMask[i], tmp);
  708.       }
  709.    }
  710.  
  711.    if (ctx->Driver.ColorMask)
  712.       ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
  713. }
  714.  
  715.  
  716. /**
  717.  * For GL_EXT_draw_buffers2 and GL3
  718.  */
  719. void GLAPIENTRY
  720. _mesa_ColorMaski( GLuint buf, GLboolean red, GLboolean green,
  721.                         GLboolean blue, GLboolean alpha )
  722. {
  723.    GLubyte tmp[4];
  724.    GET_CURRENT_CONTEXT(ctx);
  725.  
  726.    if (MESA_VERBOSE & VERBOSE_API)
  727.       _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
  728.                   buf, red, green, blue, alpha);
  729.  
  730.    if (buf >= ctx->Const.MaxDrawBuffers) {
  731.       _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
  732.       return;
  733.    }
  734.  
  735.    /* Shouldn't have any information about channel depth in core mesa
  736.     * -- should probably store these as the native booleans:
  737.     */
  738.    tmp[RCOMP] = red    ? 0xff : 0x0;
  739.    tmp[GCOMP] = green  ? 0xff : 0x0;
  740.    tmp[BCOMP] = blue   ? 0xff : 0x0;
  741.    tmp[ACOMP] = alpha  ? 0xff : 0x0;
  742.  
  743.    if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
  744.       return;
  745.  
  746.    FLUSH_VERTICES(ctx, _NEW_COLOR);
  747.    COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
  748.  
  749.    if (ctx->Driver.ColorMaskIndexed)
  750.       ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
  751. }
  752.  
  753.  
  754. void GLAPIENTRY
  755. _mesa_ClampColor(GLenum target, GLenum clamp)
  756. {
  757.    GET_CURRENT_CONTEXT(ctx);
  758.  
  759.    if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
  760.       _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
  761.       return;
  762.    }
  763.  
  764.    switch (target) {
  765.    case GL_CLAMP_VERTEX_COLOR_ARB:
  766.       if (ctx->API == API_OPENGL_CORE &&
  767.           !ctx->Extensions.ARB_color_buffer_float) {
  768.          goto invalid_enum;
  769.       }
  770.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  771.       ctx->Light.ClampVertexColor = clamp;
  772.       _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer);
  773.       break;
  774.    case GL_CLAMP_FRAGMENT_COLOR_ARB:
  775.       if (ctx->API == API_OPENGL_CORE &&
  776.           !ctx->Extensions.ARB_color_buffer_float) {
  777.          goto invalid_enum;
  778.       }
  779.       FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
  780.       ctx->Color.ClampFragmentColor = clamp;
  781.       _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer);
  782.       break;
  783.    case GL_CLAMP_READ_COLOR_ARB:
  784.       ctx->Color.ClampReadColor = clamp;
  785.       break;
  786.    default:
  787.       goto invalid_enum;
  788.    }
  789.    return;
  790.  
  791. invalid_enum:
  792.    _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)",
  793.                _mesa_lookup_enum_by_nr(target));
  794. }
  795.  
  796. static GLboolean
  797. get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp)
  798. {
  799.    if (clamp == GL_TRUE || clamp == GL_FALSE)
  800.       return clamp;
  801.  
  802.    assert(clamp == GL_FIXED_ONLY);
  803.    if (!fb)
  804.       return GL_TRUE;
  805.  
  806.    return fb->_AllColorBuffersFixedPoint;
  807. }
  808.  
  809. GLboolean
  810. _mesa_get_clamp_fragment_color(const struct gl_context *ctx,
  811.                                const struct gl_framebuffer *drawFb)
  812. {
  813.    return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor);
  814. }
  815.  
  816. GLboolean
  817. _mesa_get_clamp_vertex_color(const struct gl_context *ctx,
  818.                              const struct gl_framebuffer *drawFb)
  819. {
  820.    return get_clamp_color(drawFb, ctx->Light.ClampVertexColor);
  821. }
  822.  
  823. GLboolean
  824. _mesa_get_clamp_read_color(const struct gl_context *ctx,
  825.                            const struct gl_framebuffer *readFb)
  826. {
  827.    return get_clamp_color(readFb, ctx->Color.ClampReadColor);
  828. }
  829.  
  830. /**
  831.  * Update the ctx->Color._ClampFragmentColor field
  832.  */
  833. void
  834. _mesa_update_clamp_fragment_color(struct gl_context *ctx,
  835.                                   const struct gl_framebuffer *drawFb)
  836. {
  837.    /* Don't clamp if:
  838.     * - there is no colorbuffer
  839.     * - all colorbuffers are unsigned normalized, so clamping has no effect
  840.     * - there is an integer colorbuffer
  841.     */
  842.    if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer ||
  843.        drawFb->_IntegerColor)
  844.       ctx->Color._ClampFragmentColor = GL_FALSE;
  845.    else
  846.       ctx->Color._ClampFragmentColor =
  847.          _mesa_get_clamp_fragment_color(ctx, drawFb);
  848. }
  849.  
  850. /**
  851.  * Update the ctx->Color._ClampVertexColor field
  852.  */
  853. void
  854. _mesa_update_clamp_vertex_color(struct gl_context *ctx,
  855.                                 const struct gl_framebuffer *drawFb)
  856. {
  857.    ctx->Light._ClampVertexColor =
  858.          _mesa_get_clamp_vertex_color(ctx, drawFb);
  859. }
  860.  
  861. /**
  862.  * Returns an appropriate mesa_format for color rendering based on the
  863.  * GL_FRAMEBUFFER_SRGB state.
  864.  *
  865.  * Some drivers implement GL_FRAMEBUFFER_SRGB using a flag on the blend state
  866.  * (which GL_FRAMEBUFFER_SRGB maps to reasonably), but some have to do so by
  867.  * overriding the format of the surface.  This is a helper for doing the
  868.  * surface format override variant.
  869.  */
  870. mesa_format
  871. _mesa_get_render_format(const struct gl_context *ctx, mesa_format format)
  872. {
  873.    if (ctx->Color.sRGBEnabled)
  874.       return format;
  875.    else
  876.       return _mesa_get_srgb_format_linear(format);
  877. }
  878.  
  879. /**********************************************************************/
  880. /** \name Initialization */
  881. /*@{*/
  882.  
  883. /**
  884.  * Initialization of the context's Color attribute group.
  885.  *
  886.  * \param ctx GL context.
  887.  *
  888.  * Initializes the related fields in the context color attribute group,
  889.  * __struct gl_contextRec::Color.
  890.  */
  891. void _mesa_init_color( struct gl_context * ctx )
  892. {
  893.    GLuint i;
  894.  
  895.    /* Color buffer group */
  896.    ctx->Color.IndexMask = ~0u;
  897.    memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
  898.    ctx->Color.ClearIndex = 0;
  899.    ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 );
  900.    ctx->Color.AlphaEnabled = GL_FALSE;
  901.    ctx->Color.AlphaFunc = GL_ALWAYS;
  902.    ctx->Color.AlphaRef = 0;
  903.    ctx->Color.BlendEnabled = 0x0;
  904.    for (i = 0; i < ARRAY_SIZE(ctx->Color.Blend); i++) {
  905.       ctx->Color.Blend[i].SrcRGB = GL_ONE;
  906.       ctx->Color.Blend[i].DstRGB = GL_ZERO;
  907.       ctx->Color.Blend[i].SrcA = GL_ONE;
  908.       ctx->Color.Blend[i].DstA = GL_ZERO;
  909.       ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD;
  910.       ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
  911.    }
  912.    ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
  913.    ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 );
  914.    ctx->Color.IndexLogicOpEnabled = GL_FALSE;
  915.    ctx->Color.ColorLogicOpEnabled = GL_FALSE;
  916.    ctx->Color.LogicOp = GL_COPY;
  917.    ctx->Color.DitherFlag = GL_TRUE;
  918.  
  919.    /* GL_FRONT is not possible on GLES. Instead GL_BACK will render to either
  920.     * the front or the back buffer depending on the config */
  921.    if (ctx->Visual.doubleBufferMode || _mesa_is_gles(ctx)) {
  922.       ctx->Color.DrawBuffer[0] = GL_BACK;
  923.    }
  924.    else {
  925.       ctx->Color.DrawBuffer[0] = GL_FRONT;
  926.    }
  927.  
  928.    ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ?
  929.                                    GL_FIXED_ONLY_ARB : GL_FALSE;
  930.    ctx->Color._ClampFragmentColor = GL_FALSE;
  931.    ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
  932.  
  933.    if (ctx->API == API_OPENGLES2) {
  934.       /* GLES 3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled. */
  935.       ctx->Color.sRGBEnabled = GL_TRUE;
  936.    } else {
  937.       ctx->Color.sRGBEnabled = GL_FALSE;
  938.    }
  939. }
  940.  
  941. /*@}*/
  942.