• 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 
119    if (rb) {
120       for (c = 0; c < 4; c++) {
121          if (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  */
143 static ALWAYS_INLINE void
clear(struct gl_context * ctx,GLbitfield mask,bool no_error)144 clear(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 
226 void GLAPIENTRY
_mesa_Clear_no_error(GLbitfield mask)227 _mesa_Clear_no_error(GLbitfield mask)
228 {
229    GET_CURRENT_CONTEXT(ctx);
230    clear(ctx, mask, true);
231 }
232 
233 
234 void GLAPIENTRY
_mesa_Clear(GLbitfield mask)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  */
255 static GLbitfield
make_color_buffer_mask(struct gl_context * ctx,GLint drawbuffer)256 make_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  */
342 static ALWAYS_INLINE void
clear_bufferiv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLint * value,bool no_error)343 clear_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 
418 void GLAPIENTRY
_mesa_ClearBufferiv_no_error(GLenum buffer,GLint drawbuffer,const GLint * value)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 
426 void GLAPIENTRY
_mesa_ClearBufferiv(GLenum buffer,GLint drawbuffer,const GLint * value)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  */
439 void GLAPIENTRY
_mesa_ClearNamedFramebufferiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLint * value)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  */
456 static ALWAYS_INLINE void
clear_bufferuiv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLuint * value,bool no_error)457 clear_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 
506 void GLAPIENTRY
_mesa_ClearBufferuiv_no_error(GLenum buffer,GLint drawbuffer,const GLuint * value)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 
515 void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer,GLint drawbuffer,const GLuint * value)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  */
528 void GLAPIENTRY
_mesa_ClearNamedFramebufferuiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLuint * value)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  */
545 static ALWAYS_INLINE void
clear_bufferfv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLfloat * value,bool no_error)546 clear_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 
622 void GLAPIENTRY
_mesa_ClearBufferfv_no_error(GLenum buffer,GLint drawbuffer,const GLfloat * value)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 
631 void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat * value)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  */
644 void GLAPIENTRY
_mesa_ClearNamedFramebufferfv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLfloat * value)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  */
661 static ALWAYS_INLINE void
clear_bufferfi(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil,bool no_error)662 clear_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 
722 void GLAPIENTRY
_mesa_ClearBufferfi_no_error(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)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 
731 void GLAPIENTRY
_mesa_ClearBufferfi(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)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  */
745 void GLAPIENTRY
_mesa_ClearNamedFramebufferfi(GLuint framebuffer,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)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