• 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 "clear.h"
36 #include "context.h"
37 #include "enums.h"
38 #include "fbobject.h"
39 #include "get.h"
40 #include "macros.h"
41 #include "mtypes.h"
42 #include "state.h"
43 
44 
45 
46 void GLAPIENTRY
_mesa_ClearIndex(GLfloat c)47 _mesa_ClearIndex( GLfloat c )
48 {
49    GET_CURRENT_CONTEXT(ctx);
50 
51    ctx->Color.ClearIndex = (GLuint) c;
52 }
53 
54 
55 /**
56  * Specify the clear values for the color buffers.
57  *
58  * \param red red color component.
59  * \param green green color component.
60  * \param blue blue color component.
61  * \param alpha alpha component.
62  *
63  * \sa glClearColor().
64  */
65 void GLAPIENTRY
_mesa_ClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)66 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
67 {
68    GET_CURRENT_CONTEXT(ctx);
69 
70    ctx->Color.ClearColor.f[0] = red;
71    ctx->Color.ClearColor.f[1] = green;
72    ctx->Color.ClearColor.f[2] = blue;
73    ctx->Color.ClearColor.f[3] = alpha;
74 }
75 
76 
77 /**
78  * GL_EXT_texture_integer
79  */
80 void GLAPIENTRY
_mesa_ClearColorIiEXT(GLint r,GLint g,GLint b,GLint a)81 _mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
82 {
83    GET_CURRENT_CONTEXT(ctx);
84 
85    ctx->Color.ClearColor.i[0] = r;
86    ctx->Color.ClearColor.i[1] = g;
87    ctx->Color.ClearColor.i[2] = b;
88    ctx->Color.ClearColor.i[3] = a;
89 }
90 
91 
92 /**
93  * GL_EXT_texture_integer
94  */
95 void GLAPIENTRY
_mesa_ClearColorIuiEXT(GLuint r,GLuint g,GLuint b,GLuint a)96 _mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
97 {
98    GET_CURRENT_CONTEXT(ctx);
99 
100    ctx->Color.ClearColor.ui[0] = r;
101    ctx->Color.ClearColor.ui[1] = g;
102    ctx->Color.ClearColor.ui[2] = b;
103    ctx->Color.ClearColor.ui[3] = a;
104 }
105 
106 
107 /**
108  * Returns true if color writes are enabled for the given color attachment.
109  *
110  * Beyond checking ColorMask, this uses _mesa_format_has_color_component to
111  * ignore components that don't actually exist in the format (such as X in
112  * XRGB).
113  */
114 static bool
color_buffer_writes_enabled(const struct gl_context * ctx,unsigned idx)115 color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx)
116 {
117    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx];
118    GLuint c;
119 
120    if (rb) {
121       for (c = 0; c < 4; c++) {
122          if (GET_COLORMASK_BIT(ctx->Color.ColorMask, idx, c) &&
123              _mesa_format_has_color_component(rb->Format, c)) {
124             return true;
125          }
126       }
127    }
128 
129    return false;
130 }
131 
132 
133 /**
134  * Clear buffers.
135  *
136  * \param mask bit-mask indicating the buffers to be cleared.
137  *
138  * Flushes the vertices and verifies the parameter.
139  * If __struct gl_contextRec::NewState is set then calls _mesa_update_state()
140  * to update gl_frame_buffer::_Xmin, etc.  If the rasterization mode is set to
141  * GL_RENDER then requests the driver to clear the buffers, via the
142  * dd_function_table::Clear callback.
143  */
144 static ALWAYS_INLINE void
clear(struct gl_context * ctx,GLbitfield mask,bool no_error)145 clear(struct gl_context *ctx, GLbitfield mask, bool no_error)
146 {
147    FLUSH_VERTICES(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.depthBits > 0) {
207          bufferMask |= BUFFER_BIT_DEPTH;
208       }
209 
210       if ((mask & GL_STENCIL_BUFFER_BIT)
211           && ctx->DrawBuffer->Visual.stencilBits > 0) {
212          bufferMask |= BUFFER_BIT_STENCIL;
213       }
214 
215       if ((mask & GL_ACCUM_BUFFER_BIT)
216           && ctx->DrawBuffer->Visual.accumRedBits > 0) {
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 
348    if (ctx->NewState) {
349       _mesa_update_state( ctx );
350    }
351 
352    if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
353       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
354                   "glClearBufferiv(incomplete framebuffer)");
355       return;
356    }
357 
358    switch (buffer) {
359    case GL_STENCIL:
360       /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
361        *
362        *     "ClearBuffer generates an INVALID VALUE error if buffer is
363        *     COLOR and drawbuffer is less than zero, or greater than the
364        *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
365        *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
366        */
367       if (!no_error && drawbuffer != 0) {
368          _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
369                      drawbuffer);
370          return;
371       }
372       else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer
373                && !ctx->RasterDiscard) {
374          /* Save current stencil clear value, set to 'value', do the
375           * stencil clear and restore the clear value.
376           * XXX in the future we may have a new ctx->Driver.ClearBuffer()
377           * hook instead.
378           */
379          const GLuint clearSave = ctx->Stencil.Clear;
380          ctx->Stencil.Clear = *value;
381          ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
382          ctx->Stencil.Clear = clearSave;
383       }
384       break;
385    case GL_COLOR:
386       {
387          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
388          if (!no_error && mask == INVALID_MASK) {
389             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
390                         drawbuffer);
391             return;
392          }
393          else if (mask && !ctx->RasterDiscard) {
394             union gl_color_union clearSave;
395 
396             /* save color */
397             clearSave = ctx->Color.ClearColor;
398             /* set color */
399             COPY_4V(ctx->Color.ClearColor.i, value);
400             /* clear buffer(s) */
401             ctx->Driver.Clear(ctx, mask);
402             /* restore color */
403             ctx->Color.ClearColor = clearSave;
404          }
405       }
406       break;
407    default:
408       if (!no_error) {
409          /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
410           * of the OpenGL 4.5 spec states:
411           *
412           *    "An INVALID_ENUM error is generated by ClearBufferiv and
413           *     ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
414           */
415          _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
416                      _mesa_enum_to_string(buffer));
417       }
418       return;
419    }
420 }
421 
422 
423 void GLAPIENTRY
_mesa_ClearBufferiv_no_error(GLenum buffer,GLint drawbuffer,const GLint * value)424 _mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value)
425 {
426    GET_CURRENT_CONTEXT(ctx);
427    clear_bufferiv(ctx, buffer, drawbuffer, value, true);
428 }
429 
430 
431 void GLAPIENTRY
_mesa_ClearBufferiv(GLenum buffer,GLint drawbuffer,const GLint * value)432 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
433 {
434    GET_CURRENT_CONTEXT(ctx);
435    clear_bufferiv(ctx, buffer, drawbuffer, value, false);
436 }
437 
438 
439 /**
440  * The ClearBuffer framework is so complicated and so riddled with the
441  * assumption that the framebuffer is bound that, for now, we will just fake
442  * direct state access clearing for the user.
443  */
444 void GLAPIENTRY
_mesa_ClearNamedFramebufferiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLint * value)445 _mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
446                               GLint drawbuffer, const GLint *value)
447 {
448    GLint oldfb;
449 
450    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
451    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
452    _mesa_ClearBufferiv(buffer, drawbuffer, value);
453    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
454 }
455 
456 
457 /**
458  * New in GL 3.0
459  * Clear unsigned integer color buffer (not depth, not stencil).
460  */
461 static ALWAYS_INLINE void
clear_bufferuiv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLuint * value,bool no_error)462 clear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
463                 const GLuint *value, bool no_error)
464 {
465    FLUSH_VERTICES(ctx, 0);
466 
467    if (ctx->NewState) {
468       _mesa_update_state( ctx );
469    }
470 
471    if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
472       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION,
473                   "glClearBufferuiv(incomplete framebuffer)");
474       return;
475    }
476 
477    switch (buffer) {
478    case GL_COLOR:
479       {
480          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
481          if (!no_error && mask == INVALID_MASK) {
482             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
483                         drawbuffer);
484             return;
485          }
486          else if (mask && !ctx->RasterDiscard) {
487             union gl_color_union clearSave;
488 
489             /* save color */
490             clearSave = ctx->Color.ClearColor;
491             /* set color */
492             COPY_4V(ctx->Color.ClearColor.ui, value);
493             /* clear buffer(s) */
494             ctx->Driver.Clear(ctx, mask);
495             /* restore color */
496             ctx->Color.ClearColor = clearSave;
497          }
498       }
499       break;
500    default:
501       if (!no_error) {
502          /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
503           * of the OpenGL 4.5 spec states:
504           *
505           *    "An INVALID_ENUM error is generated by ClearBufferuiv and
506           *     ClearNamedFramebufferuiv if buffer is not COLOR."
507           */
508          _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
509                      _mesa_enum_to_string(buffer));
510       }
511       return;
512    }
513 }
514 
515 
516 void GLAPIENTRY
_mesa_ClearBufferuiv_no_error(GLenum buffer,GLint drawbuffer,const GLuint * value)517 _mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer,
518                               const GLuint *value)
519 {
520    GET_CURRENT_CONTEXT(ctx);
521    clear_bufferuiv(ctx, buffer, drawbuffer, value, true);
522 }
523 
524 
525 void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer,GLint drawbuffer,const GLuint * value)526 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
527 {
528    GET_CURRENT_CONTEXT(ctx);
529    clear_bufferuiv(ctx, buffer, drawbuffer, value, false);
530 }
531 
532 
533 /**
534  * The ClearBuffer framework is so complicated and so riddled with the
535  * assumption that the framebuffer is bound that, for now, we will just fake
536  * direct state access clearing for the user.
537  */
538 void GLAPIENTRY
_mesa_ClearNamedFramebufferuiv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLuint * value)539 _mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
540                                GLint drawbuffer, const GLuint *value)
541 {
542    GLint oldfb;
543 
544    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
545    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
546    _mesa_ClearBufferuiv(buffer, drawbuffer, value);
547    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
548 }
549 
550 
551 /**
552  * New in GL 3.0
553  * Clear fixed-pt or float color buffer or depth buffer (not stencil).
554  */
555 static ALWAYS_INLINE void
clear_bufferfv(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,const GLfloat * value,bool no_error)556 clear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
557                const GLfloat *value, bool no_error)
558 {
559    FLUSH_VERTICES(ctx, 0);
560 
561    if (ctx->NewState) {
562       _mesa_update_state( ctx );
563    }
564 
565    if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
566       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION,
567                   "glClearBufferfv(incomplete framebuffer)");
568       return;
569    }
570 
571    switch (buffer) {
572    case GL_DEPTH:
573       /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
574        *
575        *     "ClearBuffer generates an INVALID VALUE error if buffer is
576        *     COLOR and drawbuffer is less than zero, or greater than the
577        *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
578        *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
579        */
580       if (!no_error && drawbuffer != 0) {
581          _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
582                      drawbuffer);
583          return;
584       }
585       else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer
586                && !ctx->RasterDiscard) {
587          /* Save current depth clear value, set to 'value', do the
588           * depth clear and restore the clear value.
589           * XXX in the future we may have a new ctx->Driver.ClearBuffer()
590           * hook instead.
591           */
592          const GLclampd clearSave = ctx->Depth.Clear;
593 
594          /* Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says:
595           *
596           *     "If buffer is DEPTH, drawbuffer must be zero, and value points
597           *     to the single depth value to clear the depth buffer to.
598           *     Clamping and type conversion for fixed-point depth buffers are
599           *     performed in the same fashion as for ClearDepth."
600           */
601          const struct gl_renderbuffer *rb =
602             ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
603          const bool is_float_depth =
604             _mesa_has_depth_float_channel(rb->InternalFormat);
605          ctx->Depth.Clear = is_float_depth ? *value : SATURATE(*value);
606 
607          ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
608          ctx->Depth.Clear = clearSave;
609       }
610       /* clear depth buffer to value */
611       break;
612    case GL_COLOR:
613       {
614          const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
615          if (!no_error && mask == INVALID_MASK) {
616             _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
617                         drawbuffer);
618             return;
619          }
620          else if (mask && !ctx->RasterDiscard) {
621             union gl_color_union clearSave;
622 
623             /* save color */
624             clearSave = ctx->Color.ClearColor;
625             /* set color */
626             COPY_4V(ctx->Color.ClearColor.f, value);
627             /* clear buffer(s) */
628             ctx->Driver.Clear(ctx, mask);
629             /* restore color */
630             ctx->Color.ClearColor = clearSave;
631          }
632       }
633       break;
634    default:
635       if (!no_error) {
636          /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
637           * of the OpenGL 4.5 spec states:
638           *
639           *    "An INVALID_ENUM error is generated by ClearBufferfv and
640           *     ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
641           */
642          _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
643                      _mesa_enum_to_string(buffer));
644       }
645       return;
646    }
647 }
648 
649 
650 void GLAPIENTRY
_mesa_ClearBufferfv_no_error(GLenum buffer,GLint drawbuffer,const GLfloat * value)651 _mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer,
652                              const GLfloat *value)
653 {
654    GET_CURRENT_CONTEXT(ctx);
655    clear_bufferfv(ctx, buffer, drawbuffer, value, true);
656 }
657 
658 
659 void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat * value)660 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
661 {
662    GET_CURRENT_CONTEXT(ctx);
663    clear_bufferfv(ctx, buffer, drawbuffer, value, false);
664 }
665 
666 
667 /**
668  * The ClearBuffer framework is so complicated and so riddled with the
669  * assumption that the framebuffer is bound that, for now, we will just fake
670  * direct state access clearing for the user.
671  */
672 void GLAPIENTRY
_mesa_ClearNamedFramebufferfv(GLuint framebuffer,GLenum buffer,GLint drawbuffer,const GLfloat * value)673 _mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
674                               GLint drawbuffer, const GLfloat *value)
675 {
676    GLint oldfb;
677 
678    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
679    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
680    _mesa_ClearBufferfv(buffer, drawbuffer, value);
681    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
682 }
683 
684 
685 /**
686  * New in GL 3.0
687  * Clear depth/stencil buffer only.
688  */
689 static ALWAYS_INLINE void
clear_bufferfi(struct gl_context * ctx,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil,bool no_error)690 clear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
691                GLfloat depth, GLint stencil, bool no_error)
692 {
693    GLbitfield mask = 0;
694 
695    FLUSH_VERTICES(ctx, 0);
696 
697    if (!no_error) {
698       if (buffer != GL_DEPTH_STENCIL) {
699          _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
700                      _mesa_enum_to_string(buffer));
701          return;
702       }
703 
704       /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
705        *
706        *     "ClearBuffer generates an INVALID VALUE error if buffer is
707        *     COLOR and drawbuffer is less than zero, or greater than the
708        *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
709        *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
710        */
711       if (drawbuffer != 0) {
712          _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
713                      drawbuffer);
714          return;
715       }
716    }
717 
718    if (ctx->RasterDiscard)
719       return;
720 
721    if (ctx->NewState) {
722       _mesa_update_state( ctx );
723    }
724 
725    if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
726       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
727                   "glClearBufferfi(incomplete framebuffer)");
728       return;
729    }
730 
731    if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
732       mask |= BUFFER_BIT_DEPTH;
733    if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
734       mask |= BUFFER_BIT_STENCIL;
735 
736    if (mask) {
737       /* save current clear values */
738       const GLclampd clearDepthSave = ctx->Depth.Clear;
739       const GLuint clearStencilSave = ctx->Stencil.Clear;
740 
741       /* set new clear values
742        *
743        * Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says:
744        *
745        *     "depth and stencil are the values to clear the depth and stencil
746        *     buffers to, respectively. Clamping and type conversion for
747        *     fixed-point depth buffers are performed in the same fashion as
748        *     for ClearDepth."
749        */
750       const struct gl_renderbuffer *rb =
751          ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
752       const bool has_float_depth = rb &&
753          _mesa_has_depth_float_channel(rb->InternalFormat);
754       ctx->Depth.Clear = has_float_depth ? depth : SATURATE(depth);
755       ctx->Stencil.Clear = stencil;
756 
757       /* clear buffers */
758       ctx->Driver.Clear(ctx, mask);
759 
760       /* restore */
761       ctx->Depth.Clear = clearDepthSave;
762       ctx->Stencil.Clear = clearStencilSave;
763    }
764 }
765 
766 
767 void GLAPIENTRY
_mesa_ClearBufferfi_no_error(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)768 _mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer,
769                              GLfloat depth, GLint stencil)
770 {
771    GET_CURRENT_CONTEXT(ctx);
772    clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true);
773 }
774 
775 
776 void GLAPIENTRY
_mesa_ClearBufferfi(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)777 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
778                     GLfloat depth, GLint stencil)
779 {
780    GET_CURRENT_CONTEXT(ctx);
781    clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false);
782 }
783 
784 
785 /**
786  * The ClearBuffer framework is so complicated and so riddled with the
787  * assumption that the framebuffer is bound that, for now, we will just fake
788  * direct state access clearing for the user.
789  */
790 void GLAPIENTRY
_mesa_ClearNamedFramebufferfi(GLuint framebuffer,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)791 _mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
792                               GLint drawbuffer, GLfloat depth, GLint stencil)
793 {
794    GLint oldfb;
795 
796    _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
797    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
798    _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil);
799    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
800 }
801