Home | History | Annotate | Download | only in main
      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 ctx->API != API_OPENGLES
     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 (ctx->API != API_OPENGLES
    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 ctx->API != API_OPENGLES
    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_enum_to_string(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_enum_to_string(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_enum_to_string(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_enum_to_string(dfactorA));
    153       return GL_FALSE;
    154    }
    155 
    156    return GL_TRUE;
    157 }
    158 
    159 
    160 static GLboolean
    161 blend_factor_is_dual_src(GLenum factor)
    162 {
    163    return (factor == GL_SRC1_COLOR ||
    164 	   factor == GL_SRC1_ALPHA ||
    165 	   factor == GL_ONE_MINUS_SRC1_COLOR ||
    166 	   factor == GL_ONE_MINUS_SRC1_ALPHA);
    167 }
    168 
    169 static void
    170 update_uses_dual_src(struct gl_context *ctx, int buf)
    171 {
    172    ctx->Color.Blend[buf]._UsesDualSrc =
    173       (blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcRGB) ||
    174        blend_factor_is_dual_src(ctx->Color.Blend[buf].DstRGB) ||
    175        blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcA) ||
    176        blend_factor_is_dual_src(ctx->Color.Blend[buf].DstA));
    177 }
    178 
    179 
    180 /**
    181  * Return the number of per-buffer blend states to update in
    182  * glBlendFunc, glBlendFuncSeparate, glBlendEquation, etc.
    183  */
    184 static inline unsigned
    185 num_buffers(const struct gl_context *ctx)
    186 {
    187    return ctx->Extensions.ARB_draw_buffers_blend
    188       ? ctx->Const.MaxDrawBuffers : 1;
    189 }
    190 
    191 
    192 /* Returns true if there was no change */
    193 static bool
    194 skip_blend_state_update(const struct gl_context *ctx,
    195                         GLenum sfactorRGB, GLenum dfactorRGB,
    196                         GLenum sfactorA, GLenum dfactorA)
    197 {
    198    /* Check if we're really changing any state.  If not, return early. */
    199    if (ctx->Color._BlendFuncPerBuffer) {
    200       const unsigned numBuffers = num_buffers(ctx);
    201 
    202       /* Check all per-buffer states */
    203       for (unsigned buf = 0; buf < numBuffers; buf++) {
    204          if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB ||
    205              ctx->Color.Blend[buf].DstRGB != dfactorRGB ||
    206              ctx->Color.Blend[buf].SrcA != sfactorA ||
    207              ctx->Color.Blend[buf].DstA != dfactorA) {
    208             return false;
    209          }
    210       }
    211    }
    212    else {
    213       /* only need to check 0th per-buffer state */
    214       if (ctx->Color.Blend[0].SrcRGB != sfactorRGB ||
    215           ctx->Color.Blend[0].DstRGB != dfactorRGB ||
    216           ctx->Color.Blend[0].SrcA != sfactorA ||
    217           ctx->Color.Blend[0].DstA != dfactorA) {
    218          return false;
    219       }
    220    }
    221 
    222    return true;
    223 }
    224 
    225 
    226 static void
    227 blend_func_separate(struct gl_context *ctx,
    228                     GLenum sfactorRGB, GLenum dfactorRGB,
    229                     GLenum sfactorA, GLenum dfactorA)
    230 {
    231    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewBlend ? 0 : _NEW_COLOR);
    232    ctx->NewDriverState |= ctx->DriverFlags.NewBlend;
    233 
    234    const unsigned numBuffers = num_buffers(ctx);
    235    for (unsigned buf = 0; buf < numBuffers; buf++) {
    236       ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
    237       ctx->Color.Blend[buf].DstRGB = dfactorRGB;
    238       ctx->Color.Blend[buf].SrcA = sfactorA;
    239       ctx->Color.Blend[buf].DstA = dfactorA;
    240    }
    241 
    242    update_uses_dual_src(ctx, 0);
    243    for (unsigned buf = 1; buf < numBuffers; buf++) {
    244       ctx->Color.Blend[buf]._UsesDualSrc = ctx->Color.Blend[0]._UsesDualSrc;
    245    }
    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  * Specify the blending operation.
    258  *
    259  * \param sfactor source factor operator.
    260  * \param dfactor destination factor operator.
    261  *
    262  * \sa glBlendFunc, glBlendFuncSeparateEXT
    263  */
    264 void GLAPIENTRY
    265 _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
    266 {
    267    GET_CURRENT_CONTEXT(ctx);
    268 
    269    if (skip_blend_state_update(ctx, sfactor, dfactor, sfactor, dfactor))
    270       return;
    271 
    272    if (!validate_blend_factors(ctx, "glBlendFunc",
    273                                sfactor, dfactor, sfactor, dfactor)) {
    274       return;
    275    }
    276 
    277    blend_func_separate(ctx, sfactor, dfactor, sfactor, dfactor);
    278 }
    279 
    280 
    281 void GLAPIENTRY
    282 _mesa_BlendFunc_no_error(GLenum sfactor, GLenum dfactor)
    283 {
    284    GET_CURRENT_CONTEXT(ctx);
    285 
    286    if (skip_blend_state_update(ctx, sfactor, dfactor, sfactor, dfactor))
    287       return;
    288 
    289    blend_func_separate(ctx, sfactor, dfactor, sfactor, dfactor);
    290 }
    291 
    292 
    293 /**
    294  * Set the separate blend source/dest factors for all draw buffers.
    295  *
    296  * \param sfactorRGB RGB source factor operator.
    297  * \param dfactorRGB RGB destination factor operator.
    298  * \param sfactorA alpha source factor operator.
    299  * \param dfactorA alpha destination factor operator.
    300  */
    301 void GLAPIENTRY
    302 _mesa_BlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB,
    303                             GLenum sfactorA, GLenum dfactorA )
    304 {
    305    GET_CURRENT_CONTEXT(ctx);
    306 
    307    if (MESA_VERBOSE & VERBOSE_API)
    308       _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
    309                   _mesa_enum_to_string(sfactorRGB),
    310                   _mesa_enum_to_string(dfactorRGB),
    311                   _mesa_enum_to_string(sfactorA),
    312                   _mesa_enum_to_string(dfactorA));
    313 
    314 
    315 
    316    if (skip_blend_state_update(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA))
    317       return;
    318 
    319    if (!validate_blend_factors(ctx, "glBlendFuncSeparate",
    320                                sfactorRGB, dfactorRGB,
    321                                sfactorA, dfactorA)) {
    322       return;
    323    }
    324 
    325    blend_func_separate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA);
    326 }
    327 
    328 
    329 void GLAPIENTRY
    330 _mesa_BlendFuncSeparate_no_error(GLenum sfactorRGB, GLenum dfactorRGB,
    331                                  GLenum sfactorA, GLenum dfactorA)
    332 {
    333    GET_CURRENT_CONTEXT(ctx);
    334 
    335    if (skip_blend_state_update(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA))
    336       return;
    337 
    338    blend_func_separate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA);
    339 }
    340 
    341 
    342 void GLAPIENTRY
    343 _mesa_BlendFunciARB_no_error(GLuint buf, GLenum sfactor, GLenum dfactor)
    344 {
    345    _mesa_BlendFuncSeparateiARB_no_error(buf, sfactor, dfactor, sfactor,
    346                                         dfactor);
    347 }
    348 
    349 
    350 /**
    351  * Set blend source/dest factors for one color buffer/target.
    352  */
    353 void GLAPIENTRY
    354 _mesa_BlendFunciARB(GLuint buf, GLenum sfactor, GLenum dfactor)
    355 {
    356    _mesa_BlendFuncSeparateiARB(buf, sfactor, dfactor, sfactor, dfactor);
    357 }
    358 
    359 
    360 static ALWAYS_INLINE void
    361 blend_func_separatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
    362                      GLenum sfactorA, GLenum dfactorA, bool no_error)
    363 {
    364    GET_CURRENT_CONTEXT(ctx);
    365 
    366    if (!no_error) {
    367       if (!ctx->Extensions.ARB_draw_buffers_blend) {
    368          _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
    369          return;
    370       }
    371 
    372       if (buf >= ctx->Const.MaxDrawBuffers) {
    373          _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
    374                      buf);
    375          return;
    376       }
    377    }
    378 
    379    if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB &&
    380        ctx->Color.Blend[buf].DstRGB == dfactorRGB &&
    381        ctx->Color.Blend[buf].SrcA == sfactorA &&
    382        ctx->Color.Blend[buf].DstA == dfactorA)
    383       return; /* no change */
    384 
    385    if (!no_error && !validate_blend_factors(ctx, "glBlendFuncSeparatei",
    386                                             sfactorRGB, dfactorRGB,
    387                                             sfactorA, dfactorA)) {
    388       return;
    389    }
    390 
    391    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewBlend ? 0 : _NEW_COLOR);
    392    ctx->NewDriverState |= ctx->DriverFlags.NewBlend;
    393 
    394    ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
    395    ctx->Color.Blend[buf].DstRGB = dfactorRGB;
    396    ctx->Color.Blend[buf].SrcA = sfactorA;
    397    ctx->Color.Blend[buf].DstA = dfactorA;
    398    update_uses_dual_src(ctx, buf);
    399    ctx->Color._BlendFuncPerBuffer = GL_TRUE;
    400 }
    401 
    402 
    403 void GLAPIENTRY
    404 _mesa_BlendFuncSeparateiARB_no_error(GLuint buf, GLenum sfactorRGB,
    405                                      GLenum dfactorRGB, GLenum sfactorA,
    406                                      GLenum dfactorA)
    407 {
    408    blend_func_separatei(buf, sfactorRGB, dfactorRGB, sfactorA, dfactorA,
    409                         true);
    410 }
    411 
    412 
    413 /**
    414  * Set separate blend source/dest factors for one color buffer/target.
    415  */
    416 void GLAPIENTRY
    417 _mesa_BlendFuncSeparateiARB(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
    418                             GLenum sfactorA, GLenum dfactorA)
    419 {
    420    blend_func_separatei(buf, sfactorRGB, dfactorRGB, sfactorA, dfactorA,
    421                         false);
    422 }
    423 
    424 
    425 /**
    426  * Return true if \p mode is a legal blending equation, excluding
    427  * GL_KHR_blend_equation_advanced modes.
    428  */
    429 static bool
    430 legal_simple_blend_equation(const struct gl_context *ctx, GLenum mode)
    431 {
    432    switch (mode) {
    433    case GL_FUNC_ADD:
    434    case GL_FUNC_SUBTRACT:
    435    case GL_FUNC_REVERSE_SUBTRACT:
    436       return GL_TRUE;
    437    case GL_MIN:
    438    case GL_MAX:
    439       return ctx->Extensions.EXT_blend_minmax;
    440    default:
    441       return GL_FALSE;
    442    }
    443 }
    444 
    445 static enum gl_advanced_blend_mode
    446 advanced_blend_mode_from_gl_enum(GLenum mode)
    447 {
    448    switch (mode) {
    449    case GL_MULTIPLY_KHR:
    450       return BLEND_MULTIPLY;
    451    case GL_SCREEN_KHR:
    452       return BLEND_SCREEN;
    453    case GL_OVERLAY_KHR:
    454       return BLEND_OVERLAY;
    455    case GL_DARKEN_KHR:
    456       return BLEND_DARKEN;
    457    case GL_LIGHTEN_KHR:
    458       return BLEND_LIGHTEN;
    459    case GL_COLORDODGE_KHR:
    460       return BLEND_COLORDODGE;
    461    case GL_COLORBURN_KHR:
    462       return BLEND_COLORBURN;
    463    case GL_HARDLIGHT_KHR:
    464       return BLEND_HARDLIGHT;
    465    case GL_SOFTLIGHT_KHR:
    466       return BLEND_SOFTLIGHT;
    467    case GL_DIFFERENCE_KHR:
    468       return BLEND_DIFFERENCE;
    469    case GL_EXCLUSION_KHR:
    470       return BLEND_EXCLUSION;
    471    case GL_HSL_HUE_KHR:
    472       return BLEND_HSL_HUE;
    473    case GL_HSL_SATURATION_KHR:
    474       return BLEND_HSL_SATURATION;
    475    case GL_HSL_COLOR_KHR:
    476       return BLEND_HSL_COLOR;
    477    case GL_HSL_LUMINOSITY_KHR:
    478       return BLEND_HSL_LUMINOSITY;
    479    default:
    480       return BLEND_NONE;
    481    }
    482 }
    483 
    484 /**
    485  * If \p mode is one of the advanced blending equations defined by
    486  * GL_KHR_blend_equation_advanced (and the extension is supported),
    487  * return the corresponding BLEND_* enum.  Otherwise, return BLEND_NONE
    488  * (which can also be treated as false).
    489  */
    490 static enum gl_advanced_blend_mode
    491 advanced_blend_mode(const struct gl_context *ctx, GLenum mode)
    492 {
    493    return _mesa_has_KHR_blend_equation_advanced(ctx) ?
    494           advanced_blend_mode_from_gl_enum(mode) : BLEND_NONE;
    495 }
    496 
    497 /* This is really an extension function! */
    498 void GLAPIENTRY
    499 _mesa_BlendEquation( GLenum mode )
    500 {
    501    GET_CURRENT_CONTEXT(ctx);
    502    const unsigned numBuffers = num_buffers(ctx);
    503    unsigned buf;
    504    bool changed = false;
    505    enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
    506 
    507    if (MESA_VERBOSE & VERBOSE_API)
    508       _mesa_debug(ctx, "glBlendEquation(%s)\n",
    509                   _mesa_enum_to_string(mode));
    510 
    511    if (ctx->Color._BlendEquationPerBuffer) {
    512       /* Check all per-buffer states */
    513       for (buf = 0; buf < numBuffers; buf++) {
    514          if (ctx->Color.Blend[buf].EquationRGB != mode ||
    515              ctx->Color.Blend[buf].EquationA != mode) {
    516             changed = true;
    517             break;
    518          }
    519       }
    520    }
    521    else {
    522       /* only need to check 0th per-buffer state */
    523       if (ctx->Color.Blend[0].EquationRGB != mode ||
    524           ctx->Color.Blend[0].EquationA != mode) {
    525          changed = true;
    526       }
    527    }
    528 
    529    if (!changed)
    530       return;
    531 
    532 
    533    if (!legal_simple_blend_equation(ctx, mode) && !advanced_mode) {
    534       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
    535       return;
    536    }
    537 
    538    _mesa_flush_vertices_for_blend_state(ctx);
    539 
    540    for (buf = 0; buf < numBuffers; buf++) {
    541       ctx->Color.Blend[buf].EquationRGB = mode;
    542       ctx->Color.Blend[buf].EquationA = mode;
    543    }
    544    ctx->Color._BlendEquationPerBuffer = GL_FALSE;
    545    ctx->Color._AdvancedBlendMode = advanced_mode;
    546 
    547    if (ctx->Driver.BlendEquationSeparate)
    548       ctx->Driver.BlendEquationSeparate(ctx, mode, mode);
    549 }
    550 
    551 
    552 /**
    553  * Set blend equation for one color buffer/target.
    554  */
    555 static void
    556 blend_equationi(struct gl_context *ctx, GLuint buf, GLenum mode,
    557                 enum gl_advanced_blend_mode advanced_mode)
    558 {
    559    if (ctx->Color.Blend[buf].EquationRGB == mode &&
    560        ctx->Color.Blend[buf].EquationA == mode)
    561       return;  /* no change */
    562 
    563    _mesa_flush_vertices_for_blend_state(ctx);
    564    ctx->Color.Blend[buf].EquationRGB = mode;
    565    ctx->Color.Blend[buf].EquationA = mode;
    566    ctx->Color._BlendEquationPerBuffer = GL_TRUE;
    567 
    568    if (buf == 0)
    569       ctx->Color._AdvancedBlendMode = advanced_mode;
    570 }
    571 
    572 
    573 void GLAPIENTRY
    574 _mesa_BlendEquationiARB_no_error(GLuint buf, GLenum mode)
    575 {
    576    GET_CURRENT_CONTEXT(ctx);
    577 
    578    enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
    579    blend_equationi(ctx, buf, mode, advanced_mode);
    580 }
    581 
    582 
    583 void GLAPIENTRY
    584 _mesa_BlendEquationiARB(GLuint buf, GLenum mode)
    585 {
    586    GET_CURRENT_CONTEXT(ctx);
    587    enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode);
    588 
    589    if (MESA_VERBOSE & VERBOSE_API)
    590       _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
    591                   buf, _mesa_enum_to_string(mode));
    592 
    593    if (buf >= ctx->Const.MaxDrawBuffers) {
    594       _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationi(buffer=%u)",
    595                   buf);
    596       return;
    597    }
    598 
    599    if (!legal_simple_blend_equation(ctx, mode) && !advanced_mode) {
    600       _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi");
    601       return;
    602    }
    603 
    604    blend_equationi(ctx, buf, mode, advanced_mode);
    605 }
    606 
    607 
    608 static void
    609 blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA,
    610                         bool no_error)
    611 {
    612    const unsigned numBuffers = num_buffers(ctx);
    613    unsigned buf;
    614    bool changed = false;
    615 
    616    if (ctx->Color._BlendEquationPerBuffer) {
    617       /* Check all per-buffer states */
    618       for (buf = 0; buf < numBuffers; buf++) {
    619          if (ctx->Color.Blend[buf].EquationRGB != modeRGB ||
    620              ctx->Color.Blend[buf].EquationA != modeA) {
    621             changed = true;
    622             break;
    623          }
    624       }
    625    } else {
    626       /* only need to check 0th per-buffer state */
    627       if (ctx->Color.Blend[0].EquationRGB != modeRGB ||
    628           ctx->Color.Blend[0].EquationA != modeA) {
    629          changed = true;
    630       }
    631    }
    632 
    633    if (!changed)
    634       return;
    635 
    636    if (!no_error) {
    637       if ((modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate) {
    638          _mesa_error(ctx, GL_INVALID_OPERATION,
    639                      "glBlendEquationSeparateEXT not supported by driver");
    640          return;
    641       }
    642 
    643       /* Only allow simple blending equations.
    644        * The GL_KHR_blend_equation_advanced spec says:
    645        *
    646        *    "NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha>
    647        *     parameters of BlendEquationSeparate or BlendEquationSeparatei."
    648        */
    649       if (!legal_simple_blend_equation(ctx, modeRGB)) {
    650          _mesa_error(ctx, GL_INVALID_ENUM,
    651                      "glBlendEquationSeparateEXT(modeRGB)");
    652          return;
    653       }
    654 
    655       if (!legal_simple_blend_equation(ctx, modeA)) {
    656          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
    657          return;
    658       }
    659    }
    660 
    661    _mesa_flush_vertices_for_blend_state(ctx);
    662 
    663    for (buf = 0; buf < numBuffers; buf++) {
    664       ctx->Color.Blend[buf].EquationRGB = modeRGB;
    665       ctx->Color.Blend[buf].EquationA = modeA;
    666    }
    667    ctx->Color._BlendEquationPerBuffer = GL_FALSE;
    668    ctx->Color._AdvancedBlendMode = BLEND_NONE;
    669 
    670    if (ctx->Driver.BlendEquationSeparate)
    671       ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
    672 }
    673 
    674 
    675 void GLAPIENTRY
    676 _mesa_BlendEquationSeparate_no_error(GLenum modeRGB, GLenum modeA)
    677 {
    678    GET_CURRENT_CONTEXT(ctx);
    679    blend_equation_separate(ctx, modeRGB, modeA, true);
    680 }
    681 
    682 
    683 void GLAPIENTRY
    684 _mesa_BlendEquationSeparate(GLenum modeRGB, GLenum modeA)
    685 {
    686    GET_CURRENT_CONTEXT(ctx);
    687 
    688    if (MESA_VERBOSE & VERBOSE_API)
    689       _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
    690                   _mesa_enum_to_string(modeRGB),
    691                   _mesa_enum_to_string(modeA));
    692 
    693    blend_equation_separate(ctx, modeRGB, modeA, false);
    694 }
    695 
    696 
    697 static ALWAYS_INLINE void
    698 blend_equation_separatei(struct gl_context *ctx, GLuint buf, GLenum modeRGB,
    699                          GLenum modeA, bool no_error)
    700 {
    701    if (ctx->Color.Blend[buf].EquationRGB == modeRGB &&
    702        ctx->Color.Blend[buf].EquationA == modeA)
    703       return;  /* no change */
    704 
    705    if (!no_error) {
    706       /* Only allow simple blending equations.
    707        * The GL_KHR_blend_equation_advanced spec says:
    708        *
    709        *    "NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha>
    710        *     parameters of BlendEquationSeparate or BlendEquationSeparatei."
    711        */
    712       if (!legal_simple_blend_equation(ctx, modeRGB)) {
    713          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)");
    714          return;
    715       }
    716 
    717       if (!legal_simple_blend_equation(ctx, modeA)) {
    718          _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)");
    719          return;
    720       }
    721    }
    722 
    723    _mesa_flush_vertices_for_blend_state(ctx);
    724    ctx->Color.Blend[buf].EquationRGB = modeRGB;
    725    ctx->Color.Blend[buf].EquationA = modeA;
    726    ctx->Color._BlendEquationPerBuffer = GL_TRUE;
    727    ctx->Color._AdvancedBlendMode = BLEND_NONE;
    728 }
    729 
    730 
    731 void GLAPIENTRY
    732 _mesa_BlendEquationSeparateiARB_no_error(GLuint buf, GLenum modeRGB,
    733                                          GLenum modeA)
    734 {
    735    GET_CURRENT_CONTEXT(ctx);
    736    blend_equation_separatei(ctx, buf, modeRGB, modeA, true);
    737 }
    738 
    739 
    740 /**
    741  * Set separate blend equations for one color buffer/target.
    742  */
    743 void GLAPIENTRY
    744 _mesa_BlendEquationSeparateiARB(GLuint buf, GLenum modeRGB, GLenum modeA)
    745 {
    746    GET_CURRENT_CONTEXT(ctx);
    747 
    748    if (MESA_VERBOSE & VERBOSE_API)
    749       _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
    750                   _mesa_enum_to_string(modeRGB),
    751                   _mesa_enum_to_string(modeA));
    752 
    753    if (buf >= ctx->Const.MaxDrawBuffers) {
    754       _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)",
    755                   buf);
    756       return;
    757    }
    758 
    759    blend_equation_separatei(ctx, buf, modeRGB, modeA, false);
    760 }
    761 
    762 
    763 /**
    764  * Set the blending color.
    765  *
    766  * \param red red color component.
    767  * \param green green color component.
    768  * \param blue blue color component.
    769  * \param alpha alpha color component.
    770  *
    771  * \sa glBlendColor().
    772  *
    773  * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor.  On a
    774  * change, flushes the vertices and notifies the driver via
    775  * dd_function_table::BlendColor callback.
    776  */
    777 void GLAPIENTRY
    778 _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
    779 {
    780    GLfloat tmp[4];
    781    GET_CURRENT_CONTEXT(ctx);
    782 
    783    tmp[0] = red;
    784    tmp[1] = green;
    785    tmp[2] = blue;
    786    tmp[3] = alpha;
    787 
    788    if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped))
    789       return;
    790 
    791    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewBlendColor ? 0 : _NEW_COLOR);
    792    ctx->NewDriverState |= ctx->DriverFlags.NewBlendColor;
    793    COPY_4FV( ctx->Color.BlendColorUnclamped, tmp );
    794 
    795    ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
    796    ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
    797    ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
    798    ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
    799 
    800    if (ctx->Driver.BlendColor)
    801       ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor);
    802 }
    803 
    804 
    805 /**
    806  * Specify the alpha test function.
    807  *
    808  * \param func alpha comparison function.
    809  * \param ref reference value.
    810  *
    811  * Verifies the parameters and updates gl_colorbuffer_attrib.
    812  * On a change, flushes the vertices and notifies the driver via
    813  * dd_function_table::AlphaFunc callback.
    814  */
    815 void GLAPIENTRY
    816 _mesa_AlphaFunc( GLenum func, GLclampf ref )
    817 {
    818    GET_CURRENT_CONTEXT(ctx);
    819 
    820    if (MESA_VERBOSE & VERBOSE_API)
    821       _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
    822                   _mesa_enum_to_string(func), ref);
    823 
    824    if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref)
    825       return; /* no change */
    826 
    827    switch (func) {
    828    case GL_NEVER:
    829    case GL_LESS:
    830    case GL_EQUAL:
    831    case GL_LEQUAL:
    832    case GL_GREATER:
    833    case GL_NOTEQUAL:
    834    case GL_GEQUAL:
    835    case GL_ALWAYS:
    836       FLUSH_VERTICES(ctx, ctx->DriverFlags.NewAlphaTest ? 0 : _NEW_COLOR);
    837       ctx->NewDriverState |= ctx->DriverFlags.NewAlphaTest;
    838       ctx->Color.AlphaFunc = func;
    839       ctx->Color.AlphaRefUnclamped = ref;
    840       ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F);
    841 
    842       if (ctx->Driver.AlphaFunc)
    843          ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef);
    844       return;
    845 
    846    default:
    847       _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
    848       return;
    849    }
    850 }
    851 
    852 
    853 static ALWAYS_INLINE void
    854 logic_op(struct gl_context *ctx, GLenum opcode, bool no_error)
    855 {
    856    if (ctx->Color.LogicOp == opcode)
    857       return;
    858 
    859    if (!no_error) {
    860       switch (opcode) {
    861          case GL_CLEAR:
    862          case GL_SET:
    863          case GL_COPY:
    864          case GL_COPY_INVERTED:
    865          case GL_NOOP:
    866          case GL_INVERT:
    867          case GL_AND:
    868          case GL_NAND:
    869          case GL_OR:
    870          case GL_NOR:
    871          case GL_XOR:
    872          case GL_EQUIV:
    873          case GL_AND_REVERSE:
    874          case GL_AND_INVERTED:
    875          case GL_OR_REVERSE:
    876          case GL_OR_INVERTED:
    877             break;
    878          default:
    879             _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
    880             return;
    881       }
    882    }
    883 
    884    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewLogicOp ? 0 : _NEW_COLOR);
    885    ctx->NewDriverState |= ctx->DriverFlags.NewLogicOp;
    886    ctx->Color.LogicOp = opcode;
    887 
    888    if (ctx->Driver.LogicOpcode)
    889       ctx->Driver.LogicOpcode(ctx, opcode);
    890 }
    891 
    892 
    893 /**
    894  * Specify a logic pixel operation for color index rendering.
    895  *
    896  * \param opcode operation.
    897  *
    898  * Verifies that \p opcode is a valid enum and updates
    899  * gl_colorbuffer_attrib::LogicOp.
    900  * On a change, flushes the vertices and notifies the driver via the
    901  * dd_function_table::LogicOpcode callback.
    902  */
    903 void GLAPIENTRY
    904 _mesa_LogicOp( GLenum opcode )
    905 {
    906    GET_CURRENT_CONTEXT(ctx);
    907 
    908    if (MESA_VERBOSE & VERBOSE_API)
    909       _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_enum_to_string(opcode));
    910 
    911    logic_op(ctx, opcode, false);
    912 }
    913 
    914 
    915 void GLAPIENTRY
    916 _mesa_LogicOp_no_error(GLenum opcode)
    917 {
    918    GET_CURRENT_CONTEXT(ctx);
    919    logic_op(ctx, opcode, true);
    920 }
    921 
    922 
    923 void GLAPIENTRY
    924 _mesa_IndexMask( GLuint mask )
    925 {
    926    GET_CURRENT_CONTEXT(ctx);
    927 
    928    if (ctx->Color.IndexMask == mask)
    929       return;
    930 
    931    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR);
    932    ctx->NewDriverState |= ctx->DriverFlags.NewColorMask;
    933    ctx->Color.IndexMask = mask;
    934 }
    935 
    936 
    937 /**
    938  * Enable or disable writing of frame buffer color components.
    939  *
    940  * \param red whether to mask writing of the red color component.
    941  * \param green whether to mask writing of the green color component.
    942  * \param blue whether to mask writing of the blue color component.
    943  * \param alpha whether to mask writing of the alpha color component.
    944  *
    945  * \sa glColorMask().
    946  *
    947  * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask.  On a
    948  * change, flushes the vertices and notifies the driver via the
    949  * dd_function_table::ColorMask callback.
    950  */
    951 void GLAPIENTRY
    952 _mesa_ColorMask( GLboolean red, GLboolean green,
    953                  GLboolean blue, GLboolean alpha )
    954 {
    955    GET_CURRENT_CONTEXT(ctx);
    956    GLubyte tmp[4];
    957    GLuint i;
    958    GLboolean flushed;
    959 
    960    if (MESA_VERBOSE & VERBOSE_API)
    961       _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
    962                   red, green, blue, alpha);
    963 
    964    /* Shouldn't have any information about channel depth in core mesa
    965     * -- should probably store these as the native booleans:
    966     */
    967    tmp[RCOMP] = red    ? 0xff : 0x0;
    968    tmp[GCOMP] = green  ? 0xff : 0x0;
    969    tmp[BCOMP] = blue   ? 0xff : 0x0;
    970    tmp[ACOMP] = alpha  ? 0xff : 0x0;
    971 
    972    flushed = GL_FALSE;
    973    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
    974       if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
    975          if (!flushed) {
    976             FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR);
    977             ctx->NewDriverState |= ctx->DriverFlags.NewColorMask;
    978          }
    979          flushed = GL_TRUE;
    980          COPY_4UBV(ctx->Color.ColorMask[i], tmp);
    981       }
    982    }
    983 
    984    if (ctx->Driver.ColorMask)
    985       ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
    986 }
    987 
    988 
    989 /**
    990  * For GL_EXT_draw_buffers2 and GL3
    991  */
    992 void GLAPIENTRY
    993 _mesa_ColorMaski(GLuint buf, GLboolean red, GLboolean green,
    994                  GLboolean blue, GLboolean alpha)
    995 {
    996    GLubyte tmp[4];
    997    GET_CURRENT_CONTEXT(ctx);
    998 
    999    if (MESA_VERBOSE & VERBOSE_API)
   1000       _mesa_debug(ctx, "glColorMaski %u %d %d %d %d\n",
   1001                   buf, red, green, blue, alpha);
   1002 
   1003    if (buf >= ctx->Const.MaxDrawBuffers) {
   1004       _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaski(buf=%u)", buf);
   1005       return;
   1006    }
   1007 
   1008    /* Shouldn't have any information about channel depth in core mesa
   1009     * -- should probably store these as the native booleans:
   1010     */
   1011    tmp[RCOMP] = red    ? 0xff : 0x0;
   1012    tmp[GCOMP] = green  ? 0xff : 0x0;
   1013    tmp[BCOMP] = blue   ? 0xff : 0x0;
   1014    tmp[ACOMP] = alpha  ? 0xff : 0x0;
   1015 
   1016    if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
   1017       return;
   1018 
   1019    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR);
   1020    ctx->NewDriverState |= ctx->DriverFlags.NewColorMask;
   1021    COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
   1022 }
   1023 
   1024 
   1025 void GLAPIENTRY
   1026 _mesa_ClampColor(GLenum target, GLenum clamp)
   1027 {
   1028    GET_CURRENT_CONTEXT(ctx);
   1029 
   1030    /* Check for both the extension and the GL version, since the Intel driver
   1031     * does not advertise the extension in core profiles.
   1032     */
   1033    if (ctx->Version <= 30 && !ctx->Extensions.ARB_color_buffer_float) {
   1034       _mesa_error(ctx, GL_INVALID_OPERATION, "glClampColor()");
   1035       return;
   1036    }
   1037 
   1038    if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
   1039       _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
   1040       return;
   1041    }
   1042 
   1043    switch (target) {
   1044    case GL_CLAMP_VERTEX_COLOR_ARB:
   1045       if (ctx->API == API_OPENGL_CORE)
   1046          goto invalid_enum;
   1047       FLUSH_VERTICES(ctx, _NEW_LIGHT);
   1048       ctx->Light.ClampVertexColor = clamp;
   1049       _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer);
   1050       break;
   1051    case GL_CLAMP_FRAGMENT_COLOR_ARB:
   1052       if (ctx->API == API_OPENGL_CORE)
   1053          goto invalid_enum;
   1054       FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
   1055       ctx->Color.ClampFragmentColor = clamp;
   1056       _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer);
   1057       break;
   1058    case GL_CLAMP_READ_COLOR_ARB:
   1059       ctx->Color.ClampReadColor = clamp;
   1060       break;
   1061    default:
   1062       goto invalid_enum;
   1063    }
   1064    return;
   1065 
   1066 invalid_enum:
   1067    _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)",
   1068                _mesa_enum_to_string(target));
   1069 }
   1070 
   1071 static GLboolean
   1072 get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp)
   1073 {
   1074    if (clamp == GL_TRUE || clamp == GL_FALSE)
   1075       return clamp;
   1076 
   1077    assert(clamp == GL_FIXED_ONLY);
   1078    if (!fb)
   1079       return GL_TRUE;
   1080 
   1081    return fb->_AllColorBuffersFixedPoint;
   1082 }
   1083 
   1084 GLboolean
   1085 _mesa_get_clamp_fragment_color(const struct gl_context *ctx,
   1086                                const struct gl_framebuffer *drawFb)
   1087 {
   1088    return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor);
   1089 }
   1090 
   1091 GLboolean
   1092 _mesa_get_clamp_vertex_color(const struct gl_context *ctx,
   1093                              const struct gl_framebuffer *drawFb)
   1094 {
   1095    return get_clamp_color(drawFb, ctx->Light.ClampVertexColor);
   1096 }
   1097 
   1098 GLboolean
   1099 _mesa_get_clamp_read_color(const struct gl_context *ctx,
   1100                            const struct gl_framebuffer *readFb)
   1101 {
   1102    return get_clamp_color(readFb, ctx->Color.ClampReadColor);
   1103 }
   1104 
   1105 /**
   1106  * Update the ctx->Color._ClampFragmentColor field
   1107  */
   1108 void
   1109 _mesa_update_clamp_fragment_color(struct gl_context *ctx,
   1110                                   const struct gl_framebuffer *drawFb)
   1111 {
   1112    /* Don't clamp if:
   1113     * - there is no colorbuffer
   1114     * - all colorbuffers are unsigned normalized, so clamping has no effect
   1115     * - there is an integer colorbuffer
   1116     */
   1117    if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer ||
   1118        drawFb->_IntegerBuffers)
   1119       ctx->Color._ClampFragmentColor = GL_FALSE;
   1120    else
   1121       ctx->Color._ClampFragmentColor =
   1122          _mesa_get_clamp_fragment_color(ctx, drawFb);
   1123 }
   1124 
   1125 /**
   1126  * Update the ctx->Color._ClampVertexColor field
   1127  */
   1128 void
   1129 _mesa_update_clamp_vertex_color(struct gl_context *ctx,
   1130                                 const struct gl_framebuffer *drawFb)
   1131 {
   1132    ctx->Light._ClampVertexColor =
   1133          _mesa_get_clamp_vertex_color(ctx, drawFb);
   1134 }
   1135 
   1136 /**
   1137  * Returns an appropriate mesa_format for color rendering based on the
   1138  * GL_FRAMEBUFFER_SRGB state.
   1139  *
   1140  * Some drivers implement GL_FRAMEBUFFER_SRGB using a flag on the blend state
   1141  * (which GL_FRAMEBUFFER_SRGB maps to reasonably), but some have to do so by
   1142  * overriding the format of the surface.  This is a helper for doing the
   1143  * surface format override variant.
   1144  */
   1145 mesa_format
   1146 _mesa_get_render_format(const struct gl_context *ctx, mesa_format format)
   1147 {
   1148    if (ctx->Color.sRGBEnabled)
   1149       return format;
   1150    else
   1151       return _mesa_get_srgb_format_linear(format);
   1152 }
   1153 
   1154 /**********************************************************************/
   1155 /** \name Initialization */
   1156 /*@{*/
   1157 
   1158 /**
   1159  * Initialization of the context's Color attribute group.
   1160  *
   1161  * \param ctx GL context.
   1162  *
   1163  * Initializes the related fields in the context color attribute group,
   1164  * __struct gl_contextRec::Color.
   1165  */
   1166 void _mesa_init_color( struct gl_context * ctx )
   1167 {
   1168    GLuint i;
   1169 
   1170    /* Color buffer group */
   1171    ctx->Color.IndexMask = ~0u;
   1172    memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
   1173    ctx->Color.ClearIndex = 0;
   1174    ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 );
   1175    ctx->Color.AlphaEnabled = GL_FALSE;
   1176    ctx->Color.AlphaFunc = GL_ALWAYS;
   1177    ctx->Color.AlphaRef = 0;
   1178    ctx->Color.BlendEnabled = 0x0;
   1179    for (i = 0; i < ARRAY_SIZE(ctx->Color.Blend); i++) {
   1180       ctx->Color.Blend[i].SrcRGB = GL_ONE;
   1181       ctx->Color.Blend[i].DstRGB = GL_ZERO;
   1182       ctx->Color.Blend[i].SrcA = GL_ONE;
   1183       ctx->Color.Blend[i].DstA = GL_ZERO;
   1184       ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD;
   1185       ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
   1186    }
   1187    ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
   1188    ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 );
   1189    ctx->Color.IndexLogicOpEnabled = GL_FALSE;
   1190    ctx->Color.ColorLogicOpEnabled = GL_FALSE;
   1191    ctx->Color.LogicOp = GL_COPY;
   1192    ctx->Color.DitherFlag = GL_TRUE;
   1193 
   1194    /* GL_FRONT is not possible on GLES. Instead GL_BACK will render to either
   1195     * the front or the back buffer depending on the config */
   1196    if (ctx->Visual.doubleBufferMode || _mesa_is_gles(ctx)) {
   1197       ctx->Color.DrawBuffer[0] = GL_BACK;
   1198    }
   1199    else {
   1200       ctx->Color.DrawBuffer[0] = GL_FRONT;
   1201    }
   1202 
   1203    ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ?
   1204                                    GL_FIXED_ONLY_ARB : GL_FALSE;
   1205    ctx->Color._ClampFragmentColor = GL_FALSE;
   1206    ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
   1207 
   1208    /* GLES 1/2/3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled
   1209     * if EGL_KHR_gl_colorspace has been used to request sRGB.
   1210     */
   1211    ctx->Color.sRGBEnabled = _mesa_is_gles(ctx);
   1212 
   1213    ctx->Color.BlendCoherent = true;
   1214 }
   1215 
   1216 /*@}*/
   1217