glthread: handle ARB_vertex_attrib_binding
[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 "enums.h"
37 #include "fbobject.h"
38 #include "get.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 void GLAPIENTRY
65 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
66 {
67 GET_CURRENT_CONTEXT(ctx);
68
69 ctx->Color.ClearColor.f[0] = red;
70 ctx->Color.ClearColor.f[1] = green;
71 ctx->Color.ClearColor.f[2] = blue;
72 ctx->Color.ClearColor.f[3] = alpha;
73 }
74
75
76 /**
77 * GL_EXT_texture_integer
78 */
79 void GLAPIENTRY
80 _mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
81 {
82 GET_CURRENT_CONTEXT(ctx);
83
84 ctx->Color.ClearColor.i[0] = r;
85 ctx->Color.ClearColor.i[1] = g;
86 ctx->Color.ClearColor.i[2] = b;
87 ctx->Color.ClearColor.i[3] = a;
88 }
89
90
91 /**
92 * GL_EXT_texture_integer
93 */
94 void GLAPIENTRY
95 _mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
96 {
97 GET_CURRENT_CONTEXT(ctx);
98
99 ctx->Color.ClearColor.ui[0] = r;
100 ctx->Color.ClearColor.ui[1] = g;
101 ctx->Color.ClearColor.ui[2] = b;
102 ctx->Color.ClearColor.ui[3] = a;
103 }
104
105
106 /**
107 * Returns true if color writes are enabled for the given color attachment.
108 *
109 * Beyond checking ColorMask, this uses _mesa_format_has_color_component to
110 * ignore components that don't actually exist in the format (such as X in
111 * XRGB).
112 */
113 static bool
114 color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx)
115 {
116 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx];
117 GLuint c;
118
119 if (rb) {
120 for (c = 0; c < 4; c++) {
121 if (GET_COLORMASK_BIT(ctx->Color.ColorMask, idx, c) &&
122 _mesa_format_has_color_component(rb->Format, c)) {
123 return true;
124 }
125 }
126 }
127
128 return false;
129 }
130
131
132 /**
133 * Clear buffers.
134 *
135 * \param mask bit-mask indicating the buffers to be cleared.
136 *
137 * Flushes the vertices and verifies the parameter.
138 * If __struct gl_contextRec::NewState is set then calls _mesa_update_state()
139 * to update gl_frame_buffer::_Xmin, etc. If the rasterization mode is set to
140 * GL_RENDER then requests the driver to clear the buffers, via the
141 * dd_function_table::Clear callback.
142 */
143 static ALWAYS_INLINE void
144 clear(struct gl_context *ctx, GLbitfield mask, bool no_error)
145 {
146 FLUSH_VERTICES(ctx, 0);
147
148 if (!no_error) {
149 if (mask & ~(GL_COLOR_BUFFER_BIT |
150 GL_DEPTH_BUFFER_BIT |
151 GL_STENCIL_BUFFER_BIT |
152 GL_ACCUM_BUFFER_BIT)) {
153 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
154 return;
155 }
156
157 /* Accumulation buffers were removed in core contexts, and they never
158 * existed in OpenGL ES.
159 */
160 if ((mask & GL_ACCUM_BUFFER_BIT) != 0
161 && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) {
162 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)");
163 return;
164 }
165 }
166
167 if (ctx->NewState) {
168 _mesa_update_state( ctx ); /* update _Xmin, etc */
169 }
170
171 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
172 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
173 "glClear(incomplete framebuffer)");
174 return;
175 }
176
177 if (ctx->RasterDiscard)
178 return;
179
180 if (ctx->RenderMode == GL_RENDER) {
181 GLbitfield bufferMask;
182
183 /* don't clear depth buffer if depth writing disabled */
184 if (!ctx->Depth.Mask)
185 mask &= ~GL_DEPTH_BUFFER_BIT;
186
187 /* Build the bitmask to send to device driver's Clear function.
188 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
189 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
190 * BUFFER_BIT_COLORn flags.
191 */
192 bufferMask = 0;
193 if (mask & GL_COLOR_BUFFER_BIT) {
194 GLuint i;
195 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
196 gl_buffer_index buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
197
198 if (buf != BUFFER_NONE && color_buffer_writes_enabled(ctx, i)) {
199 bufferMask |= 1 << buf;
200 }
201 }
202 }
203
204 if ((mask & GL_DEPTH_BUFFER_BIT)
205 && ctx->DrawBuffer->Visual.depthBits > 0) {
206 bufferMask |= BUFFER_BIT_DEPTH;
207 }
208
209 if ((mask & GL_STENCIL_BUFFER_BIT)
210 && ctx->DrawBuffer->Visual.stencilBits > 0) {
211 bufferMask |= BUFFER_BIT_STENCIL;
212 }
213
214 if ((mask & GL_ACCUM_BUFFER_BIT)
215 && ctx->DrawBuffer->Visual.accumRedBits > 0) {
216 bufferMask |= BUFFER_BIT_ACCUM;
217 }
218
219 assert(ctx->Driver.Clear);
220 ctx->Driver.Clear(ctx, bufferMask);
221 }
222 }
223
224
225 void GLAPIENTRY
226 _mesa_Clear_no_error(GLbitfield mask)
227 {
228 GET_CURRENT_CONTEXT(ctx);
229 clear(ctx, mask, true);
230 }
231
232
233 void GLAPIENTRY
234 _mesa_Clear(GLbitfield mask)
235 {
236 GET_CURRENT_CONTEXT(ctx);
237
238 if (MESA_VERBOSE & VERBOSE_API)
239 _mesa_debug(ctx, "glClear 0x%x\n", mask);
240
241 clear(ctx, mask, false);
242 }
243
244
245 /** Returned by make_color_buffer_mask() for errors */
246 #define INVALID_MASK ~0x0U
247
248
249 /**
250 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
251 * BUFFER_BIT_x values.
252 * Return INVALID_MASK if the drawbuffer value is invalid.
253 */
254 static GLbitfield
255 make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
256 {
257 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
258 GLbitfield mask = 0x0;
259
260 /* From the GL 4.0 specification:
261 * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is
262 * specified by passing i as the parameter drawbuffer, and value
263 * points to a four-element vector specifying the R, G, B, and A
264 * color to clear that draw buffer to. If the draw buffer is one
265 * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying
266 * multiple buffers, each selected buffer is cleared to the same
267 * value.
268 *
269 * Note that "drawbuffer" and "draw buffer" have different meaning.
270 * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's
271 * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK,
272 * etc.
273 */
274 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
275 return INVALID_MASK;
276 }
277
278 switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) {
279 case GL_FRONT:
280 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
281 mask |= BUFFER_BIT_FRONT_LEFT;
282 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
283 mask |= BUFFER_BIT_FRONT_RIGHT;
284 break;
285 case GL_BACK:
286 /* For GLES contexts with a single buffered configuration, we actually
287 * only have a front renderbuffer, so any clear calls to GL_BACK should
288 * affect that buffer. See draw_buffer_enum_to_bitmask for details.
289 */
290 if (_mesa_is_gles(ctx))
291 if (!ctx->DrawBuffer->Visual.doubleBufferMode)
292 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
293 mask |= BUFFER_BIT_FRONT_LEFT;
294 if (att[BUFFER_BACK_LEFT].Renderbuffer)
295 mask |= BUFFER_BIT_BACK_LEFT;
296 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
297 mask |= BUFFER_BIT_BACK_RIGHT;
298 break;
299 case GL_LEFT:
300 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
301 mask |= BUFFER_BIT_FRONT_LEFT;
302 if (att[BUFFER_BACK_LEFT].Renderbuffer)
303 mask |= BUFFER_BIT_BACK_LEFT;
304 break;
305 case GL_RIGHT:
306 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
307 mask |= BUFFER_BIT_FRONT_RIGHT;
308 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
309 mask |= BUFFER_BIT_BACK_RIGHT;
310 break;
311 case GL_FRONT_AND_BACK:
312 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
313 mask |= BUFFER_BIT_FRONT_LEFT;
314 if (att[BUFFER_BACK_LEFT].Renderbuffer)
315 mask |= BUFFER_BIT_BACK_LEFT;
316 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
317 mask |= BUFFER_BIT_FRONT_RIGHT;
318 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
319 mask |= BUFFER_BIT_BACK_RIGHT;
320 break;
321 default:
322 {
323 gl_buffer_index buf =
324 ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer];
325
326 if (buf != BUFFER_NONE && att[buf].Renderbuffer) {
327 mask |= 1 << buf;
328 }
329 }
330 }
331
332 return mask;
333 }
334
335
336
337 /**
338 * New in GL 3.0
339 * Clear signed integer color buffer or stencil buffer (not depth).
340 */
341 static ALWAYS_INLINE void
342 clear_bufferiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
343 const GLint *value, bool no_error)
344 {
345 FLUSH_VERTICES(ctx, 0);
346
347 if (ctx->NewState) {
348 _mesa_update_state( ctx );
349 }
350
351 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
352 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
353 "glClearBufferiv(incomplete framebuffer)");
354 return;
355 }
356
357 switch (buffer) {
358 case GL_STENCIL:
359 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
360 *
361 * "ClearBuffer generates an INVALID VALUE error if buffer is
362 * COLOR and drawbuffer is less than zero, or greater than the
363 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
364 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
365 */
366 if (!no_error && drawbuffer != 0) {
367 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
368 drawbuffer);
369 return;
370 }
371 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer
372 && !ctx->RasterDiscard) {
373 /* Save current stencil clear value, set to 'value', do the
374 * stencil clear and restore the clear value.
375 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
376 * hook instead.
377 */
378 const GLuint clearSave = ctx->Stencil.Clear;
379 ctx->Stencil.Clear = *value;
380 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
381 ctx->Stencil.Clear = clearSave;
382 }
383 break;
384 case GL_COLOR:
385 {
386 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
387 if (!no_error && mask == INVALID_MASK) {
388 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
389 drawbuffer);
390 return;
391 }
392 else if (mask && !ctx->RasterDiscard) {
393 union gl_color_union clearSave;
394
395 /* save color */
396 clearSave = ctx->Color.ClearColor;
397 /* set color */
398 COPY_4V(ctx->Color.ClearColor.i, value);
399 /* clear buffer(s) */
400 ctx->Driver.Clear(ctx, mask);
401 /* restore color */
402 ctx->Color.ClearColor = clearSave;
403 }
404 }
405 break;
406 default:
407 if (!no_error) {
408 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
409 * of the OpenGL 4.5 spec states:
410 *
411 * "An INVALID_ENUM error is generated by ClearBufferiv and
412 * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
413 */
414 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
415 _mesa_enum_to_string(buffer));
416 }
417 return;
418 }
419 }
420
421
422 void GLAPIENTRY
423 _mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value)
424 {
425 GET_CURRENT_CONTEXT(ctx);
426 clear_bufferiv(ctx, buffer, drawbuffer, value, true);
427 }
428
429
430 void GLAPIENTRY
431 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
432 {
433 GET_CURRENT_CONTEXT(ctx);
434 clear_bufferiv(ctx, buffer, drawbuffer, value, false);
435 }
436
437
438 /**
439 * The ClearBuffer framework is so complicated and so riddled with the
440 * assumption that the framebuffer is bound that, for now, we will just fake
441 * direct state access clearing for the user.
442 */
443 void GLAPIENTRY
444 _mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
445 GLint drawbuffer, const GLint *value)
446 {
447 GLint oldfb;
448
449 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
450 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
451 _mesa_ClearBufferiv(buffer, drawbuffer, value);
452 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
453 }
454
455
456 /**
457 * New in GL 3.0
458 * Clear unsigned integer color buffer (not depth, not stencil).
459 */
460 static ALWAYS_INLINE void
461 clear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
462 const GLuint *value, bool no_error)
463 {
464 FLUSH_VERTICES(ctx, 0);
465
466 if (ctx->NewState) {
467 _mesa_update_state( ctx );
468 }
469
470 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
471 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION,
472 "glClearBufferuiv(incomplete framebuffer)");
473 return;
474 }
475
476 switch (buffer) {
477 case GL_COLOR:
478 {
479 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
480 if (!no_error && mask == INVALID_MASK) {
481 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(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.ui, value);
492 /* clear buffer(s) */
493 ctx->Driver.Clear(ctx, mask);
494 /* restore color */
495 ctx->Color.ClearColor = clearSave;
496 }
497 }
498 break;
499 default:
500 if (!no_error) {
501 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
502 * of the OpenGL 4.5 spec states:
503 *
504 * "An INVALID_ENUM error is generated by ClearBufferuiv and
505 * ClearNamedFramebufferuiv if buffer is not COLOR."
506 */
507 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
508 _mesa_enum_to_string(buffer));
509 }
510 return;
511 }
512 }
513
514
515 void GLAPIENTRY
516 _mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer,
517 const GLuint *value)
518 {
519 GET_CURRENT_CONTEXT(ctx);
520 clear_bufferuiv(ctx, buffer, drawbuffer, value, true);
521 }
522
523
524 void GLAPIENTRY
525 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
526 {
527 GET_CURRENT_CONTEXT(ctx);
528 clear_bufferuiv(ctx, buffer, drawbuffer, value, false);
529 }
530
531
532 /**
533 * The ClearBuffer framework is so complicated and so riddled with the
534 * assumption that the framebuffer is bound that, for now, we will just fake
535 * direct state access clearing for the user.
536 */
537 void GLAPIENTRY
538 _mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
539 GLint drawbuffer, const GLuint *value)
540 {
541 GLint oldfb;
542
543 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
544 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
545 _mesa_ClearBufferuiv(buffer, drawbuffer, value);
546 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
547 }
548
549
550 /**
551 * New in GL 3.0
552 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
553 */
554 static ALWAYS_INLINE void
555 clear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
556 const GLfloat *value, bool no_error)
557 {
558 FLUSH_VERTICES(ctx, 0);
559
560 if (ctx->NewState) {
561 _mesa_update_state( ctx );
562 }
563
564 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
565 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION,
566 "glClearBufferfv(incomplete framebuffer)");
567 return;
568 }
569
570 switch (buffer) {
571 case GL_DEPTH:
572 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
573 *
574 * "ClearBuffer generates an INVALID VALUE error if buffer is
575 * COLOR and drawbuffer is less than zero, or greater than the
576 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
577 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
578 */
579 if (!no_error && drawbuffer != 0) {
580 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
581 drawbuffer);
582 return;
583 }
584 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer
585 && !ctx->RasterDiscard) {
586 /* Save current depth clear value, set to 'value', do the
587 * depth clear and restore the clear value.
588 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
589 * hook instead.
590 */
591 const GLclampd clearSave = ctx->Depth.Clear;
592 ctx->Depth.Clear = *value;
593 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
594 ctx->Depth.Clear = clearSave;
595 }
596 /* clear depth buffer to value */
597 break;
598 case GL_COLOR:
599 {
600 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
601 if (!no_error && mask == INVALID_MASK) {
602 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
603 drawbuffer);
604 return;
605 }
606 else if (mask && !ctx->RasterDiscard) {
607 union gl_color_union clearSave;
608
609 /* save color */
610 clearSave = ctx->Color.ClearColor;
611 /* set color */
612 COPY_4V(ctx->Color.ClearColor.f, value);
613 /* clear buffer(s) */
614 ctx->Driver.Clear(ctx, mask);
615 /* restore color */
616 ctx->Color.ClearColor = clearSave;
617 }
618 }
619 break;
620 default:
621 if (!no_error) {
622 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
623 * of the OpenGL 4.5 spec states:
624 *
625 * "An INVALID_ENUM error is generated by ClearBufferfv and
626 * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
627 */
628 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
629 _mesa_enum_to_string(buffer));
630 }
631 return;
632 }
633 }
634
635
636 void GLAPIENTRY
637 _mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer,
638 const GLfloat *value)
639 {
640 GET_CURRENT_CONTEXT(ctx);
641 clear_bufferfv(ctx, buffer, drawbuffer, value, true);
642 }
643
644
645 void GLAPIENTRY
646 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
647 {
648 GET_CURRENT_CONTEXT(ctx);
649 clear_bufferfv(ctx, buffer, drawbuffer, value, false);
650 }
651
652
653 /**
654 * The ClearBuffer framework is so complicated and so riddled with the
655 * assumption that the framebuffer is bound that, for now, we will just fake
656 * direct state access clearing for the user.
657 */
658 void GLAPIENTRY
659 _mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
660 GLint drawbuffer, const GLfloat *value)
661 {
662 GLint oldfb;
663
664 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
665 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
666 _mesa_ClearBufferfv(buffer, drawbuffer, value);
667 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
668 }
669
670
671 /**
672 * New in GL 3.0
673 * Clear depth/stencil buffer only.
674 */
675 static ALWAYS_INLINE void
676 clear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
677 GLfloat depth, GLint stencil, bool no_error)
678 {
679 GLbitfield mask = 0;
680
681 FLUSH_VERTICES(ctx, 0);
682
683 if (!no_error) {
684 if (buffer != GL_DEPTH_STENCIL) {
685 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
686 _mesa_enum_to_string(buffer));
687 return;
688 }
689
690 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
691 *
692 * "ClearBuffer generates an INVALID VALUE error if buffer is
693 * COLOR and drawbuffer is less than zero, or greater than the
694 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
695 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
696 */
697 if (drawbuffer != 0) {
698 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
699 drawbuffer);
700 return;
701 }
702 }
703
704 if (ctx->RasterDiscard)
705 return;
706
707 if (ctx->NewState) {
708 _mesa_update_state( ctx );
709 }
710
711 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
712 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
713 "glClearBufferfi(incomplete framebuffer)");
714 return;
715 }
716
717 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
718 mask |= BUFFER_BIT_DEPTH;
719 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
720 mask |= BUFFER_BIT_STENCIL;
721
722 if (mask) {
723 /* save current clear values */
724 const GLclampd clearDepthSave = ctx->Depth.Clear;
725 const GLuint clearStencilSave = ctx->Stencil.Clear;
726
727 /* set new clear values */
728 ctx->Depth.Clear = depth;
729 ctx->Stencil.Clear = stencil;
730
731 /* clear buffers */
732 ctx->Driver.Clear(ctx, mask);
733
734 /* restore */
735 ctx->Depth.Clear = clearDepthSave;
736 ctx->Stencil.Clear = clearStencilSave;
737 }
738 }
739
740
741 void GLAPIENTRY
742 _mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer,
743 GLfloat depth, GLint stencil)
744 {
745 GET_CURRENT_CONTEXT(ctx);
746 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true);
747 }
748
749
750 void GLAPIENTRY
751 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
752 GLfloat depth, GLint stencil)
753 {
754 GET_CURRENT_CONTEXT(ctx);
755 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false);
756 }
757
758
759 /**
760 * The ClearBuffer framework is so complicated and so riddled with the
761 * assumption that the framebuffer is bound that, for now, we will just fake
762 * direct state access clearing for the user.
763 */
764 void GLAPIENTRY
765 _mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
766 GLint drawbuffer, GLfloat depth, GLint stencil)
767 {
768 GLint oldfb;
769
770 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
771 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
772 _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil);
773 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
774 }