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