566afed929ace693589dc8982c4b337349e853fa
3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48 _mesa_ClearIndex( GLfloat c
)
50 GET_CURRENT_CONTEXT(ctx
);
51 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClearIndex");
52 ctx
->Color
.ClearIndex
= (GLuint
) c
;
53 if (!ctx
->Visual
->RGBAflag
) {
54 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
55 (*ctx
->Driver
.ClearIndex
)( ctx
, ctx
->Color
.ClearIndex
);
62 _mesa_ClearColor( GLclampf red
, GLclampf green
,
63 GLclampf blue
, GLclampf alpha
)
65 GET_CURRENT_CONTEXT(ctx
);
66 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClearColor");
68 ctx
->Color
.ClearColor
[0] = CLAMP( red
, 0.0F
, 1.0F
);
69 ctx
->Color
.ClearColor
[1] = CLAMP( green
, 0.0F
, 1.0F
);
70 ctx
->Color
.ClearColor
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
71 ctx
->Color
.ClearColor
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
73 if (ctx
->Visual
->RGBAflag
) {
74 GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
75 GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
76 GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
77 GLubyte a
= (GLint
) (ctx
->Color
.ClearColor
[3] * 255.0F
);
78 (*ctx
->Driver
.ClearColor
)( ctx
, r
, g
, b
, a
);
86 * Clear the color buffer when glColorMask or glIndexMask is in effect.
89 clear_color_buffer_with_masking( GLcontext
*ctx
)
91 const GLint x
= ctx
->DrawBuffer
->Xmin
;
92 const GLint y
= ctx
->DrawBuffer
->Ymin
;
93 const GLint height
= ctx
->DrawBuffer
->Ymax
- ctx
->DrawBuffer
->Ymin
+ 1;
94 const GLint width
= ctx
->DrawBuffer
->Xmax
- ctx
->DrawBuffer
->Xmin
+ 1;
96 if (ctx
->Visual
->RGBAflag
) {
98 const GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
99 const GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
100 const GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
101 const GLubyte a
= (GLint
) (ctx
->Color
.ClearColor
[3] * 255.0F
);
103 for (i
= 0; i
< height
; i
++) {
104 GLubyte rgba
[MAX_WIDTH
][4];
106 for (j
=0; j
<width
; j
++) {
112 _mesa_mask_rgba_span( ctx
, width
, x
, y
+ i
, rgba
);
113 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
+ i
,
114 (CONST
GLubyte (*)[4])rgba
, NULL
);
118 /* Color index mode */
119 GLuint span
[MAX_WIDTH
];
120 GLubyte mask
[MAX_WIDTH
];
122 MEMSET( mask
, 1, width
);
123 for (i
=0;i
<height
;i
++) {
124 for (j
=0;j
<width
;j
++) {
125 span
[j
] = ctx
->Color
.ClearIndex
;
127 _mesa_mask_index_span( ctx
, width
, x
, y
+ i
, span
);
128 (*ctx
->Driver
.WriteCI32Span
)( ctx
, width
, x
, y
+ i
, span
, mask
);
136 * Clear a color buffer without index/channel masking.
139 clear_color_buffer(GLcontext
*ctx
)
141 const GLint x
= ctx
->DrawBuffer
->Xmin
;
142 const GLint y
= ctx
->DrawBuffer
->Ymin
;
143 const GLint height
= ctx
->DrawBuffer
->Ymax
- ctx
->DrawBuffer
->Ymin
+ 1;
144 const GLint width
= ctx
->DrawBuffer
->Xmax
- ctx
->DrawBuffer
->Xmin
+ 1;
146 if (ctx
->Visual
->RGBAflag
) {
148 const GLubyte r
= (GLint
) (ctx
->Color
.ClearColor
[0] * 255.0F
);
149 const GLubyte g
= (GLint
) (ctx
->Color
.ClearColor
[1] * 255.0F
);
150 const GLubyte b
= (GLint
) (ctx
->Color
.ClearColor
[2] * 255.0F
);
151 const GLubyte a
= (GLint
) (ctx
->Color
.ClearColor
[3] * 255.0F
);
152 GLubyte span
[MAX_WIDTH
][4];
155 ASSERT(!ctx
->Color
.SWmasking
);
157 for (i
= 0; i
< width
; i
++) {
163 for (i
= 0; i
< height
; i
++) {
164 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
+ i
,
165 (CONST
GLubyte (*)[4]) span
, NULL
);
169 /* Color index mode */
170 ASSERT(ctx
->Color
.IndexMask
== ~0);
171 if (ctx
->Visual
->IndexBits
== 8) {
173 GLubyte span
[MAX_WIDTH
];
175 MEMSET(span
, ctx
->Color
.ClearIndex
, width
);
176 for (i
= 0; i
< height
; i
++) {
177 (*ctx
->Driver
.WriteCI8Span
)( ctx
, width
, x
, y
+ i
, span
, NULL
);
181 /* non 8-bit clear */
182 GLuint span
[MAX_WIDTH
];
184 for (i
= 0; i
< width
; i
++) {
185 span
[i
] = ctx
->Color
.ClearIndex
;
187 for (i
= 0; i
< height
; i
++) {
188 (*ctx
->Driver
.WriteCI32Span
)( ctx
, width
, x
, y
+ i
, span
, NULL
);
197 * Clear the front/back/left/right color buffers.
198 * This function is usually only called if we need to clear the
199 * buffers with masking.
202 clear_color_buffers(GLcontext
*ctx
)
206 /* loop over four possible dest color buffers */
207 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
208 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
209 if (bufferBit
== FRONT_LEFT_BIT
) {
210 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
212 else if (bufferBit
== FRONT_RIGHT_BIT
) {
213 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
215 else if (bufferBit
== BACK_LEFT_BIT
) {
216 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
219 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
222 if (ctx
->Color
.SWmasking
) {
223 clear_color_buffer_with_masking(ctx
);
226 clear_color_buffer(ctx
);
231 /* restore default dest buffer */
232 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
238 _mesa_Clear( GLbitfield mask
)
240 GET_CURRENT_CONTEXT(ctx
);
242 GLdouble t0
= gl_time();
244 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClear");
246 if (MESA_VERBOSE
& VERBOSE_API
)
247 fprintf(stderr
, "glClear 0x%x\n", mask
);
250 gl_update_state( ctx
);
253 if (ctx
->RenderMode
==GL_RENDER
) {
254 const GLint x
= ctx
->DrawBuffer
->Xmin
;
255 const GLint y
= ctx
->DrawBuffer
->Ymin
;
256 const GLint height
= ctx
->DrawBuffer
->Ymax
- ctx
->DrawBuffer
->Ymin
+ 1;
257 const GLint width
= ctx
->DrawBuffer
->Xmax
- ctx
->DrawBuffer
->Xmin
+ 1;
261 /* don't clear depth buffer if depth writing disabled */
262 if (!ctx
->Depth
.Mask
)
263 CLEAR_BITS(mask
, GL_DEPTH_BUFFER_BIT
);
265 /* Build bitmask to send to driver Clear function */
266 ddMask
= mask
& (GL_DEPTH_BUFFER_BIT
|
267 GL_STENCIL_BUFFER_BIT
|
268 GL_ACCUM_BUFFER_BIT
);
269 if (mask
& GL_COLOR_BUFFER_BIT
) {
270 ddMask
|= ctx
->Color
.DrawDestMask
;
273 ASSERT(ctx
->Driver
.Clear
);
274 newMask
= (*ctx
->Driver
.Clear
)( ctx
, ddMask
, !ctx
->Scissor
.Enabled
,
275 x
, y
, width
, height
);
279 GLbitfield legalBits
= DD_FRONT_LEFT_BIT
|
286 assert((newMask
& (~legalBits
)) == 0);
290 /* do software clearing here */
292 if (newMask
& ctx
->Color
.DrawDestMask
) clear_color_buffers(ctx
);
293 if (newMask
& GL_DEPTH_BUFFER_BIT
) _mesa_clear_depth_buffer(ctx
);
294 if (newMask
& GL_ACCUM_BUFFER_BIT
) _mesa_clear_accum_buffer(ctx
);
295 if (newMask
& GL_STENCIL_BUFFER_BIT
) _mesa_clear_stencil_buffer(ctx
);
298 /* clear software-based alpha buffer(s) */
299 if ( (mask
& GL_COLOR_BUFFER_BIT
)
300 && ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
301 && ctx
->Color
.ColorMask
[ACOMP
]) {
302 _mesa_clear_alpha_buffers( ctx
);
306 ctx
->ClearTime
+= gl_time() - t0
;
314 _mesa_DrawBuffer( GLenum mode
)
316 GET_CURRENT_CONTEXT(ctx
);
317 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawBuffer");
319 if (MESA_VERBOSE
& VERBOSE_API
)
320 fprintf(stderr
, "glDrawBuffer %s\n", gl_lookup_enum_by_nr(mode
));
327 /* AUX buffers not implemented in Mesa at this time */
328 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
331 if (!ctx
->Visual
->StereoFlag
) {
332 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
335 if (ctx
->Visual
->DBflag
)
336 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
338 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
;
341 if (!ctx
->Visual
->StereoFlag
) {
342 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
345 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
;
348 if (!ctx
->Visual
->StereoFlag
) {
349 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
352 if (!ctx
->Visual
->DBflag
) {
353 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
356 ctx
->Color
.DrawDestMask
= BACK_RIGHT_BIT
;
359 if (!ctx
->Visual
->DBflag
) {
360 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
363 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
;
365 case GL_FRONT_AND_BACK
:
366 if (!ctx
->Visual
->DBflag
) {
367 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
370 if (ctx
->Visual
->StereoFlag
)
371 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
372 | FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
374 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
377 if (!ctx
->Visual
->DBflag
) {
378 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
381 if (ctx
->Visual
->StereoFlag
)
382 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
| BACK_RIGHT_BIT
;
384 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
;
388 if (ctx
->Visual
->DBflag
)
389 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
391 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
395 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
399 if (ctx
->Visual
->StereoFlag
)
400 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| FRONT_RIGHT_BIT
;
402 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
406 ctx
->Color
.DrawDestMask
= 0;
409 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawBuffer" );
414 * Make the dest buffer mode more precise if possible
416 if (mode
== GL_LEFT
&& !ctx
->Visual
->DBflag
)
417 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_LEFT
;
418 else if (mode
== GL_RIGHT
&& !ctx
->Visual
->DBflag
)
419 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_RIGHT
;
420 else if (mode
== GL_FRONT
&& !ctx
->Visual
->StereoFlag
)
421 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_LEFT
;
422 else if (mode
== GL_BACK
&& !ctx
->Visual
->StereoFlag
)
423 ctx
->Color
.DriverDrawBuffer
= GL_BACK_LEFT
;
425 ctx
->Color
.DriverDrawBuffer
= mode
;
428 * Set current alpha buffer pointer
430 if (ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
) {
431 if (ctx
->Color
.DriverDrawBuffer
== GL_FRONT_LEFT
)
432 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
433 else if (ctx
->Color
.DriverDrawBuffer
== GL_BACK_LEFT
)
434 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
435 else if (ctx
->Color
.DriverDrawBuffer
== GL_FRONT_RIGHT
)
436 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
437 else if (ctx
->Color
.DriverDrawBuffer
== GL_BACK_RIGHT
)
438 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
442 * If we get here there can't have been an error.
443 * Now see if device driver can implement the drawing to the target
444 * buffer(s). The driver may not be able to do GL_FRONT_AND_BACK mode
445 * for example. We'll take care of that in the core code by looping
446 * over the individual buffers.
448 ASSERT(ctx
->Driver
.SetDrawBuffer
);
449 if ( (*ctx
->Driver
.SetDrawBuffer
)(ctx
, ctx
->Color
.DriverDrawBuffer
) ) {
450 /* All OK, the driver will do all buffer writes */
451 ctx
->Color
.MultiDrawBuffer
= GL_FALSE
;
454 /* We'll have to loop over the multiple draw buffer targets */
455 ctx
->Color
.MultiDrawBuffer
= GL_TRUE
;
456 /* Set drawing buffer to front for now */
457 (void) (*ctx
->Driver
.SetDrawBuffer
)(ctx
, GL_FRONT_LEFT
);
460 ctx
->Color
.DrawBuffer
= mode
;
461 ctx
->NewState
|= NEW_RASTER_OPS
;
467 _mesa_ReadBuffer( GLenum mode
)
469 GET_CURRENT_CONTEXT(ctx
);
470 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glReadBuffer");
472 if (MESA_VERBOSE
& VERBOSE_API
)
473 fprintf(stderr
, "glReadBuffer %s\n", gl_lookup_enum_by_nr(mode
));
480 /* AUX buffers not implemented in Mesa at this time */
481 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
486 /* Front-Left buffer, always exists */
487 ctx
->Pixel
.DriverReadBuffer
= GL_FRONT_LEFT
;
491 /* Back-Left buffer, requires double buffering */
492 if (!ctx
->Visual
->DBflag
) {
493 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
496 ctx
->Pixel
.DriverReadBuffer
= GL_BACK_LEFT
;
500 if (!ctx
->Visual
->StereoFlag
) {
501 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
504 ctx
->Pixel
.DriverReadBuffer
= GL_FRONT_RIGHT
;
507 if (!ctx
->Visual
->StereoFlag
|| !ctx
->Visual
->DBflag
) {
508 gl_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
511 ctx
->Pixel
.DriverReadBuffer
= GL_BACK_RIGHT
;
514 gl_error( ctx
, GL_INVALID_ENUM
, "glReadBuffer" );
518 ctx
->Pixel
.ReadBuffer
= mode
;
519 ctx
->NewState
|= NEW_RASTER_OPS
;
524 * GL_MESA_resize_buffers extension
527 _mesa_ResizeBuffersMESA( void )
529 GLcontext
*ctx
= gl_get_current_context();
531 GLuint buf_width
, buf_height
;
533 if (MESA_VERBOSE
& VERBOSE_API
)
534 fprintf(stderr
, "glResizeBuffersMESA\n");
536 /* ask device driver for size of output buffer */
537 (*ctx
->Driver
.GetBufferSize
)( ctx
, &buf_width
, &buf_height
);
539 /* see if size of device driver's color buffer (window) has changed */
540 if (ctx
->DrawBuffer
->Width
== (GLint
) buf_width
&&
541 ctx
->DrawBuffer
->Height
== (GLint
) buf_height
)
544 ctx
->NewState
|= NEW_RASTER_OPS
; /* to update scissor / window bounds */
546 /* save buffer size */
547 ctx
->DrawBuffer
->Width
= buf_width
;
548 ctx
->DrawBuffer
->Height
= buf_height
;
550 /* Reallocate other buffers if needed. */
551 if (ctx
->DrawBuffer
->UseSoftwareDepthBuffer
) {
552 _mesa_alloc_depth_buffer( ctx
);
554 if (ctx
->DrawBuffer
->UseSoftwareStencilBuffer
) {
555 _mesa_alloc_stencil_buffer( ctx
);
557 if (ctx
->DrawBuffer
->UseSoftwareAccumBuffer
) {
558 _mesa_alloc_accum_buffer( ctx
);
560 if (ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
) {
561 _mesa_alloc_alpha_buffers( ctx
);