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 "clear.h"
36 #include "context.h"
37 #include "enums.h"
38 #include "fbobject.h"
39 #include "get.h"
40 #include "macros.h"
41 #include "mtypes.h"
42 #include "state.h"
43
44
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 assert(ctx->Driver.Clear);
225 ctx->Driver.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 GET_CURRENT_CONTEXT(ctx);
242
243 if (MESA_VERBOSE & VERBOSE_API)
244 _mesa_debug(ctx, "glClear 0x%x\n", mask);
245
246 clear(ctx, mask, false);
247 }
248
249
250 /** Returned by make_color_buffer_mask() for errors */
251 #define INVALID_MASK ~0x0U
252
253
254 /**
255 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
256 * BUFFER_BIT_x values.
257 * Return INVALID_MASK if the drawbuffer value is invalid.
258 */
259 static GLbitfield
make_color_buffer_mask(struct gl_context * ctx,GLint drawbuffer)260 make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
261 {
262 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
263 GLbitfield mask = 0x0;
264
265 /* From the GL 4.0 specification:
266 * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is
267 * specified by passing i as the parameter drawbuffer, and value
268 * points to a four-element vector specifying the R, G, B, and A
269 * color to clear that draw buffer to. If the draw buffer is one
270 * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying
271 * multiple buffers, each selected buffer is cleared to the same
272 * value.
273 *
274 * Note that "drawbuffer" and "draw buffer" have different meaning.
275 * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's
276 * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK,
277 * etc.
278 */
279 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
280 return INVALID_MASK;
281 }
282
283 switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) {
284 case GL_FRONT:
285 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
286 mask |= BUFFER_BIT_FRONT_LEFT;
287 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
288 mask |= BUFFER_BIT_FRONT_RIGHT;
289 break;
290 case GL_BACK:
291 /* For GLES contexts with a single buffered configuration, we actually
292 * only have a front renderbuffer, so any clear calls to GL_BACK should
293 * affect that buffer. See draw_buffer_enum_to_bitmask for details.
294 */
295 if (_mesa_is_gles(ctx))
296 if (!ctx->DrawBuffer->Visual.doubleBufferMode)
297 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
298 mask |= BUFFER_BIT_FRONT_LEFT;
299 if (att[BUFFER_BACK_LEFT].Renderbuffer)
300 mask |= BUFFER_BIT_BACK_LEFT;
301 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
302 mask |= BUFFER_BIT_BACK_RIGHT;
303 break;
304 case GL_LEFT:
305 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
306 mask |= BUFFER_BIT_FRONT_LEFT;
307 if (att[BUFFER_BACK_LEFT].Renderbuffer)
308 mask |= BUFFER_BIT_BACK_LEFT;
309 break;
310 case GL_RIGHT:
311 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
312 mask |= BUFFER_BIT_FRONT_RIGHT;
313 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
314 mask |= BUFFER_BIT_BACK_RIGHT;
315 break;
316 case GL_FRONT_AND_BACK:
317 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
318 mask |= BUFFER_BIT_FRONT_LEFT;
319 if (att[BUFFER_BACK_LEFT].Renderbuffer)
320 mask |= BUFFER_BIT_BACK_LEFT;
321 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
322 mask |= BUFFER_BIT_FRONT_RIGHT;
323 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
324 mask |= BUFFER_BIT_BACK_RIGHT;
325 break;
326 default:
327 {
328 gl_buffer_index buf =
329 ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer];
330
331 if (buf != BUFFER_NONE && att[buf].Renderbuffer) {
332 mask |= 1 << buf;
333 }
334 }
335 }
336
337 return mask;
338 }
339
340
341
342 /**
343 * New in GL 3.0
344 * Clear signed integer color buffer or stencil buffer (not depth).
345 */
346 static ALWAYS_INLINE void
clear_bufferiv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLint * value,bool no_error)347 clear_bufferiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
348 const GLint *value, bool no_error)
349 {
350 FLUSH_VERTICES(ctx, 0, 0);
351
352 if (ctx->NewState) {
353 _mesa_update_state( ctx );
354 }
355
356 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
357 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
358 "glClearBufferiv(incomplete framebuffer)");
359 return;
360 }
361
362 switch (buffer) {
363 case GL_STENCIL:
364 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
365 *
366 * "ClearBuffer generates an INVALID VALUE error if buffer is
367 * COLOR and drawbuffer is less than zero, or greater than the
368 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
369 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
370 */
371 if (!no_error && drawbuffer != 0) {
372 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
373 drawbuffer);
374 return;
375 }
376 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer
377 && !ctx->RasterDiscard) {
378 /* Save current stencil clear value, set to 'value', do the
379 * stencil clear and restore the clear value.
380 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
381 * hook instead.
382 */
383 const GLuint clearSave = ctx->Stencil.Clear;
384 ctx->Stencil.Clear = *value;
385 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
386 ctx->Stencil.Clear = clearSave;
387 }
388 break;
389 case GL_COLOR:
390 {
391 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
392 if (!no_error && mask == INVALID_MASK) {
393 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
394 drawbuffer);
395 return;
396 }
397 else if (mask && !ctx->RasterDiscard) {
398 union gl_color_union clearSave;
399
400 /* save color */
401 clearSave = ctx->Color.ClearColor;
402 /* set color */
403 COPY_4V(ctx->Color.ClearColor.i, value);
404 /* clear buffer(s) */
405 ctx->Driver.Clear(ctx, mask);
406 /* restore color */
407 ctx->Color.ClearColor = clearSave;
408 }
409 }
410 break;
411 default:
412 if (!no_error) {
413 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
414 * of the OpenGL 4.5 spec states:
415 *
416 * "An INVALID_ENUM error is generated by ClearBufferiv and
417 * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
418 */
419 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
420 _mesa_enum_to_string(buffer));
421 }
422 return;
423 }
424 }
425
426
427 void GLAPIENTRY
_mesa_ClearBufferiv_no_error(GLenum buffer,GLint drawbuffer,const GLint * value)428 _mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value)
429 {
430 GET_CURRENT_CONTEXT(ctx);
431 clear_bufferiv(ctx, buffer, drawbuffer, value, true);
432 }
433
434
435 void GLAPIENTRY
_mesa_ClearBufferiv(GLenum buffer,GLint drawbuffer,const GLint * value)436 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
437 {
438 GET_CURRENT_CONTEXT(ctx);
439 clear_bufferiv(ctx, buffer, drawbuffer, value, false);
440 }
441
442
443 /**
444 * The ClearBuffer framework is so complicated and so riddled with the
445 * assumption that the framebuffer is bound that, for now, we will just fake
446 * direct state access clearing for the user.
447 */
448 void GLAPIENTRY
_mesa_ClearNamedFramebufferiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLint * value)449 _mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
450 GLint drawbuffer, const GLint *value)
451 {
452 GLint oldfb;
453
454 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
455 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
456 _mesa_ClearBufferiv(buffer, drawbuffer, value);
457 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
458 }
459
460
461 /**
462 * New in GL 3.0
463 * Clear unsigned integer color buffer (not depth, not stencil).
464 */
465 static ALWAYS_INLINE void
clear_bufferuiv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLuint * value,bool no_error)466 clear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
467 const GLuint *value, bool no_error)
468 {
469 FLUSH_VERTICES(ctx, 0, 0);
470
471 if (ctx->NewState) {
472 _mesa_update_state( ctx );
473 }
474
475 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
476 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION,
477 "glClearBufferuiv(incomplete framebuffer)");
478 return;
479 }
480
481 switch (buffer) {
482 case GL_COLOR:
483 {
484 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
485 if (!no_error && mask == INVALID_MASK) {
486 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
487 drawbuffer);
488 return;
489 }
490 else if (mask && !ctx->RasterDiscard) {
491 union gl_color_union clearSave;
492
493 /* save color */
494 clearSave = ctx->Color.ClearColor;
495 /* set color */
496 COPY_4V(ctx->Color.ClearColor.ui, value);
497 /* clear buffer(s) */
498 ctx->Driver.Clear(ctx, mask);
499 /* restore color */
500 ctx->Color.ClearColor = clearSave;
501 }
502 }
503 break;
504 default:
505 if (!no_error) {
506 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
507 * of the OpenGL 4.5 spec states:
508 *
509 * "An INVALID_ENUM error is generated by ClearBufferuiv and
510 * ClearNamedFramebufferuiv if buffer is not COLOR."
511 */
512 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
513 _mesa_enum_to_string(buffer));
514 }
515 return;
516 }
517 }
518
519
520 void GLAPIENTRY
_mesa_ClearBufferuiv_no_error(GLenum buffer,GLint drawbuffer,const GLuint * value)521 _mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer,
522 const GLuint *value)
523 {
524 GET_CURRENT_CONTEXT(ctx);
525 clear_bufferuiv(ctx, buffer, drawbuffer, value, true);
526 }
527
528
529 void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer,GLint drawbuffer,const GLuint * value)530 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
531 {
532 GET_CURRENT_CONTEXT(ctx);
533 clear_bufferuiv(ctx, buffer, drawbuffer, value, false);
534 }
535
536
537 /**
538 * The ClearBuffer framework is so complicated and so riddled with the
539 * assumption that the framebuffer is bound that, for now, we will just fake
540 * direct state access clearing for the user.
541 */
542 void GLAPIENTRY
_mesa_ClearNamedFramebufferuiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLuint * value)543 _mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
544 GLint drawbuffer, const GLuint *value)
545 {
546 GLint oldfb;
547
548 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
549 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
550 _mesa_ClearBufferuiv(buffer, drawbuffer, value);
551 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
552 }
553
554
555 /**
556 * New in GL 3.0
557 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
558 */
559 static ALWAYS_INLINE void
clear_bufferfv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLfloat * value,bool no_error)560 clear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
561 const GLfloat *value, bool no_error)
562 {
563 FLUSH_VERTICES(ctx, 0, 0);
564
565 if (ctx->NewState) {
566 _mesa_update_state( ctx );
567 }
568
569 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
570 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION,
571 "glClearBufferfv(incomplete framebuffer)");
572 return;
573 }
574
575 switch (buffer) {
576 case GL_DEPTH:
577 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
578 *
579 * "ClearBuffer generates an INVALID VALUE error if buffer is
580 * COLOR and drawbuffer is less than zero, or greater than the
581 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
582 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
583 */
584 if (!no_error && drawbuffer != 0) {
585 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
586 drawbuffer);
587 return;
588 }
589 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer
590 && !ctx->RasterDiscard) {
591 /* Save current depth clear value, set to 'value', do the
592 * depth clear and restore the clear value.
593 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
594 * hook instead.
595 */
596 const GLclampd clearSave = ctx->Depth.Clear;
597
598 /* Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says:
599 *
600 * "If buffer is DEPTH, drawbuffer must be zero, and value points
601 * to the single depth value to clear the depth buffer to.
602 * Clamping and type conversion for fixed-point depth buffers are
603 * performed in the same fashion as for ClearDepth."
604 */
605 const struct gl_renderbuffer *rb =
606 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
607 const bool is_float_depth =
608 _mesa_has_depth_float_channel(rb->InternalFormat);
609 ctx->Depth.Clear = is_float_depth ? *value : SATURATE(*value);
610
611 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
612 ctx->Depth.Clear = clearSave;
613 }
614 /* clear depth buffer to value */
615 break;
616 case GL_COLOR:
617 {
618 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
619 if (!no_error && mask == INVALID_MASK) {
620 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
621 drawbuffer);
622 return;
623 }
624 else if (mask && !ctx->RasterDiscard) {
625 union gl_color_union clearSave;
626
627 /* save color */
628 clearSave = ctx->Color.ClearColor;
629 /* set color */
630 COPY_4V(ctx->Color.ClearColor.f, value);
631 /* clear buffer(s) */
632 ctx->Driver.Clear(ctx, mask);
633 /* restore color */
634 ctx->Color.ClearColor = clearSave;
635 }
636 }
637 break;
638 default:
639 if (!no_error) {
640 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
641 * of the OpenGL 4.5 spec states:
642 *
643 * "An INVALID_ENUM error is generated by ClearBufferfv and
644 * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
645 */
646 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
647 _mesa_enum_to_string(buffer));
648 }
649 return;
650 }
651 }
652
653
654 void GLAPIENTRY
_mesa_ClearBufferfv_no_error(GLenum buffer,GLint drawbuffer,const GLfloat * value)655 _mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer,
656 const GLfloat *value)
657 {
658 GET_CURRENT_CONTEXT(ctx);
659 clear_bufferfv(ctx, buffer, drawbuffer, value, true);
660 }
661
662
663 void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat * value)664 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
665 {
666 GET_CURRENT_CONTEXT(ctx);
667 clear_bufferfv(ctx, buffer, drawbuffer, value, false);
668 }
669
670
671 /**
672 * The ClearBuffer framework is so complicated and so riddled with the
673 * assumption that the framebuffer is bound that, for now, we will just fake
674 * direct state access clearing for the user.
675 */
676 void GLAPIENTRY
_mesa_ClearNamedFramebufferfv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLfloat * value)677 _mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
678 GLint drawbuffer, const GLfloat *value)
679 {
680 GLint oldfb;
681
682 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
683 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
684 _mesa_ClearBufferfv(buffer, drawbuffer, value);
685 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
686 }
687
688
689 /**
690 * New in GL 3.0
691 * Clear depth/stencil buffer only.
692 */
693 static ALWAYS_INLINE void
clear_bufferfi(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil,bool no_error)694 clear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
695 GLfloat depth, GLint stencil, bool no_error)
696 {
697 GLbitfield mask = 0;
698
699 FLUSH_VERTICES(ctx, 0, 0);
700
701 if (!no_error) {
702 if (buffer != GL_DEPTH_STENCIL) {
703 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
704 _mesa_enum_to_string(buffer));
705 return;
706 }
707
708 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
709 *
710 * "ClearBuffer generates an INVALID VALUE error if buffer is
711 * COLOR and drawbuffer is less than zero, or greater than the
712 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
713 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
714 */
715 if (drawbuffer != 0) {
716 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
717 drawbuffer);
718 return;
719 }
720 }
721
722 if (ctx->RasterDiscard)
723 return;
724
725 if (ctx->NewState) {
726 _mesa_update_state( ctx );
727 }
728
729 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
730 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
731 "glClearBufferfi(incomplete framebuffer)");
732 return;
733 }
734
735 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
736 mask |= BUFFER_BIT_DEPTH;
737 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
738 mask |= BUFFER_BIT_STENCIL;
739
740 if (mask) {
741 /* save current clear values */
742 const GLclampd clearDepthSave = ctx->Depth.Clear;
743 const GLuint clearStencilSave = ctx->Stencil.Clear;
744
745 /* set new clear values
746 *
747 * Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says:
748 *
749 * "depth and stencil are the values to clear the depth and stencil
750 * buffers to, respectively. Clamping and type conversion for
751 * fixed-point depth buffers are performed in the same fashion as
752 * for ClearDepth."
753 */
754 const struct gl_renderbuffer *rb =
755 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
756 const bool has_float_depth = rb &&
757 _mesa_has_depth_float_channel(rb->InternalFormat);
758 ctx->Depth.Clear = has_float_depth ? depth : SATURATE(depth);
759 ctx->Stencil.Clear = stencil;
760
761 /* clear buffers */
762 ctx->Driver.Clear(ctx, mask);
763
764 /* restore */
765 ctx->Depth.Clear = clearDepthSave;
766 ctx->Stencil.Clear = clearStencilSave;
767 }
768 }
769
770
771 void GLAPIENTRY
_mesa_ClearBufferfi_no_error(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)772 _mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer,
773 GLfloat depth, GLint stencil)
774 {
775 GET_CURRENT_CONTEXT(ctx);
776 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true);
777 }
778
779
780 void GLAPIENTRY
_mesa_ClearBufferfi(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)781 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
782 GLfloat depth, GLint stencil)
783 {
784 GET_CURRENT_CONTEXT(ctx);
785 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false);
786 }
787
788
789 /**
790 * The ClearBuffer framework is so complicated and so riddled with the
791 * assumption that the framebuffer is bound that, for now, we will just fake
792 * direct state access clearing for the user.
793 */
794 void GLAPIENTRY
_mesa_ClearNamedFramebufferfi(GLuint framebuffer,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)795 _mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
796 GLint drawbuffer, GLfloat depth, GLint stencil)
797 {
798 GLint oldfb;
799
800 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
801 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
802 _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil);
803 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
804 }
805