Merge branch 'llvm-cliptest-viewport'
[mesa.git] / src / mesa / main / blend.c
1 /**
2 * \file blend.c
3 * Blending operations.
4 */
5
6 /*
7 * Mesa 3-D graphics library
8 * Version: 6.5.1
9 *
10 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30
31
32 #include "glheader.h"
33 #include "blend.h"
34 #include "context.h"
35 #include "enums.h"
36 #include "macros.h"
37 #include "mtypes.h"
38
39
40 /**
41 * Specify the blending operation.
42 *
43 * \param sfactor source factor operator.
44 * \param dfactor destination factor operator.
45 *
46 * \sa glBlendFunc, glBlendFuncSeparateEXT
47 */
48 void GLAPIENTRY
49 _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
50 {
51 _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
52 }
53
54
55 /**
56 * Process GL_EXT_blend_func_separate().
57 *
58 * \param sfactorRGB RGB source factor operator.
59 * \param dfactorRGB RGB destination factor operator.
60 * \param sfactorA alpha source factor operator.
61 * \param dfactorA alpha destination factor operator.
62 *
63 * Verifies the parameters and updates gl_colorbuffer_attrib.
64 * On a change, flush the vertices and notify the driver via
65 * dd_function_table::BlendFuncSeparate.
66 */
67 void GLAPIENTRY
68 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
69 GLenum sfactorA, GLenum dfactorA )
70 {
71 GET_CURRENT_CONTEXT(ctx);
72 ASSERT_OUTSIDE_BEGIN_END(ctx);
73
74 if (MESA_VERBOSE & VERBOSE_API)
75 _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
76 _mesa_lookup_enum_by_nr(sfactorRGB),
77 _mesa_lookup_enum_by_nr(dfactorRGB),
78 _mesa_lookup_enum_by_nr(sfactorA),
79 _mesa_lookup_enum_by_nr(dfactorA));
80
81 switch (sfactorRGB) {
82 case GL_SRC_COLOR:
83 case GL_ONE_MINUS_SRC_COLOR:
84 if (!ctx->Extensions.NV_blend_square) {
85 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
86 return;
87 }
88 /* fall-through */
89 case GL_ZERO:
90 case GL_ONE:
91 case GL_DST_COLOR:
92 case GL_ONE_MINUS_DST_COLOR:
93 case GL_SRC_ALPHA:
94 case GL_ONE_MINUS_SRC_ALPHA:
95 case GL_DST_ALPHA:
96 case GL_ONE_MINUS_DST_ALPHA:
97 case GL_SRC_ALPHA_SATURATE:
98 case GL_CONSTANT_COLOR:
99 case GL_ONE_MINUS_CONSTANT_COLOR:
100 case GL_CONSTANT_ALPHA:
101 case GL_ONE_MINUS_CONSTANT_ALPHA:
102 break;
103 default:
104 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
105 return;
106 }
107
108 switch (dfactorRGB) {
109 case GL_DST_COLOR:
110 case GL_ONE_MINUS_DST_COLOR:
111 if (!ctx->Extensions.NV_blend_square) {
112 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
113 return;
114 }
115 /* fall-through */
116 case GL_ZERO:
117 case GL_ONE:
118 case GL_SRC_COLOR:
119 case GL_ONE_MINUS_SRC_COLOR:
120 case GL_SRC_ALPHA:
121 case GL_ONE_MINUS_SRC_ALPHA:
122 case GL_DST_ALPHA:
123 case GL_ONE_MINUS_DST_ALPHA:
124 case GL_CONSTANT_COLOR:
125 case GL_ONE_MINUS_CONSTANT_COLOR:
126 case GL_CONSTANT_ALPHA:
127 case GL_ONE_MINUS_CONSTANT_ALPHA:
128 break;
129 default:
130 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
131 return;
132 }
133
134 switch (sfactorA) {
135 case GL_SRC_COLOR:
136 case GL_ONE_MINUS_SRC_COLOR:
137 if (!ctx->Extensions.NV_blend_square) {
138 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
139 return;
140 }
141 /* fall-through */
142 case GL_ZERO:
143 case GL_ONE:
144 case GL_DST_COLOR:
145 case GL_ONE_MINUS_DST_COLOR:
146 case GL_SRC_ALPHA:
147 case GL_ONE_MINUS_SRC_ALPHA:
148 case GL_DST_ALPHA:
149 case GL_ONE_MINUS_DST_ALPHA:
150 case GL_SRC_ALPHA_SATURATE:
151 case GL_CONSTANT_COLOR:
152 case GL_ONE_MINUS_CONSTANT_COLOR:
153 case GL_CONSTANT_ALPHA:
154 case GL_ONE_MINUS_CONSTANT_ALPHA:
155 break;
156 default:
157 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
158 return;
159 }
160
161 switch (dfactorA) {
162 case GL_DST_COLOR:
163 case GL_ONE_MINUS_DST_COLOR:
164 if (!ctx->Extensions.NV_blend_square) {
165 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)");
166 return;
167 }
168 /* fall-through */
169 case GL_ZERO:
170 case GL_ONE:
171 case GL_SRC_COLOR:
172 case GL_ONE_MINUS_SRC_COLOR:
173 case GL_SRC_ALPHA:
174 case GL_ONE_MINUS_SRC_ALPHA:
175 case GL_DST_ALPHA:
176 case GL_ONE_MINUS_DST_ALPHA:
177 case GL_CONSTANT_COLOR:
178 case GL_ONE_MINUS_CONSTANT_COLOR:
179 case GL_CONSTANT_ALPHA:
180 case GL_ONE_MINUS_CONSTANT_ALPHA:
181 break;
182 default:
183 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)" );
184 return;
185 }
186
187 if (ctx->Color.BlendSrcRGB == sfactorRGB &&
188 ctx->Color.BlendDstRGB == dfactorRGB &&
189 ctx->Color.BlendSrcA == sfactorA &&
190 ctx->Color.BlendDstA == dfactorA)
191 return;
192
193 FLUSH_VERTICES(ctx, _NEW_COLOR);
194
195 ctx->Color.BlendSrcRGB = sfactorRGB;
196 ctx->Color.BlendDstRGB = dfactorRGB;
197 ctx->Color.BlendSrcA = sfactorA;
198 ctx->Color.BlendDstA = dfactorA;
199
200 if (ctx->Driver.BlendFuncSeparate) {
201 (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
202 sfactorA, dfactorA );
203 }
204 }
205
206
207 #if _HAVE_FULL_GL
208
209 static GLboolean
210 _mesa_validate_blend_equation( struct gl_context *ctx,
211 GLenum mode, GLboolean is_separate )
212 {
213 switch (mode) {
214 case GL_FUNC_ADD:
215 break;
216 case GL_MIN:
217 case GL_MAX:
218 if (!ctx->Extensions.EXT_blend_minmax) {
219 return GL_FALSE;
220 }
221 break;
222 /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
223 */
224 case GL_LOGIC_OP:
225 if (!ctx->Extensions.EXT_blend_logic_op || is_separate) {
226 return GL_FALSE;
227 }
228 break;
229 case GL_FUNC_SUBTRACT:
230 case GL_FUNC_REVERSE_SUBTRACT:
231 if (!ctx->Extensions.EXT_blend_subtract) {
232 return GL_FALSE;
233 }
234 break;
235 default:
236 return GL_FALSE;
237 }
238
239 return GL_TRUE;
240 }
241
242
243 /* This is really an extension function! */
244 void GLAPIENTRY
245 _mesa_BlendEquation( GLenum mode )
246 {
247 GET_CURRENT_CONTEXT(ctx);
248 ASSERT_OUTSIDE_BEGIN_END(ctx);
249
250 if (MESA_VERBOSE & VERBOSE_API)
251 _mesa_debug(ctx, "glBlendEquation %s\n",
252 _mesa_lookup_enum_by_nr(mode));
253
254 if ( ! _mesa_validate_blend_equation( ctx, mode, GL_FALSE ) ) {
255 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
256 return;
257 }
258
259 if ( (ctx->Color.BlendEquationRGB == mode) &&
260 (ctx->Color.BlendEquationA == mode) )
261 return;
262
263 FLUSH_VERTICES(ctx, _NEW_COLOR);
264 ctx->Color.BlendEquationRGB = mode;
265 ctx->Color.BlendEquationA = mode;
266
267 if (ctx->Driver.BlendEquationSeparate)
268 (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
269 }
270
271
272 void GLAPIENTRY
273 _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
274 {
275 GET_CURRENT_CONTEXT(ctx);
276 ASSERT_OUTSIDE_BEGIN_END(ctx);
277
278 if (MESA_VERBOSE & VERBOSE_API)
279 _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n",
280 _mesa_lookup_enum_by_nr(modeRGB),
281 _mesa_lookup_enum_by_nr(modeA));
282
283 if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
284 _mesa_error(ctx, GL_INVALID_OPERATION,
285 "glBlendEquationSeparateEXT not supported by driver");
286 return;
287 }
288
289 if ( ! _mesa_validate_blend_equation( ctx, modeRGB, GL_TRUE ) ) {
290 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
291 return;
292 }
293
294 if ( ! _mesa_validate_blend_equation( ctx, modeA, GL_TRUE ) ) {
295 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
296 return;
297 }
298
299
300 if ( (ctx->Color.BlendEquationRGB == modeRGB) &&
301 (ctx->Color.BlendEquationA == modeA) )
302 return;
303
304 FLUSH_VERTICES(ctx, _NEW_COLOR);
305 ctx->Color.BlendEquationRGB = modeRGB;
306 ctx->Color.BlendEquationA = modeA;
307
308 if (ctx->Driver.BlendEquationSeparate)
309 (*ctx->Driver.BlendEquationSeparate)( ctx, modeRGB, modeA );
310 }
311 #endif
312
313
314 /**
315 * Set the blending color.
316 *
317 * \param red red color component.
318 * \param green green color component.
319 * \param blue blue color component.
320 * \param alpha alpha color component.
321 *
322 * \sa glBlendColor().
323 *
324 * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
325 * change, flushes the vertices and notifies the driver via
326 * dd_function_table::BlendColor callback.
327 */
328 void GLAPIENTRY
329 _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
330 {
331 GLfloat tmp[4];
332 GET_CURRENT_CONTEXT(ctx);
333 ASSERT_OUTSIDE_BEGIN_END(ctx);
334
335 tmp[0] = CLAMP( red, 0.0F, 1.0F );
336 tmp[1] = CLAMP( green, 0.0F, 1.0F );
337 tmp[2] = CLAMP( blue, 0.0F, 1.0F );
338 tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
339
340 if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
341 return;
342
343 FLUSH_VERTICES(ctx, _NEW_COLOR);
344 COPY_4FV( ctx->Color.BlendColor, tmp );
345
346 if (ctx->Driver.BlendColor)
347 (*ctx->Driver.BlendColor)(ctx, tmp);
348 }
349
350
351 /**
352 * Specify the alpha test function.
353 *
354 * \param func alpha comparison function.
355 * \param ref reference value.
356 *
357 * Verifies the parameters and updates gl_colorbuffer_attrib.
358 * On a change, flushes the vertices and notifies the driver via
359 * dd_function_table::AlphaFunc callback.
360 */
361 void GLAPIENTRY
362 _mesa_AlphaFunc( GLenum func, GLclampf ref )
363 {
364 GET_CURRENT_CONTEXT(ctx);
365 ASSERT_OUTSIDE_BEGIN_END(ctx);
366
367 switch (func) {
368 case GL_NEVER:
369 case GL_LESS:
370 case GL_EQUAL:
371 case GL_LEQUAL:
372 case GL_GREATER:
373 case GL_NOTEQUAL:
374 case GL_GEQUAL:
375 case GL_ALWAYS:
376 ref = CLAMP(ref, 0.0F, 1.0F);
377
378 if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
379 return; /* no change */
380
381 FLUSH_VERTICES(ctx, _NEW_COLOR);
382 ctx->Color.AlphaFunc = func;
383 ctx->Color.AlphaRef = ref;
384
385 if (ctx->Driver.AlphaFunc)
386 ctx->Driver.AlphaFunc(ctx, func, ref);
387 return;
388
389 default:
390 _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
391 return;
392 }
393 }
394
395
396 /**
397 * Specify a logic pixel operation for color index rendering.
398 *
399 * \param opcode operation.
400 *
401 * Verifies that \p opcode is a valid enum and updates
402 gl_colorbuffer_attrib::LogicOp.
403 * On a change, flushes the vertices and notifies the driver via the
404 * dd_function_table::LogicOpcode callback.
405 */
406 void GLAPIENTRY
407 _mesa_LogicOp( GLenum opcode )
408 {
409 GET_CURRENT_CONTEXT(ctx);
410 ASSERT_OUTSIDE_BEGIN_END(ctx);
411
412 switch (opcode) {
413 case GL_CLEAR:
414 case GL_SET:
415 case GL_COPY:
416 case GL_COPY_INVERTED:
417 case GL_NOOP:
418 case GL_INVERT:
419 case GL_AND:
420 case GL_NAND:
421 case GL_OR:
422 case GL_NOR:
423 case GL_XOR:
424 case GL_EQUIV:
425 case GL_AND_REVERSE:
426 case GL_AND_INVERTED:
427 case GL_OR_REVERSE:
428 case GL_OR_INVERTED:
429 break;
430 default:
431 _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
432 return;
433 }
434
435 if (ctx->Color.LogicOp == opcode)
436 return;
437
438 FLUSH_VERTICES(ctx, _NEW_COLOR);
439 ctx->Color.LogicOp = opcode;
440
441 if (ctx->Driver.LogicOpcode)
442 ctx->Driver.LogicOpcode( ctx, opcode );
443 }
444
445 #if _HAVE_FULL_GL
446 void GLAPIENTRY
447 _mesa_IndexMask( GLuint mask )
448 {
449 GET_CURRENT_CONTEXT(ctx);
450 ASSERT_OUTSIDE_BEGIN_END(ctx);
451
452 if (ctx->Color.IndexMask == mask)
453 return;
454
455 FLUSH_VERTICES(ctx, _NEW_COLOR);
456 ctx->Color.IndexMask = mask;
457 }
458 #endif
459
460
461 /**
462 * Enable or disable writing of frame buffer color components.
463 *
464 * \param red whether to mask writing of the red color component.
465 * \param green whether to mask writing of the green color component.
466 * \param blue whether to mask writing of the blue color component.
467 * \param alpha whether to mask writing of the alpha color component.
468 *
469 * \sa glColorMask().
470 *
471 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
472 * change, flushes the vertices and notifies the driver via the
473 * dd_function_table::ColorMask callback.
474 */
475 void GLAPIENTRY
476 _mesa_ColorMask( GLboolean red, GLboolean green,
477 GLboolean blue, GLboolean alpha )
478 {
479 GET_CURRENT_CONTEXT(ctx);
480 GLubyte tmp[4];
481 GLuint i;
482 GLboolean flushed;
483 ASSERT_OUTSIDE_BEGIN_END(ctx);
484
485 if (MESA_VERBOSE & VERBOSE_API)
486 _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
487
488 /* Shouldn't have any information about channel depth in core mesa
489 * -- should probably store these as the native booleans:
490 */
491 tmp[RCOMP] = red ? 0xff : 0x0;
492 tmp[GCOMP] = green ? 0xff : 0x0;
493 tmp[BCOMP] = blue ? 0xff : 0x0;
494 tmp[ACOMP] = alpha ? 0xff : 0x0;
495
496 flushed = GL_FALSE;
497 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
498 if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
499 if (!flushed) {
500 FLUSH_VERTICES(ctx, _NEW_COLOR);
501 }
502 flushed = GL_TRUE;
503 COPY_4UBV(ctx->Color.ColorMask[i], tmp);
504 }
505 }
506
507 if (ctx->Driver.ColorMask)
508 ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
509 }
510
511
512 /**
513 * For GL_EXT_draw_buffers2 and GL3
514 */
515 void GLAPIENTRY
516 _mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
517 GLboolean blue, GLboolean alpha )
518 {
519 GLubyte tmp[4];
520 GET_CURRENT_CONTEXT(ctx);
521 ASSERT_OUTSIDE_BEGIN_END(ctx);
522
523 if (MESA_VERBOSE & VERBOSE_API)
524 _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
525 buf, red, green, blue, alpha);
526
527 if (buf >= ctx->Const.MaxDrawBuffers) {
528 _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
529 return;
530 }
531
532 /* Shouldn't have any information about channel depth in core mesa
533 * -- should probably store these as the native booleans:
534 */
535 tmp[RCOMP] = red ? 0xff : 0x0;
536 tmp[GCOMP] = green ? 0xff : 0x0;
537 tmp[BCOMP] = blue ? 0xff : 0x0;
538 tmp[ACOMP] = alpha ? 0xff : 0x0;
539
540 if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
541 return;
542
543 FLUSH_VERTICES(ctx, _NEW_COLOR);
544 COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
545
546 if (ctx->Driver.ColorMaskIndexed)
547 ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
548 }
549
550
551 extern void GLAPIENTRY
552 _mesa_ClampColorARB(GLenum target, GLenum clamp)
553 {
554 GET_CURRENT_CONTEXT(ctx);
555
556 ASSERT_OUTSIDE_BEGIN_END(ctx);
557
558 if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
559 _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
560 return;
561 }
562
563 switch (target) {
564 case GL_CLAMP_VERTEX_COLOR_ARB:
565 ctx->Light.ClampVertexColor = clamp;
566 break;
567 case GL_CLAMP_FRAGMENT_COLOR_ARB:
568 ctx->Color.ClampFragmentColor = clamp;
569 break;
570 case GL_CLAMP_READ_COLOR_ARB:
571 ctx->Color.ClampReadColor = clamp;
572 break;
573 default:
574 _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
575 return;
576 }
577 }
578
579
580
581
582 /**********************************************************************/
583 /** \name Initialization */
584 /*@{*/
585
586 /**
587 * Initialization of the context's Color attribute group.
588 *
589 * \param ctx GL context.
590 *
591 * Initializes the related fields in the context color attribute group,
592 * __struct gl_contextRec::Color.
593 */
594 void _mesa_init_color( struct gl_context * ctx )
595 {
596 /* Color buffer group */
597 ctx->Color.IndexMask = ~0u;
598 memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
599 ctx->Color.ClearIndex = 0;
600 ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
601 ctx->Color.AlphaEnabled = GL_FALSE;
602 ctx->Color.AlphaFunc = GL_ALWAYS;
603 ctx->Color.AlphaRef = 0;
604 ctx->Color.BlendEnabled = 0x0;
605 ctx->Color.BlendSrcRGB = GL_ONE;
606 ctx->Color.BlendDstRGB = GL_ZERO;
607 ctx->Color.BlendSrcA = GL_ONE;
608 ctx->Color.BlendDstA = GL_ZERO;
609 ctx->Color.BlendEquationRGB = GL_FUNC_ADD;
610 ctx->Color.BlendEquationA = GL_FUNC_ADD;
611 ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
612 ctx->Color.IndexLogicOpEnabled = GL_FALSE;
613 ctx->Color.ColorLogicOpEnabled = GL_FALSE;
614 ctx->Color._LogicOpEnabled = GL_FALSE;
615 ctx->Color.LogicOp = GL_COPY;
616 ctx->Color.DitherFlag = GL_TRUE;
617
618 if (ctx->Visual.doubleBufferMode) {
619 ctx->Color.DrawBuffer[0] = GL_BACK;
620 }
621 else {
622 ctx->Color.DrawBuffer[0] = GL_FRONT;
623 }
624
625 ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
626 ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
627 }
628
629 /*@}*/