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