clear.c revision af69d88d
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"
36c1f859d4Smrg#include "colormac.h"
37cdc920a0Smrg#include "enums.h"
383464ebd5Sriastradh#include "macros.h"
393464ebd5Sriastradh#include "mtypes.h"
40c1f859d4Smrg#include "state.h"
41c1f859d4Smrg
42c1f859d4Smrg
43c1f859d4Smrg
44c1f859d4Smrgvoid GLAPIENTRY
45c1f859d4Smrg_mesa_ClearIndex( GLfloat c )
46c1f859d4Smrg{
47c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
48c1f859d4Smrg
49c1f859d4Smrg   ctx->Color.ClearIndex = (GLuint) c;
50c1f859d4Smrg}
51c1f859d4Smrg
52c1f859d4Smrg
53c1f859d4Smrg/**
54c1f859d4Smrg * Specify the clear values for the color buffers.
55c1f859d4Smrg *
56c1f859d4Smrg * \param red red color component.
57c1f859d4Smrg * \param green green color component.
58c1f859d4Smrg * \param blue blue color component.
59c1f859d4Smrg * \param alpha alpha component.
60c1f859d4Smrg *
61c1f859d4Smrg * \sa glClearColor().
62c1f859d4Smrg *
63c1f859d4Smrg * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor.  On a
64c1f859d4Smrg * change, flushes the vertices and notifies the driver via the
65c1f859d4Smrg * dd_function_table::ClearColor callback.
66c1f859d4Smrg */
67c1f859d4Smrgvoid GLAPIENTRY
68c1f859d4Smrg_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
69c1f859d4Smrg{
70c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
713464ebd5Sriastradh
72af69d88dSmrg   ctx->Color.ClearColor.f[0] = red;
73af69d88dSmrg   ctx->Color.ClearColor.f[1] = green;
74af69d88dSmrg   ctx->Color.ClearColor.f[2] = blue;
75af69d88dSmrg   ctx->Color.ClearColor.f[3] = alpha;
76c1f859d4Smrg}
77c1f859d4Smrg
78c1f859d4Smrg
793464ebd5Sriastradh/**
803464ebd5Sriastradh * GL_EXT_texture_integer
813464ebd5Sriastradh */
823464ebd5Sriastradhvoid GLAPIENTRY
833464ebd5Sriastradh_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
843464ebd5Sriastradh{
853464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
863464ebd5Sriastradh
87af69d88dSmrg   ctx->Color.ClearColor.i[0] = r;
88af69d88dSmrg   ctx->Color.ClearColor.i[1] = g;
89af69d88dSmrg   ctx->Color.ClearColor.i[2] = b;
90af69d88dSmrg   ctx->Color.ClearColor.i[3] = a;
913464ebd5Sriastradh}
923464ebd5Sriastradh
933464ebd5Sriastradh
943464ebd5Sriastradh/**
953464ebd5Sriastradh * GL_EXT_texture_integer
963464ebd5Sriastradh */
973464ebd5Sriastradhvoid GLAPIENTRY
983464ebd5Sriastradh_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
993464ebd5Sriastradh{
1003464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
1013464ebd5Sriastradh
102af69d88dSmrg   ctx->Color.ClearColor.ui[0] = r;
103af69d88dSmrg   ctx->Color.ClearColor.ui[1] = g;
104af69d88dSmrg   ctx->Color.ClearColor.ui[2] = b;
105af69d88dSmrg   ctx->Color.ClearColor.ui[3] = a;
106af69d88dSmrg}
1073464ebd5Sriastradh
1083464ebd5Sriastradh
109af69d88dSmrg/**
110af69d88dSmrg * Returns true if color writes are enabled for the given color attachment.
111af69d88dSmrg *
112af69d88dSmrg * Beyond checking ColorMask, this uses _mesa_format_has_color_component to
113af69d88dSmrg * ignore components that don't actually exist in the format (such as X in
114af69d88dSmrg * XRGB).
115af69d88dSmrg */
116af69d88dSmrgstatic bool
117af69d88dSmrgcolor_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx)
118af69d88dSmrg{
119af69d88dSmrg   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx];
120af69d88dSmrg   GLuint c;
121af69d88dSmrg   GLubyte colorMask = 0;
122af69d88dSmrg
123af69d88dSmrg   if (rb) {
124af69d88dSmrg      for (c = 0; c < 4; c++) {
125af69d88dSmrg         if (_mesa_format_has_color_component(rb->Format, c))
126af69d88dSmrg            colorMask |= ctx->Color.ColorMask[idx][c];
127af69d88dSmrg      }
1283464ebd5Sriastradh   }
129af69d88dSmrg
130af69d88dSmrg   return colorMask != 0;
1313464ebd5Sriastradh}
1323464ebd5Sriastradh
1333464ebd5Sriastradh
134c1f859d4Smrg/**
135c1f859d4Smrg * Clear buffers.
136c1f859d4Smrg *
137c1f859d4Smrg * \param mask bit-mask indicating the buffers to be cleared.
138c1f859d4Smrg *
1393464ebd5Sriastradh * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState
140c1f859d4Smrg * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
141c1f859d4Smrg * etc. If the rasterization mode is set to GL_RENDER then requests the driver
142c1f859d4Smrg * to clear the buffers, via the dd_function_table::Clear callback.
143c1f859d4Smrg */
144c1f859d4Smrgvoid GLAPIENTRY
145c1f859d4Smrg_mesa_Clear( GLbitfield mask )
146c1f859d4Smrg{
147c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
148af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
149c1f859d4Smrg
150c1f859d4Smrg   FLUSH_CURRENT(ctx, 0);
151c1f859d4Smrg
152c1f859d4Smrg   if (MESA_VERBOSE & VERBOSE_API)
153c1f859d4Smrg      _mesa_debug(ctx, "glClear 0x%x\n", mask);
154c1f859d4Smrg
155c1f859d4Smrg   if (mask & ~(GL_COLOR_BUFFER_BIT |
156c1f859d4Smrg                GL_DEPTH_BUFFER_BIT |
157c1f859d4Smrg                GL_STENCIL_BUFFER_BIT |
158c1f859d4Smrg                GL_ACCUM_BUFFER_BIT)) {
159c1f859d4Smrg      /* invalid bit set */
160c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
161c1f859d4Smrg      return;
162c1f859d4Smrg   }
163c1f859d4Smrg
164af69d88dSmrg   /* Accumulation buffers were removed in core contexts, and they never
165af69d88dSmrg    * existed in OpenGL ES.
166af69d88dSmrg    */
167af69d88dSmrg   if ((mask & GL_ACCUM_BUFFER_BIT) != 0
168af69d88dSmrg       && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) {
169af69d88dSmrg      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)");
170af69d88dSmrg      return;
171af69d88dSmrg   }
172af69d88dSmrg
173c1f859d4Smrg   if (ctx->NewState) {
174c1f859d4Smrg      _mesa_update_state( ctx );	/* update _Xmin, etc */
175c1f859d4Smrg   }
176c1f859d4Smrg
177c1f859d4Smrg   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
178c1f859d4Smrg      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
179c1f859d4Smrg                  "glClear(incomplete framebuffer)");
180c1f859d4Smrg      return;
181c1f859d4Smrg   }
182c1f859d4Smrg
183af69d88dSmrg   if (ctx->RasterDiscard)
184c1f859d4Smrg      return;
185c1f859d4Smrg
186c1f859d4Smrg   if (ctx->RenderMode == GL_RENDER) {
187c1f859d4Smrg      GLbitfield bufferMask;
188c1f859d4Smrg
189c1f859d4Smrg      /* don't clear depth buffer if depth writing disabled */
190c1f859d4Smrg      if (!ctx->Depth.Mask)
191c1f859d4Smrg         mask &= ~GL_DEPTH_BUFFER_BIT;
192c1f859d4Smrg
193c1f859d4Smrg      /* Build the bitmask to send to device driver's Clear function.
194c1f859d4Smrg       * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
195c1f859d4Smrg       * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
196c1f859d4Smrg       * BUFFER_BIT_COLORn flags.
197c1f859d4Smrg       */
198c1f859d4Smrg      bufferMask = 0;
199c1f859d4Smrg      if (mask & GL_COLOR_BUFFER_BIT) {
200c1f859d4Smrg         GLuint i;
201c1f859d4Smrg         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
202af69d88dSmrg            GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
203af69d88dSmrg
204af69d88dSmrg            if (buf >= 0 && color_buffer_writes_enabled(ctx, i)) {
205af69d88dSmrg               bufferMask |= 1 << buf;
206af69d88dSmrg            }
207c1f859d4Smrg         }
208c1f859d4Smrg      }
209c1f859d4Smrg
210c1f859d4Smrg      if ((mask & GL_DEPTH_BUFFER_BIT)
211c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveDepthBuffer) {
212c1f859d4Smrg         bufferMask |= BUFFER_BIT_DEPTH;
213c1f859d4Smrg      }
214c1f859d4Smrg
215c1f859d4Smrg      if ((mask & GL_STENCIL_BUFFER_BIT)
216c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveStencilBuffer) {
217c1f859d4Smrg         bufferMask |= BUFFER_BIT_STENCIL;
218c1f859d4Smrg      }
219c1f859d4Smrg
220c1f859d4Smrg      if ((mask & GL_ACCUM_BUFFER_BIT)
221c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveAccumBuffer) {
222c1f859d4Smrg         bufferMask |= BUFFER_BIT_ACCUM;
223c1f859d4Smrg      }
224c1f859d4Smrg
225c1f859d4Smrg      ASSERT(ctx->Driver.Clear);
226c1f859d4Smrg      ctx->Driver.Clear(ctx, bufferMask);
227c1f859d4Smrg   }
228c1f859d4Smrg}
229cdc920a0Smrg
230cdc920a0Smrg
231cdc920a0Smrg/** Returned by make_color_buffer_mask() for errors */
232cdc920a0Smrg#define INVALID_MASK ~0x0
233cdc920a0Smrg
234cdc920a0Smrg
235cdc920a0Smrg/**
236cdc920a0Smrg * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
237cdc920a0Smrg * BUFFER_BIT_x values.
238cdc920a0Smrg * Return INVALID_MASK if the drawbuffer value is invalid.
239cdc920a0Smrg */
240cdc920a0Smrgstatic GLbitfield
2413464ebd5Sriastradhmake_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
242cdc920a0Smrg{
243cdc920a0Smrg   const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
244cdc920a0Smrg   GLbitfield mask = 0x0;
245cdc920a0Smrg
246af69d88dSmrg   /* From the GL 4.0 specification:
247af69d88dSmrg    *	If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is
248af69d88dSmrg    *	specified by passing i as the parameter drawbuffer, and value
249af69d88dSmrg    *	points to a four-element vector specifying the R, G, B, and A
250af69d88dSmrg    *	color to clear that draw buffer to. If the draw buffer is one
251af69d88dSmrg    *	of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying
252af69d88dSmrg    *	multiple buffers, each selected buffer is cleared to the same
253af69d88dSmrg    *	value.
254af69d88dSmrg    *
255af69d88dSmrg    * Note that "drawbuffer" and "draw buffer" have different meaning.
256af69d88dSmrg    * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's
257af69d88dSmrg    * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK,
258af69d88dSmrg    * etc.
259af69d88dSmrg    */
260af69d88dSmrg   if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
261af69d88dSmrg      return INVALID_MASK;
262af69d88dSmrg   }
263af69d88dSmrg
264af69d88dSmrg   switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) {
265cdc920a0Smrg   case GL_FRONT:
266cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
267cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
268cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
269cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
270cdc920a0Smrg      break;
271cdc920a0Smrg   case GL_BACK:
272cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
273cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
274cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
275cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
276cdc920a0Smrg      break;
277cdc920a0Smrg   case GL_LEFT:
278cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
279cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
280cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
281cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
282cdc920a0Smrg      break;
283cdc920a0Smrg   case GL_RIGHT:
284cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
285cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
286cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
287cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
288cdc920a0Smrg      break;
289cdc920a0Smrg   case GL_FRONT_AND_BACK:
290cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
291cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
292cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
293cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
294cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
295cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
296cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
297cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
298cdc920a0Smrg      break;
299cdc920a0Smrg   default:
300af69d88dSmrg      {
301af69d88dSmrg         GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer];
302af69d88dSmrg
303af69d88dSmrg         if (buf >= 0 && att[buf].Renderbuffer) {
304af69d88dSmrg            mask |= 1 << buf;
305af69d88dSmrg         }
306cdc920a0Smrg      }
307cdc920a0Smrg   }
308cdc920a0Smrg
309cdc920a0Smrg   return mask;
310cdc920a0Smrg}
311cdc920a0Smrg
312cdc920a0Smrg
313cdc920a0Smrg
314cdc920a0Smrg/**
315cdc920a0Smrg * New in GL 3.0
316cdc920a0Smrg * Clear signed integer color buffer or stencil buffer (not depth).
317cdc920a0Smrg */
318cdc920a0Smrgvoid GLAPIENTRY
319cdc920a0Smrg_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
320cdc920a0Smrg{
321cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
322af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
323cdc920a0Smrg
324cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
325cdc920a0Smrg
326cdc920a0Smrg   if (ctx->NewState) {
327cdc920a0Smrg      _mesa_update_state( ctx );
328cdc920a0Smrg   }
329cdc920a0Smrg
330cdc920a0Smrg   switch (buffer) {
331cdc920a0Smrg   case GL_STENCIL:
332af69d88dSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
333af69d88dSmrg       *
334af69d88dSmrg       *     "ClearBuffer generates an INVALID VALUE error if buffer is
335af69d88dSmrg       *     COLOR and drawbuffer is less than zero, or greater than the
336af69d88dSmrg       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
337af69d88dSmrg       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
338af69d88dSmrg       */
339cdc920a0Smrg      if (drawbuffer != 0) {
340cdc920a0Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
341cdc920a0Smrg                     drawbuffer);
342cdc920a0Smrg         return;
343cdc920a0Smrg      }
344af69d88dSmrg      else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer && !ctx->RasterDiscard) {
345cdc920a0Smrg         /* Save current stencil clear value, set to 'value', do the
346cdc920a0Smrg          * stencil clear and restore the clear value.
347cdc920a0Smrg          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
348cdc920a0Smrg          * hook instead.
349cdc920a0Smrg          */
350cdc920a0Smrg         const GLuint clearSave = ctx->Stencil.Clear;
351cdc920a0Smrg         ctx->Stencil.Clear = *value;
352cdc920a0Smrg         ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
353cdc920a0Smrg         ctx->Stencil.Clear = clearSave;
354cdc920a0Smrg      }
355cdc920a0Smrg      break;
356cdc920a0Smrg   case GL_COLOR:
357cdc920a0Smrg      {
358cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
359cdc920a0Smrg         if (mask == INVALID_MASK) {
360cdc920a0Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
361cdc920a0Smrg                        drawbuffer);
362cdc920a0Smrg            return;
363cdc920a0Smrg         }
364af69d88dSmrg         else if (mask && !ctx->RasterDiscard) {
365af69d88dSmrg            union gl_color_union clearSave;
366af69d88dSmrg
367cdc920a0Smrg            /* save color */
368af69d88dSmrg            clearSave = ctx->Color.ClearColor;
369cdc920a0Smrg            /* set color */
370af69d88dSmrg            COPY_4V(ctx->Color.ClearColor.i, value);
371cdc920a0Smrg            /* clear buffer(s) */
372cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
373cdc920a0Smrg            /* restore color */
374af69d88dSmrg            ctx->Color.ClearColor = clearSave;
375cdc920a0Smrg         }
376cdc920a0Smrg      }
377cdc920a0Smrg      break;
378af69d88dSmrg   case GL_DEPTH:
379af69d88dSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
380af69d88dSmrg       *
381af69d88dSmrg       *     "The result of ClearBuffer is undefined if no conversion between
382af69d88dSmrg       *     the type of the specified value and the type of the buffer being
383af69d88dSmrg       *     cleared is defined (for example, if ClearBufferiv is called for a
384af69d88dSmrg       *     fixed- or floating-point buffer, or if ClearBufferfv is called
385af69d88dSmrg       *     for a signed or unsigned integer buffer). This is not an error."
386af69d88dSmrg       *
387af69d88dSmrg       * In this case we take "undefined" and "not an error" to mean "ignore."
388af69d88dSmrg       * Note that we still need to generate an error for the invalid
389af69d88dSmrg       * drawbuffer case (see the GL_STENCIL case above).
390af69d88dSmrg       */
391af69d88dSmrg      if (drawbuffer != 0) {
392af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
393af69d88dSmrg                     drawbuffer);
394af69d88dSmrg         return;
395af69d88dSmrg      }
396af69d88dSmrg      return;
397cdc920a0Smrg   default:
398cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
399cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
400cdc920a0Smrg      return;
401cdc920a0Smrg   }
402cdc920a0Smrg}
403cdc920a0Smrg
404cdc920a0Smrg
405cdc920a0Smrg/**
406cdc920a0Smrg * New in GL 3.0
407cdc920a0Smrg * Clear unsigned integer color buffer (not depth, not stencil).
408cdc920a0Smrg */
409cdc920a0Smrgvoid GLAPIENTRY
410cdc920a0Smrg_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
411cdc920a0Smrg{
412cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
413cdc920a0Smrg
414af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
415cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
416cdc920a0Smrg
417cdc920a0Smrg   if (ctx->NewState) {
418cdc920a0Smrg      _mesa_update_state( ctx );
419cdc920a0Smrg   }
420cdc920a0Smrg
421cdc920a0Smrg   switch (buffer) {
422cdc920a0Smrg   case GL_COLOR:
423cdc920a0Smrg      {
424cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
425cdc920a0Smrg         if (mask == INVALID_MASK) {
4263464ebd5Sriastradh            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
427cdc920a0Smrg                        drawbuffer);
428cdc920a0Smrg            return;
429cdc920a0Smrg         }
430af69d88dSmrg         else if (mask && !ctx->RasterDiscard) {
431af69d88dSmrg            union gl_color_union clearSave;
432af69d88dSmrg
433cdc920a0Smrg            /* save color */
434af69d88dSmrg            clearSave = ctx->Color.ClearColor;
435cdc920a0Smrg            /* set color */
436af69d88dSmrg            COPY_4V(ctx->Color.ClearColor.ui, value);
437cdc920a0Smrg            /* clear buffer(s) */
438cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
439cdc920a0Smrg            /* restore color */
440af69d88dSmrg            ctx->Color.ClearColor = clearSave;
441cdc920a0Smrg         }
442cdc920a0Smrg      }
443cdc920a0Smrg      break;
444af69d88dSmrg   case GL_DEPTH:
445af69d88dSmrg   case GL_STENCIL:
446af69d88dSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
447af69d88dSmrg       *
448af69d88dSmrg       *     "The result of ClearBuffer is undefined if no conversion between
449af69d88dSmrg       *     the type of the specified value and the type of the buffer being
450af69d88dSmrg       *     cleared is defined (for example, if ClearBufferiv is called for a
451af69d88dSmrg       *     fixed- or floating-point buffer, or if ClearBufferfv is called
452af69d88dSmrg       *     for a signed or unsigned integer buffer). This is not an error."
453af69d88dSmrg       *
454af69d88dSmrg       * In this case we take "undefined" and "not an error" to mean "ignore."
455af69d88dSmrg       * Even though we could do something sensible for GL_STENCIL, page 263
456af69d88dSmrg       * (page 279 of the PDF) says:
457af69d88dSmrg       *
458af69d88dSmrg       *     "Only ClearBufferiv should be used to clear stencil buffers."
459af69d88dSmrg       *
460af69d88dSmrg       * Note that we still need to generate an error for the invalid
461af69d88dSmrg       * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv).
462af69d88dSmrg       */
463af69d88dSmrg      if (drawbuffer != 0) {
464af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
465af69d88dSmrg                     drawbuffer);
466af69d88dSmrg         return;
467af69d88dSmrg      }
468af69d88dSmrg      return;
469cdc920a0Smrg   default:
470cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
471cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
472cdc920a0Smrg      return;
473cdc920a0Smrg   }
474cdc920a0Smrg}
475cdc920a0Smrg
476cdc920a0Smrg
477cdc920a0Smrg/**
478cdc920a0Smrg * New in GL 3.0
479cdc920a0Smrg * Clear fixed-pt or float color buffer or depth buffer (not stencil).
480cdc920a0Smrg */
481cdc920a0Smrgvoid GLAPIENTRY
482cdc920a0Smrg_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
483cdc920a0Smrg{
484cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
485cdc920a0Smrg
486af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
487cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
488cdc920a0Smrg
489cdc920a0Smrg   if (ctx->NewState) {
490cdc920a0Smrg      _mesa_update_state( ctx );
491cdc920a0Smrg   }
492cdc920a0Smrg
493cdc920a0Smrg   switch (buffer) {
494cdc920a0Smrg   case GL_DEPTH:
495af69d88dSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
496af69d88dSmrg       *
497af69d88dSmrg       *     "ClearBuffer generates an INVALID VALUE error if buffer is
498af69d88dSmrg       *     COLOR and drawbuffer is less than zero, or greater than the
499af69d88dSmrg       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
500af69d88dSmrg       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
501af69d88dSmrg       */
502cdc920a0Smrg      if (drawbuffer != 0) {
503cdc920a0Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
504cdc920a0Smrg                     drawbuffer);
505cdc920a0Smrg         return;
506cdc920a0Smrg      }
507af69d88dSmrg      else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) {
508cdc920a0Smrg         /* Save current depth clear value, set to 'value', do the
509cdc920a0Smrg          * depth clear and restore the clear value.
510cdc920a0Smrg          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
511cdc920a0Smrg          * hook instead.
512cdc920a0Smrg          */
513cdc920a0Smrg         const GLclampd clearSave = ctx->Depth.Clear;
514cdc920a0Smrg         ctx->Depth.Clear = *value;
515cdc920a0Smrg         ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
516cdc920a0Smrg         ctx->Depth.Clear = clearSave;
517cdc920a0Smrg      }
518cdc920a0Smrg      /* clear depth buffer to value */
519cdc920a0Smrg      break;
520cdc920a0Smrg   case GL_COLOR:
521cdc920a0Smrg      {
522cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
523cdc920a0Smrg         if (mask == INVALID_MASK) {
524cdc920a0Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
525cdc920a0Smrg                        drawbuffer);
526cdc920a0Smrg            return;
527cdc920a0Smrg         }
528af69d88dSmrg         else if (mask && !ctx->RasterDiscard) {
529af69d88dSmrg            union gl_color_union clearSave;
530af69d88dSmrg
531cdc920a0Smrg            /* save color */
532af69d88dSmrg            clearSave = ctx->Color.ClearColor;
533cdc920a0Smrg            /* set color */
534af69d88dSmrg            COPY_4V(ctx->Color.ClearColor.f, value);
535cdc920a0Smrg            /* clear buffer(s) */
536cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
537cdc920a0Smrg            /* restore color */
538af69d88dSmrg            ctx->Color.ClearColor = clearSave;
539cdc920a0Smrg         }
540cdc920a0Smrg      }
541cdc920a0Smrg      break;
542af69d88dSmrg   case GL_STENCIL:
543af69d88dSmrg      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
544af69d88dSmrg       *
545af69d88dSmrg       *     "The result of ClearBuffer is undefined if no conversion between
546af69d88dSmrg       *     the type of the specified value and the type of the buffer being
547af69d88dSmrg       *     cleared is defined (for example, if ClearBufferiv is called for a
548af69d88dSmrg       *     fixed- or floating-point buffer, or if ClearBufferfv is called
549af69d88dSmrg       *     for a signed or unsigned integer buffer). This is not an error."
550af69d88dSmrg       *
551af69d88dSmrg       * In this case we take "undefined" and "not an error" to mean "ignore."
552af69d88dSmrg       * Note that we still need to generate an error for the invalid
553af69d88dSmrg       * drawbuffer case (see the GL_DEPTH case above).
554af69d88dSmrg       */
555af69d88dSmrg      if (drawbuffer != 0) {
556af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
557af69d88dSmrg                     drawbuffer);
558af69d88dSmrg         return;
559af69d88dSmrg      }
560af69d88dSmrg      return;
561cdc920a0Smrg   default:
562cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
563cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
564cdc920a0Smrg      return;
565cdc920a0Smrg   }
566cdc920a0Smrg}
567cdc920a0Smrg
568cdc920a0Smrg
569cdc920a0Smrg/**
570cdc920a0Smrg * New in GL 3.0
571cdc920a0Smrg * Clear depth/stencil buffer only.
572cdc920a0Smrg */
573cdc920a0Smrgvoid GLAPIENTRY
574cdc920a0Smrg_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
575cdc920a0Smrg                    GLfloat depth, GLint stencil)
576cdc920a0Smrg{
577cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
578af69d88dSmrg   GLbitfield mask = 0;
579cdc920a0Smrg
580af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
581cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
582cdc920a0Smrg
583cdc920a0Smrg   if (buffer != GL_DEPTH_STENCIL) {
584cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
585cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
586cdc920a0Smrg      return;
587cdc920a0Smrg   }
588cdc920a0Smrg
589af69d88dSmrg   /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
590af69d88dSmrg    *
591af69d88dSmrg    *     "ClearBuffer generates an INVALID VALUE error if buffer is
592af69d88dSmrg    *     COLOR and drawbuffer is less than zero, or greater than the
593af69d88dSmrg    *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
594af69d88dSmrg    *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
595af69d88dSmrg    */
596cdc920a0Smrg   if (drawbuffer != 0) {
597cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
598cdc920a0Smrg                  drawbuffer);
599cdc920a0Smrg      return;
600cdc920a0Smrg   }
601cdc920a0Smrg
602af69d88dSmrg   if (ctx->RasterDiscard)
603af69d88dSmrg      return;
604af69d88dSmrg
605cdc920a0Smrg   if (ctx->NewState) {
606cdc920a0Smrg      _mesa_update_state( ctx );
607cdc920a0Smrg   }
608cdc920a0Smrg
609af69d88dSmrg   if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
610af69d88dSmrg      mask |= BUFFER_BIT_DEPTH;
611af69d88dSmrg   if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
612af69d88dSmrg      mask |= BUFFER_BIT_STENCIL;
613af69d88dSmrg
614af69d88dSmrg   if (mask) {
615cdc920a0Smrg      /* save current clear values */
616cdc920a0Smrg      const GLclampd clearDepthSave = ctx->Depth.Clear;
617cdc920a0Smrg      const GLuint clearStencilSave = ctx->Stencil.Clear;
618cdc920a0Smrg
619cdc920a0Smrg      /* set new clear values */
620cdc920a0Smrg      ctx->Depth.Clear = depth;
621cdc920a0Smrg      ctx->Stencil.Clear = stencil;
622cdc920a0Smrg
623cdc920a0Smrg      /* clear buffers */
624af69d88dSmrg      ctx->Driver.Clear(ctx, mask);
625cdc920a0Smrg
626cdc920a0Smrg      /* restore */
627cdc920a0Smrg      ctx->Depth.Clear = clearDepthSave;
628cdc920a0Smrg      ctx->Stencil.Clear = clearStencilSave;
629cdc920a0Smrg   }
630cdc920a0Smrg}
631