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