mesa: Add ARB_shader_image_load_store to the extension table.
[mesa.git] / src / mesa / main / clear.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * 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 GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
183
184 if (buf >= 0) {
185 bufferMask |= 1 << buf;
186 }
187 }
188 }
189
190 if ((mask & GL_DEPTH_BUFFER_BIT)
191 && ctx->DrawBuffer->Visual.haveDepthBuffer) {
192 bufferMask |= BUFFER_BIT_DEPTH;
193 }
194
195 if ((mask & GL_STENCIL_BUFFER_BIT)
196 && ctx->DrawBuffer->Visual.haveStencilBuffer) {
197 bufferMask |= BUFFER_BIT_STENCIL;
198 }
199
200 if ((mask & GL_ACCUM_BUFFER_BIT)
201 && ctx->DrawBuffer->Visual.haveAccumBuffer) {
202 bufferMask |= BUFFER_BIT_ACCUM;
203 }
204
205 ASSERT(ctx->Driver.Clear);
206 ctx->Driver.Clear(ctx, bufferMask);
207 }
208 }
209
210
211 /** Returned by make_color_buffer_mask() for errors */
212 #define INVALID_MASK ~0x0
213
214
215 /**
216 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
217 * BUFFER_BIT_x values.
218 * Return INVALID_MASK if the drawbuffer value is invalid.
219 */
220 static GLbitfield
221 make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
222 {
223 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
224 GLbitfield mask = 0x0;
225
226 /* From the GL 4.0 specification:
227 * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is
228 * specified by passing i as the parameter drawbuffer, and value
229 * points to a four-element vector specifying the R, G, B, and A
230 * color to clear that draw buffer to. If the draw buffer is one
231 * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying
232 * multiple buffers, each selected buffer is cleared to the same
233 * value.
234 *
235 * Note that "drawbuffer" and "draw buffer" have different meaning.
236 * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's
237 * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK,
238 * etc.
239 */
240 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
241 return INVALID_MASK;
242 }
243
244 switch (ctx->DrawBuffer->ColorDrawBuffer[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 {
281 GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer];
282
283 if (buf >= 0 && att[buf].Renderbuffer) {
284 mask |= 1 << buf;
285 }
286 }
287 }
288
289 return mask;
290 }
291
292
293
294 /**
295 * New in GL 3.0
296 * Clear signed integer color buffer or stencil buffer (not depth).
297 */
298 void GLAPIENTRY
299 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
300 {
301 GET_CURRENT_CONTEXT(ctx);
302 FLUSH_VERTICES(ctx, 0);
303
304 FLUSH_CURRENT(ctx, 0);
305
306 if (ctx->NewState) {
307 _mesa_update_state( ctx );
308 }
309
310 switch (buffer) {
311 case GL_STENCIL:
312 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
313 *
314 * "ClearBuffer generates an INVALID VALUE error if buffer is
315 * COLOR and drawbuffer is less than zero, or greater than the
316 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
317 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
318 */
319 if (drawbuffer != 0) {
320 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
321 drawbuffer);
322 return;
323 }
324 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer && !ctx->RasterDiscard) {
325 /* Save current stencil clear value, set to 'value', do the
326 * stencil clear and restore the clear value.
327 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
328 * hook instead.
329 */
330 const GLuint clearSave = ctx->Stencil.Clear;
331 ctx->Stencil.Clear = *value;
332 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
333 ctx->Stencil.Clear = clearSave;
334 }
335 break;
336 case GL_COLOR:
337 {
338 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
339 if (mask == INVALID_MASK) {
340 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
341 drawbuffer);
342 return;
343 }
344 else if (mask && !ctx->RasterDiscard) {
345 union gl_color_union clearSave;
346
347 /* save color */
348 clearSave = ctx->Color.ClearColor;
349 /* set color */
350 COPY_4V(ctx->Color.ClearColor.i, value);
351 /* clear buffer(s) */
352 ctx->Driver.Clear(ctx, mask);
353 /* restore color */
354 ctx->Color.ClearColor = clearSave;
355 }
356 }
357 break;
358 case GL_DEPTH:
359 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
360 *
361 * "The result of ClearBuffer is undefined if no conversion between
362 * the type of the specified value and the type of the buffer being
363 * cleared is defined (for example, if ClearBufferiv is called for a
364 * fixed- or floating-point buffer, or if ClearBufferfv is called
365 * for a signed or unsigned integer buffer). This is not an error."
366 *
367 * In this case we take "undefined" and "not an error" to mean "ignore."
368 * Note that we still need to generate an error for the invalid
369 * drawbuffer case (see the GL_STENCIL case above).
370 */
371 if (drawbuffer != 0) {
372 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
373 drawbuffer);
374 return;
375 }
376 return;
377 default:
378 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
379 _mesa_lookup_enum_by_nr(buffer));
380 return;
381 }
382 }
383
384
385 /**
386 * New in GL 3.0
387 * Clear unsigned integer color buffer (not depth, not stencil).
388 */
389 void GLAPIENTRY
390 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
391 {
392 GET_CURRENT_CONTEXT(ctx);
393
394 FLUSH_VERTICES(ctx, 0);
395 FLUSH_CURRENT(ctx, 0);
396
397 if (ctx->NewState) {
398 _mesa_update_state( ctx );
399 }
400
401 switch (buffer) {
402 case GL_COLOR:
403 {
404 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
405 if (mask == INVALID_MASK) {
406 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
407 drawbuffer);
408 return;
409 }
410 else if (mask && !ctx->RasterDiscard) {
411 union gl_color_union clearSave;
412
413 /* save color */
414 clearSave = ctx->Color.ClearColor;
415 /* set color */
416 COPY_4V(ctx->Color.ClearColor.ui, value);
417 /* clear buffer(s) */
418 ctx->Driver.Clear(ctx, mask);
419 /* restore color */
420 ctx->Color.ClearColor = clearSave;
421 }
422 }
423 break;
424 case GL_DEPTH:
425 case GL_STENCIL:
426 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
427 *
428 * "The result of ClearBuffer is undefined if no conversion between
429 * the type of the specified value and the type of the buffer being
430 * cleared is defined (for example, if ClearBufferiv is called for a
431 * fixed- or floating-point buffer, or if ClearBufferfv is called
432 * for a signed or unsigned integer buffer). This is not an error."
433 *
434 * In this case we take "undefined" and "not an error" to mean "ignore."
435 * Even though we could do something sensible for GL_STENCIL, page 263
436 * (page 279 of the PDF) says:
437 *
438 * "Only ClearBufferiv should be used to clear stencil buffers."
439 *
440 * Note that we still need to generate an error for the invalid
441 * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv).
442 */
443 if (drawbuffer != 0) {
444 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
445 drawbuffer);
446 return;
447 }
448 return;
449 default:
450 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
451 _mesa_lookup_enum_by_nr(buffer));
452 return;
453 }
454 }
455
456
457 /**
458 * New in GL 3.0
459 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
460 */
461 void GLAPIENTRY
462 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
463 {
464 GET_CURRENT_CONTEXT(ctx);
465
466 FLUSH_VERTICES(ctx, 0);
467 FLUSH_CURRENT(ctx, 0);
468
469 if (ctx->NewState) {
470 _mesa_update_state( ctx );
471 }
472
473 switch (buffer) {
474 case GL_DEPTH:
475 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
476 *
477 * "ClearBuffer generates an INVALID VALUE error if buffer is
478 * COLOR and drawbuffer is less than zero, or greater than the
479 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
480 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
481 */
482 if (drawbuffer != 0) {
483 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
484 drawbuffer);
485 return;
486 }
487 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) {
488 /* Save current depth clear value, set to 'value', do the
489 * depth clear and restore the clear value.
490 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
491 * hook instead.
492 */
493 const GLclampd clearSave = ctx->Depth.Clear;
494 ctx->Depth.Clear = *value;
495 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
496 ctx->Depth.Clear = clearSave;
497 }
498 /* clear depth buffer to value */
499 break;
500 case GL_COLOR:
501 {
502 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
503 if (mask == INVALID_MASK) {
504 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
505 drawbuffer);
506 return;
507 }
508 else if (mask && !ctx->RasterDiscard) {
509 union gl_color_union clearSave;
510
511 /* save color */
512 clearSave = ctx->Color.ClearColor;
513 /* set color */
514 COPY_4V(ctx->Color.ClearColor.f, value);
515 /* clear buffer(s) */
516 ctx->Driver.Clear(ctx, mask);
517 /* restore color */
518 ctx->Color.ClearColor = clearSave;
519 }
520 }
521 break;
522 case GL_STENCIL:
523 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
524 *
525 * "The result of ClearBuffer is undefined if no conversion between
526 * the type of the specified value and the type of the buffer being
527 * cleared is defined (for example, if ClearBufferiv is called for a
528 * fixed- or floating-point buffer, or if ClearBufferfv is called
529 * for a signed or unsigned integer buffer). This is not an error."
530 *
531 * In this case we take "undefined" and "not an error" to mean "ignore."
532 * Note that we still need to generate an error for the invalid
533 * drawbuffer case (see the GL_DEPTH case above).
534 */
535 if (drawbuffer != 0) {
536 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
537 drawbuffer);
538 return;
539 }
540 return;
541 default:
542 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
543 _mesa_lookup_enum_by_nr(buffer));
544 return;
545 }
546 }
547
548
549 /**
550 * New in GL 3.0
551 * Clear depth/stencil buffer only.
552 */
553 void GLAPIENTRY
554 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
555 GLfloat depth, GLint stencil)
556 {
557 GET_CURRENT_CONTEXT(ctx);
558 GLbitfield mask = 0;
559
560 FLUSH_VERTICES(ctx, 0);
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 }