• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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