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