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