cfb060018c7ca5634e6f946eaad4dd51d156d28c
[mesa.git] / src / mesa / main / clear.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * \file clear.c
28 * glClearColor, glClearIndex, glClear() functions.
29 */
30
31
32
33 #include "glheader.h"
34 #include "clear.h"
35 #include "context.h"
36 #include "colormac.h"
37 #include "enums.h"
38 #include "macros.h"
39 #include "mtypes.h"
40 #include "state.h"
41
42
43
44 #if _HAVE_FULL_GL
45 void GLAPIENTRY
46 _mesa_ClearIndex( GLfloat c )
47 {
48 GET_CURRENT_CONTEXT(ctx);
49 ASSERT_OUTSIDE_BEGIN_END(ctx);
50
51 if (ctx->Color.ClearIndex == (GLuint) c)
52 return;
53
54 FLUSH_VERTICES(ctx, _NEW_COLOR);
55 ctx->Color.ClearIndex = (GLuint) c;
56 }
57 #endif
58
59
60 /**
61 * Specify the clear values for the color buffers.
62 *
63 * \param red red color component.
64 * \param green green color component.
65 * \param blue blue color component.
66 * \param alpha alpha component.
67 *
68 * \sa glClearColor().
69 *
70 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a
71 * change, flushes the vertices and notifies the driver via the
72 * dd_function_table::ClearColor callback.
73 */
74 void GLAPIENTRY
75 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
76 {
77 GLfloat tmp[4];
78 GET_CURRENT_CONTEXT(ctx);
79 ASSERT_OUTSIDE_BEGIN_END(ctx);
80
81 tmp[0] = red;
82 tmp[1] = green;
83 tmp[2] = blue;
84 tmp[3] = alpha;
85
86 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.f))
87 return; /* no change */
88
89 FLUSH_VERTICES(ctx, _NEW_COLOR);
90 COPY_4V(ctx->Color.ClearColor.f, tmp);
91 }
92
93
94 /**
95 * GL_EXT_texture_integer
96 */
97 void GLAPIENTRY
98 _mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
99 {
100 GLint tmp[4];
101 GET_CURRENT_CONTEXT(ctx);
102 ASSERT_OUTSIDE_BEGIN_END(ctx);
103
104 tmp[0] = r;
105 tmp[1] = g;
106 tmp[2] = b;
107 tmp[3] = a;
108
109 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.i))
110 return; /* no change */
111
112 FLUSH_VERTICES(ctx, _NEW_COLOR);
113 COPY_4V(ctx->Color.ClearColor.i, tmp);
114 }
115
116
117 /**
118 * GL_EXT_texture_integer
119 */
120 void GLAPIENTRY
121 _mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
122 {
123 GLuint tmp[4];
124 GET_CURRENT_CONTEXT(ctx);
125 ASSERT_OUTSIDE_BEGIN_END(ctx);
126
127 tmp[0] = r;
128 tmp[1] = g;
129 tmp[2] = b;
130 tmp[3] = a;
131
132 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.ui))
133 return; /* no change */
134
135 FLUSH_VERTICES(ctx, _NEW_COLOR);
136 COPY_4V(ctx->Color.ClearColor.ui, tmp);
137 }
138
139
140 /**
141 * Clear buffers.
142 *
143 * \param mask bit-mask indicating the buffers to be cleared.
144 *
145 * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState
146 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
147 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
148 * to clear the buffers, via the dd_function_table::Clear callback.
149 */
150 void GLAPIENTRY
151 _mesa_Clear( GLbitfield mask )
152 {
153 GET_CURRENT_CONTEXT(ctx);
154 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
155
156 FLUSH_CURRENT(ctx, 0);
157
158 if (MESA_VERBOSE & VERBOSE_API)
159 _mesa_debug(ctx, "glClear 0x%x\n", mask);
160
161 if (mask & ~(GL_COLOR_BUFFER_BIT |
162 GL_DEPTH_BUFFER_BIT |
163 GL_STENCIL_BUFFER_BIT |
164 GL_ACCUM_BUFFER_BIT)) {
165 /* invalid bit set */
166 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
167 return;
168 }
169
170 if (ctx->NewState) {
171 _mesa_update_state( ctx ); /* update _Xmin, etc */
172 }
173
174 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
175 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
176 "glClear(incomplete framebuffer)");
177 return;
178 }
179
180 if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 ||
181 ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax ||
182 ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax)
183 return;
184
185 if (ctx->RasterDiscard)
186 return;
187
188 if (ctx->RenderMode == GL_RENDER) {
189 GLbitfield bufferMask;
190
191 /* don't clear depth buffer if depth writing disabled */
192 if (!ctx->Depth.Mask)
193 mask &= ~GL_DEPTH_BUFFER_BIT;
194
195 /* Build the bitmask to send to device driver's Clear function.
196 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
197 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
198 * BUFFER_BIT_COLORn flags.
199 */
200 bufferMask = 0;
201 if (mask & GL_COLOR_BUFFER_BIT) {
202 GLuint i;
203 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
204 bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]);
205 }
206 }
207
208 if ((mask & GL_DEPTH_BUFFER_BIT)
209 && ctx->DrawBuffer->Visual.haveDepthBuffer) {
210 bufferMask |= BUFFER_BIT_DEPTH;
211 }
212
213 if ((mask & GL_STENCIL_BUFFER_BIT)
214 && ctx->DrawBuffer->Visual.haveStencilBuffer) {
215 bufferMask |= BUFFER_BIT_STENCIL;
216 }
217
218 if ((mask & GL_ACCUM_BUFFER_BIT)
219 && ctx->DrawBuffer->Visual.haveAccumBuffer) {
220 bufferMask |= BUFFER_BIT_ACCUM;
221 }
222
223 ASSERT(ctx->Driver.Clear);
224 ctx->Driver.Clear(ctx, bufferMask);
225 }
226 }
227
228
229 /** Returned by make_color_buffer_mask() for errors */
230 #define INVALID_MASK ~0x0
231
232
233 /**
234 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
235 * BUFFER_BIT_x values.
236 * Return INVALID_MASK if the drawbuffer value is invalid.
237 */
238 static GLbitfield
239 make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
240 {
241 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
242 GLbitfield mask = 0x0;
243
244 switch (drawbuffer) {
245 case GL_FRONT:
246 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
247 mask |= BUFFER_BIT_FRONT_LEFT;
248 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
249 mask |= BUFFER_BIT_FRONT_RIGHT;
250 break;
251 case GL_BACK:
252 if (att[BUFFER_BACK_LEFT].Renderbuffer)
253 mask |= BUFFER_BIT_BACK_LEFT;
254 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
255 mask |= BUFFER_BIT_BACK_RIGHT;
256 break;
257 case GL_LEFT:
258 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
259 mask |= BUFFER_BIT_FRONT_LEFT;
260 if (att[BUFFER_BACK_LEFT].Renderbuffer)
261 mask |= BUFFER_BIT_BACK_LEFT;
262 break;
263 case GL_RIGHT:
264 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
265 mask |= BUFFER_BIT_FRONT_RIGHT;
266 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
267 mask |= BUFFER_BIT_BACK_RIGHT;
268 break;
269 case GL_FRONT_AND_BACK:
270 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
271 mask |= BUFFER_BIT_FRONT_LEFT;
272 if (att[BUFFER_BACK_LEFT].Renderbuffer)
273 mask |= BUFFER_BIT_BACK_LEFT;
274 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
275 mask |= BUFFER_BIT_FRONT_RIGHT;
276 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
277 mask |= BUFFER_BIT_BACK_RIGHT;
278 break;
279 default:
280 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
281 mask = INVALID_MASK;
282 }
283 else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) {
284 mask |= (BUFFER_BIT_COLOR0 << drawbuffer);
285 }
286 }
287
288 return mask;
289 }
290
291
292
293 /**
294 * New in GL 3.0
295 * Clear signed integer color buffer or stencil buffer (not depth).
296 */
297 void GLAPIENTRY
298 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
299 {
300 GET_CURRENT_CONTEXT(ctx);
301 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
302
303 FLUSH_CURRENT(ctx, 0);
304
305 if (ctx->NewState) {
306 _mesa_update_state( ctx );
307 }
308
309 switch (buffer) {
310 case GL_STENCIL:
311 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
312 *
313 * "ClearBuffer generates an INVALID VALUE error if buffer is
314 * COLOR and drawbuffer is less than zero, or greater than the
315 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
316 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
317 */
318 if (drawbuffer != 0) {
319 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
320 drawbuffer);
321 return;
322 }
323 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer && !ctx->RasterDiscard) {
324 /* Save current stencil clear value, set to 'value', do the
325 * stencil clear and restore the clear value.
326 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
327 * hook instead.
328 */
329 const GLuint clearSave = ctx->Stencil.Clear;
330 ctx->Stencil.Clear = *value;
331 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
332 ctx->Stencil.Clear = clearSave;
333 }
334 break;
335 case GL_COLOR:
336 {
337 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
338 if (mask == INVALID_MASK) {
339 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
340 drawbuffer);
341 return;
342 }
343 else if (mask && !ctx->RasterDiscard) {
344 union gl_color_union clearSave;
345
346 /* save color */
347 clearSave = ctx->Color.ClearColor;
348 /* set color */
349 COPY_4V(ctx->Color.ClearColor.i, value);
350 /* clear buffer(s) */
351 ctx->Driver.Clear(ctx, mask);
352 /* restore color */
353 ctx->Color.ClearColor = clearSave;
354 }
355 }
356 break;
357 case GL_DEPTH:
358 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
359 *
360 * "The result of ClearBuffer is undefined if no conversion between
361 * the type of the specified value and the type of the buffer being
362 * cleared is defined (for example, if ClearBufferiv is called for a
363 * fixed- or floating-point buffer, or if ClearBufferfv is called
364 * for a signed or unsigned integer buffer). This is not an error."
365 *
366 * In this case we take "undefined" and "not an error" to mean "ignore."
367 * Note that we still need to generate an error for the invalid
368 * drawbuffer case (see the GL_STENCIL case above).
369 */
370 if (drawbuffer != 0) {
371 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
372 drawbuffer);
373 return;
374 }
375 return;
376 default:
377 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
378 _mesa_lookup_enum_by_nr(buffer));
379 return;
380 }
381 }
382
383
384 /**
385 * New in GL 3.0
386 * Clear unsigned integer color buffer (not depth, not stencil).
387 */
388 void GLAPIENTRY
389 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
390 {
391 GET_CURRENT_CONTEXT(ctx);
392 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
393
394 FLUSH_CURRENT(ctx, 0);
395
396 if (ctx->NewState) {
397 _mesa_update_state( ctx );
398 }
399
400 switch (buffer) {
401 case GL_COLOR:
402 {
403 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
404 if (mask == INVALID_MASK) {
405 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
406 drawbuffer);
407 return;
408 }
409 else if (mask && !ctx->RasterDiscard) {
410 union gl_color_union clearSave;
411
412 /* save color */
413 clearSave = ctx->Color.ClearColor;
414 /* set color */
415 COPY_4V(ctx->Color.ClearColor.ui, value);
416 /* clear buffer(s) */
417 ctx->Driver.Clear(ctx, mask);
418 /* restore color */
419 ctx->Color.ClearColor = clearSave;
420 }
421 }
422 break;
423 case GL_DEPTH:
424 case GL_STENCIL:
425 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
426 *
427 * "The result of ClearBuffer is undefined if no conversion between
428 * the type of the specified value and the type of the buffer being
429 * cleared is defined (for example, if ClearBufferiv is called for a
430 * fixed- or floating-point buffer, or if ClearBufferfv is called
431 * for a signed or unsigned integer buffer). This is not an error."
432 *
433 * In this case we take "undefined" and "not an error" to mean "ignore."
434 * Even though we could do something sensible for GL_STENCIL, page 263
435 * (page 279 of the PDF) says:
436 *
437 * "Only ClearBufferiv should be used to clear stencil buffers."
438 *
439 * Note that we still need to generate an error for the invalid
440 * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv).
441 */
442 if (drawbuffer != 0) {
443 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
444 drawbuffer);
445 return;
446 }
447 return;
448 default:
449 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
450 _mesa_lookup_enum_by_nr(buffer));
451 return;
452 }
453 }
454
455
456 /**
457 * New in GL 3.0
458 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
459 */
460 void GLAPIENTRY
461 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
462 {
463 GET_CURRENT_CONTEXT(ctx);
464 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
465
466 FLUSH_CURRENT(ctx, 0);
467
468 if (ctx->NewState) {
469 _mesa_update_state( ctx );
470 }
471
472 switch (buffer) {
473 case GL_DEPTH:
474 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
475 *
476 * "ClearBuffer generates an INVALID VALUE error if buffer is
477 * COLOR and drawbuffer is less than zero, or greater than the
478 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
479 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
480 */
481 if (drawbuffer != 0) {
482 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
483 drawbuffer);
484 return;
485 }
486 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) {
487 /* Save current depth clear value, set to 'value', do the
488 * depth clear and restore the clear value.
489 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
490 * hook instead.
491 */
492 const GLclampd clearSave = ctx->Depth.Clear;
493 ctx->Depth.Clear = *value;
494 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
495 ctx->Depth.Clear = clearSave;
496 }
497 /* clear depth buffer to value */
498 break;
499 case GL_COLOR:
500 {
501 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
502 if (mask == INVALID_MASK) {
503 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
504 drawbuffer);
505 return;
506 }
507 else if (mask && !ctx->RasterDiscard) {
508 union gl_color_union clearSave;
509
510 /* save color */
511 clearSave = ctx->Color.ClearColor;
512 /* set color */
513 COPY_4V(ctx->Color.ClearColor.f, value);
514 /* clear buffer(s) */
515 ctx->Driver.Clear(ctx, mask);
516 /* restore color */
517 ctx->Color.ClearColor = clearSave;
518 }
519 }
520 break;
521 case GL_STENCIL:
522 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
523 *
524 * "The result of ClearBuffer is undefined if no conversion between
525 * the type of the specified value and the type of the buffer being
526 * cleared is defined (for example, if ClearBufferiv is called for a
527 * fixed- or floating-point buffer, or if ClearBufferfv is called
528 * for a signed or unsigned integer buffer). This is not an error."
529 *
530 * In this case we take "undefined" and "not an error" to mean "ignore."
531 * Note that we still need to generate an error for the invalid
532 * drawbuffer case (see the GL_DEPTH case above).
533 */
534 if (drawbuffer != 0) {
535 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
536 drawbuffer);
537 return;
538 }
539 return;
540 default:
541 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
542 _mesa_lookup_enum_by_nr(buffer));
543 return;
544 }
545 }
546
547
548 /**
549 * New in GL 3.0
550 * Clear depth/stencil buffer only.
551 */
552 void GLAPIENTRY
553 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
554 GLfloat depth, GLint stencil)
555 {
556 GET_CURRENT_CONTEXT(ctx);
557 GLbitfield mask = 0;
558
559 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
560
561 FLUSH_CURRENT(ctx, 0);
562
563 if (buffer != GL_DEPTH_STENCIL) {
564 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
565 _mesa_lookup_enum_by_nr(buffer));
566 return;
567 }
568
569 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
570 *
571 * "ClearBuffer generates an INVALID VALUE error if buffer is
572 * COLOR and drawbuffer is less than zero, or greater than the
573 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
574 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
575 */
576 if (drawbuffer != 0) {
577 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
578 drawbuffer);
579 return;
580 }
581
582 if (ctx->RasterDiscard)
583 return;
584
585 if (ctx->NewState) {
586 _mesa_update_state( ctx );
587 }
588
589 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
590 mask |= BUFFER_BIT_DEPTH;
591 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
592 mask |= BUFFER_BIT_STENCIL;
593
594 if (mask) {
595 /* save current clear values */
596 const GLclampd clearDepthSave = ctx->Depth.Clear;
597 const GLuint clearStencilSave = ctx->Stencil.Clear;
598
599 /* set new clear values */
600 ctx->Depth.Clear = depth;
601 ctx->Stencil.Clear = stencil;
602
603 /* clear buffers */
604 ctx->Driver.Clear(ctx, mask);
605
606 /* restore */
607 ctx->Depth.Clear = clearDepthSave;
608 ctx->Stencil.Clear = clearStencilSave;
609 }
610 }