1 /* $Id: buffers.c,v 1.27 2001/03/03 20:33:27 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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(ctx
);
54 if (ctx
->Color
.ClearIndex
== (GLuint
) c
)
57 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
58 ctx
->Color
.ClearIndex
= (GLuint
) c
;
60 if (!ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearIndex
) {
61 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
62 (*ctx
->Driver
.ClearIndex
)( ctx
, ctx
->Color
.ClearIndex
);
69 _mesa_ClearColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
72 GET_CURRENT_CONTEXT(ctx
);
73 ASSERT_OUTSIDE_BEGIN_END(ctx
);
75 UNCLAMPED_FLOAT_TO_CHAN(tmp
[0], red
);
76 UNCLAMPED_FLOAT_TO_CHAN(tmp
[1], green
);
77 UNCLAMPED_FLOAT_TO_CHAN(tmp
[2], blue
);
78 UNCLAMPED_FLOAT_TO_CHAN(tmp
[3], alpha
);
80 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
))
83 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
84 COPY_CHAN4(ctx
->Color
.ClearColor
, tmp
);
86 if (ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearColor
) {
87 /* it's OK to call glClearColor in CI mode but it should be a NOP */
88 (*ctx
->Driver
.ClearColor
)(ctx
, ctx
->Color
.ClearColor
);
95 _mesa_Clear( GLbitfield mask
)
97 GET_CURRENT_CONTEXT(ctx
);
98 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
100 if (MESA_VERBOSE
& VERBOSE_API
)
101 fprintf(stderr
, "glClear 0x%x\n", mask
);
104 _mesa_update_state( ctx
); /* update _Xmin, etc */
107 if (ctx
->RenderMode
==GL_RENDER
) {
108 const GLint x
= ctx
->DrawBuffer
->_Xmin
;
109 const GLint y
= ctx
->DrawBuffer
->_Ymin
;
110 const GLint height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
111 const GLint width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
114 /* don't clear depth buffer if depth writing disabled */
115 if (!ctx
->Depth
.Mask
)
116 CLEAR_BITS(mask
, GL_DEPTH_BUFFER_BIT
);
118 /* Build bitmask to send to driver Clear function */
119 ddMask
= mask
& (GL_DEPTH_BUFFER_BIT
|
120 GL_STENCIL_BUFFER_BIT
|
121 GL_ACCUM_BUFFER_BIT
);
122 if (mask
& GL_COLOR_BUFFER_BIT
) {
123 ddMask
|= ctx
->Color
.DrawDestMask
;
126 ASSERT(ctx
->Driver
.Clear
);
127 ctx
->Driver
.Clear( ctx
, ddMask
, !ctx
->Scissor
.Enabled
,
128 x
, y
, width
, height
);
134 _mesa_DrawBuffer( GLenum mode
)
136 GET_CURRENT_CONTEXT(ctx
);
137 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* too complex... */
140 if (MESA_VERBOSE
& VERBOSE_API
)
141 fprintf(stderr
, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(mode
));
148 /* AUX buffers not implemented in Mesa at this time */
149 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
152 if (!ctx
->Visual
.stereoMode
) {
153 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
155 if (ctx
->Visual
.doubleBufferMode
)
156 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
158 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
;
161 if (!ctx
->Visual
.stereoMode
) {
162 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
165 ctx
->Color
.DrawDestMask
= FRONT_RIGHT_BIT
;
168 if (!ctx
->Visual
.stereoMode
) {
169 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
172 if (!ctx
->Visual
.doubleBufferMode
) {
173 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
176 ctx
->Color
.DrawDestMask
= BACK_RIGHT_BIT
;
179 if (!ctx
->Visual
.doubleBufferMode
) {
180 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
183 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
;
185 case GL_FRONT_AND_BACK
:
186 if (!ctx
->Visual
.doubleBufferMode
) {
187 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
190 if (ctx
->Visual
.stereoMode
)
191 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
192 | FRONT_RIGHT_BIT
| BACK_RIGHT_BIT
;
194 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
197 if (!ctx
->Visual
.doubleBufferMode
) {
198 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawBuffer" );
201 if (ctx
->Visual
.stereoMode
)
202 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
| BACK_RIGHT_BIT
;
204 ctx
->Color
.DrawDestMask
= BACK_LEFT_BIT
;
208 if (ctx
->Visual
.doubleBufferMode
)
209 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| BACK_LEFT_BIT
;
211 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
215 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
219 if (ctx
->Visual
.stereoMode
)
220 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
| FRONT_RIGHT_BIT
;
222 ctx
->Color
.DrawDestMask
= FRONT_LEFT_BIT
;
226 ctx
->Color
.DrawDestMask
= 0;
229 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawBuffer" );
234 * Make the dest buffer mode more precise if possible
236 if (mode
== GL_LEFT
&& !ctx
->Visual
.doubleBufferMode
)
237 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_LEFT
;
238 else if (mode
== GL_RIGHT
&& !ctx
->Visual
.doubleBufferMode
)
239 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_RIGHT
;
240 else if (mode
== GL_FRONT
&& !ctx
->Visual
.stereoMode
)
241 ctx
->Color
.DriverDrawBuffer
= GL_FRONT_LEFT
;
242 else if (mode
== GL_BACK
&& !ctx
->Visual
.stereoMode
)
243 ctx
->Color
.DriverDrawBuffer
= GL_BACK_LEFT
;
245 ctx
->Color
.DriverDrawBuffer
= mode
;
248 * Set current alpha buffer pointer
250 if (ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
) {
251 if (ctx
->Color
.DriverDrawBuffer
== GL_FRONT_LEFT
)
252 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
253 else if (ctx
->Color
.DriverDrawBuffer
== GL_BACK_LEFT
)
254 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
255 else if (ctx
->Color
.DriverDrawBuffer
== GL_FRONT_RIGHT
)
256 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
257 else if (ctx
->Color
.DriverDrawBuffer
== GL_BACK_RIGHT
)
258 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
262 * If we get here there can't have been an error.
263 * Now see if device driver can implement the drawing to the target
264 * buffer(s). The driver may not be able to do GL_FRONT_AND_BACK mode
265 * for example. We'll take care of that in the core code by looping
266 * over the individual buffers.
268 ASSERT(ctx
->Driver
.SetDrawBuffer
);
269 if ( (*ctx
->Driver
.SetDrawBuffer
)(ctx
, ctx
->Color
.DriverDrawBuffer
) ) {
270 /* All OK, the driver will do all buffer writes */
271 ctx
->Color
.MultiDrawBuffer
= GL_FALSE
;
274 /* We'll have to loop over the multiple draw buffer targets */
275 ctx
->Color
.MultiDrawBuffer
= GL_TRUE
;
276 /* Set drawing buffer to front for now */
277 (void) (*ctx
->Driver
.SetDrawBuffer
)(ctx
, GL_FRONT_LEFT
);
280 ctx
->Color
.DrawBuffer
= mode
;
281 ctx
->NewState
|= _NEW_COLOR
;
287 _mesa_ReadBuffer( GLenum mode
)
289 GET_CURRENT_CONTEXT(ctx
);
290 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
292 if (MESA_VERBOSE
& VERBOSE_API
)
293 fprintf(stderr
, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(mode
));
300 /* AUX buffers not implemented in Mesa at this time */
301 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
306 /* Front-Left buffer, always exists */
307 ctx
->Pixel
.DriverReadBuffer
= GL_FRONT_LEFT
;
311 /* Back-Left buffer, requires double buffering */
312 if (!ctx
->Visual
.doubleBufferMode
) {
313 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
316 ctx
->Pixel
.DriverReadBuffer
= GL_BACK_LEFT
;
320 if (!ctx
->Visual
.stereoMode
) {
321 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
324 ctx
->Pixel
.DriverReadBuffer
= GL_FRONT_RIGHT
;
327 if (!ctx
->Visual
.stereoMode
|| !ctx
->Visual
.doubleBufferMode
) {
328 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glReadBuffer" );
331 ctx
->Pixel
.DriverReadBuffer
= GL_BACK_RIGHT
;
334 _mesa_error( ctx
, GL_INVALID_ENUM
, "glReadBuffer" );
338 ctx
->Pixel
.ReadBuffer
= mode
;
339 ctx
->NewState
|= _NEW_PIXEL
;
344 * GL_MESA_resize_buffers extension
347 _mesa_ResizeBuffersMESA( void )
349 GLcontext
*ctx
= _mesa_get_current_context();
350 GLuint buf_width
, buf_height
;
351 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx
);
354 if (MESA_VERBOSE
& VERBOSE_API
)
355 fprintf(stderr
, "glResizeBuffersMESA\n");
357 /* ask device driver for size of output buffer */
358 (*ctx
->Driver
.GetBufferSize
)( ctx
, &buf_width
, &buf_height
);
360 /* see if size of device driver's color buffer (window) has changed */
361 if (ctx
->DrawBuffer
->Width
== (GLint
) buf_width
&&
362 ctx
->DrawBuffer
->Height
== (GLint
) buf_height
)
365 ctx
->NewState
|= _NEW_BUFFERS
; /* to update scissor / window bounds */
367 /* save buffer size */
368 ctx
->DrawBuffer
->Width
= buf_width
;
369 ctx
->DrawBuffer
->Height
= buf_height
;
371 ctx
->Driver
.ResizeBuffersMESA( ctx
);