1 /* $Id: buffers.c,v 1.42 2002/10/24 23:57:19 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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.
44 _mesa_ClearIndex( GLfloat c
)
46 GET_CURRENT_CONTEXT(ctx
);
47 ASSERT_OUTSIDE_BEGIN_END(ctx
);
49 if (ctx
->Color
.ClearIndex
== (GLuint
) c
)
52 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
53 ctx
->Color
.ClearIndex
= (GLuint
) c
;
55 if (!ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearIndex
) {
56 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
57 (*ctx
->Driver
.ClearIndex
)( ctx
, ctx
->Color
.ClearIndex
);
64 _mesa_ClearColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
67 GET_CURRENT_CONTEXT(ctx
);
68 ASSERT_OUTSIDE_BEGIN_END(ctx
);
70 tmp
[0] = CLAMP(red
, 0.0F
, 1.0F
);
71 tmp
[1] = CLAMP(green
, 0.0F
, 1.0F
);
72 tmp
[2] = CLAMP(blue
, 0.0F
, 1.0F
);
73 tmp
[3] = CLAMP(alpha
, 0.0F
, 1.0F
);
75 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
))
76 return; /* no change */
78 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
79 COPY_4V(ctx
->Color
.ClearColor
, tmp
);
81 if (ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearColor
) {
82 /* it's OK to call glClearColor in CI mode but it should be a NOP */
83 (*ctx
->Driver
.ClearColor
)(ctx
, ctx
->Color
.ClearColor
);
90 _mesa_Clear( GLbitfield mask
)
92 GET_CURRENT_CONTEXT(ctx
);
93 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
95 if (MESA_VERBOSE
& VERBOSE_API
)
96 _mesa_debug(ctx
, "glClear 0x%x\n", mask
);
98 if (mask
& ~(GL_COLOR_BUFFER_BIT
|
100 GL_STENCIL_BUFFER_BIT
|
101 GL_ACCUM_BUFFER_BIT
)) {
102 /* invalid bit set */
103 _mesa_error( ctx
, GL_INVALID_VALUE
, "glClear(mask)");
108 _mesa_update_state( ctx
); /* update _Xmin, etc */
111 if (ctx
->RenderMode
==GL_RENDER
) {
112 const GLint x
= ctx
->DrawBuffer
->_Xmin
;
113 const GLint y
= ctx
->DrawBuffer
->_Ymin
;
114 const GLint height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
115 const GLint width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
118 /* don't clear depth buffer if depth writing disabled */
119 if (!ctx
->Depth
.Mask
)
120 mask
&= ~GL_DEPTH_BUFFER_BIT
;
122 /* Build bitmask to send to driver Clear function */
123 ddMask
= mask
& (GL_DEPTH_BUFFER_BIT
|
124 GL_STENCIL_BUFFER_BIT
|
125 GL_ACCUM_BUFFER_BIT
);
126 if (mask
& GL_COLOR_BUFFER_BIT
) {
127 ddMask
|= ctx
->Color
._DrawDestMask
;
130 ASSERT(ctx
->Driver
.Clear
);
131 ctx
->Driver
.Clear( ctx
, ddMask
, (GLboolean
) !ctx
->Scissor
.Enabled
,
132 x
, y
, width
, height
);
138 _mesa_DrawBuffer( GLenum mode
)
140 GET_CURRENT_CONTEXT(ctx
);
141 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* too complex... */
143 if (MESA_VERBOSE
& VERBOSE_API
)
144 _mesa_debug(ctx
, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(mode
));
147 * Do error checking and compute the _DrawDestMask bitfield.
151 if (!ctx
->Visual
.stereoMode
) {
152 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
154 if (ctx
->Visual
.doubleBufferMode
)
155 ctx
->Color
._DrawDestMask
= FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
157 ctx
->Color
._DrawDestMask
= FRONT_RIGHT_BIT
;
160 if (!ctx
->Visual
.stereoMode
) {
161 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
164 ctx
->Color
._DrawDestMask
= FRONT_RIGHT_BIT
;
167 if (!ctx
->Visual
.stereoMode
|| !ctx
->Visual
.doubleBufferMode
) {
168 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
171 ctx
->Color
._DrawDestMask
= BACK_RIGHT_BIT
;
174 if (!ctx
->Visual
.doubleBufferMode
) {
175 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
178 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
;
180 case GL_FRONT_AND_BACK
:
181 if (!ctx
->Visual
.doubleBufferMode
) {
182 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
185 if (ctx
->Visual
.stereoMode
)
186 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
187 | FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
189 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
192 if (!ctx
->Visual
.doubleBufferMode
) {
193 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
196 if (ctx
->Visual
.stereoMode
)
197 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
| BACK_RIGHT_BIT
;
199 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
;
203 if (ctx
->Visual
.doubleBufferMode
)
204 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
206 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;
210 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;
214 if (ctx
->Visual
.stereoMode
)
215 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| FRONT_RIGHT_BIT
;
217 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;
221 ctx
->Color
._DrawDestMask
= 0;
224 if (ctx
->Const
.NumAuxBuffers
>= 1) {
225 ctx
->Color
._DrawDestMask
= AUX0_BIT
;
228 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer(GL_AUX0)" );
233 if (ctx
->Const
.NumAuxBuffers
>= 2) {
234 ctx
->Color
._DrawDestMask
= AUX1_BIT
;
237 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer(GL_AUX1)" );
242 if (ctx
->Const
.NumAuxBuffers
>= 3) {
243 ctx
->Color
._DrawDestMask
= AUX2_BIT
;
246 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer(GL_AUX2)" );
251 if (ctx
->Const
.NumAuxBuffers
>= 4) {
252 ctx
->Color
._DrawDestMask
= AUX3_BIT
;
255 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer(GL_AUX3)" );
260 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawBuffer" );
264 ctx
->Color
.DrawBuffer
= mode
;
265 ctx
->NewState
|= _NEW_COLOR
;
268 * Call device driver function.
270 if (ctx
->Driver
.DrawBuffer
)
271 (*ctx
->Driver
.DrawBuffer
)(ctx
, mode
);
277 _mesa_ReadBuffer( GLenum mode
)
279 GET_CURRENT_CONTEXT(ctx
);
280 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
282 if (MESA_VERBOSE
& VERBOSE_API
)
283 _mesa_debug(ctx
, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(mode
));
286 * Do error checking and compute ctx->Pixel._ReadSrcMask.
292 /* Front-Left buffer, always exists */
293 ctx
->Pixel
._ReadSrcMask
= FRONT_LEFT_BIT
;
297 /* Back-Left buffer, requires double buffering */
298 if (!ctx
->Visual
.doubleBufferMode
) {
299 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
302 ctx
->Pixel
._ReadSrcMask
= BACK_LEFT_BIT
;
306 if (!ctx
->Visual
.stereoMode
) {
307 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
310 ctx
->Pixel
._ReadSrcMask
= FRONT_RIGHT_BIT
;
313 if (!ctx
->Visual
.stereoMode
|| !ctx
->Visual
.doubleBufferMode
) {
314 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
317 ctx
->Pixel
._ReadSrcMask
= BACK_RIGHT_BIT
;
320 if (ctx
->Const
.NumAuxBuffers
>= 1) {
321 ctx
->Pixel
._ReadSrcMask
= AUX0_BIT
;
324 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer(GL_AUX0)" );
329 if (ctx
->Const
.NumAuxBuffers
>= 2) {
330 ctx
->Pixel
._ReadSrcMask
= AUX1_BIT
;
333 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer(GL_AUX1)" );
338 if (ctx
->Const
.NumAuxBuffers
>= 3) {
339 ctx
->Pixel
._ReadSrcMask
= AUX2_BIT
;
342 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer(GL_AUX2)" );
347 if (ctx
->Const
.NumAuxBuffers
>= 4) {
348 ctx
->Pixel
._ReadSrcMask
= AUX3_BIT
;
351 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer(GL_AUX3)" );
356 _mesa_error( ctx
, GL_INVALID_ENUM
, "glReadBuffer" );
360 ctx
->Pixel
.ReadBuffer
= mode
;
361 ctx
->NewState
|= _NEW_PIXEL
;
364 * Call device driver function.
366 if (ctx
->Driver
.ReadBuffer
)
367 (*ctx
->Driver
.ReadBuffer
)(ctx
, mode
);
372 * GL_MESA_resize_buffers extension
373 * When this function is called, we'll ask the window system how large
374 * the current window is. If it's not what we expect, we'll have to
375 * resize/reallocate the software accum/stencil/depth/alpha buffers.
378 _mesa_ResizeBuffersMESA( void )
380 GLcontext
*ctx
= _mesa_get_current_context();
382 if (MESA_VERBOSE
& VERBOSE_API
)
383 _mesa_debug(ctx
, "glResizeBuffersMESA\n");
386 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx
);
388 if (ctx
->DrawBuffer
) {
389 GLuint buf_width
, buf_height
;
390 GLframebuffer
*buffer
= ctx
->DrawBuffer
;
392 /* ask device driver for size of output buffer */
393 (*ctx
->Driver
.GetBufferSize
)( buffer
, &buf_width
, &buf_height
);
395 /* see if size of device driver's color buffer (window) has changed */
396 if (buffer
->Width
== buf_width
&& buffer
->Height
== buf_height
)
397 return; /* size is as expected */
399 buffer
->Width
= buf_width
;
400 buffer
->Height
= buf_height
;
402 ctx
->Driver
.ResizeBuffers( buffer
);
405 if (ctx
->ReadBuffer
&& ctx
->ReadBuffer
!= ctx
->DrawBuffer
) {
406 GLuint buf_width
, buf_height
;
407 GLframebuffer
*buffer
= ctx
->DrawBuffer
;
409 /* ask device driver for size of output buffer */
410 (*ctx
->Driver
.GetBufferSize
)( buffer
, &buf_width
, &buf_height
);
412 /* see if size of device driver's color buffer (window) has changed */
413 if (buffer
->Width
== buf_width
&& buffer
->Height
== buf_height
)
414 return; /* size is as expected */
416 buffer
->Width
= buf_width
;
417 buffer
->Height
= buf_height
;
419 ctx
->Driver
.ResizeBuffers( buffer
);
422 ctx
->NewState
|= _NEW_BUFFERS
; /* to update scissor / window bounds */
428 _mesa_Scissor( GLint x
, GLint y
, GLsizei width
, GLsizei height
)
430 GET_CURRENT_CONTEXT(ctx
);
431 ASSERT_OUTSIDE_BEGIN_END(ctx
);
433 if (width
< 0 || height
< 0) {
434 _mesa_error( ctx
, GL_INVALID_VALUE
, "glScissor" );
438 if (MESA_VERBOSE
& VERBOSE_API
)
439 _mesa_debug(ctx
, "glScissor %d %d %d %d\n", x
, y
, width
, height
);
441 if (x
== ctx
->Scissor
.X
&&
442 y
== ctx
->Scissor
.Y
&&
443 width
== ctx
->Scissor
.Width
&&
444 height
== ctx
->Scissor
.Height
)
447 FLUSH_VERTICES(ctx
, _NEW_SCISSOR
);
450 ctx
->Scissor
.Width
= width
;
451 ctx
->Scissor
.Height
= height
;
453 if (ctx
->Driver
.Scissor
)
454 ctx
->Driver
.Scissor( ctx
, x
, y
, width
, height
);
459 * XXX move somewhere else someday?
462 _mesa_SampleCoverageARB(GLclampf value
, GLboolean invert
)
464 GLcontext
*ctx
= _mesa_get_current_context();
466 if (!ctx
->Extensions
.ARB_multisample
) {
467 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSampleCoverageARB");
471 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx
);
472 ctx
->Multisample
.SampleCoverageValue
= (GLfloat
) CLAMP(value
, 0.0, 1.0);
473 ctx
->Multisample
.SampleCoverageInvert
= invert
;
474 ctx
->NewState
|= _NEW_MULTISAMPLE
;