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