Merge branch 'mesa_7_7_branch'
[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( 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! */
246 void 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
274 void 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 */
330 void 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 */
363 void 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
404 gl_colorbuffer_attrib::LogicOp.
405 * On a change, flushes the vertices and notifies the driver via the
406 * dd_function_table::LogicOpcode callback.
407 */
408 void 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
448 void 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 if (ctx->Driver.IndexMask)
461 ctx->Driver.IndexMask( ctx, mask );
462 }
463 #endif
464
465
466 /**
467 * Enable or disable writing of frame buffer color components.
468 *
469 * \param red whether to mask writing of the red color component.
470 * \param green whether to mask writing of the green color component.
471 * \param blue whether to mask writing of the blue color component.
472 * \param alpha whether to mask writing of the alpha color component.
473 *
474 * \sa glColorMask().
475 *
476 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
477 * change, flushes the vertices and notifies the driver via the
478 * dd_function_table::ColorMask callback.
479 */
480 void GLAPIENTRY
481 _mesa_ColorMask( GLboolean red, GLboolean green,
482 GLboolean blue, GLboolean alpha )
483 {
484 GET_CURRENT_CONTEXT(ctx);
485 GLubyte tmp[4];
486 GLuint i;
487 GLboolean flushed;
488 ASSERT_OUTSIDE_BEGIN_END(ctx);
489
490 if (MESA_VERBOSE & VERBOSE_API)
491 _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
492
493 /* Shouldn't have any information about channel depth in core mesa
494 * -- should probably store these as the native booleans:
495 */
496 tmp[RCOMP] = red ? 0xff : 0x0;
497 tmp[GCOMP] = green ? 0xff : 0x0;
498 tmp[BCOMP] = blue ? 0xff : 0x0;
499 tmp[ACOMP] = alpha ? 0xff : 0x0;
500
501 flushed = GL_FALSE;
502 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
503 if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
504 if (!flushed) {
505 FLUSH_VERTICES(ctx, _NEW_COLOR);
506 }
507 flushed = GL_TRUE;
508 COPY_4UBV(ctx->Color.ColorMask[i], tmp);
509 }
510 }
511
512 if (ctx->Driver.ColorMask)
513 ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
514 }
515
516
517 /**
518 * For GL_EXT_draw_buffers2 and GL3
519 */
520 void GLAPIENTRY
521 _mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
522 GLboolean blue, GLboolean alpha )
523 {
524 GLubyte tmp[4];
525 GET_CURRENT_CONTEXT(ctx);
526 ASSERT_OUTSIDE_BEGIN_END(ctx);
527
528 if (MESA_VERBOSE & VERBOSE_API)
529 _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
530 buf, red, green, blue, alpha);
531
532 if (buf >= ctx->Const.MaxDrawBuffers) {
533 _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
534 return;
535 }
536
537 /* Shouldn't have any information about channel depth in core mesa
538 * -- should probably store these as the native booleans:
539 */
540 tmp[RCOMP] = red ? 0xff : 0x0;
541 tmp[GCOMP] = green ? 0xff : 0x0;
542 tmp[BCOMP] = blue ? 0xff : 0x0;
543 tmp[ACOMP] = alpha ? 0xff : 0x0;
544
545 if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
546 return;
547
548 FLUSH_VERTICES(ctx, _NEW_COLOR);
549 COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
550
551 if (ctx->Driver.ColorMaskIndexed)
552 ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
553 }
554
555
556 extern void GLAPIENTRY
557 _mesa_ClampColorARB(GLenum target, GLenum clamp)
558 {
559 GET_CURRENT_CONTEXT(ctx);
560
561 ASSERT_OUTSIDE_BEGIN_END(ctx);
562
563 if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
564 _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
565 return;
566 }
567
568 switch (target) {
569 case GL_CLAMP_VERTEX_COLOR_ARB:
570 ctx->Light.ClampVertexColor = clamp;
571 break;
572 case GL_CLAMP_FRAGMENT_COLOR_ARB:
573 ctx->Color.ClampFragmentColor = clamp;
574 break;
575 case GL_CLAMP_READ_COLOR_ARB:
576 ctx->Color.ClampReadColor = clamp;
577 break;
578 default:
579 _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
580 return;
581 }
582 }
583
584
585
586
587 /**********************************************************************/
588 /** \name Initialization */
589 /*@{*/
590
591 /**
592 * Initialization of the context's Color attribute group.
593 *
594 * \param ctx GL context.
595 *
596 * Initializes the related fields in the context color attribute group,
597 * __GLcontextRec::Color.
598 */
599 void _mesa_init_color( GLcontext * ctx )
600 {
601 /* Color buffer group */
602 ctx->Color.IndexMask = ~0u;
603 memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
604 ctx->Color.ClearIndex = 0;
605 ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
606 ctx->Color.AlphaEnabled = GL_FALSE;
607 ctx->Color.AlphaFunc = GL_ALWAYS;
608 ctx->Color.AlphaRef = 0;
609 ctx->Color.BlendEnabled = 0x0;
610 ctx->Color.BlendSrcRGB = GL_ONE;
611 ctx->Color.BlendDstRGB = GL_ZERO;
612 ctx->Color.BlendSrcA = GL_ONE;
613 ctx->Color.BlendDstA = GL_ZERO;
614 ctx->Color.BlendEquationRGB = GL_FUNC_ADD;
615 ctx->Color.BlendEquationA = GL_FUNC_ADD;
616 ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
617 ctx->Color.IndexLogicOpEnabled = GL_FALSE;
618 ctx->Color.ColorLogicOpEnabled = GL_FALSE;
619 ctx->Color._LogicOpEnabled = GL_FALSE;
620 ctx->Color.LogicOp = GL_COPY;
621 ctx->Color.DitherFlag = GL_TRUE;
622
623 if (ctx->Visual.doubleBufferMode) {
624 ctx->Color.DrawBuffer[0] = GL_BACK;
625 }
626 else {
627 ctx->Color.DrawBuffer[0] = GL_FRONT;
628 }
629
630 ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
631 ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
632 }
633
634 /*@}*/