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