1 /* $Id: buffers.c,v 1.37 2002/07/09 01:22:50 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.
48 _mesa_ClearIndex( GLfloat c
)
50 GET_CURRENT_CONTEXT(ctx
);
51 ASSERT_OUTSIDE_BEGIN_END(ctx
);
53 if (ctx
->Color
.ClearIndex
== (GLuint
) c
)
56 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
57 ctx
->Color
.ClearIndex
= (GLuint
) c
;
59 if (!ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearIndex
) {
60 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
61 (*ctx
->Driver
.ClearIndex
)( ctx
, ctx
->Color
.ClearIndex
);
68 _mesa_ClearColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
71 GET_CURRENT_CONTEXT(ctx
);
72 ASSERT_OUTSIDE_BEGIN_END(ctx
);
74 UNCLAMPED_FLOAT_TO_CHAN(tmp
[0], red
);
75 UNCLAMPED_FLOAT_TO_CHAN(tmp
[1], green
);
76 UNCLAMPED_FLOAT_TO_CHAN(tmp
[2], blue
);
77 UNCLAMPED_FLOAT_TO_CHAN(tmp
[3], alpha
);
79 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
))
82 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
83 COPY_CHAN4(ctx
->Color
.ClearColor
, tmp
);
85 if (ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearColor
) {
86 /* it's OK to call glClearColor in CI mode but it should be a NOP */
87 (*ctx
->Driver
.ClearColor
)(ctx
, ctx
->Color
.ClearColor
);
94 _mesa_Clear( GLbitfield mask
)
96 GET_CURRENT_CONTEXT(ctx
);
97 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
99 if (MESA_VERBOSE
& VERBOSE_API
)
100 _mesa_debug(ctx
, "glClear 0x%x\n", mask
);
102 if (mask
& ~(GL_COLOR_BUFFER_BIT
|
103 GL_DEPTH_BUFFER_BIT
|
104 GL_STENCIL_BUFFER_BIT
|
105 GL_ACCUM_BUFFER_BIT
)) {
106 /* invalid bit set */
107 _mesa_error( ctx
, GL_INVALID_VALUE
, "glClear(mask)");
112 _mesa_update_state( ctx
); /* update _Xmin, etc */
115 if (ctx
->RenderMode
==GL_RENDER
) {
116 const GLint x
= ctx
->DrawBuffer
->_Xmin
;
117 const GLint y
= ctx
->DrawBuffer
->_Ymin
;
118 const GLint height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
119 const GLint width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
122 /* don't clear depth buffer if depth writing disabled */
123 if (!ctx
->Depth
.Mask
)
124 mask
&= ~GL_DEPTH_BUFFER_BIT
;
126 /* Build bitmask to send to driver Clear function */
127 ddMask
= mask
& (GL_DEPTH_BUFFER_BIT
|
128 GL_STENCIL_BUFFER_BIT
|
129 GL_ACCUM_BUFFER_BIT
);
130 if (mask
& GL_COLOR_BUFFER_BIT
) {
131 ddMask
|= ctx
->Color
._DrawDestMask
;
134 ASSERT(ctx
->Driver
.Clear
);
135 ctx
->Driver
.Clear( ctx
, ddMask
, (GLboolean
) !ctx
->Scissor
.Enabled
,
136 x
, y
, width
, height
);
142 _mesa_DrawBuffer( GLenum mode
)
144 GET_CURRENT_CONTEXT(ctx
);
145 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* too complex... */
148 if (MESA_VERBOSE
& VERBOSE_API
)
149 _mesa_debug(ctx
, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(mode
));
152 * Do error checking and compute the _DrawDestMask bitfield.
159 /* AUX buffers not implemented in Mesa at this time */
160 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
163 if (!ctx
->Visual
.stereoMode
) {
164 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
166 if (ctx
->Visual
.doubleBufferMode
)
167 ctx
->Color
._DrawDestMask
= FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
169 ctx
->Color
._DrawDestMask
= FRONT_RIGHT_BIT
;
172 if (!ctx
->Visual
.stereoMode
) {
173 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
176 ctx
->Color
._DrawDestMask
= FRONT_RIGHT_BIT
;
179 if (!ctx
->Visual
.stereoMode
) {
180 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
183 if (!ctx
->Visual
.doubleBufferMode
) {
184 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
187 ctx
->Color
._DrawDestMask
= BACK_RIGHT_BIT
;
190 if (!ctx
->Visual
.doubleBufferMode
) {
191 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
194 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
;
196 case GL_FRONT_AND_BACK
:
197 if (!ctx
->Visual
.doubleBufferMode
) {
198 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
201 if (ctx
->Visual
.stereoMode
)
202 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
203 | FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
205 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
208 if (!ctx
->Visual
.doubleBufferMode
) {
209 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
212 if (ctx
->Visual
.stereoMode
)
213 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
| BACK_RIGHT_BIT
;
215 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
;
219 if (ctx
->Visual
.doubleBufferMode
)
220 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
222 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;
226 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;
230 if (ctx
->Visual
.stereoMode
)
231 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
| FRONT_RIGHT_BIT
;
233 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;
237 ctx
->Color
._DrawDestMask
= 0;
240 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawBuffer" );
244 ctx
->Color
.DrawBuffer
= mode
;
245 ctx
->NewState
|= _NEW_COLOR
;
248 * Call device driver function.
250 if (ctx
->Driver
.DrawBuffer
)
251 (*ctx
->Driver
.DrawBuffer
)(ctx
, mode
);
257 _mesa_ReadBuffer( GLenum mode
)
259 GET_CURRENT_CONTEXT(ctx
);
260 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
262 if (MESA_VERBOSE
& VERBOSE_API
)
263 _mesa_debug(ctx
, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(mode
));
270 /* AUX buffers not implemented in Mesa at this time */
271 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
276 /* Front-Left buffer, always exists */
277 ctx
->Pixel
._DriverReadBuffer
= GL_FRONT_LEFT
;
281 /* Back-Left buffer, requires double buffering */
282 if (!ctx
->Visual
.doubleBufferMode
) {
283 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
286 ctx
->Pixel
._DriverReadBuffer
= GL_BACK_LEFT
;
290 if (!ctx
->Visual
.stereoMode
) {
291 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
294 ctx
->Pixel
._DriverReadBuffer
= GL_FRONT_RIGHT
;
297 if (!ctx
->Visual
.stereoMode
|| !ctx
->Visual
.doubleBufferMode
) {
298 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
301 ctx
->Pixel
._DriverReadBuffer
= GL_BACK_RIGHT
;
304 _mesa_error( ctx
, GL_INVALID_ENUM
, "glReadBuffer" );
308 ctx
->Pixel
.ReadBuffer
= mode
;
309 ctx
->NewState
|= _NEW_PIXEL
;
312 * Call device driver function.
314 if (ctx
->Driver
.ReadBuffer
)
315 (*ctx
->Driver
.ReadBuffer
)(ctx
, mode
);
320 * GL_MESA_resize_buffers extension
321 * When this function is called, we'll ask the window system how large
322 * the current window is. If it's not what we expect, we'll have to
323 * resize/reallocate the software accum/stencil/depth/alpha buffers.
326 _mesa_ResizeBuffersMESA( void )
328 GLcontext
*ctx
= _mesa_get_current_context();
330 if (MESA_VERBOSE
& VERBOSE_API
)
331 _mesa_debug(ctx
, "glResizeBuffersMESA\n");
334 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx
);
336 if (ctx
->DrawBuffer
) {
337 GLuint buf_width
, buf_height
;
338 GLframebuffer
*buffer
= ctx
->DrawBuffer
;
340 /* ask device driver for size of output buffer */
341 (*ctx
->Driver
.GetBufferSize
)( buffer
, &buf_width
, &buf_height
);
343 /* see if size of device driver's color buffer (window) has changed */
344 if (buffer
->Width
== buf_width
&& buffer
->Height
== buf_height
)
345 return; /* size is as expected */
347 buffer
->Width
= buf_width
;
348 buffer
->Height
= buf_height
;
350 ctx
->Driver
.ResizeBuffers( buffer
);
353 if (ctx
->ReadBuffer
&& ctx
->ReadBuffer
!= ctx
->DrawBuffer
) {
354 GLuint buf_width
, buf_height
;
355 GLframebuffer
*buffer
= ctx
->DrawBuffer
;
357 /* ask device driver for size of output buffer */
358 (*ctx
->Driver
.GetBufferSize
)( buffer
, &buf_width
, &buf_height
);
360 /* see if size of device driver's color buffer (window) has changed */
361 if (buffer
->Width
== buf_width
&& buffer
->Height
== buf_height
)
362 return; /* size is as expected */
364 buffer
->Width
= buf_width
;
365 buffer
->Height
= buf_height
;
367 ctx
->Driver
.ResizeBuffers( buffer
);
370 ctx
->NewState
|= _NEW_BUFFERS
; /* to update scissor / window bounds */
376 _mesa_Scissor( GLint x
, GLint y
, GLsizei width
, GLsizei height
)
378 GET_CURRENT_CONTEXT(ctx
);
379 ASSERT_OUTSIDE_BEGIN_END(ctx
);
381 if (width
< 0 || height
< 0) {
382 _mesa_error( ctx
, GL_INVALID_VALUE
, "glScissor" );
386 if (MESA_VERBOSE
& VERBOSE_API
)
387 _mesa_debug(ctx
, "glScissor %d %d %d %d\n", x
, y
, width
, height
);
389 if (x
== ctx
->Scissor
.X
&&
390 y
== ctx
->Scissor
.Y
&&
391 width
== ctx
->Scissor
.Width
&&
392 height
== ctx
->Scissor
.Height
)
395 FLUSH_VERTICES(ctx
, _NEW_SCISSOR
);
398 ctx
->Scissor
.Width
= width
;
399 ctx
->Scissor
.Height
= height
;
401 if (ctx
->Driver
.Scissor
)
402 ctx
->Driver
.Scissor( ctx
, x
, y
, width
, height
);
407 * XXX move somewhere else someday?
410 _mesa_SampleCoverageARB(GLclampf value
, GLboolean invert
)
412 GLcontext
*ctx
= _mesa_get_current_context();
414 if (!ctx
->Extensions
.ARB_multisample
) {
415 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSampleCoverageARB");
419 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx
);
420 ctx
->Multisample
.SampleCoverageValue
= (GLfloat
) CLAMP(value
, 0.0, 1.0);
421 ctx
->Multisample
.SampleCoverageInvert
= invert
;
422 ctx
->NewState
|= _NEW_MULTISAMPLE
;