clear.c revision cdc920a0
1c1f859d4Smrg/*
2c1f859d4Smrg * Mesa 3-D graphics library
3c1f859d4Smrg * Version:  7.1
4c1f859d4Smrg *
5c1f859d4Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6c1f859d4Smrg *
7c1f859d4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8c1f859d4Smrg * copy of this software and associated documentation files (the "Software"),
9c1f859d4Smrg * to deal in the Software without restriction, including without limitation
10c1f859d4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11c1f859d4Smrg * and/or sell copies of the Software, and to permit persons to whom the
12c1f859d4Smrg * Software is furnished to do so, subject to the following conditions:
13c1f859d4Smrg *
14c1f859d4Smrg * The above copyright notice and this permission notice shall be included
15c1f859d4Smrg * in all copies or substantial portions of the Software.
16c1f859d4Smrg *
17c1f859d4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18c1f859d4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19c1f859d4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20c1f859d4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21c1f859d4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22c1f859d4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR 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"
38c1f859d4Smrg#include "state.h"
39c1f859d4Smrg
40c1f859d4Smrg
41c1f859d4Smrg
42c1f859d4Smrg#if _HAVE_FULL_GL
43c1f859d4Smrgvoid GLAPIENTRY
44c1f859d4Smrg_mesa_ClearIndex( GLfloat c )
45c1f859d4Smrg{
46c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
47c1f859d4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
48c1f859d4Smrg
49c1f859d4Smrg   if (ctx->Color.ClearIndex == (GLuint) c)
50c1f859d4Smrg      return;
51c1f859d4Smrg
52c1f859d4Smrg   FLUSH_VERTICES(ctx, _NEW_COLOR);
53c1f859d4Smrg   ctx->Color.ClearIndex = (GLuint) c;
54c1f859d4Smrg}
55c1f859d4Smrg#endif
56c1f859d4Smrg
57c1f859d4Smrg
58c1f859d4Smrg/**
59c1f859d4Smrg * Specify the clear values for the color buffers.
60c1f859d4Smrg *
61c1f859d4Smrg * \param red red color component.
62c1f859d4Smrg * \param green green color component.
63c1f859d4Smrg * \param blue blue color component.
64c1f859d4Smrg * \param alpha alpha component.
65c1f859d4Smrg *
66c1f859d4Smrg * \sa glClearColor().
67c1f859d4Smrg *
68c1f859d4Smrg * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor.  On a
69c1f859d4Smrg * change, flushes the vertices and notifies the driver via the
70c1f859d4Smrg * dd_function_table::ClearColor callback.
71c1f859d4Smrg */
72c1f859d4Smrgvoid GLAPIENTRY
73c1f859d4Smrg_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
74c1f859d4Smrg{
75c1f859d4Smrg   GLfloat tmp[4];
76c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
77c1f859d4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
78c1f859d4Smrg
79c1f859d4Smrg   tmp[0] = CLAMP(red,   0.0F, 1.0F);
80c1f859d4Smrg   tmp[1] = CLAMP(green, 0.0F, 1.0F);
81c1f859d4Smrg   tmp[2] = CLAMP(blue,  0.0F, 1.0F);
82c1f859d4Smrg   tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
83c1f859d4Smrg
84c1f859d4Smrg   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
85c1f859d4Smrg      return; /* no change */
86c1f859d4Smrg
87c1f859d4Smrg   FLUSH_VERTICES(ctx, _NEW_COLOR);
88c1f859d4Smrg   COPY_4V(ctx->Color.ClearColor, tmp);
89c1f859d4Smrg
90cdc920a0Smrg   if (ctx->Driver.ClearColor) {
91c1f859d4Smrg      /* it's OK to call glClearColor in CI mode but it should be a NOP */
92c1f859d4Smrg      (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor);
93c1f859d4Smrg   }
94c1f859d4Smrg}
95c1f859d4Smrg
96c1f859d4Smrg
97c1f859d4Smrg/**
98c1f859d4Smrg * Clear buffers.
99c1f859d4Smrg *
100c1f859d4Smrg * \param mask bit-mask indicating the buffers to be cleared.
101c1f859d4Smrg *
102c1f859d4Smrg * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState
103c1f859d4Smrg * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
104c1f859d4Smrg * etc. If the rasterization mode is set to GL_RENDER then requests the driver
105c1f859d4Smrg * to clear the buffers, via the dd_function_table::Clear callback.
106c1f859d4Smrg */
107c1f859d4Smrgvoid GLAPIENTRY
108c1f859d4Smrg_mesa_Clear( GLbitfield mask )
109c1f859d4Smrg{
110c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
111c1f859d4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
112c1f859d4Smrg
113c1f859d4Smrg   FLUSH_CURRENT(ctx, 0);
114c1f859d4Smrg
115c1f859d4Smrg   if (MESA_VERBOSE & VERBOSE_API)
116c1f859d4Smrg      _mesa_debug(ctx, "glClear 0x%x\n", mask);
117c1f859d4Smrg
118c1f859d4Smrg   if (mask & ~(GL_COLOR_BUFFER_BIT |
119c1f859d4Smrg                GL_DEPTH_BUFFER_BIT |
120c1f859d4Smrg                GL_STENCIL_BUFFER_BIT |
121c1f859d4Smrg                GL_ACCUM_BUFFER_BIT)) {
122c1f859d4Smrg      /* invalid bit set */
123c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
124c1f859d4Smrg      return;
125c1f859d4Smrg   }
126c1f859d4Smrg
127c1f859d4Smrg   if (ctx->NewState) {
128c1f859d4Smrg      _mesa_update_state( ctx );	/* update _Xmin, etc */
129c1f859d4Smrg   }
130c1f859d4Smrg
131c1f859d4Smrg   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
132c1f859d4Smrg      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
133c1f859d4Smrg                  "glClear(incomplete framebuffer)");
134c1f859d4Smrg      return;
135c1f859d4Smrg   }
136c1f859d4Smrg
137c1f859d4Smrg   if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 ||
138c1f859d4Smrg       ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax ||
139c1f859d4Smrg       ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax)
140c1f859d4Smrg      return;
141c1f859d4Smrg
142c1f859d4Smrg   if (ctx->RenderMode == GL_RENDER) {
143c1f859d4Smrg      GLbitfield bufferMask;
144c1f859d4Smrg
145c1f859d4Smrg      /* don't clear depth buffer if depth writing disabled */
146c1f859d4Smrg      if (!ctx->Depth.Mask)
147c1f859d4Smrg         mask &= ~GL_DEPTH_BUFFER_BIT;
148c1f859d4Smrg
149c1f859d4Smrg      /* Build the bitmask to send to device driver's Clear function.
150c1f859d4Smrg       * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
151c1f859d4Smrg       * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
152c1f859d4Smrg       * BUFFER_BIT_COLORn flags.
153c1f859d4Smrg       */
154c1f859d4Smrg      bufferMask = 0;
155c1f859d4Smrg      if (mask & GL_COLOR_BUFFER_BIT) {
156c1f859d4Smrg         GLuint i;
157c1f859d4Smrg         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
158c1f859d4Smrg            bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]);
159c1f859d4Smrg         }
160c1f859d4Smrg      }
161c1f859d4Smrg
162c1f859d4Smrg      if ((mask & GL_DEPTH_BUFFER_BIT)
163c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveDepthBuffer) {
164c1f859d4Smrg         bufferMask |= BUFFER_BIT_DEPTH;
165c1f859d4Smrg      }
166c1f859d4Smrg
167c1f859d4Smrg      if ((mask & GL_STENCIL_BUFFER_BIT)
168c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveStencilBuffer) {
169c1f859d4Smrg         bufferMask |= BUFFER_BIT_STENCIL;
170c1f859d4Smrg      }
171c1f859d4Smrg
172c1f859d4Smrg      if ((mask & GL_ACCUM_BUFFER_BIT)
173c1f859d4Smrg          && ctx->DrawBuffer->Visual.haveAccumBuffer) {
174c1f859d4Smrg         bufferMask |= BUFFER_BIT_ACCUM;
175c1f859d4Smrg      }
176c1f859d4Smrg
177c1f859d4Smrg      ASSERT(ctx->Driver.Clear);
178c1f859d4Smrg      ctx->Driver.Clear(ctx, bufferMask);
179c1f859d4Smrg   }
180c1f859d4Smrg}
181cdc920a0Smrg
182cdc920a0Smrg
183cdc920a0Smrg/** Returned by make_color_buffer_mask() for errors */
184cdc920a0Smrg#define INVALID_MASK ~0x0
185cdc920a0Smrg
186cdc920a0Smrg
187cdc920a0Smrg/**
188cdc920a0Smrg * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
189cdc920a0Smrg * BUFFER_BIT_x values.
190cdc920a0Smrg * Return INVALID_MASK if the drawbuffer value is invalid.
191cdc920a0Smrg */
192cdc920a0Smrgstatic GLbitfield
193cdc920a0Smrgmake_color_buffer_mask(GLcontext *ctx, GLint drawbuffer)
194cdc920a0Smrg{
195cdc920a0Smrg   const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
196cdc920a0Smrg   GLbitfield mask = 0x0;
197cdc920a0Smrg
198cdc920a0Smrg   switch (drawbuffer) {
199cdc920a0Smrg   case GL_FRONT:
200cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
201cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
202cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
203cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
204cdc920a0Smrg      break;
205cdc920a0Smrg   case GL_BACK:
206cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
207cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
208cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
209cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
210cdc920a0Smrg      break;
211cdc920a0Smrg   case GL_LEFT:
212cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
213cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
214cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
215cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
216cdc920a0Smrg      break;
217cdc920a0Smrg   case GL_RIGHT:
218cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
219cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
220cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
221cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
222cdc920a0Smrg      break;
223cdc920a0Smrg   case GL_FRONT_AND_BACK:
224cdc920a0Smrg      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
225cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_LEFT;
226cdc920a0Smrg      if (att[BUFFER_BACK_LEFT].Renderbuffer)
227cdc920a0Smrg         mask |= BUFFER_BIT_BACK_LEFT;
228cdc920a0Smrg      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
229cdc920a0Smrg         mask |= BUFFER_BIT_FRONT_RIGHT;
230cdc920a0Smrg      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
231cdc920a0Smrg         mask |= BUFFER_BIT_BACK_RIGHT;
232cdc920a0Smrg      break;
233cdc920a0Smrg   default:
234cdc920a0Smrg      if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
235cdc920a0Smrg         mask = INVALID_MASK;
236cdc920a0Smrg      }
237cdc920a0Smrg      else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) {
238cdc920a0Smrg         mask |= (BUFFER_BIT_COLOR0 << drawbuffer);
239cdc920a0Smrg      }
240cdc920a0Smrg   }
241cdc920a0Smrg
242cdc920a0Smrg   return mask;
243cdc920a0Smrg}
244cdc920a0Smrg
245cdc920a0Smrg
246cdc920a0Smrg
247cdc920a0Smrg/**
248cdc920a0Smrg * New in GL 3.0
249cdc920a0Smrg * Clear signed integer color buffer or stencil buffer (not depth).
250cdc920a0Smrg */
251cdc920a0Smrgvoid GLAPIENTRY
252cdc920a0Smrg_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
253cdc920a0Smrg{
254cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
255cdc920a0Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
256cdc920a0Smrg
257cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
258cdc920a0Smrg
259cdc920a0Smrg   if (ctx->NewState) {
260cdc920a0Smrg      _mesa_update_state( ctx );
261cdc920a0Smrg   }
262cdc920a0Smrg
263cdc920a0Smrg   switch (buffer) {
264cdc920a0Smrg   case GL_STENCIL:
265cdc920a0Smrg      if (drawbuffer != 0) {
266cdc920a0Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
267cdc920a0Smrg                     drawbuffer);
268cdc920a0Smrg         return;
269cdc920a0Smrg      }
270cdc920a0Smrg      else {
271cdc920a0Smrg         /* Save current stencil clear value, set to 'value', do the
272cdc920a0Smrg          * stencil clear and restore the clear value.
273cdc920a0Smrg          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
274cdc920a0Smrg          * hook instead.
275cdc920a0Smrg          */
276cdc920a0Smrg         const GLuint clearSave = ctx->Stencil.Clear;
277cdc920a0Smrg         ctx->Stencil.Clear = *value;
278cdc920a0Smrg         if (ctx->Driver.ClearStencil)
279cdc920a0Smrg            ctx->Driver.ClearStencil(ctx, *value);
280cdc920a0Smrg         ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
281cdc920a0Smrg         ctx->Stencil.Clear = clearSave;
282cdc920a0Smrg         if (ctx->Driver.ClearStencil)
283cdc920a0Smrg            ctx->Driver.ClearStencil(ctx, clearSave);
284cdc920a0Smrg      }
285cdc920a0Smrg      break;
286cdc920a0Smrg   case GL_COLOR:
287cdc920a0Smrg      {
288cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
289cdc920a0Smrg         if (mask == INVALID_MASK) {
290cdc920a0Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
291cdc920a0Smrg                        drawbuffer);
292cdc920a0Smrg            return;
293cdc920a0Smrg         }
294cdc920a0Smrg         else if (mask) {
295cdc920a0Smrg            /* XXX note: we're putting the integer clear values into the
296cdc920a0Smrg             * floating point state var.  This will not always work.  We'll
297cdc920a0Smrg             * need a new ctx->Driver.ClearBuffer() hook....
298cdc920a0Smrg             */
299cdc920a0Smrg            GLclampf clearSave[4];
300cdc920a0Smrg            /* save color */
301cdc920a0Smrg            COPY_4V(clearSave, ctx->Color.ClearColor);
302cdc920a0Smrg            /* set color */
303cdc920a0Smrg            COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
304cdc920a0Smrg            if (ctx->Driver.ClearColor)
305cdc920a0Smrg               ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
306cdc920a0Smrg            /* clear buffer(s) */
307cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
308cdc920a0Smrg            /* restore color */
309cdc920a0Smrg            COPY_4V(ctx->Color.ClearColor, clearSave);
310cdc920a0Smrg            if (ctx->Driver.ClearColor)
311cdc920a0Smrg               ctx->Driver.ClearColor(ctx, clearSave);
312cdc920a0Smrg         }
313cdc920a0Smrg      }
314cdc920a0Smrg      break;
315cdc920a0Smrg   default:
316cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
317cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
318cdc920a0Smrg      return;
319cdc920a0Smrg   }
320cdc920a0Smrg}
321cdc920a0Smrg
322cdc920a0Smrg
323cdc920a0Smrg/**
324cdc920a0Smrg * New in GL 3.0
325cdc920a0Smrg * Clear unsigned integer color buffer (not depth, not stencil).
326cdc920a0Smrg */
327cdc920a0Smrgvoid GLAPIENTRY
328cdc920a0Smrg_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
329cdc920a0Smrg{
330cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
331cdc920a0Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
332cdc920a0Smrg
333cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
334cdc920a0Smrg
335cdc920a0Smrg   if (ctx->NewState) {
336cdc920a0Smrg      _mesa_update_state( ctx );
337cdc920a0Smrg   }
338cdc920a0Smrg
339cdc920a0Smrg   switch (buffer) {
340cdc920a0Smrg   case GL_COLOR:
341cdc920a0Smrg      {
342cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
343cdc920a0Smrg         if (mask == INVALID_MASK) {
344cdc920a0Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
345cdc920a0Smrg                        drawbuffer);
346cdc920a0Smrg            return;
347cdc920a0Smrg         }
348cdc920a0Smrg         else if (mask) {
349cdc920a0Smrg            /* XXX note: we're putting the uint clear values into the
350cdc920a0Smrg             * floating point state var.  This will not always work.  We'll
351cdc920a0Smrg             * need a new ctx->Driver.ClearBuffer() hook....
352cdc920a0Smrg             */
353cdc920a0Smrg            GLclampf clearSave[4];
354cdc920a0Smrg            /* save color */
355cdc920a0Smrg            COPY_4V(clearSave, ctx->Color.ClearColor);
356cdc920a0Smrg            /* set color */
357cdc920a0Smrg            COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
358cdc920a0Smrg            if (ctx->Driver.ClearColor)
359cdc920a0Smrg               ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
360cdc920a0Smrg            /* clear buffer(s) */
361cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
362cdc920a0Smrg            /* restore color */
363cdc920a0Smrg            COPY_4V(ctx->Color.ClearColor, clearSave);
364cdc920a0Smrg            if (ctx->Driver.ClearColor)
365cdc920a0Smrg               ctx->Driver.ClearColor(ctx, clearSave);
366cdc920a0Smrg         }
367cdc920a0Smrg      }
368cdc920a0Smrg      break;
369cdc920a0Smrg   default:
370cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
371cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
372cdc920a0Smrg      return;
373cdc920a0Smrg   }
374cdc920a0Smrg}
375cdc920a0Smrg
376cdc920a0Smrg
377cdc920a0Smrg/**
378cdc920a0Smrg * New in GL 3.0
379cdc920a0Smrg * Clear fixed-pt or float color buffer or depth buffer (not stencil).
380cdc920a0Smrg */
381cdc920a0Smrgvoid GLAPIENTRY
382cdc920a0Smrg_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
383cdc920a0Smrg{
384cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
385cdc920a0Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
386cdc920a0Smrg
387cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
388cdc920a0Smrg
389cdc920a0Smrg   if (ctx->NewState) {
390cdc920a0Smrg      _mesa_update_state( ctx );
391cdc920a0Smrg   }
392cdc920a0Smrg
393cdc920a0Smrg   switch (buffer) {
394cdc920a0Smrg   case GL_DEPTH:
395cdc920a0Smrg      if (drawbuffer != 0) {
396cdc920a0Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
397cdc920a0Smrg                     drawbuffer);
398cdc920a0Smrg         return;
399cdc920a0Smrg      }
400cdc920a0Smrg      else {
401cdc920a0Smrg         /* Save current depth clear value, set to 'value', do the
402cdc920a0Smrg          * depth clear and restore the clear value.
403cdc920a0Smrg          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
404cdc920a0Smrg          * hook instead.
405cdc920a0Smrg          */
406cdc920a0Smrg         const GLclampd clearSave = ctx->Depth.Clear;
407cdc920a0Smrg         ctx->Depth.Clear = *value;
408cdc920a0Smrg         if (ctx->Driver.ClearDepth)
409cdc920a0Smrg            ctx->Driver.ClearDepth(ctx, *value);
410cdc920a0Smrg         ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
411cdc920a0Smrg         ctx->Depth.Clear = clearSave;
412cdc920a0Smrg         if (ctx->Driver.ClearDepth)
413cdc920a0Smrg            ctx->Driver.ClearDepth(ctx, clearSave);
414cdc920a0Smrg      }
415cdc920a0Smrg      /* clear depth buffer to value */
416cdc920a0Smrg      break;
417cdc920a0Smrg   case GL_COLOR:
418cdc920a0Smrg      {
419cdc920a0Smrg         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
420cdc920a0Smrg         if (mask == INVALID_MASK) {
421cdc920a0Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
422cdc920a0Smrg                        drawbuffer);
423cdc920a0Smrg            return;
424cdc920a0Smrg         }
425cdc920a0Smrg         else if (mask) {
426cdc920a0Smrg            GLclampf clearSave[4];
427cdc920a0Smrg            /* save color */
428cdc920a0Smrg            COPY_4V(clearSave, ctx->Color.ClearColor);
429cdc920a0Smrg            /* set color */
430cdc920a0Smrg            COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
431cdc920a0Smrg            if (ctx->Driver.ClearColor)
432cdc920a0Smrg               ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
433cdc920a0Smrg            /* clear buffer(s) */
434cdc920a0Smrg            ctx->Driver.Clear(ctx, mask);
435cdc920a0Smrg            /* restore color */
436cdc920a0Smrg            COPY_4V(ctx->Color.ClearColor, clearSave);
437cdc920a0Smrg            if (ctx->Driver.ClearColor)
438cdc920a0Smrg               ctx->Driver.ClearColor(ctx, clearSave);
439cdc920a0Smrg         }
440cdc920a0Smrg      }
441cdc920a0Smrg      break;
442cdc920a0Smrg   default:
443cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
444cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
445cdc920a0Smrg      return;
446cdc920a0Smrg   }
447cdc920a0Smrg}
448cdc920a0Smrg
449cdc920a0Smrg
450cdc920a0Smrg/**
451cdc920a0Smrg * New in GL 3.0
452cdc920a0Smrg * Clear depth/stencil buffer only.
453cdc920a0Smrg */
454cdc920a0Smrgvoid GLAPIENTRY
455cdc920a0Smrg_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
456cdc920a0Smrg                    GLfloat depth, GLint stencil)
457cdc920a0Smrg{
458cdc920a0Smrg   GET_CURRENT_CONTEXT(ctx);
459cdc920a0Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
460cdc920a0Smrg
461cdc920a0Smrg   FLUSH_CURRENT(ctx, 0);
462cdc920a0Smrg
463cdc920a0Smrg   if (buffer != GL_DEPTH_STENCIL) {
464cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
465cdc920a0Smrg                  _mesa_lookup_enum_by_nr(buffer));
466cdc920a0Smrg      return;
467cdc920a0Smrg   }
468cdc920a0Smrg
469cdc920a0Smrg   if (drawbuffer != 0) {
470cdc920a0Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
471cdc920a0Smrg                  drawbuffer);
472cdc920a0Smrg      return;
473cdc920a0Smrg   }
474cdc920a0Smrg
475cdc920a0Smrg   if (ctx->NewState) {
476cdc920a0Smrg      _mesa_update_state( ctx );
477cdc920a0Smrg   }
478cdc920a0Smrg
479cdc920a0Smrg   {
480cdc920a0Smrg      /* save current clear values */
481cdc920a0Smrg      const GLclampd clearDepthSave = ctx->Depth.Clear;
482cdc920a0Smrg      const GLuint clearStencilSave = ctx->Stencil.Clear;
483cdc920a0Smrg
484cdc920a0Smrg      /* set new clear values */
485cdc920a0Smrg      ctx->Depth.Clear = depth;
486cdc920a0Smrg      ctx->Stencil.Clear = stencil;
487cdc920a0Smrg      if (ctx->Driver.ClearDepth)
488cdc920a0Smrg         ctx->Driver.ClearDepth(ctx, depth);
489cdc920a0Smrg      if (ctx->Driver.ClearStencil)
490cdc920a0Smrg         ctx->Driver.ClearStencil(ctx, stencil);
491cdc920a0Smrg
492cdc920a0Smrg      /* clear buffers */
493cdc920a0Smrg      ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
494cdc920a0Smrg
495cdc920a0Smrg      /* restore */
496cdc920a0Smrg      ctx->Depth.Clear = clearDepthSave;
497cdc920a0Smrg      ctx->Stencil.Clear = clearStencilSave;
498cdc920a0Smrg      if (ctx->Driver.ClearDepth)
499cdc920a0Smrg         ctx->Driver.ClearDepth(ctx, clearDepthSave);
500cdc920a0Smrg      if (ctx->Driver.ClearStencil)
501cdc920a0Smrg         ctx->Driver.ClearStencil(ctx, clearStencilSave);
502cdc920a0Smrg   }
503cdc920a0Smrg}
504