• 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 "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 
46 void GLAPIENTRY
_mesa_ClearIndex(GLfloat c)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  */
66 void GLAPIENTRY
_mesa_ClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)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  */
82 void GLAPIENTRY
_mesa_ClearColorIiEXT(GLint r,GLint g,GLint b,GLint a)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  */
98 void GLAPIENTRY
_mesa_ClearColorIuiEXT(GLuint r,GLuint g,GLuint b,GLuint a)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  */
118 static bool
color_buffer_writes_enabled(const struct gl_context * ctx,unsigned idx)119 color_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  */
148 static ALWAYS_INLINE void
clear(struct gl_context * ctx,GLbitfield mask,bool no_error)149 clear(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 
229 void GLAPIENTRY
_mesa_Clear_no_error(GLbitfield mask)230 _mesa_Clear_no_error(GLbitfield mask)
231 {
232    GET_CURRENT_CONTEXT(ctx);
233    clear(ctx, mask, true);
234 }
235 
236 
237 void GLAPIENTRY
_mesa_Clear(GLbitfield mask)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  */
258 static GLbitfield
make_color_buffer_mask(struct gl_context * ctx,GLint drawbuffer)259 make_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  */
345 static ALWAYS_INLINE void
clear_bufferiv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLint * value,bool no_error)346 clear_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 
426 void GLAPIENTRY
_mesa_ClearBufferiv_no_error(GLenum buffer,GLint drawbuffer,const GLint * value)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 
434 void GLAPIENTRY
_mesa_ClearBufferiv(GLenum buffer,GLint drawbuffer,const GLint * value)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  */
447 void GLAPIENTRY
_mesa_ClearNamedFramebufferiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLint * value)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  */
464 static ALWAYS_INLINE void
clear_bufferuiv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLuint * value,bool no_error)465 clear_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 
519 void GLAPIENTRY
_mesa_ClearBufferuiv_no_error(GLenum buffer,GLint drawbuffer,const GLuint * value)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 
528 void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer,GLint drawbuffer,const GLuint * value)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  */
541 void GLAPIENTRY
_mesa_ClearNamedFramebufferuiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLuint * value)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  */
558 static ALWAYS_INLINE void
clear_bufferfv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLfloat * value,bool no_error)559 clear_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 
653 void GLAPIENTRY
_mesa_ClearBufferfv_no_error(GLenum buffer,GLint drawbuffer,const GLfloat * value)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 
662 void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat * value)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  */
675 void GLAPIENTRY
_mesa_ClearNamedFramebufferfv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLfloat * value)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  */
692 static ALWAYS_INLINE void
clear_bufferfi(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil,bool no_error)693 clear_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 
770 void GLAPIENTRY
_mesa_ClearBufferfi_no_error(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)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 
779 void GLAPIENTRY
_mesa_ClearBufferfi(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)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  */
793 void GLAPIENTRY
_mesa_ClearNamedFramebufferfi(GLuint framebuffer,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)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