OSDN Git Service

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