7d6528291b58c3b66ebd25e389e24fceafe22631
[mesa.git] / src / mesa / main / buffers.c
1 /* $Id: buffers.c,v 1.15 2000/10/28 18:34:48 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "accum.h"
33 #include "alphabuf.h"
34 #include "buffers.h"
35 #include "context.h"
36 #include "depth.h"
37 #include "enums.h"
38 #include "macros.h"
39 #include "masking.h"
40 #include "mem.h"
41 #include "stencil.h"
42 #include "state.h"
43 #include "types.h"
44 #endif
45
46
47
48 void
49 _mesa_ClearIndex( GLfloat c )
50 {
51 GET_CURRENT_CONTEXT(ctx);
52 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearIndex");
53 ctx->Color.ClearIndex = (GLuint) c;
54 if (!ctx->Visual.RGBAflag) {
55 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
56 (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
57 }
58 }
59
60
61
62 void
63 _mesa_ClearColor( GLclampf red, GLclampf green,
64 GLclampf blue, GLclampf alpha )
65 {
66 GET_CURRENT_CONTEXT(ctx);
67 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearColor");
68
69 ctx->Color.ClearColor[0] = CLAMP( red, 0.0F, 1.0F );
70 ctx->Color.ClearColor[1] = CLAMP( green, 0.0F, 1.0F );
71 ctx->Color.ClearColor[2] = CLAMP( blue, 0.0F, 1.0F );
72 ctx->Color.ClearColor[3] = CLAMP( alpha, 0.0F, 1.0F );
73
74 if (ctx->Visual.RGBAflag) {
75 GLchan r = (GLint) (ctx->Color.ClearColor[0] * CHAN_MAXF);
76 GLchan g = (GLint) (ctx->Color.ClearColor[1] * CHAN_MAXF);
77 GLchan b = (GLint) (ctx->Color.ClearColor[2] * CHAN_MAXF);
78 GLchan a = (GLint) (ctx->Color.ClearColor[3] * CHAN_MAXF);
79 (*ctx->Driver.ClearColor)( ctx, r, g, b, a );
80 }
81 }
82
83
84
85
86 /*
87 * Clear the color buffer when glColorMask or glIndexMask is in effect.
88 */
89 static void
90 clear_color_buffer_with_masking( GLcontext *ctx )
91 {
92 const GLint x = ctx->DrawBuffer->Xmin;
93 const GLint y = ctx->DrawBuffer->Ymin;
94 const GLint height = ctx->DrawBuffer->Ymax - ctx->DrawBuffer->Ymin;
95 const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin;
96
97 if (ctx->Visual.RGBAflag) {
98 /* RGBA mode */
99 const GLchan r = (GLint) (ctx->Color.ClearColor[0] * CHAN_MAXF);
100 const GLchan g = (GLint) (ctx->Color.ClearColor[1] * CHAN_MAXF);
101 const GLchan b = (GLint) (ctx->Color.ClearColor[2] * CHAN_MAXF);
102 const GLchan a = (GLint) (ctx->Color.ClearColor[3] * CHAN_MAXF);
103 GLint i;
104 for (i = 0; i < height; i++) {
105 GLchan rgba[MAX_WIDTH][4];
106 GLint j;
107 for (j=0; j<width; j++) {
108 rgba[j][RCOMP] = r;
109 rgba[j][GCOMP] = g;
110 rgba[j][BCOMP] = b;
111 rgba[j][ACOMP] = a;
112 }
113 _mesa_mask_rgba_span( ctx, width, x, y + i, rgba );
114 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y + i,
115 (CONST GLchan (*)[4]) rgba, NULL );
116 }
117 }
118 else {
119 /* Color index mode */
120 GLuint span[MAX_WIDTH];
121 GLubyte mask[MAX_WIDTH];
122 GLint i, j;
123 MEMSET( mask, 1, width );
124 for (i=0;i<height;i++) {
125 for (j=0;j<width;j++) {
126 span[j] = ctx->Color.ClearIndex;
127 }
128 _mesa_mask_index_span( ctx, width, x, y + i, span );
129 (*ctx->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask );
130 }
131 }
132 }
133
134
135
136 /*
137 * Clear a color buffer without index/channel masking.
138 */
139 static void
140 clear_color_buffer(GLcontext *ctx)
141 {
142 const GLint x = ctx->DrawBuffer->Xmin;
143 const GLint y = ctx->DrawBuffer->Ymin;
144 const GLint height = ctx->DrawBuffer->Ymax - ctx->DrawBuffer->Ymin;
145 const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin;
146 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
147
148 if (ctx->Visual.RGBAflag) {
149 /* RGBA mode */
150 const GLchan r = (GLint) (ctx->Color.ClearColor[0] * CHAN_MAXF);
151 const GLchan g = (GLint) (ctx->Color.ClearColor[1] * CHAN_MAXF);
152 const GLchan b = (GLint) (ctx->Color.ClearColor[2] * CHAN_MAXF);
153 const GLchan a = (GLint) (ctx->Color.ClearColor[3] * CHAN_MAXF);
154 GLchan span[MAX_WIDTH][4];
155 GLint i;
156
157 ASSERT(colorMask == 0xffffffff);
158
159 for (i = 0; i < width; i++) {
160 span[i][RCOMP] = r;
161 span[i][GCOMP] = g;
162 span[i][BCOMP] = b;
163 span[i][ACOMP] = a;
164 }
165 for (i = 0; i < height; i++) {
166 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y + i,
167 (CONST GLchan (*)[4]) span, NULL );
168 }
169 }
170 else {
171 /* Color index mode */
172 ASSERT(ctx->Color.IndexMask == ~0);
173 if (ctx->Visual.IndexBits == 8) {
174 /* 8-bit clear */
175 GLchan span[MAX_WIDTH];
176 GLint i;
177 MEMSET(span, ctx->Color.ClearIndex, width);
178 for (i = 0; i < height; i++) {
179 (*ctx->Driver.WriteCI8Span)( ctx, width, x, y + i, span, NULL );
180 }
181 }
182 else {
183 /* non 8-bit clear */
184 GLuint span[MAX_WIDTH];
185 GLint i;
186 for (i = 0; i < width; i++) {
187 span[i] = ctx->Color.ClearIndex;
188 }
189 for (i = 0; i < height; i++) {
190 (*ctx->Driver.WriteCI32Span)( ctx, width, x, y + i, span, NULL );
191 }
192 }
193 }
194 }
195
196
197
198 /*
199 * Clear the front/back/left/right color buffers.
200 * This function is usually only called if we need to clear the
201 * buffers with masking.
202 */
203 static void
204 clear_color_buffers(GLcontext *ctx)
205 {
206 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
207 GLuint bufferBit;
208
209 /* loop over four possible dest color buffers */
210 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
211 if (bufferBit & ctx->Color.DrawDestMask) {
212 if (bufferBit == FRONT_LEFT_BIT) {
213 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
214 (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_FRONT_LEFT);
215 }
216 else if (bufferBit == FRONT_RIGHT_BIT) {
217 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
218 (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_FRONT_RIGHT);
219 }
220 else if (bufferBit == BACK_LEFT_BIT) {
221 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
222 (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_BACK_LEFT);
223 }
224 else {
225 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
226 (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_BACK_RIGHT);
227 }
228
229 if (colorMask != 0xffffffff) {
230 clear_color_buffer_with_masking(ctx);
231 }
232 else {
233 clear_color_buffer(ctx);
234 }
235 }
236 }
237
238 /* restore default read/draw buffers */
239 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
240 (void) (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer );
241 }
242
243
244
245 void
246 _mesa_Clear( GLbitfield mask )
247 {
248 GET_CURRENT_CONTEXT(ctx);
249 #ifdef PROFILE
250 GLdouble t0 = gl_time();
251 #endif
252 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClear");
253
254 if (MESA_VERBOSE & VERBOSE_API)
255 fprintf(stderr, "glClear 0x%x\n", mask);
256
257 if (ctx->NewState) {
258 gl_update_state( ctx );
259 }
260
261 if (ctx->RenderMode==GL_RENDER) {
262 const GLint x = ctx->DrawBuffer->Xmin;
263 const GLint y = ctx->DrawBuffer->Ymin;
264 const GLint height = ctx->DrawBuffer->Ymax - ctx->DrawBuffer->Ymin;
265 const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin;
266 GLbitfield ddMask;
267 GLbitfield newMask;
268
269 /* don't clear depth buffer if depth writing disabled */
270 if (!ctx->Depth.Mask)
271 CLEAR_BITS(mask, GL_DEPTH_BUFFER_BIT);
272
273 /* Build bitmask to send to driver Clear function */
274 ddMask = mask & (GL_DEPTH_BUFFER_BIT |
275 GL_STENCIL_BUFFER_BIT |
276 GL_ACCUM_BUFFER_BIT);
277 if (mask & GL_COLOR_BUFFER_BIT) {
278 ddMask |= ctx->Color.DrawDestMask;
279 }
280
281 ASSERT(ctx->Driver.Clear);
282 newMask = (*ctx->Driver.Clear)( ctx, ddMask, !ctx->Scissor.Enabled,
283 x, y, width, height );
284
285 #ifdef DEBUG
286 {
287 GLbitfield legalBits = DD_FRONT_LEFT_BIT |
288 DD_FRONT_RIGHT_BIT |
289 DD_BACK_LEFT_BIT |
290 DD_BACK_RIGHT_BIT |
291 DD_DEPTH_BIT |
292 DD_STENCIL_BIT |
293 DD_ACCUM_BIT;
294 assert((newMask & (~legalBits)) == 0);
295 }
296 #endif
297
298 RENDER_START(ctx);
299
300 /* do software clearing here */
301 if (newMask) {
302 if (newMask & ctx->Color.DrawDestMask) clear_color_buffers(ctx);
303 if (newMask & GL_DEPTH_BUFFER_BIT) _mesa_clear_depth_buffer(ctx);
304 if (newMask & GL_ACCUM_BUFFER_BIT) _mesa_clear_accum_buffer(ctx);
305 if (newMask & GL_STENCIL_BUFFER_BIT) _mesa_clear_stencil_buffer(ctx);
306 }
307
308 /* clear software-based alpha buffer(s) */
309 if ( (mask & GL_COLOR_BUFFER_BIT)
310 && ctx->DrawBuffer->UseSoftwareAlphaBuffers
311 && ctx->Color.ColorMask[ACOMP]) {
312 _mesa_clear_alpha_buffers( ctx );
313 }
314
315 RENDER_FINISH(ctx);
316
317 #ifdef PROFILE
318 ctx->ClearTime += gl_time() - t0;
319 ctx->ClearCount++;
320 #endif
321 }
322 }
323
324
325 void
326 _mesa_DrawBuffer( GLenum mode )
327 {
328 GET_CURRENT_CONTEXT(ctx);
329 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawBuffer");
330
331 if (MESA_VERBOSE & VERBOSE_API)
332 fprintf(stderr, "glDrawBuffer %s\n", gl_lookup_enum_by_nr(mode));
333
334 switch (mode) {
335 case GL_AUX0:
336 case GL_AUX1:
337 case GL_AUX2:
338 case GL_AUX3:
339 /* AUX buffers not implemented in Mesa at this time */
340 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
341 return;
342 case GL_RIGHT:
343 if (!ctx->Visual.StereoFlag) {
344 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
345 return;}
346 if (ctx->Visual.DBflag)
347 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
348 else
349 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
350 break;
351 case GL_FRONT_RIGHT:
352 if (!ctx->Visual.StereoFlag) {
353 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
354 return;
355 }
356 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
357 break;
358 case GL_BACK_RIGHT:
359 if (!ctx->Visual.StereoFlag) {
360 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
361 return;
362 }
363 if (!ctx->Visual.DBflag) {
364 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
365 return;
366 }
367 ctx->Color.DrawDestMask = BACK_RIGHT_BIT;
368 break;
369 case GL_BACK_LEFT:
370 if (!ctx->Visual.DBflag) {
371 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
372 return;
373 }
374 ctx->Color.DrawDestMask = BACK_LEFT_BIT;
375 break;
376 case GL_FRONT_AND_BACK:
377 if (!ctx->Visual.DBflag) {
378 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
379 return;
380 }
381 if (ctx->Visual.StereoFlag)
382 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT
383 | FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
384 else
385 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
386 break;
387 case GL_BACK:
388 if (!ctx->Visual.DBflag) {
389 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
390 return;
391 }
392 if (ctx->Visual.StereoFlag)
393 ctx->Color.DrawDestMask = BACK_LEFT_BIT | BACK_RIGHT_BIT;
394 else
395 ctx->Color.DrawDestMask = BACK_LEFT_BIT;
396 break;
397 case GL_LEFT:
398 /* never an error */
399 if (ctx->Visual.DBflag)
400 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
401 else
402 ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
403 break;
404 case GL_FRONT_LEFT:
405 /* never an error */
406 ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
407 break;
408 case GL_FRONT:
409 /* never an error */
410 if (ctx->Visual.StereoFlag)
411 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | FRONT_RIGHT_BIT;
412 else
413 ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
414 break;
415 case GL_NONE:
416 /* never an error */
417 ctx->Color.DrawDestMask = 0;
418 break;
419 default:
420 gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
421 return;
422 }
423
424 /*
425 * Make the dest buffer mode more precise if possible
426 */
427 if (mode == GL_LEFT && !ctx->Visual.DBflag)
428 ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
429 else if (mode == GL_RIGHT && !ctx->Visual.DBflag)
430 ctx->Color.DriverDrawBuffer = GL_FRONT_RIGHT;
431 else if (mode == GL_FRONT && !ctx->Visual.StereoFlag)
432 ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
433 else if (mode == GL_BACK && !ctx->Visual.StereoFlag)
434 ctx->Color.DriverDrawBuffer = GL_BACK_LEFT;
435 else
436 ctx->Color.DriverDrawBuffer = mode;
437
438 /*
439 * Set current alpha buffer pointer
440 */
441 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) {
442 if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT)
443 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
444 else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT)
445 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
446 else if (ctx->Color.DriverDrawBuffer == GL_FRONT_RIGHT)
447 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
448 else if (ctx->Color.DriverDrawBuffer == GL_BACK_RIGHT)
449 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
450 }
451
452 /*
453 * If we get here there can't have been an error.
454 * Now see if device driver can implement the drawing to the target
455 * buffer(s). The driver may not be able to do GL_FRONT_AND_BACK mode
456 * for example. We'll take care of that in the core code by looping
457 * over the individual buffers.
458 */
459 ASSERT(ctx->Driver.SetDrawBuffer);
460 if ( (*ctx->Driver.SetDrawBuffer)(ctx, ctx->Color.DriverDrawBuffer) ) {
461 /* All OK, the driver will do all buffer writes */
462 ctx->Color.MultiDrawBuffer = GL_FALSE;
463 }
464 else {
465 /* We'll have to loop over the multiple draw buffer targets */
466 ctx->Color.MultiDrawBuffer = GL_TRUE;
467 /* Set drawing buffer to front for now */
468 (void) (*ctx->Driver.SetDrawBuffer)(ctx, GL_FRONT_LEFT);
469 }
470
471 ctx->Color.DrawBuffer = mode;
472 ctx->NewState |= NEW_RASTER_OPS;
473 }
474
475
476
477 void
478 _mesa_ReadBuffer( GLenum mode )
479 {
480 GET_CURRENT_CONTEXT(ctx);
481 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glReadBuffer");
482
483 if (MESA_VERBOSE & VERBOSE_API)
484 fprintf(stderr, "glReadBuffer %s\n", gl_lookup_enum_by_nr(mode));
485
486 switch (mode) {
487 case GL_AUX0:
488 case GL_AUX1:
489 case GL_AUX2:
490 case GL_AUX3:
491 /* AUX buffers not implemented in Mesa at this time */
492 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
493 return;
494 case GL_LEFT:
495 case GL_FRONT:
496 case GL_FRONT_LEFT:
497 /* Front-Left buffer, always exists */
498 ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT;
499 break;
500 case GL_BACK:
501 case GL_BACK_LEFT:
502 /* Back-Left buffer, requires double buffering */
503 if (!ctx->Visual.DBflag) {
504 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
505 return;
506 }
507 ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT;
508 break;
509 case GL_FRONT_RIGHT:
510 case GL_RIGHT:
511 if (!ctx->Visual.StereoFlag) {
512 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
513 return;
514 }
515 ctx->Pixel.DriverReadBuffer = GL_FRONT_RIGHT;
516 break;
517 case GL_BACK_RIGHT:
518 if (!ctx->Visual.StereoFlag || !ctx->Visual.DBflag) {
519 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
520 return;
521 }
522 ctx->Pixel.DriverReadBuffer = GL_BACK_RIGHT;
523 break;
524 default:
525 gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
526 return;
527 }
528
529 ctx->Pixel.ReadBuffer = mode;
530 ctx->NewState |= NEW_RASTER_OPS;
531 }
532
533
534 /*
535 * GL_MESA_resize_buffers extension
536 */
537 void
538 _mesa_ResizeBuffersMESA( void )
539 {
540 GLcontext *ctx = _mesa_get_current_context();
541
542 GLuint buf_width, buf_height;
543
544 if (MESA_VERBOSE & VERBOSE_API)
545 fprintf(stderr, "glResizeBuffersMESA\n");
546
547 /* ask device driver for size of output buffer */
548 (*ctx->Driver.GetBufferSize)( ctx, &buf_width, &buf_height );
549
550 /* see if size of device driver's color buffer (window) has changed */
551 if (ctx->DrawBuffer->Width == (GLint) buf_width &&
552 ctx->DrawBuffer->Height == (GLint) buf_height)
553 return;
554
555 ctx->NewState |= NEW_RASTER_OPS; /* to update scissor / window bounds */
556
557 /* save buffer size */
558 ctx->DrawBuffer->Width = buf_width;
559 ctx->DrawBuffer->Height = buf_height;
560
561 /* Reallocate other buffers if needed. */
562 if (ctx->DrawBuffer->UseSoftwareDepthBuffer) {
563 _mesa_alloc_depth_buffer( ctx );
564 }
565 if (ctx->DrawBuffer->UseSoftwareStencilBuffer) {
566 _mesa_alloc_stencil_buffer( ctx );
567 }
568 if (ctx->DrawBuffer->UseSoftwareAccumBuffer) {
569 _mesa_alloc_accum_buffer( ctx );
570 }
571 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) {
572 _mesa_alloc_alpha_buffers( ctx );
573 }
574 }