1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/**
27 * \file clear.c
28 * glClearColor, glClearIndex, glClear() functions.
29 */
30
31
32
33#include "glheader.h"
34#include "clear.h"
35#include "context.h"
36#include "colormac.h"
37#include "enums.h"
38#include "macros.h"
39#include "mtypes.h"
40#include "state.h"
41
42
43
44#if _HAVE_FULL_GL
45void GLAPIENTRY
46_mesa_ClearIndex( GLfloat c )
47{
48   GET_CURRENT_CONTEXT(ctx);
49   ASSERT_OUTSIDE_BEGIN_END(ctx);
50
51   if (ctx->Color.ClearIndex == (GLuint) c)
52      return;
53
54   FLUSH_VERTICES(ctx, _NEW_COLOR);
55   ctx->Color.ClearIndex = (GLuint) c;
56}
57#endif
58
59
60/**
61 * Specify the clear values for the color buffers.
62 *
63 * \param red red color component.
64 * \param green green color component.
65 * \param blue blue color component.
66 * \param alpha alpha component.
67 *
68 * \sa glClearColor().
69 *
70 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor.  On a
71 * change, flushes the vertices and notifies the driver via the
72 * dd_function_table::ClearColor callback.
73 */
74void GLAPIENTRY
75_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
76{
77   GLfloat tmp[4];
78   GET_CURRENT_CONTEXT(ctx);
79   ASSERT_OUTSIDE_BEGIN_END(ctx);
80
81   tmp[0] = red;
82   tmp[1] = green;
83   tmp[2] = blue;
84   tmp[3] = alpha;
85
86   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.f))
87      return; /* no change */
88
89   FLUSH_VERTICES(ctx, _NEW_COLOR);
90   COPY_4V(ctx->Color.ClearColor.f, tmp);
91}
92
93
94/**
95 * GL_EXT_texture_integer
96 */
97void GLAPIENTRY
98_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
99{
100   GLint tmp[4];
101   GET_CURRENT_CONTEXT(ctx);
102   ASSERT_OUTSIDE_BEGIN_END(ctx);
103
104   tmp[0] = r;
105   tmp[1] = g;
106   tmp[2] = b;
107   tmp[3] = a;
108
109   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.i))
110      return; /* no change */
111
112   FLUSH_VERTICES(ctx, _NEW_COLOR);
113   COPY_4V(ctx->Color.ClearColor.i, tmp);
114}
115
116
117/**
118 * GL_EXT_texture_integer
119 */
120void GLAPIENTRY
121_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
122{
123   GLuint tmp[4];
124   GET_CURRENT_CONTEXT(ctx);
125   ASSERT_OUTSIDE_BEGIN_END(ctx);
126
127   tmp[0] = r;
128   tmp[1] = g;
129   tmp[2] = b;
130   tmp[3] = a;
131
132   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.ui))
133      return; /* no change */
134
135   FLUSH_VERTICES(ctx, _NEW_COLOR);
136   COPY_4V(ctx->Color.ClearColor.ui, tmp);
137}
138
139
140/**
141 * Clear buffers.
142 *
143 * \param mask bit-mask indicating the buffers to be cleared.
144 *
145 * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState
146 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
147 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
148 * to clear the buffers, via the dd_function_table::Clear callback.
149 */
150void GLAPIENTRY
151_mesa_Clear( GLbitfield mask )
152{
153   GET_CURRENT_CONTEXT(ctx);
154   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
155
156   FLUSH_CURRENT(ctx, 0);
157
158   if (MESA_VERBOSE & VERBOSE_API)
159      _mesa_debug(ctx, "glClear 0x%x\n", mask);
160
161   if (mask & ~(GL_COLOR_BUFFER_BIT |
162                GL_DEPTH_BUFFER_BIT |
163                GL_STENCIL_BUFFER_BIT |
164                GL_ACCUM_BUFFER_BIT)) {
165      /* invalid bit set */
166      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
167      return;
168   }
169
170   /* Accumulation buffers were removed in core contexts, and they never
171    * existed in OpenGL ES.
172    */
173   if ((mask & GL_ACCUM_BUFFER_BIT) != 0
174       && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) {
175      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)");
176      return;
177   }
178
179   if (ctx->NewState) {
180      _mesa_update_state( ctx );	/* update _Xmin, etc */
181   }
182
183   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
184      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
185                  "glClear(incomplete framebuffer)");
186      return;
187   }
188
189   if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 ||
190       ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax ||
191       ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax)
192      return;
193
194   if (ctx->RasterDiscard)
195      return;
196
197   if (ctx->RenderMode == GL_RENDER) {
198      GLbitfield bufferMask;
199
200      /* don't clear depth buffer if depth writing disabled */
201      if (!ctx->Depth.Mask)
202         mask &= ~GL_DEPTH_BUFFER_BIT;
203
204      /* Build the bitmask to send to device driver's Clear function.
205       * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
206       * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
207       * BUFFER_BIT_COLORn flags.
208       */
209      bufferMask = 0;
210      if (mask & GL_COLOR_BUFFER_BIT) {
211         GLuint i;
212         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
213            bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]);
214         }
215      }
216
217      if ((mask & GL_DEPTH_BUFFER_BIT)
218          && ctx->DrawBuffer->Visual.haveDepthBuffer) {
219         bufferMask |= BUFFER_BIT_DEPTH;
220      }
221
222      if ((mask & GL_STENCIL_BUFFER_BIT)
223          && ctx->DrawBuffer->Visual.haveStencilBuffer) {
224         bufferMask |= BUFFER_BIT_STENCIL;
225      }
226
227      if ((mask & GL_ACCUM_BUFFER_BIT)
228          && ctx->DrawBuffer->Visual.haveAccumBuffer) {
229         bufferMask |= BUFFER_BIT_ACCUM;
230      }
231
232      ASSERT(ctx->Driver.Clear);
233      ctx->Driver.Clear(ctx, bufferMask);
234   }
235}
236
237
238/** Returned by make_color_buffer_mask() for errors */
239#define INVALID_MASK ~0x0
240
241
242/**
243 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
244 * BUFFER_BIT_x values.
245 * Return INVALID_MASK if the drawbuffer value is invalid.
246 */
247static GLbitfield
248make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer)
249{
250   const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
251   GLbitfield mask = 0x0;
252
253   switch (drawbuffer) {
254   case GL_FRONT:
255      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
256         mask |= BUFFER_BIT_FRONT_LEFT;
257      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
258         mask |= BUFFER_BIT_FRONT_RIGHT;
259      break;
260   case GL_BACK:
261      if (att[BUFFER_BACK_LEFT].Renderbuffer)
262         mask |= BUFFER_BIT_BACK_LEFT;
263      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
264         mask |= BUFFER_BIT_BACK_RIGHT;
265      break;
266   case GL_LEFT:
267      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
268         mask |= BUFFER_BIT_FRONT_LEFT;
269      if (att[BUFFER_BACK_LEFT].Renderbuffer)
270         mask |= BUFFER_BIT_BACK_LEFT;
271      break;
272   case GL_RIGHT:
273      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
274         mask |= BUFFER_BIT_FRONT_RIGHT;
275      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
276         mask |= BUFFER_BIT_BACK_RIGHT;
277      break;
278   case GL_FRONT_AND_BACK:
279      if (att[BUFFER_FRONT_LEFT].Renderbuffer)
280         mask |= BUFFER_BIT_FRONT_LEFT;
281      if (att[BUFFER_BACK_LEFT].Renderbuffer)
282         mask |= BUFFER_BIT_BACK_LEFT;
283      if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
284         mask |= BUFFER_BIT_FRONT_RIGHT;
285      if (att[BUFFER_BACK_RIGHT].Renderbuffer)
286         mask |= BUFFER_BIT_BACK_RIGHT;
287      break;
288   default:
289      if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
290         mask = INVALID_MASK;
291      }
292      else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) {
293         mask |= (BUFFER_BIT_COLOR0 << drawbuffer);
294      }
295   }
296
297   return mask;
298}
299
300
301
302/**
303 * New in GL 3.0
304 * Clear signed integer color buffer or stencil buffer (not depth).
305 */
306void GLAPIENTRY
307_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
308{
309   GET_CURRENT_CONTEXT(ctx);
310   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
311
312   FLUSH_CURRENT(ctx, 0);
313
314   if (ctx->NewState) {
315      _mesa_update_state( ctx );
316   }
317
318   switch (buffer) {
319   case GL_STENCIL:
320      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
321       *
322       *     "ClearBuffer generates an INVALID VALUE error if buffer is
323       *     COLOR and drawbuffer is less than zero, or greater than the
324       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
325       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
326       */
327      if (drawbuffer != 0) {
328         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
329                     drawbuffer);
330         return;
331      }
332      else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer && !ctx->RasterDiscard) {
333         /* Save current stencil clear value, set to 'value', do the
334          * stencil clear and restore the clear value.
335          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
336          * hook instead.
337          */
338         const GLuint clearSave = ctx->Stencil.Clear;
339         ctx->Stencil.Clear = *value;
340         ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
341         ctx->Stencil.Clear = clearSave;
342      }
343      break;
344   case GL_COLOR:
345      {
346         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
347         if (mask == INVALID_MASK) {
348            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
349                        drawbuffer);
350            return;
351         }
352         else if (mask && !ctx->RasterDiscard) {
353            union gl_color_union clearSave;
354
355            /* save color */
356            clearSave = ctx->Color.ClearColor;
357            /* set color */
358            COPY_4V(ctx->Color.ClearColor.i, value);
359            /* clear buffer(s) */
360            ctx->Driver.Clear(ctx, mask);
361            /* restore color */
362            ctx->Color.ClearColor = clearSave;
363         }
364      }
365      break;
366   case GL_DEPTH:
367      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
368       *
369       *     "The result of ClearBuffer is undefined if no conversion between
370       *     the type of the specified value and the type of the buffer being
371       *     cleared is defined (for example, if ClearBufferiv is called for a
372       *     fixed- or floating-point buffer, or if ClearBufferfv is called
373       *     for a signed or unsigned integer buffer). This is not an error."
374       *
375       * In this case we take "undefined" and "not an error" to mean "ignore."
376       * Note that we still need to generate an error for the invalid
377       * drawbuffer case (see the GL_STENCIL case above).
378       */
379      if (drawbuffer != 0) {
380         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
381                     drawbuffer);
382         return;
383      }
384      return;
385   default:
386      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
387                  _mesa_lookup_enum_by_nr(buffer));
388      return;
389   }
390}
391
392
393/**
394 * New in GL 3.0
395 * Clear unsigned integer color buffer (not depth, not stencil).
396 */
397void GLAPIENTRY
398_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
399{
400   GET_CURRENT_CONTEXT(ctx);
401   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
402
403   FLUSH_CURRENT(ctx, 0);
404
405   if (ctx->NewState) {
406      _mesa_update_state( ctx );
407   }
408
409   switch (buffer) {
410   case GL_COLOR:
411      {
412         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
413         if (mask == INVALID_MASK) {
414            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
415                        drawbuffer);
416            return;
417         }
418         else if (mask && !ctx->RasterDiscard) {
419            union gl_color_union clearSave;
420
421            /* save color */
422            clearSave = ctx->Color.ClearColor;
423            /* set color */
424            COPY_4V(ctx->Color.ClearColor.ui, value);
425            /* clear buffer(s) */
426            ctx->Driver.Clear(ctx, mask);
427            /* restore color */
428            ctx->Color.ClearColor = clearSave;
429         }
430      }
431      break;
432   case GL_DEPTH:
433   case GL_STENCIL:
434      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
435       *
436       *     "The result of ClearBuffer is undefined if no conversion between
437       *     the type of the specified value and the type of the buffer being
438       *     cleared is defined (for example, if ClearBufferiv is called for a
439       *     fixed- or floating-point buffer, or if ClearBufferfv is called
440       *     for a signed or unsigned integer buffer). This is not an error."
441       *
442       * In this case we take "undefined" and "not an error" to mean "ignore."
443       * Even though we could do something sensible for GL_STENCIL, page 263
444       * (page 279 of the PDF) says:
445       *
446       *     "Only ClearBufferiv should be used to clear stencil buffers."
447       *
448       * Note that we still need to generate an error for the invalid
449       * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv).
450       */
451      if (drawbuffer != 0) {
452         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
453                     drawbuffer);
454         return;
455      }
456      return;
457   default:
458      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
459                  _mesa_lookup_enum_by_nr(buffer));
460      return;
461   }
462}
463
464
465/**
466 * New in GL 3.0
467 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
468 */
469void GLAPIENTRY
470_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
471{
472   GET_CURRENT_CONTEXT(ctx);
473   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
474
475   FLUSH_CURRENT(ctx, 0);
476
477   if (ctx->NewState) {
478      _mesa_update_state( ctx );
479   }
480
481   switch (buffer) {
482   case GL_DEPTH:
483      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
484       *
485       *     "ClearBuffer generates an INVALID VALUE error if buffer is
486       *     COLOR and drawbuffer is less than zero, or greater than the
487       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
488       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
489       */
490      if (drawbuffer != 0) {
491         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
492                     drawbuffer);
493         return;
494      }
495      else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) {
496         /* Save current depth clear value, set to 'value', do the
497          * depth clear and restore the clear value.
498          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
499          * hook instead.
500          */
501         const GLclampd clearSave = ctx->Depth.Clear;
502         ctx->Depth.Clear = *value;
503         ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
504         ctx->Depth.Clear = clearSave;
505      }
506      /* clear depth buffer to value */
507      break;
508   case GL_COLOR:
509      {
510         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
511         if (mask == INVALID_MASK) {
512            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
513                        drawbuffer);
514            return;
515         }
516         else if (mask && !ctx->RasterDiscard) {
517            union gl_color_union clearSave;
518
519            /* save color */
520            clearSave = ctx->Color.ClearColor;
521            /* set color */
522            COPY_4V(ctx->Color.ClearColor.f, value);
523            /* clear buffer(s) */
524            ctx->Driver.Clear(ctx, mask);
525            /* restore color */
526            ctx->Color.ClearColor = clearSave;
527         }
528      }
529      break;
530   case GL_STENCIL:
531      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
532       *
533       *     "The result of ClearBuffer is undefined if no conversion between
534       *     the type of the specified value and the type of the buffer being
535       *     cleared is defined (for example, if ClearBufferiv is called for a
536       *     fixed- or floating-point buffer, or if ClearBufferfv is called
537       *     for a signed or unsigned integer buffer). This is not an error."
538       *
539       * In this case we take "undefined" and "not an error" to mean "ignore."
540       * Note that we still need to generate an error for the invalid
541       * drawbuffer case (see the GL_DEPTH case above).
542       */
543      if (drawbuffer != 0) {
544         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
545                     drawbuffer);
546         return;
547      }
548      return;
549   default:
550      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
551                  _mesa_lookup_enum_by_nr(buffer));
552      return;
553   }
554}
555
556
557/**
558 * New in GL 3.0
559 * Clear depth/stencil buffer only.
560 */
561void GLAPIENTRY
562_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
563                    GLfloat depth, GLint stencil)
564{
565   GET_CURRENT_CONTEXT(ctx);
566   GLbitfield mask = 0;
567
568   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
569
570   FLUSH_CURRENT(ctx, 0);
571
572   if (buffer != GL_DEPTH_STENCIL) {
573      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
574                  _mesa_lookup_enum_by_nr(buffer));
575      return;
576   }
577
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 (drawbuffer != 0) {
586      _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
587                  drawbuffer);
588      return;
589   }
590
591   if (ctx->RasterDiscard)
592      return;
593
594   if (ctx->NewState) {
595      _mesa_update_state( ctx );
596   }
597
598   if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer)
599      mask |= BUFFER_BIT_DEPTH;
600   if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer)
601      mask |= BUFFER_BIT_STENCIL;
602
603   if (mask) {
604      /* save current clear values */
605      const GLclampd clearDepthSave = ctx->Depth.Clear;
606      const GLuint clearStencilSave = ctx->Stencil.Clear;
607
608      /* set new clear values */
609      ctx->Depth.Clear = depth;
610      ctx->Stencil.Clear = stencil;
611
612      /* clear buffers */
613      ctx->Driver.Clear(ctx, mask);
614
615      /* restore */
616      ctx->Depth.Clear = clearDepthSave;
617      ctx->Stencil.Clear = clearStencilSave;
618   }
619}
620