blend.c revision cdc920a0
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 */
48void 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 */
67void 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
209static GLboolean
210_mesa_validate_blend_equation( GLcontext *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             !ctx->Extensions.ARB_imaging) {
220            return GL_FALSE;
221         }
222         break;
223      /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
224       */
225      case GL_LOGIC_OP:
226         if (!ctx->Extensions.EXT_blend_logic_op || is_separate) {
227            return GL_FALSE;
228         }
229         break;
230      case GL_FUNC_SUBTRACT:
231      case GL_FUNC_REVERSE_SUBTRACT:
232         if (!ctx->Extensions.EXT_blend_subtract &&
233             !ctx->Extensions.ARB_imaging) {
234            return GL_FALSE;
235         }
236         break;
237      default:
238         return GL_FALSE;
239   }
240
241   return GL_TRUE;
242}
243
244
245/* This is really an extension function! */
246void GLAPIENTRY
247_mesa_BlendEquation( GLenum mode )
248{
249   GET_CURRENT_CONTEXT(ctx);
250   ASSERT_OUTSIDE_BEGIN_END(ctx);
251
252   if (MESA_VERBOSE & VERBOSE_API)
253      _mesa_debug(ctx, "glBlendEquation %s\n",
254                  _mesa_lookup_enum_by_nr(mode));
255
256   if ( ! _mesa_validate_blend_equation( ctx, mode, GL_FALSE ) ) {
257      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
258      return;
259   }
260
261   if ( (ctx->Color.BlendEquationRGB == mode) &&
262	(ctx->Color.BlendEquationA == mode) )
263      return;
264
265   FLUSH_VERTICES(ctx, _NEW_COLOR);
266   ctx->Color.BlendEquationRGB = mode;
267   ctx->Color.BlendEquationA = mode;
268
269   if (ctx->Driver.BlendEquationSeparate)
270      (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
271}
272
273
274void GLAPIENTRY
275_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
276{
277   GET_CURRENT_CONTEXT(ctx);
278   ASSERT_OUTSIDE_BEGIN_END(ctx);
279
280   if (MESA_VERBOSE & VERBOSE_API)
281      _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n",
282                  _mesa_lookup_enum_by_nr(modeRGB),
283                  _mesa_lookup_enum_by_nr(modeA));
284
285   if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
286      _mesa_error(ctx, GL_INVALID_OPERATION,
287		  "glBlendEquationSeparateEXT not supported by driver");
288      return;
289   }
290
291   if ( ! _mesa_validate_blend_equation( ctx, modeRGB, GL_TRUE ) ) {
292      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
293      return;
294   }
295
296   if ( ! _mesa_validate_blend_equation( ctx, modeA, GL_TRUE ) ) {
297      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
298      return;
299   }
300
301
302   if ( (ctx->Color.BlendEquationRGB == modeRGB) &&
303	(ctx->Color.BlendEquationA == modeA) )
304      return;
305
306   FLUSH_VERTICES(ctx, _NEW_COLOR);
307   ctx->Color.BlendEquationRGB = modeRGB;
308   ctx->Color.BlendEquationA = modeA;
309
310   if (ctx->Driver.BlendEquationSeparate)
311      (*ctx->Driver.BlendEquationSeparate)( ctx, modeRGB, modeA );
312}
313#endif
314
315
316/**
317 * Set the blending color.
318 *
319 * \param red red color component.
320 * \param green green color component.
321 * \param blue blue color component.
322 * \param alpha alpha color component.
323 *
324 * \sa glBlendColor().
325 *
326 * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor.  On a
327 * change, flushes the vertices and notifies the driver via
328 * dd_function_table::BlendColor callback.
329 */
330void GLAPIENTRY
331_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
332{
333   GLfloat tmp[4];
334   GET_CURRENT_CONTEXT(ctx);
335   ASSERT_OUTSIDE_BEGIN_END(ctx);
336
337   tmp[0] = CLAMP( red,   0.0F, 1.0F );
338   tmp[1] = CLAMP( green, 0.0F, 1.0F );
339   tmp[2] = CLAMP( blue,  0.0F, 1.0F );
340   tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
341
342   if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
343      return;
344
345   FLUSH_VERTICES(ctx, _NEW_COLOR);
346   COPY_4FV( ctx->Color.BlendColor, tmp );
347
348   if (ctx->Driver.BlendColor)
349      (*ctx->Driver.BlendColor)(ctx, tmp);
350}
351
352
353/**
354 * Specify the alpha test function.
355 *
356 * \param func alpha comparison function.
357 * \param ref reference value.
358 *
359 * Verifies the parameters and updates gl_colorbuffer_attrib.
360 * On a change, flushes the vertices and notifies the driver via
361 * dd_function_table::AlphaFunc callback.
362 */
363void GLAPIENTRY
364_mesa_AlphaFunc( GLenum func, GLclampf ref )
365{
366   GET_CURRENT_CONTEXT(ctx);
367   ASSERT_OUTSIDE_BEGIN_END(ctx);
368
369   switch (func) {
370   case GL_NEVER:
371   case GL_LESS:
372   case GL_EQUAL:
373   case GL_LEQUAL:
374   case GL_GREATER:
375   case GL_NOTEQUAL:
376   case GL_GEQUAL:
377   case GL_ALWAYS:
378      ref = CLAMP(ref, 0.0F, 1.0F);
379
380      if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
381         return; /* no change */
382
383      FLUSH_VERTICES(ctx, _NEW_COLOR);
384      ctx->Color.AlphaFunc = func;
385      ctx->Color.AlphaRef = ref;
386
387      if (ctx->Driver.AlphaFunc)
388         ctx->Driver.AlphaFunc(ctx, func, ref);
389      return;
390
391   default:
392      _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
393      return;
394   }
395}
396
397
398/**
399 * Specify a logic pixel operation for color index rendering.
400 *
401 * \param opcode operation.
402 *
403 * Verifies that \p opcode is a valid enum and updates
404gl_colorbuffer_attrib::LogicOp.
405 * On a change, flushes the vertices and notifies the driver via the
406 * dd_function_table::LogicOpcode callback.
407 */
408void GLAPIENTRY
409_mesa_LogicOp( GLenum opcode )
410{
411   GET_CURRENT_CONTEXT(ctx);
412   ASSERT_OUTSIDE_BEGIN_END(ctx);
413
414   switch (opcode) {
415      case GL_CLEAR:
416      case GL_SET:
417      case GL_COPY:
418      case GL_COPY_INVERTED:
419      case GL_NOOP:
420      case GL_INVERT:
421      case GL_AND:
422      case GL_NAND:
423      case GL_OR:
424      case GL_NOR:
425      case GL_XOR:
426      case GL_EQUIV:
427      case GL_AND_REVERSE:
428      case GL_AND_INVERTED:
429      case GL_OR_REVERSE:
430      case GL_OR_INVERTED:
431	 break;
432      default:
433         _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
434	 return;
435   }
436
437   if (ctx->Color.LogicOp == opcode)
438      return;
439
440   FLUSH_VERTICES(ctx, _NEW_COLOR);
441   ctx->Color.LogicOp = opcode;
442
443   if (ctx->Driver.LogicOpcode)
444      ctx->Driver.LogicOpcode( ctx, opcode );
445}
446
447#if _HAVE_FULL_GL
448void GLAPIENTRY
449_mesa_IndexMask( GLuint mask )
450{
451   GET_CURRENT_CONTEXT(ctx);
452   ASSERT_OUTSIDE_BEGIN_END(ctx);
453
454   if (ctx->Color.IndexMask == mask)
455      return;
456
457   FLUSH_VERTICES(ctx, _NEW_COLOR);
458   ctx->Color.IndexMask = mask;
459}
460#endif
461
462
463/**
464 * Enable or disable writing of frame buffer color components.
465 *
466 * \param red whether to mask writing of the red color component.
467 * \param green whether to mask writing of the green color component.
468 * \param blue whether to mask writing of the blue color component.
469 * \param alpha whether to mask writing of the alpha color component.
470 *
471 * \sa glColorMask().
472 *
473 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask.  On a
474 * change, flushes the vertices and notifies the driver via the
475 * dd_function_table::ColorMask callback.
476 */
477void GLAPIENTRY
478_mesa_ColorMask( GLboolean red, GLboolean green,
479                 GLboolean blue, GLboolean alpha )
480{
481   GET_CURRENT_CONTEXT(ctx);
482   GLubyte tmp[4];
483   GLuint i;
484   GLboolean flushed;
485   ASSERT_OUTSIDE_BEGIN_END(ctx);
486
487   if (MESA_VERBOSE & VERBOSE_API)
488      _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
489
490   /* Shouldn't have any information about channel depth in core mesa
491    * -- should probably store these as the native booleans:
492    */
493   tmp[RCOMP] = red    ? 0xff : 0x0;
494   tmp[GCOMP] = green  ? 0xff : 0x0;
495   tmp[BCOMP] = blue   ? 0xff : 0x0;
496   tmp[ACOMP] = alpha  ? 0xff : 0x0;
497
498   flushed = GL_FALSE;
499   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
500      if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
501         if (!flushed) {
502            FLUSH_VERTICES(ctx, _NEW_COLOR);
503         }
504         flushed = GL_TRUE;
505         COPY_4UBV(ctx->Color.ColorMask[i], tmp);
506      }
507   }
508
509   if (ctx->Driver.ColorMask)
510      ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
511}
512
513
514/**
515 * For GL_EXT_draw_buffers2 and GL3
516 */
517void GLAPIENTRY
518_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
519                        GLboolean blue, GLboolean alpha )
520{
521   GLubyte tmp[4];
522   GET_CURRENT_CONTEXT(ctx);
523   ASSERT_OUTSIDE_BEGIN_END(ctx);
524
525   if (MESA_VERBOSE & VERBOSE_API)
526      _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
527                  buf, red, green, blue, alpha);
528
529   if (buf >= ctx->Const.MaxDrawBuffers) {
530      _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
531      return;
532   }
533
534   /* Shouldn't have any information about channel depth in core mesa
535    * -- should probably store these as the native booleans:
536    */
537   tmp[RCOMP] = red    ? 0xff : 0x0;
538   tmp[GCOMP] = green  ? 0xff : 0x0;
539   tmp[BCOMP] = blue   ? 0xff : 0x0;
540   tmp[ACOMP] = alpha  ? 0xff : 0x0;
541
542   if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
543      return;
544
545   FLUSH_VERTICES(ctx, _NEW_COLOR);
546   COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
547
548   if (ctx->Driver.ColorMaskIndexed)
549      ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
550}
551
552
553extern void GLAPIENTRY
554_mesa_ClampColorARB(GLenum target, GLenum clamp)
555{
556   GET_CURRENT_CONTEXT(ctx);
557
558   ASSERT_OUTSIDE_BEGIN_END(ctx);
559
560   if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
561      _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
562      return;
563   }
564
565   switch (target) {
566   case GL_CLAMP_VERTEX_COLOR_ARB:
567      ctx->Light.ClampVertexColor = clamp;
568      break;
569   case GL_CLAMP_FRAGMENT_COLOR_ARB:
570      ctx->Color.ClampFragmentColor = clamp;
571      break;
572   case GL_CLAMP_READ_COLOR_ARB:
573      ctx->Color.ClampReadColor = clamp;
574      break;
575   default:
576      _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
577      return;
578   }
579}
580
581
582
583
584/**********************************************************************/
585/** \name Initialization */
586/*@{*/
587
588/**
589 * Initialization of the context's Color attribute group.
590 *
591 * \param ctx GL context.
592 *
593 * Initializes the related fields in the context color attribute group,
594 * __GLcontextRec::Color.
595 */
596void _mesa_init_color( GLcontext * ctx )
597{
598   /* Color buffer group */
599   ctx->Color.IndexMask = ~0u;
600   memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
601   ctx->Color.ClearIndex = 0;
602   ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
603   ctx->Color.AlphaEnabled = GL_FALSE;
604   ctx->Color.AlphaFunc = GL_ALWAYS;
605   ctx->Color.AlphaRef = 0;
606   ctx->Color.BlendEnabled = 0x0;
607   ctx->Color.BlendSrcRGB = GL_ONE;
608   ctx->Color.BlendDstRGB = GL_ZERO;
609   ctx->Color.BlendSrcA = GL_ONE;
610   ctx->Color.BlendDstA = GL_ZERO;
611   ctx->Color.BlendEquationRGB = GL_FUNC_ADD;
612   ctx->Color.BlendEquationA = GL_FUNC_ADD;
613   ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
614   ctx->Color.IndexLogicOpEnabled = GL_FALSE;
615   ctx->Color.ColorLogicOpEnabled = GL_FALSE;
616   ctx->Color._LogicOpEnabled = GL_FALSE;
617   ctx->Color.LogicOp = GL_COPY;
618   ctx->Color.DitherFlag = GL_TRUE;
619
620   if (ctx->Visual.doubleBufferMode) {
621      ctx->Color.DrawBuffer[0] = GL_BACK;
622   }
623   else {
624      ctx->Color.DrawBuffer[0] = GL_FRONT;
625   }
626
627   ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
628   ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
629}
630
631/*@}*/
632