undo previous check-in (check if ctx->Color.DrawBuffer == mode)
[mesa.git] / src / mesa / main / buffers.c
1 /* $Id: buffers.c,v 1.40 2002/10/11 15:17:12 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 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 "mem.h"
40 #include "stencil.h"
41 #include "state.h"
42 #include "mtypes.h"
43 #endif
44
45
46
47 void
48 _mesa_ClearIndex( GLfloat c )
49 {
50 GET_CURRENT_CONTEXT(ctx);
51 ASSERT_OUTSIDE_BEGIN_END(ctx);
52
53 if (ctx->Color.ClearIndex == (GLuint) c)
54 return;
55
56 FLUSH_VERTICES(ctx, _NEW_COLOR);
57 ctx->Color.ClearIndex = (GLuint) c;
58
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 );
62 }
63 }
64
65
66
67 void
68 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
69 {
70 GLfloat tmp[4];
71 GET_CURRENT_CONTEXT(ctx);
72 ASSERT_OUTSIDE_BEGIN_END(ctx);
73
74 tmp[0] = CLAMP(red, 0.0F, 1.0F);
75 tmp[1] = CLAMP(green, 0.0F, 1.0F);
76 tmp[2] = CLAMP(blue, 0.0F, 1.0F);
77 tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
78
79 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
80 return; /* no change */
81
82 FLUSH_VERTICES(ctx, _NEW_COLOR);
83 COPY_4V(ctx->Color.ClearColor, tmp);
84
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);
88 }
89 }
90
91
92
93 void
94 _mesa_Clear( GLbitfield mask )
95 {
96 GET_CURRENT_CONTEXT(ctx);
97 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
98
99 if (MESA_VERBOSE & VERBOSE_API)
100 _mesa_debug(ctx, "glClear 0x%x\n", mask);
101
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)");
108 return;
109 }
110
111 if (ctx->NewState) {
112 _mesa_update_state( ctx ); /* update _Xmin, etc */
113 }
114
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;
120 GLbitfield ddMask;
121
122 /* don't clear depth buffer if depth writing disabled */
123 if (!ctx->Depth.Mask)
124 mask &= ~GL_DEPTH_BUFFER_BIT;
125
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;
132 }
133
134 ASSERT(ctx->Driver.Clear);
135 ctx->Driver.Clear( ctx, ddMask, (GLboolean) !ctx->Scissor.Enabled,
136 x, y, width, height );
137 }
138 }
139
140
141 void
142 _mesa_DrawBuffer( GLenum mode )
143 {
144 GET_CURRENT_CONTEXT(ctx);
145 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */
146
147 if (MESA_VERBOSE & VERBOSE_API)
148 _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(mode));
149
150 /*
151 * Do error checking and compute the _DrawDestMask bitfield.
152 */
153 switch (mode) {
154 case GL_AUX0:
155 case GL_AUX1:
156 case GL_AUX2:
157 case GL_AUX3:
158 /* AUX buffers not implemented in Mesa at this time */
159 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
160 return;
161 case GL_RIGHT:
162 if (!ctx->Visual.stereoMode) {
163 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
164 return;}
165 if (ctx->Visual.doubleBufferMode)
166 ctx->Color._DrawDestMask = FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
167 else
168 ctx->Color._DrawDestMask = FRONT_RIGHT_BIT;
169 break;
170 case GL_FRONT_RIGHT:
171 if (!ctx->Visual.stereoMode) {
172 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
173 return;
174 }
175 ctx->Color._DrawDestMask = FRONT_RIGHT_BIT;
176 break;
177 case GL_BACK_RIGHT:
178 if (!ctx->Visual.stereoMode) {
179 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
180 return;
181 }
182 if (!ctx->Visual.doubleBufferMode) {
183 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
184 return;
185 }
186 ctx->Color._DrawDestMask = BACK_RIGHT_BIT;
187 break;
188 case GL_BACK_LEFT:
189 if (!ctx->Visual.doubleBufferMode) {
190 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
191 return;
192 }
193 ctx->Color._DrawDestMask = BACK_LEFT_BIT;
194 break;
195 case GL_FRONT_AND_BACK:
196 if (!ctx->Visual.doubleBufferMode) {
197 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
198 return;
199 }
200 if (ctx->Visual.stereoMode)
201 ctx->Color._DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT
202 | FRONT_RIGHT_BIT | BACK_RIGHT_BIT;
203 else
204 ctx->Color._DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
205 break;
206 case GL_BACK:
207 if (!ctx->Visual.doubleBufferMode) {
208 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
209 return;
210 }
211 if (ctx->Visual.stereoMode)
212 ctx->Color._DrawDestMask = BACK_LEFT_BIT | BACK_RIGHT_BIT;
213 else
214 ctx->Color._DrawDestMask = BACK_LEFT_BIT;
215 break;
216 case GL_LEFT:
217 /* never an error */
218 if (ctx->Visual.doubleBufferMode)
219 ctx->Color._DrawDestMask = FRONT_LEFT_BIT | BACK_LEFT_BIT;
220 else
221 ctx->Color._DrawDestMask = FRONT_LEFT_BIT;
222 break;
223 case GL_FRONT_LEFT:
224 /* never an error */
225 ctx->Color._DrawDestMask = FRONT_LEFT_BIT;
226 break;
227 case GL_FRONT:
228 /* never an error */
229 if (ctx->Visual.stereoMode)
230 ctx->Color._DrawDestMask = FRONT_LEFT_BIT | FRONT_RIGHT_BIT;
231 else
232 ctx->Color._DrawDestMask = FRONT_LEFT_BIT;
233 break;
234 case GL_NONE:
235 /* never an error */
236 ctx->Color._DrawDestMask = 0;
237 break;
238 default:
239 _mesa_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
240 return;
241 }
242
243 ctx->Color.DrawBuffer = mode;
244 ctx->NewState |= _NEW_COLOR;
245
246 /*
247 * Call device driver function.
248 */
249 if (ctx->Driver.DrawBuffer)
250 (*ctx->Driver.DrawBuffer)(ctx, mode);
251 }
252
253
254
255 void
256 _mesa_ReadBuffer( GLenum mode )
257 {
258 GET_CURRENT_CONTEXT(ctx);
259 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
260
261 if (MESA_VERBOSE & VERBOSE_API)
262 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(mode));
263
264 if (ctx->Pixel.ReadBuffer == mode)
265 return; /* no change */
266
267 switch (mode) {
268 case GL_AUX0:
269 case GL_AUX1:
270 case GL_AUX2:
271 case GL_AUX3:
272 /* AUX buffers not implemented in Mesa at this time */
273 _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
274 return;
275 case GL_LEFT:
276 case GL_FRONT:
277 case GL_FRONT_LEFT:
278 /* Front-Left buffer, always exists */
279 ctx->Pixel._DriverReadBuffer = GL_FRONT_LEFT;
280 break;
281 case GL_BACK:
282 case GL_BACK_LEFT:
283 /* Back-Left buffer, requires double buffering */
284 if (!ctx->Visual.doubleBufferMode) {
285 _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
286 return;
287 }
288 ctx->Pixel._DriverReadBuffer = GL_BACK_LEFT;
289 break;
290 case GL_FRONT_RIGHT:
291 case GL_RIGHT:
292 if (!ctx->Visual.stereoMode) {
293 _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
294 return;
295 }
296 ctx->Pixel._DriverReadBuffer = GL_FRONT_RIGHT;
297 break;
298 case GL_BACK_RIGHT:
299 if (!ctx->Visual.stereoMode || !ctx->Visual.doubleBufferMode) {
300 _mesa_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
301 return;
302 }
303 ctx->Pixel._DriverReadBuffer = GL_BACK_RIGHT;
304 break;
305 default:
306 _mesa_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
307 return;
308 }
309
310 ctx->Pixel.ReadBuffer = mode;
311 ctx->NewState |= _NEW_PIXEL;
312
313 /*
314 * Call device driver function.
315 */
316 if (ctx->Driver.ReadBuffer)
317 (*ctx->Driver.ReadBuffer)(ctx, mode);
318 }
319
320
321 /*
322 * GL_MESA_resize_buffers extension
323 * When this function is called, we'll ask the window system how large
324 * the current window is. If it's not what we expect, we'll have to
325 * resize/reallocate the software accum/stencil/depth/alpha buffers.
326 */
327 void
328 _mesa_ResizeBuffersMESA( void )
329 {
330 GLcontext *ctx = _mesa_get_current_context();
331
332 if (MESA_VERBOSE & VERBOSE_API)
333 _mesa_debug(ctx, "glResizeBuffersMESA\n");
334
335 if (ctx) {
336 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
337
338 if (ctx->DrawBuffer) {
339 GLuint buf_width, buf_height;
340 GLframebuffer *buffer = ctx->DrawBuffer;
341
342 /* ask device driver for size of output buffer */
343 (*ctx->Driver.GetBufferSize)( buffer, &buf_width, &buf_height );
344
345 /* see if size of device driver's color buffer (window) has changed */
346 if (buffer->Width == buf_width && buffer->Height == buf_height)
347 return; /* size is as expected */
348
349 buffer->Width = buf_width;
350 buffer->Height = buf_height;
351
352 ctx->Driver.ResizeBuffers( buffer );
353 }
354
355 if (ctx->ReadBuffer && ctx->ReadBuffer != ctx->DrawBuffer) {
356 GLuint buf_width, buf_height;
357 GLframebuffer *buffer = ctx->DrawBuffer;
358
359 /* ask device driver for size of output buffer */
360 (*ctx->Driver.GetBufferSize)( buffer, &buf_width, &buf_height );
361
362 /* see if size of device driver's color buffer (window) has changed */
363 if (buffer->Width == buf_width && buffer->Height == buf_height)
364 return; /* size is as expected */
365
366 buffer->Width = buf_width;
367 buffer->Height = buf_height;
368
369 ctx->Driver.ResizeBuffers( buffer );
370 }
371
372 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
373 }
374 }
375
376
377 void
378 _mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
379 {
380 GET_CURRENT_CONTEXT(ctx);
381 ASSERT_OUTSIDE_BEGIN_END(ctx);
382
383 if (width < 0 || height < 0) {
384 _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" );
385 return;
386 }
387
388 if (MESA_VERBOSE & VERBOSE_API)
389 _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height);
390
391 if (x == ctx->Scissor.X &&
392 y == ctx->Scissor.Y &&
393 width == ctx->Scissor.Width &&
394 height == ctx->Scissor.Height)
395 return;
396
397 FLUSH_VERTICES(ctx, _NEW_SCISSOR);
398 ctx->Scissor.X = x;
399 ctx->Scissor.Y = y;
400 ctx->Scissor.Width = width;
401 ctx->Scissor.Height = height;
402
403 if (ctx->Driver.Scissor)
404 ctx->Driver.Scissor( ctx, x, y, width, height );
405 }
406
407
408 /*
409 * XXX move somewhere else someday?
410 */
411 void
412 _mesa_SampleCoverageARB(GLclampf value, GLboolean invert)
413 {
414 GLcontext *ctx = _mesa_get_current_context();
415
416 if (!ctx->Extensions.ARB_multisample) {
417 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB");
418 return;
419 }
420
421 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
422 ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0);
423 ctx->Multisample.SampleCoverageInvert = invert;
424 ctx->NewState |= _NEW_MULTISAMPLE;
425 }
426