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