9a0f713bb1ee41b03e46d4b9a2b53dbc34017895
1 /* $Id: buffers.c,v 1.3 2000/02/02 22:16:04 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
49 _mesa_ClearIndex( GLfloat c
)
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
);
63 _mesa_ClearColor( GLclampf red
, GLclampf green
,
64 GLclampf blue
, GLclampf alpha
)
66 GET_CURRENT_CONTEXT(ctx
);
67 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClearColor");
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
);
74 if (ctx
->Visual
->RGBAflag
) {
75 GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
76 GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
77 GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
78 GLubyte a
= (GLint
) (ctx
->Color
.ClearColor
[3] * 255.0F
);
79 (*ctx
->Driver
.ClearColor
)( ctx
, r
, g
, b
, a
);
87 * Clear the color buffer when glColorMask or glIndexMask is in effect.
90 clear_color_buffer_with_masking( GLcontext
*ctx
)
92 const GLint x
= ctx
->DrawBuffer
->Xmin
;
93 const GLint y
= ctx
->DrawBuffer
->Ymin
;
94 const GLint height
= ctx
->DrawBuffer
->Ymax
- ctx
->DrawBuffer
->Ymin
+ 1;
95 const GLint width
= ctx
->DrawBuffer
->Xmax
- ctx
->DrawBuffer
->Xmin
+ 1;
97 if (ctx
->Visual
->RGBAflag
) {
99 const GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
100 const GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
101 const GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
102 const GLubyte a
= (GLint
) (ctx
->Color
.ClearColor
[3] * 255.0F
);
104 for (i
= 0; i
< height
; i
++) {
105 GLubyte rgba
[MAX_WIDTH
][4];
107 for (j
=0; j
<width
; j
++) {
113 gl_mask_rgba_span( ctx
, width
, x
, y
+ i
, rgba
);
114 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
+ i
,
115 (CONST
GLubyte (*)[4])rgba
, NULL
);
119 /* Color index mode */
120 GLuint span
[MAX_WIDTH
];
121 GLubyte mask
[MAX_WIDTH
];
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
;
128 gl_mask_index_span( ctx
, width
, x
, y
+ i
, span
);
129 (*ctx
->Driver
.WriteCI32Span
)( ctx
, width
, x
, y
+ i
, span
, mask
);
137 * Clear a color buffer without index/channel masking.
140 clear_color_buffer(GLcontext
*ctx
)
142 const GLint x
= ctx
->DrawBuffer
->Xmin
;
143 const GLint y
= ctx
->DrawBuffer
->Ymin
;
144 const GLint height
= ctx
->DrawBuffer
->Ymax
- ctx
->DrawBuffer
->Ymin
+ 1;
145 const GLint width
= ctx
->DrawBuffer
->Xmax
- ctx
->DrawBuffer
->Xmin
+ 1;
147 if (ctx
->Visual
->RGBAflag
) {
149 const GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
150 const GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
151 const GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
152 const GLubyte a
= (GLint
) (ctx
->Color
.ClearColor
[3] * 255.0F
);
153 GLubyte span
[MAX_WIDTH
][4];
155 ASSERT(ctx
->Color
.ColorMask
[0] &&
156 ctx
->Color
.ColorMask
[1] &&
157 ctx
->Color
.ColorMask
[2] &&
158 ctx
->Color
.ColorMask
[3]);
159 for (i
= 0; i
< width
; i
++) {
165 for (i
= 0; i
< height
; i
++) {
166 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
+ i
,
167 (CONST
GLubyte (*)[4]) span
, NULL
);
171 /* Color index mode */
172 ASSERT(ctx
->Color
.IndexMask
== ~0);
173 if (ctx
->Visual
->IndexBits
== 8) {
175 GLubyte span
[MAX_WIDTH
];
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
);
183 /* non 8-bit clear */
184 GLuint span
[MAX_WIDTH
];
186 for (i
= 0; i
< width
; i
++) {
187 span
[i
] = ctx
->Color
.ClearIndex
;
189 for (i
= 0; i
< height
; i
++) {
190 (*ctx
->Driver
.WriteCI32Span
)( ctx
, width
, x
, y
+ i
, span
, NULL
);
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.
204 clear_color_buffers(GLcontext
*ctx
)
208 /* loop over four possible dest color buffers */
209 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
210 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
211 if (bufferBit
== FRONT_LEFT_BIT
) {
212 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
214 else if (bufferBit
== FRONT_RIGHT_BIT
) {
215 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
217 else if (bufferBit
== BACK_LEFT_BIT
) {
218 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
221 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
224 if (ctx
->Color
.SWmasking
) {
225 clear_color_buffer_with_masking(ctx
);
228 clear_color_buffer(ctx
);
233 /* restore default dest buffer */
234 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
240 _mesa_Clear( GLbitfield mask
)
242 GET_CURRENT_CONTEXT(ctx
);
244 GLdouble t0
= gl_time();
246 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClear");
248 if (MESA_VERBOSE
& VERBOSE_API
)
249 fprintf(stderr
, "glClear 0x%x\n", mask
);
252 gl_update_state( ctx
);
255 if (ctx
->RenderMode
==GL_RENDER
) {
256 const GLint x
= ctx
->DrawBuffer
->Xmin
;
257 const GLint y
= ctx
->DrawBuffer
->Ymin
;
258 const GLint height
= ctx
->DrawBuffer
->Ymax
- ctx
->DrawBuffer
->Ymin
+ 1;
259 const GLint width
= ctx
->DrawBuffer
->Xmax
- ctx
->DrawBuffer
->Xmin
+ 1;
263 /* don't clear depth buffer if depth writing disabled */
264 if (!ctx
->Depth
.Mask
)
265 CLEAR_BITS(mask
, GL_DEPTH_BUFFER_BIT
);
267 /* Build bitmask to send to driver Clear function */
268 ddMask
= mask
& (GL_DEPTH_BUFFER_BIT
|
269 GL_STENCIL_BUFFER_BIT
|
270 GL_ACCUM_BUFFER_BIT
);
271 if (mask
& GL_COLOR_BUFFER_BIT
) {
272 ddMask
|= ctx
->Color
.DrawDestMask
;
275 ASSERT(ctx
->Driver
.Clear
);
276 newMask
= (*ctx
->Driver
.Clear
)( ctx
, ddMask
, !ctx
->Scissor
.Enabled
,
277 x
, y
, width
, height
);
281 GLbitfield legalBits
= DD_FRONT_LEFT_BIT
|
288 assert((newMask
& (~legalBits
)) == 0);
292 /* do software clearing here */
294 if (newMask
& ctx
->Color
.DrawDestMask
) clear_color_buffers( ctx
);
295 if (newMask
& GL_DEPTH_BUFFER_BIT
) _mesa_clear_depth_buffer( ctx
);
296 if (newMask
& GL_ACCUM_BUFFER_BIT
) _mesa_clear_accum_buffer( ctx
);
297 if (newMask
& GL_STENCIL_BUFFER_BIT
) gl_clear_stencil_buffer( ctx
);
300 /* clear software-based alpha buffer(s) */
301 if ( (mask
& GL_COLOR_BUFFER_BIT
) && ctx
->Visual
->SoftwareAlpha
302 && ctx
->Color
.ColorMask
[RCOMP
]) {
303 gl_clear_alpha_buffers( ctx
);
307 ctx
->ClearTime
+= gl_time() - t0
;
315 _mesa_DrawBuffer( GLenum mode
)
317 GET_CURRENT_CONTEXT(ctx
);
318 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawBuffer");
320 if (MESA_VERBOSE
& VERBOSE_API
)
321 fprintf(stderr
, "glDrawBuffer %s\n", gl_lookup_enum_by_nr(mode
));
328 /* AUX buffers not implemented in Mesa at this time */
329 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
332 if (!ctx
->Visual
->StereoFlag
) {
333 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
336 if (ctx
->Visual
->DBflag
)
337 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
339 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
;
342 if (!ctx
->Visual
->StereoFlag
) {
343 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
346 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
;
349 if (!ctx
->Visual
->StereoFlag
) {
350 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
353 if (!ctx
->Visual
->DBflag
) {
354 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
357 ctx
->Color
.DrawDestMask
= BACK_RIGHT_BIT
;
360 if (!ctx
->Visual
->DBflag
) {
361 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
364 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
;
366 case GL_FRONT_AND_BACK
:
367 if (!ctx
->Visual
->DBflag
) {
368 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
371 if (ctx
->Visual
->StereoFlag
)
372 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
373 | FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
375 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
378 if (!ctx
->Visual
->DBflag
) {
379 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
382 if (ctx
->Visual
->StereoFlag
)
383 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
| BACK_RIGHT_BIT
;
385 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
;
389 if (ctx
->Visual
->DBflag
)
390 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
392 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
396 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
400 if (ctx
->Visual
->StereoFlag
)
401 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| FRONT_RIGHT_BIT
;
403 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
407 ctx
->Color
.DrawDestMask
= 0;
410 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawBuffer" );
415 * Make the dest buffer mode more precise if possible
417 if (mode
== GL_LEFT
&& !ctx
->Visual
->DBflag
)
418 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_LEFT
;
419 else if (mode
== GL_RIGHT
&& !ctx
->Visual
->DBflag
)
420 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_RIGHT
;
421 else if (mode
== GL_FRONT
&& !ctx
->Visual
->StereoFlag
)
422 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_LEFT
;
423 else if (mode
== GL_BACK
&& !ctx
->Visual
->StereoFlag
)
424 ctx
->Color
.DriverDrawBuffer
= GL_BACK_LEFT
;
426 ctx
->Color
.DriverDrawBuffer
= mode
;
429 * Set current alpha buffer pointer
431 if (ctx
->Visual
->SoftwareAlpha
) {
432 if (ctx
->Color
.DriverDrawBuffer
== GL_FRONT_LEFT
)
433 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
434 else if (ctx
->Color
.DriverDrawBuffer
== GL_BACK_LEFT
)
435 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
436 else if (ctx
->Color
.DriverDrawBuffer
== GL_FRONT_RIGHT
)
437 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
438 else if (ctx
->Color
.DriverDrawBuffer
== GL_BACK_RIGHT
)
439 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
443 * If we get here there can't have been an error.
444 * Now see if device driver can implement the drawing to the target
445 * buffer(s). The driver may not be able to do GL_FRONT_AND_BACK mode
446 * for example. We'll take care of that in the core code by looping
447 * over the individual buffers.
449 ASSERT(ctx
->Driver
.SetDrawBuffer
);
450 if ( (*ctx
->Driver
.SetDrawBuffer
)(ctx
, ctx
->Color
.DriverDrawBuffer
) ) {
451 /* All OK, the driver will do all buffer writes */
452 ctx
->Color
.MultiDrawBuffer
= GL_FALSE
;
455 /* We'll have to loop over the multiple draw buffer targets */
456 ctx
->Color
.MultiDrawBuffer
= GL_TRUE
;
457 /* Set drawing buffer to front for now */
458 (void) (*ctx
->Driver
.SetDrawBuffer
)(ctx
, GL_FRONT_LEFT
);
461 ctx
->Color
.DrawBuffer
= mode
;
462 ctx
->NewState
|= NEW_RASTER_OPS
;
468 _mesa_ReadBuffer( GLenum mode
)
470 GET_CURRENT_CONTEXT(ctx
);
471 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glReadBuffer");
473 if (MESA_VERBOSE
& VERBOSE_API
)
474 fprintf(stderr
, "glReadBuffer %s\n", gl_lookup_enum_by_nr(mode
));
481 /* AUX buffers not implemented in Mesa at this time */
482 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
487 /* Front-Left buffer, always exists */
488 ctx
->Pixel
.DriverReadBuffer
= GL_FRONT_LEFT
;
492 /* Back-Left buffer, requires double buffering */
493 if (!ctx
->Visual
->DBflag
) {
494 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
497 ctx
->Pixel
.DriverReadBuffer
= GL_BACK_LEFT
;
501 if (!ctx
->Visual
->StereoFlag
) {
502 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
505 ctx
->Pixel
.DriverReadBuffer
= GL_FRONT_RIGHT
;
508 if (!ctx
->Visual
->StereoFlag
|| !ctx
->Visual
->DBflag
) {
509 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
512 ctx
->Pixel
.DriverReadBuffer
= GL_BACK_RIGHT
;
515 gl_error( ctx
, GL_INVALID_ENUM
, "glReadBuffer" );
519 ctx
->Pixel
.ReadBuffer
= mode
;
520 ctx
->NewState
|= NEW_RASTER_OPS
;
525 * GL_MESA_resize_buffers extension
528 _mesa_ResizeBuffersMESA( void )
530 GLcontext
*ctx
= gl_get_current_context();
532 GLuint buf_width
, buf_height
;
534 if (MESA_VERBOSE
& VERBOSE_API
)
535 fprintf(stderr
, "glResizeBuffersMESA\n");
537 /* ask device driver for size of output buffer */
538 (*ctx
->Driver
.GetBufferSize
)( ctx
, &buf_width
, &buf_height
);
540 /* see if size of device driver's color buffer (window) has changed */
541 if (ctx
->DrawBuffer
->Width
== (GLint
) buf_width
&&
542 ctx
->DrawBuffer
->Height
== (GLint
) buf_height
)
545 ctx
->NewState
|= NEW_RASTER_OPS
; /* to update scissor / window bounds */
547 /* save buffer size */
548 ctx
->DrawBuffer
->Width
= buf_width
;
549 ctx
->DrawBuffer
->Height
= buf_height
;
551 /* Reallocate other buffers if needed. */
552 if (ctx
->DrawBuffer
->UseSoftwareDepthBuffer
) {
553 _mesa_alloc_depth_buffer( ctx
);
555 if (ctx
->DrawBuffer
->UseSoftwareStencilBuffer
) {
556 gl_alloc_stencil_buffer( ctx
);
558 if (ctx
->DrawBuffer
->UseSoftwareAccumBuffer
) {
559 _mesa_alloc_accum_buffer( ctx
);
561 if (ctx
->Visual
->SoftwareAlpha
) {
562 gl_alloc_alpha_buffers( ctx
);