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