b08804a796751ec04b4e2ddce97c9f12938d7409
[mesa.git] / src / mesa / main / buffers.c
1 /* $Id: buffers.c,v 1.25 2001/01/29 20:47:39 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "accum.h"
33 #include "buffers.h"
34 #include "colormac.h"
35 #include "context.h"
36 #include "depth.h"
37 #include "enums.h"
38 #include "macros.h"
39 #include "masking.h"
40 #include "mem.h"
41 #include "stencil.h"
42 #include "state.h"
43 #include "mtypes.h"
44 #endif
45
46
47
48 void
49 _mesa_ClearIndex( GLfloat c )
50 {
51 GET_CURRENT_CONTEXT(ctx);
52 ASSERT_OUTSIDE_BEGIN_END(ctx);
53
54 if (ctx->Color.ClearIndex == (GLuint) c)
55 return;
56
57 FLUSH_VERTICES(ctx, _NEW_COLOR);
58 ctx->Color.ClearIndex = (GLuint) c;
59
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 );
63 }
64 }
65
66
67
68 void
69 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
70 {
71 GLchan tmp[4];
72 GET_CURRENT_CONTEXT(ctx);
73 ASSERT_OUTSIDE_BEGIN_END(ctx);
74
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);
79
80 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
81 return;
82
83 FLUSH_VERTICES(ctx, _NEW_COLOR);
84 COPY_CHAN4(ctx->Color.ClearColor, tmp);
85
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);
89 }
90 }
91
92
93
94 void
95 _mesa_Clear( GLbitfield mask )
96 {
97 GET_CURRENT_CONTEXT(ctx);
98 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
99
100 if (MESA_VERBOSE & VERBOSE_API)
101 fprintf(stderr, "glClear 0x%x\n", mask);
102
103 if (ctx->NewState) {
104 gl_update_state( ctx ); /* update _Xmin, etc */
105 }
106
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;
112 GLbitfield ddMask;
113 GLbitfield newMask;
114
115 /* don't clear depth buffer if depth writing disabled */
116 if (!ctx->Depth.Mask)
117 CLEAR_BITS(mask, GL_DEPTH_BUFFER_BIT);
118
119 /* Build bitmask to send to driver Clear function */
120 ddMask = mask & (GL_DEPTH_BUFFER_BIT |
121 GL_STENCIL_BUFFER_BIT |
122 GL_ACCUM_BUFFER_BIT);
123 if (mask & GL_COLOR_BUFFER_BIT) {
124 ddMask |= ctx->Color.DrawDestMask;
125 }
126
127 ASSERT(ctx->Driver.Clear);
128 ctx->Driver.Clear( ctx, ddMask, !ctx->Scissor.Enabled,
129 x, y, width, height );
130 }
131 }
132
133
134 void
135 _mesa_DrawBuffer( GLenum mode )
136 {
137 GET_CURRENT_CONTEXT(ctx);
138 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */
139
140
141 if (MESA_VERBOSE & VERBOSE_API)
142 fprintf(stderr, "glDrawBuffer %s\n", gl_lookup_enum_by_nr(mode));
143
144 switch (mode) {
145 case GL_AUX0:
146 case GL_AUX1:
147 case GL_AUX2:
148 case GL_AUX3:
149 /* AUX buffers not implemented in Mesa at this time */
150 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
151 return;
152 case GL_RIGHT:
153 if (!ctx->Visual.stereoMode) {
154 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
155 return;}
156 if (ctx->Visual.doubleBufferMode)
157 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
158 else
159 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
160 break;
161 case GL_FRONT_RIGHT:
162 if (!ctx->Visual.stereoMode) {
163 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
164 return;
165 }
166 ctx->Color.DrawDestMask = FRONT_RIGHT_BIT;
167 break;
168 case GL_BACK_RIGHT:
169 if (!ctx->Visual.stereoMode) {
170 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
171 return;
172 }
173 if (!ctx->Visual.doubleBufferMode) {
174 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
175 return;
176 }
177 ctx->Color.DrawDestMask = BACK_RIGHT_BIT;
178 break;
179 case GL_BACK_LEFT:
180 if (!ctx->Visual.doubleBufferMode) {
181 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
182 return;
183 }
184 ctx->Color.DrawDestMask = BACK_LEFT_BIT;
185 break;
186 case GL_FRONT_AND_BACK:
187 if (!ctx->Visual.doubleBufferMode) {
188 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
189 return;
190 }
191 if (ctx->Visual.stereoMode)
192 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT
193 | FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
194 else
195 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
196 break;
197 case GL_BACK:
198 if (!ctx->Visual.doubleBufferMode) {
199 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
200 return;
201 }
202 if (ctx->Visual.stereoMode)
203 ctx->Color.DrawDestMask = BACK_LEFT_BIT | BACK_RIGHT_BIT;
204 else
205 ctx->Color.DrawDestMask = BACK_LEFT_BIT;
206 break;
207 case GL_LEFT:
208 /* never an error */
209 if (ctx->Visual.doubleBufferMode)
210 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
211 else
212 ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
213 break;
214 case GL_FRONT_LEFT:
215 /* never an error */
216 ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
217 break;
218 case GL_FRONT:
219 /* never an error */
220 if (ctx->Visual.stereoMode)
221 ctx->Color.DrawDestMask = FRONT_LEFT_BIT | FRONT_RIGHT_BIT;
222 else
223 ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
224 break;
225 case GL_NONE:
226 /* never an error */
227 ctx->Color.DrawDestMask = 0;
228 break;
229 default:
230 gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
231 return;
232 }
233
234 /*
235 * Make the dest buffer mode more precise if possible
236 */
237 if (mode == GL_LEFT && !ctx->Visual.doubleBufferMode)
238 ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
239 else if (mode == GL_RIGHT && !ctx->Visual.doubleBufferMode)
240 ctx->Color.DriverDrawBuffer = GL_FRONT_RIGHT;
241 else if (mode == GL_FRONT && !ctx->Visual.stereoMode)
242 ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
243 else if (mode == GL_BACK && !ctx->Visual.stereoMode)
244 ctx->Color.DriverDrawBuffer = GL_BACK_LEFT;
245 else
246 ctx->Color.DriverDrawBuffer = mode;
247
248 /*
249 * Set current alpha buffer pointer
250 */
251 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) {
252 if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT)
253 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
254 else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT)
255 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
256 else if (ctx->Color.DriverDrawBuffer == GL_FRONT_RIGHT)
257 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
258 else if (ctx->Color.DriverDrawBuffer == GL_BACK_RIGHT)
259 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
260 }
261
262 /*
263 * If we get here there can't have been an error.
264 * Now see if device driver can implement the drawing to the target
265 * buffer(s). The driver may not be able to do GL_FRONT_AND_BACK mode
266 * for example. We'll take care of that in the core code by looping
267 * over the individual buffers.
268 */
269 ASSERT(ctx->Driver.SetDrawBuffer);
270 if ( (*ctx->Driver.SetDrawBuffer)(ctx, ctx->Color.DriverDrawBuffer) ) {
271 /* All OK, the driver will do all buffer writes */
272 ctx->Color.MultiDrawBuffer = GL_FALSE;
273 }
274 else {
275 /* We'll have to loop over the multiple draw buffer targets */
276 ctx->Color.MultiDrawBuffer = GL_TRUE;
277 /* Set drawing buffer to front for now */
278 (void) (*ctx->Driver.SetDrawBuffer)(ctx, GL_FRONT_LEFT);
279 }
280
281 ctx->Color.DrawBuffer = mode;
282 ctx->NewState |= _NEW_COLOR;
283 }
284
285
286
287 void
288 _mesa_ReadBuffer( GLenum mode )
289 {
290 GET_CURRENT_CONTEXT(ctx);
291 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
292
293 if (MESA_VERBOSE & VERBOSE_API)
294 fprintf(stderr, "glReadBuffer %s\n", gl_lookup_enum_by_nr(mode));
295
296 switch (mode) {
297 case GL_AUX0:
298 case GL_AUX1:
299 case GL_AUX2:
300 case GL_AUX3:
301 /* AUX buffers not implemented in Mesa at this time */
302 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
303 return;
304 case GL_LEFT:
305 case GL_FRONT:
306 case GL_FRONT_LEFT:
307 /* Front-Left buffer, always exists */
308 ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT;
309 break;
310 case GL_BACK:
311 case GL_BACK_LEFT:
312 /* Back-Left buffer, requires double buffering */
313 if (!ctx->Visual.doubleBufferMode) {
314 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
315 return;
316 }
317 ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT;
318 break;
319 case GL_FRONT_RIGHT:
320 case GL_RIGHT:
321 if (!ctx->Visual.stereoMode) {
322 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
323 return;
324 }
325 ctx->Pixel.DriverReadBuffer = GL_FRONT_RIGHT;
326 break;
327 case GL_BACK_RIGHT:
328 if (!ctx->Visual.stereoMode || !ctx->Visual.doubleBufferMode) {
329 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
330 return;
331 }
332 ctx->Pixel.DriverReadBuffer = GL_BACK_RIGHT;
333 break;
334 default:
335 gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
336 return;
337 }
338
339 ctx->Pixel.ReadBuffer = mode;
340 ctx->NewState |= _NEW_PIXEL;
341 }
342
343
344 /*
345 * GL_MESA_resize_buffers extension
346 */
347 void
348 _mesa_ResizeBuffersMESA( void )
349 {
350 GLcontext *ctx = _mesa_get_current_context();
351 GLuint buf_width, buf_height;
352 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
353
354
355 if (MESA_VERBOSE & VERBOSE_API)
356 fprintf(stderr, "glResizeBuffersMESA\n");
357
358 /* ask device driver for size of output buffer */
359 (*ctx->Driver.GetBufferSize)( ctx, &buf_width, &buf_height );
360
361 /* see if size of device driver's color buffer (window) has changed */
362 if (ctx->DrawBuffer->Width == (GLint) buf_width &&
363 ctx->DrawBuffer->Height == (GLint) buf_height)
364 return;
365
366 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
367
368 /* save buffer size */
369 ctx->DrawBuffer->Width = buf_width;
370 ctx->DrawBuffer->Height = buf_height;
371
372 ctx->Driver.ResizeBuffersMESA( ctx );
373 }