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
46void GLAPIENTRY
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 */
66void GLAPIENTRY
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 */
82void GLAPIENTRY
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 */
98void GLAPIENTRY
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 */
118static bool
119color_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 */
148static ALWAYS_INLINE void
149clear(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
230void GLAPIENTRY
231_mesa_Clear_no_error(GLbitfield mask)
232{
233   GET_CURRENT_CONTEXT(ctx);
234   clear(ctx, mask, true);
235}
236
237
238void GLAPIENTRY
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 */
259static GLbitfield
260make_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 */
346static ALWAYS_INLINE void
347clear_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
427void GLAPIENTRY
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
435void GLAPIENTRY
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 */
448void GLAPIENTRY
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 */
465static ALWAYS_INLINE void
466clear_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
520void GLAPIENTRY
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
529void GLAPIENTRY
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 */
542void GLAPIENTRY
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 */
559static ALWAYS_INLINE void
560clear_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
654void GLAPIENTRY
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
663void GLAPIENTRY
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 */
676void GLAPIENTRY
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 */
693static ALWAYS_INLINE void
694clear_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
771void GLAPIENTRY
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
780void GLAPIENTRY
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 */
794void GLAPIENTRY
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