• 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 "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 
45 void GLAPIENTRY
_mesa_ClearIndex(GLfloat c)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  */
64 void GLAPIENTRY
_mesa_ClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)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  */
79 void GLAPIENTRY
_mesa_ClearColorIiEXT(GLint r,GLint g,GLint b,GLint a)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  */
94 void GLAPIENTRY
_mesa_ClearColorIuiEXT(GLuint r,GLuint g,GLuint b,GLuint a)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  */
113 static bool
color_buffer_writes_enabled(const struct gl_context * ctx,unsigned idx)114 color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx)
115 {
116    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx];
117    GLuint c;
118    GLubyte colorMask = 0;
119 
120    if (rb) {
121       for (c = 0; c < 4; c++) {
122          if (_mesa_format_has_color_component(rb->Format, c))
123             colorMask |= ctx->Color.ColorMask[idx][c];
124       }
125    }
126 
127    return colorMask != 0;
128 }
129 
130 
131 /**
132  * Clear buffers.
133  *
134  * \param mask bit-mask indicating the buffers to be cleared.
135  *
136  * Flushes the vertices and verifies the parameter.
137  * If __struct gl_contextRec::NewState is set then calls _mesa_update_state()
138  * to update gl_frame_buffer::_Xmin, etc.  If the rasterization mode is set to
139  * GL_RENDER then requests the driver to clear the buffers, via the
140  * dd_function_table::Clear callback.
141  */
142 void GLAPIENTRY
_mesa_Clear(GLbitfield mask)143 _mesa_Clear( GLbitfield mask )
144 {
145    GET_CURRENT_CONTEXT(ctx);
146    FLUSH_VERTICES(ctx, 0);
147 
148    FLUSH_CURRENT(ctx, 0);
149 
150    if (MESA_VERBOSE & VERBOSE_API)
151       _mesa_debug(ctx, "glClear 0x%x\n", mask);
152 
153    if (mask & ~(GL_COLOR_BUFFER_BIT |
154                 GL_DEPTH_BUFFER_BIT |
155                 GL_STENCIL_BUFFER_BIT |
156                 GL_ACCUM_BUFFER_BIT)) {
157       /* invalid bit set */
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    if (ctx->NewState) {
172       _mesa_update_state( ctx );	/* update _Xmin, etc */
173    }
174 
175    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
176       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
177                   "glClear(incomplete framebuffer)");
178       return;
179    }
180 
181    if (ctx->RasterDiscard)
182       return;
183 
184    if (ctx->RenderMode == GL_RENDER) {
185       GLbitfield bufferMask;
186 
187       /* don't clear depth buffer if depth writing disabled */
188       if (!ctx->Depth.Mask)
189          mask &= ~GL_DEPTH_BUFFER_BIT;
190 
191       /* Build the bitmask to send to device driver's Clear function.
192        * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
193        * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
194        * BUFFER_BIT_COLORn flags.
195        */
196       bufferMask = 0;
197       if (mask & GL_COLOR_BUFFER_BIT) {
198          GLuint i;
199          for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
200             GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
201 
202             if (buf >= 0 && color_buffer_writes_enabled(ctx, i)) {
203                bufferMask |= 1 << buf;
204             }
205          }
206       }
207 
208       if ((mask & GL_DEPTH_BUFFER_BIT)
209           && ctx->DrawBuffer->Visual.haveDepthBuffer) {
210          bufferMask |= BUFFER_BIT_DEPTH;
211       }
212 
213       if ((mask & GL_STENCIL_BUFFER_BIT)
214           && ctx->DrawBuffer->Visual.haveStencilBuffer) {
215          bufferMask |= BUFFER_BIT_STENCIL;
216       }
217 
218       if ((mask & GL_ACCUM_BUFFER_BIT)
219           && ctx->DrawBuffer->Visual.haveAccumBuffer) {
220          bufferMask |= BUFFER_BIT_ACCUM;
221       }
222 
223       assert(ctx->Driver.Clear);
224       ctx->Driver.Clear(ctx, bufferMask);
225    }
226 }
227 
228 
229 /** Returned by make_color_buffer_mask() for errors */
230 #define INVALID_MASK ~0x0U
231 
232 
233 /**
234  * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
235  * BUFFER_BIT_x values.
236  * Return INVALID_MASK if the drawbuffer value is invalid.
237  */
238 static GLbitfield
make_color_buffer_mask(struct gl_context * ctx,GLint drawbuffer)239 make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
240 {
241    const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
242    GLbitfield mask = 0x0;
243 
244    /* From the GL 4.0 specification:
245     *	If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is
246     *	specified by passing i as the parameter drawbuffer, and value
247     *	points to a four-element vector specifying the R, G, B, and A
248     *	color to clear that draw buffer to. If the draw buffer is one
249     *	of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying
250     *	multiple buffers, each selected buffer is cleared to the same
251     *	value.
252     *
253     * Note that "drawbuffer" and "draw buffer" have different meaning.
254     * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's
255     * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK,
256     * etc.
257     */
258    if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
259       return INVALID_MASK;
260    }
261 
262    switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) {
263    case GL_FRONT:
264       if (att[BUFFER_FRONT_LEFT].Renderbuffer)
265          mask |= BUFFER_BIT_FRONT_LEFT;
266       if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
267          mask |= BUFFER_BIT_FRONT_RIGHT;
268       break;
269    case GL_BACK:
270       /* For GLES contexts with a single buffered configuration, we actually
271        * only have a front renderbuffer, so any clear calls to GL_BACK should
272        * affect that buffer. See draw_buffer_enum_to_bitmask for details.
273        */
274       if (_mesa_is_gles(ctx))
275          if (!ctx->DrawBuffer->Visual.doubleBufferMode)
276             if (att[BUFFER_FRONT_LEFT].Renderbuffer)
277                mask |= BUFFER_BIT_FRONT_LEFT;
278       if (att[BUFFER_BACK_LEFT].Renderbuffer)
279          mask |= BUFFER_BIT_BACK_LEFT;
280       if (att[BUFFER_BACK_RIGHT].Renderbuffer)
281          mask |= BUFFER_BIT_BACK_RIGHT;
282       break;
283    case GL_LEFT:
284       if (att[BUFFER_FRONT_LEFT].Renderbuffer)
285          mask |= BUFFER_BIT_FRONT_LEFT;
286       if (att[BUFFER_BACK_LEFT].Renderbuffer)
287          mask |= BUFFER_BIT_BACK_LEFT;
288       break;
289    case GL_RIGHT:
290       if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
291          mask |= BUFFER_BIT_FRONT_RIGHT;
292       if (att[BUFFER_BACK_RIGHT].Renderbuffer)
293          mask |= BUFFER_BIT_BACK_RIGHT;
294       break;
295    case GL_FRONT_AND_BACK:
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_FRONT_RIGHT].Renderbuffer)
301          mask |= BUFFER_BIT_FRONT_RIGHT;
302       if (att[BUFFER_BACK_RIGHT].Renderbuffer)
303          mask |= BUFFER_BIT_BACK_RIGHT;
304       break;
305    default:
306       {
307          GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer];
308 
309          if (buf >= 0 && att[buf].Renderbuffer) {
310             mask |= 1 << buf;
311          }
312       }
313    }
314 
315    return mask;
316 }
317 
318 
319 
320 /**
321  * New in GL 3.0
322  * Clear signed integer color buffer or stencil buffer (not depth).
323  */
324 void GLAPIENTRY
_mesa_ClearBufferiv(GLenum buffer,GLint drawbuffer,const GLint * value)325 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
326 {
327    GET_CURRENT_CONTEXT(ctx);
328    FLUSH_VERTICES(ctx, 0);
329 
330    FLUSH_CURRENT(ctx, 0);
331 
332    if (ctx->NewState) {
333       _mesa_update_state( ctx );
334    }
335 
336    switch (buffer) {
337    case GL_STENCIL:
338       /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
339        *
340        *     "ClearBuffer generates an INVALID VALUE error if buffer is
341        *     COLOR and drawbuffer is less than zero, or greater than the
342        *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
343        *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
344        */
345       if (drawbuffer != 0) {
346          _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
347                      drawbuffer);
348          return;
349       }
350       else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer
351                && !ctx->RasterDiscard) {
352          /* Save current stencil clear value, set to 'value', do the
353           * stencil clear and restore the clear value.
354           * XXX in the future we may have a new ctx->Driver.ClearBuffer()
355           * hook instead.
356           */
357          const GLuint clearSave = ctx->Stencil.Clear;
358          ctx->Stencil.Clear = *value;
359          ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
360          ctx->Stencil.Clear = clearSave;
361       }
362       break;
363    case GL_COLOR:
364       {
365          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
366          if (mask == INVALID_MASK) {
367             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
368                         drawbuffer);
369             return;
370          }
371          else if (mask && !ctx->RasterDiscard) {
372             union gl_color_union clearSave;
373 
374             /* save color */
375             clearSave = ctx->Color.ClearColor;
376             /* set color */
377             COPY_4V(ctx->Color.ClearColor.i, value);
378             /* clear buffer(s) */
379             ctx->Driver.Clear(ctx, mask);
380             /* restore color */
381             ctx->Color.ClearColor = clearSave;
382          }
383       }
384       break;
385    default:
386       /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
387        * of the OpenGL 4.5 spec states:
388        *
389        *    "An INVALID_ENUM error is generated by ClearBufferiv and
390        *     ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
391        */
392       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
393                   _mesa_enum_to_string(buffer));
394       return;
395    }
396 }
397 
398 
399 /**
400  * The ClearBuffer framework is so complicated and so riddled with the
401  * assumption that the framebuffer is bound that, for now, we will just fake
402  * direct state access clearing for the user.
403  */
404 void GLAPIENTRY
_mesa_ClearNamedFramebufferiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLint * value)405 _mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
406                               GLint drawbuffer, const GLint *value)
407 {
408    GLint oldfb;
409 
410    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
411    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
412    _mesa_ClearBufferiv(buffer, drawbuffer, value);
413    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
414 }
415 
416 
417 /**
418  * New in GL 3.0
419  * Clear unsigned integer color buffer (not depth, not stencil).
420  */
421 void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer,GLint drawbuffer,const GLuint * value)422 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
423 {
424    GET_CURRENT_CONTEXT(ctx);
425 
426    FLUSH_VERTICES(ctx, 0);
427    FLUSH_CURRENT(ctx, 0);
428 
429    if (ctx->NewState) {
430       _mesa_update_state( ctx );
431    }
432 
433    switch (buffer) {
434    case GL_COLOR:
435       {
436          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
437          if (mask == INVALID_MASK) {
438             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
439                         drawbuffer);
440             return;
441          }
442          else if (mask && !ctx->RasterDiscard) {
443             union gl_color_union clearSave;
444 
445             /* save color */
446             clearSave = ctx->Color.ClearColor;
447             /* set color */
448             COPY_4V(ctx->Color.ClearColor.ui, value);
449             /* clear buffer(s) */
450             ctx->Driver.Clear(ctx, mask);
451             /* restore color */
452             ctx->Color.ClearColor = clearSave;
453          }
454       }
455       break;
456    default:
457       /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
458        * of the OpenGL 4.5 spec states:
459        *
460        *    "An INVALID_ENUM error is generated by ClearBufferuiv and
461        *     ClearNamedFramebufferuiv if buffer is not COLOR."
462        */
463       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
464                   _mesa_enum_to_string(buffer));
465       return;
466    }
467 }
468 
469 
470 /**
471  * The ClearBuffer framework is so complicated and so riddled with the
472  * assumption that the framebuffer is bound that, for now, we will just fake
473  * direct state access clearing for the user.
474  */
475 void GLAPIENTRY
_mesa_ClearNamedFramebufferuiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLuint * value)476 _mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
477                                GLint drawbuffer, const GLuint *value)
478 {
479    GLint oldfb;
480 
481    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
482    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
483    _mesa_ClearBufferuiv(buffer, drawbuffer, value);
484    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
485 }
486 
487 
488 /**
489  * New in GL 3.0
490  * Clear fixed-pt or float color buffer or depth buffer (not stencil).
491  */
492 void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat * value)493 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
494 {
495    GET_CURRENT_CONTEXT(ctx);
496 
497    FLUSH_VERTICES(ctx, 0);
498    FLUSH_CURRENT(ctx, 0);
499 
500    if (ctx->NewState) {
501       _mesa_update_state( ctx );
502    }
503 
504    switch (buffer) {
505    case GL_DEPTH:
506       /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
507        *
508        *     "ClearBuffer generates an INVALID VALUE error if buffer is
509        *     COLOR and drawbuffer is less than zero, or greater than the
510        *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
511        *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
512        */
513       if (drawbuffer != 0) {
514          _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
515                      drawbuffer);
516          return;
517       }
518       else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer
519                && !ctx->RasterDiscard) {
520          /* Save current depth clear value, set to 'value', do the
521           * depth clear and restore the clear value.
522           * XXX in the future we may have a new ctx->Driver.ClearBuffer()
523           * hook instead.
524           */
525          const GLclampd clearSave = ctx->Depth.Clear;
526          ctx->Depth.Clear = *value;
527          ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
528          ctx->Depth.Clear = clearSave;
529       }
530       /* clear depth buffer to value */
531       break;
532    case GL_COLOR:
533       {
534          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
535          if (mask == INVALID_MASK) {
536             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
537                         drawbuffer);
538             return;
539          }
540          else if (mask && !ctx->RasterDiscard) {
541             union gl_color_union clearSave;
542 
543             /* save color */
544             clearSave = ctx->Color.ClearColor;
545             /* set color */
546             COPY_4V(ctx->Color.ClearColor.f, value);
547             /* clear buffer(s) */
548             ctx->Driver.Clear(ctx, mask);
549             /* restore color */
550             ctx->Color.ClearColor = clearSave;
551          }
552       }
553       break;
554    default:
555       /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
556        * of the OpenGL 4.5 spec states:
557        *
558        *    "An INVALID_ENUM error is generated by ClearBufferfv and
559        *     ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
560        */
561       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
562                   _mesa_enum_to_string(buffer));
563       return;
564    }
565 }
566 
567 
568 /**
569  * The ClearBuffer framework is so complicated and so riddled with the
570  * assumption that the framebuffer is bound that, for now, we will just fake
571  * direct state access clearing for the user.
572  */
573 void GLAPIENTRY
_mesa_ClearNamedFramebufferfv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLfloat * value)574 _mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
575                               GLint drawbuffer, const GLfloat *value)
576 {
577    GLint oldfb;
578 
579    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
580    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
581    _mesa_ClearBufferfv(buffer, drawbuffer, value);
582    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
583 }
584 
585 
586 /**
587  * New in GL 3.0
588  * Clear depth/stencil buffer only.
589  */
590 void GLAPIENTRY
_mesa_ClearBufferfi(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)591 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
592                     GLfloat depth, GLint stencil)
593 {
594    GET_CURRENT_CONTEXT(ctx);
595    GLbitfield mask = 0;
596 
597    FLUSH_VERTICES(ctx, 0);
598    FLUSH_CURRENT(ctx, 0);
599 
600    if (buffer != GL_DEPTH_STENCIL) {
601       _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
602                   _mesa_enum_to_string(buffer));
603       return;
604    }
605 
606    /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
607     *
608     *     "ClearBuffer generates an INVALID VALUE error if buffer is
609     *     COLOR and drawbuffer is less than zero, or greater than the
610     *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
611     *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
612     */
613    if (drawbuffer != 0) {
614       _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
615                   drawbuffer);
616       return;
617    }
618 
619    if (ctx->RasterDiscard)
620       return;
621 
622    if (ctx->NewState) {
623       _mesa_update_state( ctx );
624    }
625 
626    if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
627       mask |= BUFFER_BIT_DEPTH;
628    if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
629       mask |= BUFFER_BIT_STENCIL;
630 
631    if (mask) {
632       /* save current clear values */
633       const GLclampd clearDepthSave = ctx->Depth.Clear;
634       const GLuint clearStencilSave = ctx->Stencil.Clear;
635 
636       /* set new clear values */
637       ctx->Depth.Clear = depth;
638       ctx->Stencil.Clear = stencil;
639 
640       /* clear buffers */
641       ctx->Driver.Clear(ctx, mask);
642 
643       /* restore */
644       ctx->Depth.Clear = clearDepthSave;
645       ctx->Stencil.Clear = clearStencilSave;
646    }
647 }
648 
649 
650 /**
651  * The ClearBuffer framework is so complicated and so riddled with the
652  * assumption that the framebuffer is bound that, for now, we will just fake
653  * direct state access clearing for the user.
654  */
655 void GLAPIENTRY
_mesa_ClearNamedFramebufferfi(GLuint framebuffer,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)656 _mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
657                               GLint drawbuffer, GLfloat depth, GLint stencil)
658 {
659    GLint oldfb;
660 
661    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
662    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
663    _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil);
664    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
665 }
666