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