xref: /third_party/mesa3d/src/mesa/main/clear.c (revision bf215546)
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
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      st_Clear(ctx, bufferMask);
225   }
226}
227
228
229void GLAPIENTRY
230_mesa_Clear_no_error(GLbitfield mask)
231{
232   GET_CURRENT_CONTEXT(ctx);
233   clear(ctx, mask, true);
234}
235
236
237void GLAPIENTRY
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 */
258static GLbitfield
259make_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 */
345static ALWAYS_INLINE void
346clear_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
426void GLAPIENTRY
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
434void GLAPIENTRY
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 */
447void GLAPIENTRY
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 */
464static ALWAYS_INLINE void
465clear_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
519void GLAPIENTRY
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
528void GLAPIENTRY
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 */
541void GLAPIENTRY
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 */
558static ALWAYS_INLINE void
559clear_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
653void GLAPIENTRY
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
662void GLAPIENTRY
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 */
675void GLAPIENTRY
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 */
692static ALWAYS_INLINE void
693clear_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
770void GLAPIENTRY
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
779void GLAPIENTRY
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 */
793void GLAPIENTRY
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