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