clear.c revision 01e04c3f
1c1f859d4Smrg/*
2c1f859d4Smrg * Mesa 3-D graphics library
3c1f859d4Smrg *
4c1f859d4Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5c1f859d4Smrg *
6c1f859d4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7c1f859d4Smrg * copy of this software and associated documentation files (the "Software"),
8c1f859d4Smrg * to deal in the Software without restriction, including without limitation
9c1f859d4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10c1f859d4Smrg * and/or sell copies of the Software, and to permit persons to whom the
11c1f859d4Smrg * Software is furnished to do so, subject to the following conditions:
12c1f859d4Smrg *
13c1f859d4Smrg * The above copyright notice and this permission notice shall be included
14c1f859d4Smrg * in all copies or substantial portions of the Software.
15c1f859d4Smrg *
16c1f859d4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17c1f859d4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18c1f859d4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
23c1f859d4Smrg */
24c1f859d4Smrg
25c1f859d4Smrg
26c1f859d4Smrg/**
27c1f859d4Smrg * \file clear.c
28c1f859d4Smrg * glClearColor, glClearIndex, glClear() functions.
29c1f859d4Smrg */
30c1f859d4Smrg
31c1f859d4Smrg
32c1f859d4Smrg
33c1f859d4Smrg#include "glheader.h"
34c1f859d4Smrg#include "clear.h"
35c1f859d4Smrg#include "context.h"
36cdc920a0Smrg#include "enums.h"
3701e04c3fSmrg#include "fbobject.h"
3801e04c3fSmrg#include "get.h"
393464ebd5Sriastradh#include "macros.h"
403464ebd5Sriastradh#include "mtypes.h"
41c1f859d4Smrg#include "state.h"
42c1f859d4Smrg
43c1f859d4Smrg
44c1f859d4Smrg
45c1f859d4Smrgvoid GLAPIENTRY
46c1f859d4Smrg_mesa_ClearIndex( GLfloat c )
47c1f859d4Smrg{
48c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
49c1f859d4Smrg
50c1f859d4Smrg   ctx->Color.ClearIndex = (GLuint) c;
51c1f859d4Smrg}
52c1f859d4Smrg
53c1f859d4Smrg
54c1f859d4Smrg/**
55c1f859d4Smrg * Specify the clear values for the color buffers.
56c1f859d4Smrg *
57c1f859d4Smrg * \param red red color component.
58c1f859d4Smrg * \param green green color component.
59c1f859d4Smrg * \param blue blue color component.
60c1f859d4Smrg * \param alpha alpha component.
61c1f859d4Smrg *
62c1f859d4Smrg * \sa glClearColor().
63c1f859d4Smrg */
64c1f859d4Smrgvoid GLAPIENTRY
65c1f859d4Smrg_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
66c1f859d4Smrg{
67c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
683464ebd5Sriastradh
69af69d88dSmrg   ctx->Color.ClearColor.f[0] = red;
70af69d88dSmrg   ctx->Color.ClearColor.f[1] = green;
71af69d88dSmrg   ctx->Color.ClearColor.f[2] = blue;
72af69d88dSmrg   ctx->Color.ClearColor.f[3] = alpha;
73c1f859d4Smrg}
74c1f859d4Smrg
75c1f859d4Smrg
763464ebd5Sriastradh/**
773464ebd5Sriastradh * GL_EXT_texture_integer
783464ebd5Sriastradh */
793464ebd5Sriastradhvoid GLAPIENTRY
803464ebd5Sriastradh_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
813464ebd5Sriastradh{
823464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
833464ebd5Sriastradh
84af69d88dSmrg   ctx->Color.ClearColor.i[0] = r;
85af69d88dSmrg   ctx->Color.ClearColor.i[1] = g;
86af69d88dSmrg   ctx->Color.ClearColor.i[2] = b;
87af69d88dSmrg   ctx->Color.ClearColor.i[3] = a;
883464ebd5Sriastradh}
893464ebd5Sriastradh
903464ebd5Sriastradh
913464ebd5Sriastradh/**
923464ebd5Sriastradh * GL_EXT_texture_integer
933464ebd5Sriastradh */
943464ebd5Sriastradhvoid GLAPIENTRY
953464ebd5Sriastradh_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
963464ebd5Sriastradh{
973464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
983464ebd5Sriastradh
99af69d88dSmrg   ctx->Color.ClearColor.ui[0] = r;
100af69d88dSmrg   ctx->Color.ClearColor.ui[1] = g;
101af69d88dSmrg   ctx->Color.ClearColor.ui[2] = b;
102af69d88dSmrg   ctx->Color.ClearColor.ui[3] = a;
103af69d88dSmrg}
1043464ebd5Sriastradh
1053464ebd5Sriastradh
106af69d88dSmrg/**
107af69d88dSmrg * Returns true if color writes are enabled for the given color attachment.
108af69d88dSmrg *
109af69d88dSmrg * Beyond checking ColorMask, this uses _mesa_format_has_color_component to
110af69d88dSmrg * ignore components that don't actually exist in the format (such as X in
111af69d88dSmrg * XRGB).
112af69d88dSmrg */
113af69d88dSmrgstatic bool
114af69d88dSmrgcolor_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx)
115af69d88dSmrg{
116af69d88dSmrg   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx];
117af69d88dSmrg   GLuint c;
118af69d88dSmrg
119af69d88dSmrg   if (rb) {
120af69d88dSmrg      for (c = 0; c < 4; c++) {
12101e04c3fSmrg         if (GET_COLORMASK_BIT(ctx->Color.ColorMask, idx, c) &&
12201e04c3fSmrg             _mesa_format_has_color_component(rb->Format, c)) {
12301e04c3fSmrg            return true;
12401e04c3fSmrg         }
125af69d88dSmrg      }
1263464ebd5Sriastradh   }
127af69d88dSmrg
12801e04c3fSmrg   return false;
1293464ebd5Sriastradh}
1303464ebd5Sriastradh
1313464ebd5Sriastradh
132c1f859d4Smrg/**
133c1f859d4Smrg * Clear buffers.
13401e04c3fSmrg *
135c1f859d4Smrg * \param mask bit-mask indicating the buffers to be cleared.
136c1f859d4Smrg *
13701e04c3fSmrg * Flushes the vertices and verifies the parameter.
13801e04c3fSmrg * If __struct gl_contextRec::NewState is set then calls _mesa_update_state()
13901e04c3fSmrg * to update gl_frame_buffer::_Xmin, etc.  If the rasterization mode is set to
14001e04c3fSmrg * GL_RENDER then requests the driver to clear the buffers, via the
14101e04c3fSmrg * dd_function_table::Clear callback.
14201e04c3fSmrg */
14301e04c3fSmrgstatic ALWAYS_INLINE void
14401e04c3fSmrgclear(struct gl_context *ctx, GLbitfield mask, bool no_error)
145c1f859d4Smrg{
146af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
147c1f859d4Smrg   FLUSH_CURRENT(ctx, 0);
148c1f859d4Smrg
14901e04c3fSmrg   if (!no_error) {
15001e04c3fSmrg      if (mask & ~(GL_COLOR_BUFFER_BIT |
15101e04c3fSmrg                   GL_DEPTH_BUFFER_BIT |
15201e04c3fSmrg                   GL_STENCIL_BUFFER_BIT |
15301e04c3fSmrg                   GL_ACCUM_BUFFER_BIT)) {
15401e04c3fSmrg         _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
15501e04c3fSmrg         return;
15601e04c3fSmrg      }
157c1f859d4Smrg
15801e04c3fSmrg      /* Accumulation buffers were removed in core contexts, and they never
15901e04c3fSmrg       * existed in OpenGL ES.
16001e04c3fSmrg       */
16101e04c3fSmrg      if ((mask & GL_ACCUM_BUFFER_BIT) != 0
16201e04c3fSmrg          && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) {
16301e04c3fSmrg         _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)");
16401e04c3fSmrg         return;
16501e04c3fSmrg      }
166af69d88dSmrg   }
167af69d88dSmrg
168c1f859d4Smrg   if (ctx->NewState) {
169c1f859d4Smrg      _mesa_update_state( ctx );	/* update _Xmin, etc */
170c1f859d4Smrg   }
171c1f859d4Smrg
17201e04c3fSmrg   if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
173c1f859d4Smrg      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
174c1f859d4Smrg                  "glClear(incomplete framebuffer)");
175c1f859d4Smrg      return;
176c1f859d4Smrg   }
177c1f859d4Smrg
178af69d88dSmrg   if (ctx->RasterDiscard)
179c1f859d4Smrg      return;
180c1f859d4Smrg
181c1f859d4Smrg   if (ctx->RenderMode == GL_RENDER) {
182c1f859d4Smrg      GLbitfield bufferMask;
183c1f859d4Smrg
184c1f859d4Smrg      /* don't clear depth buffer if depth writing disabled */
185c1f859d4Smrg      if (!ctx->Depth.Mask)
186c1f859d4Smrg         mask &= ~GL_DEPTH_BUFFER_BIT;
187c1f859d4Smrg
188c1f859d4Smrg      /* Build the bitmask to send to device driver's Clear function.
189c1f859d4Smrg       * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
190c1f859d4Smrg       * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
191c1f859d4Smrg       * BUFFER_BIT_COLORn flags.
192c1f859d4Smrg       */
193c1f859d4Smrg      bufferMask = 0;
194c1f859d4Smrg      if (mask & GL_COLOR_BUFFER_BIT) {
195c1f859d4Smrg         GLuint i;
196c1f859d4Smrg         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
19701e04c3fSmrg            gl_buffer_index buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
198af69d88dSmrg
19901e04c3fSmrg            if (buf != BUFFER_NONE && color_buffer_writes_enabled(ctx, i)) {
200af69d88dSmrg               bufferMask |= 1 << buf;
201af69d88dSmrg            }
202c1f859d4Smrg         }
203c1f859d4Smrg      }
204c1f859d4Smrg
205c1f859d4Smrg      if ((mask & GL_DEPTH_BUFFER_BIT)
206c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveDepthBuffer) {
207c1f859d4Smrg         bufferMask |= BUFFER_BIT_DEPTH;
208c1f859d4Smrg      }
209c1f859d4Smrg
210c1f859d4Smrg      if ((mask & GL_STENCIL_BUFFER_BIT)
211c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveStencilBuffer) {
212c1f859d4Smrg         bufferMask |= BUFFER_BIT_STENCIL;
213c1f859d4Smrg      }
214c1f859d4Smrg
215c1f859d4Smrg      if ((mask & GL_ACCUM_BUFFER_BIT)
216c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveAccumBuffer) {
217c1f859d4Smrg         bufferMask |= BUFFER_BIT_ACCUM;
218c1f859d4Smrg      }
219c1f859d4Smrg
22001e04c3fSmrg      assert(ctx->Driver.Clear);
221c1f859d4Smrg      ctx->Driver.Clear(ctx, bufferMask);
222c1f859d4Smrg   }
223c1f859d4Smrg}
224cdc920a0Smrg
225cdc920a0Smrg
22601e04c3fSmrgvoid GLAPIENTRY
22701e04c3fSmrg_mesa_Clear_no_error(GLbitfield mask)
22801e04c3fSmrg{
22901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
23001e04c3fSmrg   clear(ctx, mask, true);
23101e04c3fSmrg}
23201e04c3fSmrg
23301e04c3fSmrg
23401e04c3fSmrgvoid GLAPIENTRY
23501e04c3fSmrg_mesa_Clear(GLbitfield mask)
23601e04c3fSmrg{
23701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
23801e04c3fSmrg
23901e04c3fSmrg   if (MESA_VERBOSE & VERBOSE_API)
24001e04c3fSmrg      _mesa_debug(ctx, "glClear 0x%x\n", mask);
24101e04c3fSmrg
24201e04c3fSmrg   clear(ctx, mask, false);
24301e04c3fSmrg}
24401e04c3fSmrg
24501e04c3fSmrg
246cdc920a0Smrg/** Returned by make_color_buffer_mask() for errors */
24701e04c3fSmrg#define INVALID_MASK ~0x0U
248cdc920a0Smrg
249cdc920a0Smrg
250cdc920a0Smrg/**
251cdc920a0Smrg * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
252cdc920a0Smrg * BUFFER_BIT_x values.
253cdc920a0Smrg * Return INVALID_MASK if the drawbuffer value is invalid.
254cdc920a0Smrg */
255cdc920a0Smrgstatic GLbitfield
2563464ebd5Sriastradhmake_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
257cdc920a0Smrg{
258cdc920a0Smrg   const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
259cdc920a0Smrg   GLbitfield mask = 0x0;
260cdc920a0Smrg
261af69d88dSmrg   /* From the GL 4.0 specification:
262af69d88dSmrg    *	If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is
263af69d88dSmrg    *	specified by passing i as the parameter drawbuffer, and value
264af69d88dSmrg    *	points to a four-element vector specifying the R, G, B, and A
265af69d88dSmrg    *	color to clear that draw buffer to. If the draw buffer is one
266af69d88dSmrg    *	of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying
267af69d88dSmrg    *	multiple buffers, each selected buffer is cleared to the same
268af69d88dSmrg    *	value.
269af69d88dSmrg    *
270af69d88dSmrg    * Note that "drawbuffer" and "draw buffer" have different meaning.
271af69d88dSmrg    * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's
272af69d88dSmrg    * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK,
273af69d88dSmrg    * etc.
274af69d88dSmrg    */
275af69d88dSmrg   if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
276af69d88dSmrg      return INVALID_MASK;
277af69d88dSmrg   }
278af69d88dSmrg
279af69d88dSmrg   switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) {
280cdc920a0Smrg   case GL_FRONT:
281cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
282cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
283cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
284cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
285cdc920a0Smrg      break;
286cdc920a0Smrg   case GL_BACK:
28701e04c3fSmrg      /* For GLES contexts with a single buffered configuration, we actually
28801e04c3fSmrg       * only have a front renderbuffer, so any clear calls to GL_BACK should
28901e04c3fSmrg       * affect that buffer. See draw_buffer_enum_to_bitmask for details.
29001e04c3fSmrg       */
29101e04c3fSmrg      if (_mesa_is_gles(ctx))
29201e04c3fSmrg         if (!ctx->DrawBuffer->Visual.doubleBufferMode)
29301e04c3fSmrg            if (att[BUFFER_FRONT_LEFT].Renderbuffer)
29401e04c3fSmrg               mask |= BUFFER_BIT_FRONT_LEFT;
295cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
296cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
297cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
298cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
299cdc920a0Smrg      break;
300cdc920a0Smrg   case GL_LEFT:
301cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
302cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
303cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
304cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
305cdc920a0Smrg      break;
306cdc920a0Smrg   case GL_RIGHT:
307cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
308cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
309cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
310cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
311cdc920a0Smrg      break;
312cdc920a0Smrg   case GL_FRONT_AND_BACK:
313cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
314cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
315cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
316cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
317cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
318cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
319cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
320cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
321cdc920a0Smrg      break;
322cdc920a0Smrg   default:
323af69d88dSmrg      {
32401e04c3fSmrg         gl_buffer_index buf =
32501e04c3fSmrg            ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer];
326af69d88dSmrg
32701e04c3fSmrg         if (buf != BUFFER_NONE && att[buf].Renderbuffer) {
328af69d88dSmrg            mask |= 1 << buf;
329af69d88dSmrg         }
330cdc920a0Smrg      }
331cdc920a0Smrg   }
332cdc920a0Smrg
333cdc920a0Smrg   return mask;
334cdc920a0Smrg}
335cdc920a0Smrg
336cdc920a0Smrg
337cdc920a0Smrg
338cdc920a0Smrg/**
339cdc920a0Smrg * New in GL 3.0
340cdc920a0Smrg * Clear signed integer color buffer or stencil buffer (not depth).
341cdc920a0Smrg */
34201e04c3fSmrgstatic ALWAYS_INLINE void
34301e04c3fSmrgclear_bufferiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
34401e04c3fSmrg               const GLint *value, bool no_error)
345cdc920a0Smrg{
346af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
347cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
348cdc920a0Smrg
349cdc920a0Smrg   if (ctx->NewState) {
350cdc920a0Smrg      _mesa_update_state( ctx );
351cdc920a0Smrg   }
352cdc920a0Smrg
353cdc920a0Smrg   switch (buffer) {
354cdc920a0Smrg   case GL_STENCIL:
355af69d88dSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
356af69d88dSmrg       *
357af69d88dSmrg       *     "ClearBuffer generates an INVALID VALUE error if buffer is
358af69d88dSmrg       *     COLOR and drawbuffer is less than zero, or greater than the
359af69d88dSmrg       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
360af69d88dSmrg       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
361af69d88dSmrg       */
36201e04c3fSmrg      if (!no_error && drawbuffer != 0) {
363cdc920a0Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
364cdc920a0Smrg                     drawbuffer);
365cdc920a0Smrg         return;
366cdc920a0Smrg      }
36701e04c3fSmrg      else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer
36801e04c3fSmrg               && !ctx->RasterDiscard) {
369cdc920a0Smrg         /* Save current stencil clear value, set to 'value', do the
370cdc920a0Smrg          * stencil clear and restore the clear value.
371cdc920a0Smrg          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
372cdc920a0Smrg          * hook instead.
373cdc920a0Smrg          */
374cdc920a0Smrg         const GLuint clearSave = ctx->Stencil.Clear;
375cdc920a0Smrg         ctx->Stencil.Clear = *value;
376cdc920a0Smrg         ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
377cdc920a0Smrg         ctx->Stencil.Clear = clearSave;
378cdc920a0Smrg      }
379cdc920a0Smrg      break;
380cdc920a0Smrg   case GL_COLOR:
381cdc920a0Smrg      {
382cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
38301e04c3fSmrg         if (!no_error && mask == INVALID_MASK) {
384cdc920a0Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
385cdc920a0Smrg                        drawbuffer);
386cdc920a0Smrg            return;
387cdc920a0Smrg         }
388af69d88dSmrg         else if (mask && !ctx->RasterDiscard) {
389af69d88dSmrg            union gl_color_union clearSave;
390af69d88dSmrg
391cdc920a0Smrg            /* save color */
392af69d88dSmrg            clearSave = ctx->Color.ClearColor;
393cdc920a0Smrg            /* set color */
394af69d88dSmrg            COPY_4V(ctx->Color.ClearColor.i, value);
395cdc920a0Smrg            /* clear buffer(s) */
396cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
397cdc920a0Smrg            /* restore color */
398af69d88dSmrg            ctx->Color.ClearColor = clearSave;
399cdc920a0Smrg         }
400cdc920a0Smrg      }
401cdc920a0Smrg      break;
402cdc920a0Smrg   default:
40301e04c3fSmrg      if (!no_error) {
40401e04c3fSmrg         /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
40501e04c3fSmrg          * of the OpenGL 4.5 spec states:
40601e04c3fSmrg          *
40701e04c3fSmrg          *    "An INVALID_ENUM error is generated by ClearBufferiv and
40801e04c3fSmrg          *     ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
40901e04c3fSmrg          */
41001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
41101e04c3fSmrg                     _mesa_enum_to_string(buffer));
41201e04c3fSmrg      }
413cdc920a0Smrg      return;
414cdc920a0Smrg   }
415cdc920a0Smrg}
416cdc920a0Smrg
417cdc920a0Smrg
41801e04c3fSmrgvoid GLAPIENTRY
41901e04c3fSmrg_mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value)
42001e04c3fSmrg{
42101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
42201e04c3fSmrg   clear_bufferiv(ctx, buffer, drawbuffer, value, true);
42301e04c3fSmrg}
42401e04c3fSmrg
42501e04c3fSmrg
42601e04c3fSmrgvoid GLAPIENTRY
42701e04c3fSmrg_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
42801e04c3fSmrg{
42901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
43001e04c3fSmrg   clear_bufferiv(ctx, buffer, drawbuffer, value, false);
43101e04c3fSmrg}
43201e04c3fSmrg
43301e04c3fSmrg
434cdc920a0Smrg/**
43501e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the
43601e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake
43701e04c3fSmrg * direct state access clearing for the user.
438cdc920a0Smrg */
439cdc920a0Smrgvoid GLAPIENTRY
44001e04c3fSmrg_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
44101e04c3fSmrg                              GLint drawbuffer, const GLint *value)
442cdc920a0Smrg{
44301e04c3fSmrg   GLint oldfb;
44401e04c3fSmrg
44501e04c3fSmrg   _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
44601e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
44701e04c3fSmrg   _mesa_ClearBufferiv(buffer, drawbuffer, value);
44801e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
44901e04c3fSmrg}
45001e04c3fSmrg
451cdc920a0Smrg
45201e04c3fSmrg/**
45301e04c3fSmrg * New in GL 3.0
45401e04c3fSmrg * Clear unsigned integer color buffer (not depth, not stencil).
45501e04c3fSmrg */
45601e04c3fSmrgstatic ALWAYS_INLINE void
45701e04c3fSmrgclear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
45801e04c3fSmrg                const GLuint *value, bool no_error)
45901e04c3fSmrg{
460af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
461cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
462cdc920a0Smrg
463cdc920a0Smrg   if (ctx->NewState) {
464cdc920a0Smrg      _mesa_update_state( ctx );
465cdc920a0Smrg   }
466cdc920a0Smrg
467cdc920a0Smrg   switch (buffer) {
468cdc920a0Smrg   case GL_COLOR:
469cdc920a0Smrg      {
470cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
47101e04c3fSmrg         if (!no_error && mask == INVALID_MASK) {
4723464ebd5Sriastradh            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
473cdc920a0Smrg                        drawbuffer);
474cdc920a0Smrg            return;
475cdc920a0Smrg         }
476af69d88dSmrg         else if (mask && !ctx->RasterDiscard) {
477af69d88dSmrg            union gl_color_union clearSave;
478af69d88dSmrg
479cdc920a0Smrg            /* save color */
480af69d88dSmrg            clearSave = ctx->Color.ClearColor;
481cdc920a0Smrg            /* set color */
482af69d88dSmrg            COPY_4V(ctx->Color.ClearColor.ui, value);
483cdc920a0Smrg            /* clear buffer(s) */
484cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
485cdc920a0Smrg            /* restore color */
486af69d88dSmrg            ctx->Color.ClearColor = clearSave;
487cdc920a0Smrg         }
488cdc920a0Smrg      }
489cdc920a0Smrg      break;
490cdc920a0Smrg   default:
49101e04c3fSmrg      if (!no_error) {
49201e04c3fSmrg         /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
49301e04c3fSmrg          * of the OpenGL 4.5 spec states:
49401e04c3fSmrg          *
49501e04c3fSmrg          *    "An INVALID_ENUM error is generated by ClearBufferuiv and
49601e04c3fSmrg          *     ClearNamedFramebufferuiv if buffer is not COLOR."
49701e04c3fSmrg          */
49801e04c3fSmrg         _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
49901e04c3fSmrg                     _mesa_enum_to_string(buffer));
50001e04c3fSmrg      }
501cdc920a0Smrg      return;
502cdc920a0Smrg   }
503cdc920a0Smrg}
504cdc920a0Smrg
505cdc920a0Smrg
50601e04c3fSmrgvoid GLAPIENTRY
50701e04c3fSmrg_mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer,
50801e04c3fSmrg                              const GLuint *value)
50901e04c3fSmrg{
51001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
51101e04c3fSmrg   clear_bufferuiv(ctx, buffer, drawbuffer, value, true);
51201e04c3fSmrg}
51301e04c3fSmrg
51401e04c3fSmrg
51501e04c3fSmrgvoid GLAPIENTRY
51601e04c3fSmrg_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
51701e04c3fSmrg{
51801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
51901e04c3fSmrg   clear_bufferuiv(ctx, buffer, drawbuffer, value, false);
52001e04c3fSmrg}
52101e04c3fSmrg
52201e04c3fSmrg
523cdc920a0Smrg/**
52401e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the
52501e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake
52601e04c3fSmrg * direct state access clearing for the user.
527cdc920a0Smrg */
528cdc920a0Smrgvoid GLAPIENTRY
52901e04c3fSmrg_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
53001e04c3fSmrg                               GLint drawbuffer, const GLuint *value)
531cdc920a0Smrg{
53201e04c3fSmrg   GLint oldfb;
533cdc920a0Smrg
53401e04c3fSmrg   _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
53501e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
53601e04c3fSmrg   _mesa_ClearBufferuiv(buffer, drawbuffer, value);
53701e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
53801e04c3fSmrg}
53901e04c3fSmrg
54001e04c3fSmrg
54101e04c3fSmrg/**
54201e04c3fSmrg * New in GL 3.0
54301e04c3fSmrg * Clear fixed-pt or float color buffer or depth buffer (not stencil).
54401e04c3fSmrg */
54501e04c3fSmrgstatic ALWAYS_INLINE void
54601e04c3fSmrgclear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
54701e04c3fSmrg               const GLfloat *value, bool no_error)
54801e04c3fSmrg{
549af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
550cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
551cdc920a0Smrg
552cdc920a0Smrg   if (ctx->NewState) {
553cdc920a0Smrg      _mesa_update_state( ctx );
554cdc920a0Smrg   }
555cdc920a0Smrg
556cdc920a0Smrg   switch (buffer) {
557cdc920a0Smrg   case GL_DEPTH:
558af69d88dSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
559af69d88dSmrg       *
560af69d88dSmrg       *     "ClearBuffer generates an INVALID VALUE error if buffer is
561af69d88dSmrg       *     COLOR and drawbuffer is less than zero, or greater than the
562af69d88dSmrg       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
563af69d88dSmrg       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
564af69d88dSmrg       */
56501e04c3fSmrg      if (!no_error && drawbuffer != 0) {
566cdc920a0Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
567cdc920a0Smrg                     drawbuffer);
568cdc920a0Smrg         return;
569cdc920a0Smrg      }
57001e04c3fSmrg      else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer
57101e04c3fSmrg               && !ctx->RasterDiscard) {
572cdc920a0Smrg         /* Save current depth clear value, set to 'value', do the
573cdc920a0Smrg          * depth clear and restore the clear value.
574cdc920a0Smrg          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
575cdc920a0Smrg          * hook instead.
576cdc920a0Smrg          */
577cdc920a0Smrg         const GLclampd clearSave = ctx->Depth.Clear;
578cdc920a0Smrg         ctx->Depth.Clear = *value;
579cdc920a0Smrg         ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
580cdc920a0Smrg         ctx->Depth.Clear = clearSave;
581cdc920a0Smrg      }
582cdc920a0Smrg      /* clear depth buffer to value */
583cdc920a0Smrg      break;
584cdc920a0Smrg   case GL_COLOR:
585cdc920a0Smrg      {
586cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
58701e04c3fSmrg         if (!no_error && mask == INVALID_MASK) {
588cdc920a0Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
589cdc920a0Smrg                        drawbuffer);
590cdc920a0Smrg            return;
591cdc920a0Smrg         }
592af69d88dSmrg         else if (mask && !ctx->RasterDiscard) {
593af69d88dSmrg            union gl_color_union clearSave;
594af69d88dSmrg
595cdc920a0Smrg            /* save color */
596af69d88dSmrg            clearSave = ctx->Color.ClearColor;
597cdc920a0Smrg            /* set color */
598af69d88dSmrg            COPY_4V(ctx->Color.ClearColor.f, value);
599cdc920a0Smrg            /* clear buffer(s) */
600cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
601cdc920a0Smrg            /* restore color */
602af69d88dSmrg            ctx->Color.ClearColor = clearSave;
603cdc920a0Smrg         }
604cdc920a0Smrg      }
605cdc920a0Smrg      break;
606cdc920a0Smrg   default:
60701e04c3fSmrg      if (!no_error) {
60801e04c3fSmrg         /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
60901e04c3fSmrg          * of the OpenGL 4.5 spec states:
61001e04c3fSmrg          *
61101e04c3fSmrg          *    "An INVALID_ENUM error is generated by ClearBufferfv and
61201e04c3fSmrg          *     ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
61301e04c3fSmrg          */
61401e04c3fSmrg         _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
61501e04c3fSmrg                     _mesa_enum_to_string(buffer));
61601e04c3fSmrg      }
617cdc920a0Smrg      return;
618cdc920a0Smrg   }
619cdc920a0Smrg}
620cdc920a0Smrg
621cdc920a0Smrg
62201e04c3fSmrgvoid GLAPIENTRY
62301e04c3fSmrg_mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer,
62401e04c3fSmrg                             const GLfloat *value)
62501e04c3fSmrg{
62601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
62701e04c3fSmrg   clear_bufferfv(ctx, buffer, drawbuffer, value, true);
62801e04c3fSmrg}
62901e04c3fSmrg
63001e04c3fSmrg
63101e04c3fSmrgvoid GLAPIENTRY
63201e04c3fSmrg_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
63301e04c3fSmrg{
63401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
63501e04c3fSmrg   clear_bufferfv(ctx, buffer, drawbuffer, value, false);
63601e04c3fSmrg}
63701e04c3fSmrg
63801e04c3fSmrg
63901e04c3fSmrg/**
64001e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the
64101e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake
64201e04c3fSmrg * direct state access clearing for the user.
64301e04c3fSmrg */
64401e04c3fSmrgvoid GLAPIENTRY
64501e04c3fSmrg_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
64601e04c3fSmrg                              GLint drawbuffer, const GLfloat *value)
64701e04c3fSmrg{
64801e04c3fSmrg   GLint oldfb;
64901e04c3fSmrg
65001e04c3fSmrg   _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
65101e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
65201e04c3fSmrg   _mesa_ClearBufferfv(buffer, drawbuffer, value);
65301e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
65401e04c3fSmrg}
65501e04c3fSmrg
65601e04c3fSmrg
657cdc920a0Smrg/**
658cdc920a0Smrg * New in GL 3.0
659cdc920a0Smrg * Clear depth/stencil buffer only.
660cdc920a0Smrg */
66101e04c3fSmrgstatic ALWAYS_INLINE void
66201e04c3fSmrgclear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer,
66301e04c3fSmrg               GLfloat depth, GLint stencil, bool no_error)
664cdc920a0Smrg{
665af69d88dSmrg   GLbitfield mask = 0;
666cdc920a0Smrg
667af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
668cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
669cdc920a0Smrg
67001e04c3fSmrg   if (!no_error) {
67101e04c3fSmrg      if (buffer != GL_DEPTH_STENCIL) {
67201e04c3fSmrg         _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
67301e04c3fSmrg                     _mesa_enum_to_string(buffer));
67401e04c3fSmrg         return;
67501e04c3fSmrg      }
676cdc920a0Smrg
67701e04c3fSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
67801e04c3fSmrg       *
67901e04c3fSmrg       *     "ClearBuffer generates an INVALID VALUE error if buffer is
68001e04c3fSmrg       *     COLOR and drawbuffer is less than zero, or greater than the
68101e04c3fSmrg       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
68201e04c3fSmrg       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
68301e04c3fSmrg       */
68401e04c3fSmrg      if (drawbuffer != 0) {
68501e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
68601e04c3fSmrg                     drawbuffer);
68701e04c3fSmrg         return;
68801e04c3fSmrg      }
689cdc920a0Smrg   }
690cdc920a0Smrg
691af69d88dSmrg   if (ctx->RasterDiscard)
692af69d88dSmrg      return;
693af69d88dSmrg
694cdc920a0Smrg   if (ctx->NewState) {
695cdc920a0Smrg      _mesa_update_state( ctx );
696cdc920a0Smrg   }
697cdc920a0Smrg
698af69d88dSmrg   if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
699af69d88dSmrg      mask |= BUFFER_BIT_DEPTH;
700af69d88dSmrg   if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
701af69d88dSmrg      mask |= BUFFER_BIT_STENCIL;
702af69d88dSmrg
703af69d88dSmrg   if (mask) {
704cdc920a0Smrg      /* save current clear values */
705cdc920a0Smrg      const GLclampd clearDepthSave = ctx->Depth.Clear;
706cdc920a0Smrg      const GLuint clearStencilSave = ctx->Stencil.Clear;
707cdc920a0Smrg
708cdc920a0Smrg      /* set new clear values */
709cdc920a0Smrg      ctx->Depth.Clear = depth;
710cdc920a0Smrg      ctx->Stencil.Clear = stencil;
711cdc920a0Smrg
712cdc920a0Smrg      /* clear buffers */
713af69d88dSmrg      ctx->Driver.Clear(ctx, mask);
714cdc920a0Smrg
715cdc920a0Smrg      /* restore */
716cdc920a0Smrg      ctx->Depth.Clear = clearDepthSave;
717cdc920a0Smrg      ctx->Stencil.Clear = clearStencilSave;
718cdc920a0Smrg   }
719cdc920a0Smrg}
72001e04c3fSmrg
72101e04c3fSmrg
72201e04c3fSmrgvoid GLAPIENTRY
72301e04c3fSmrg_mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer,
72401e04c3fSmrg                             GLfloat depth, GLint stencil)
72501e04c3fSmrg{
72601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
72701e04c3fSmrg   clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true);
72801e04c3fSmrg}
72901e04c3fSmrg
73001e04c3fSmrg
73101e04c3fSmrgvoid GLAPIENTRY
73201e04c3fSmrg_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
73301e04c3fSmrg                    GLfloat depth, GLint stencil)
73401e04c3fSmrg{
73501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
73601e04c3fSmrg   clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false);
73701e04c3fSmrg}
73801e04c3fSmrg
73901e04c3fSmrg
74001e04c3fSmrg/**
74101e04c3fSmrg * The ClearBuffer framework is so complicated and so riddled with the
74201e04c3fSmrg * assumption that the framebuffer is bound that, for now, we will just fake
74301e04c3fSmrg * direct state access clearing for the user.
74401e04c3fSmrg */
74501e04c3fSmrgvoid GLAPIENTRY
74601e04c3fSmrg_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
74701e04c3fSmrg                              GLint drawbuffer, GLfloat depth, GLint stencil)
74801e04c3fSmrg{
74901e04c3fSmrg   GLint oldfb;
75001e04c3fSmrg
75101e04c3fSmrg   _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
75201e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
75301e04c3fSmrg   _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil);
75401e04c3fSmrg   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
75501e04c3fSmrg}
756