2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
28 * glClearColor, glClearIndex, glClear() functions.
46 _mesa_ClearIndex( GLfloat c
)
48 GET_CURRENT_CONTEXT(ctx
);
49 ASSERT_OUTSIDE_BEGIN_END(ctx
);
51 if (ctx
->Color
.ClearIndex
== (GLuint
) c
)
54 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
55 ctx
->Color
.ClearIndex
= (GLuint
) c
;
61 * Specify the clear values for the color buffers.
63 * \param red red color component.
64 * \param green green color component.
65 * \param blue blue color component.
66 * \param alpha alpha component.
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.
75 _mesa_ClearColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
78 GET_CURRENT_CONTEXT(ctx
);
79 ASSERT_OUTSIDE_BEGIN_END(ctx
);
86 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
.f
))
87 return; /* no change */
89 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
90 COPY_4V(ctx
->Color
.ClearColor
.f
, tmp
);
92 if (ctx
->Driver
.ClearColor
) {
93 /* it's OK to call glClearColor in CI mode but it should be a NOP */
94 /* we pass the clamped color, since all drivers that need this don't
95 * support GL_ARB_color_buffer_float
97 (*ctx
->Driver
.ClearColor
)(ctx
, ctx
->Color
.ClearColor
);
103 * GL_EXT_texture_integer
106 _mesa_ClearColorIiEXT(GLint r
, GLint g
, GLint b
, GLint a
)
109 GET_CURRENT_CONTEXT(ctx
);
110 ASSERT_OUTSIDE_BEGIN_END(ctx
);
117 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
.i
))
118 return; /* no change */
120 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
121 COPY_4V(ctx
->Color
.ClearColor
.i
, tmp
);
123 /* these should be NOP calls for drivers supporting EXT_texture_integer */
124 if (ctx
->Driver
.ClearColor
) {
125 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
131 * GL_EXT_texture_integer
134 _mesa_ClearColorIuiEXT(GLuint r
, GLuint g
, GLuint b
, GLuint a
)
137 GET_CURRENT_CONTEXT(ctx
);
138 ASSERT_OUTSIDE_BEGIN_END(ctx
);
145 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
.ui
))
146 return; /* no change */
148 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
149 COPY_4V(ctx
->Color
.ClearColor
.ui
, tmp
);
151 /* these should be NOP calls for drivers supporting EXT_texture_integer */
152 if (ctx
->Driver
.ClearColor
) {
153 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
161 * \param mask bit-mask indicating the buffers to be cleared.
163 * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState
164 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
165 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
166 * to clear the buffers, via the dd_function_table::Clear callback.
169 _mesa_Clear( GLbitfield mask
)
171 GET_CURRENT_CONTEXT(ctx
);
172 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
174 FLUSH_CURRENT(ctx
, 0);
176 if (MESA_VERBOSE
& VERBOSE_API
)
177 _mesa_debug(ctx
, "glClear 0x%x\n", mask
);
179 if (mask
& ~(GL_COLOR_BUFFER_BIT
|
180 GL_DEPTH_BUFFER_BIT
|
181 GL_STENCIL_BUFFER_BIT
|
182 GL_ACCUM_BUFFER_BIT
)) {
183 /* invalid bit set */
184 _mesa_error( ctx
, GL_INVALID_VALUE
, "glClear(0x%x)", mask
);
189 _mesa_update_state( ctx
); /* update _Xmin, etc */
192 if (ctx
->DrawBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
193 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
194 "glClear(incomplete framebuffer)");
198 if (ctx
->DrawBuffer
->Width
== 0 || ctx
->DrawBuffer
->Height
== 0 ||
199 ctx
->DrawBuffer
->_Xmin
>= ctx
->DrawBuffer
->_Xmax
||
200 ctx
->DrawBuffer
->_Ymin
>= ctx
->DrawBuffer
->_Ymax
)
203 if (ctx
->RenderMode
== GL_RENDER
) {
204 GLbitfield bufferMask
;
206 /* don't clear depth buffer if depth writing disabled */
207 if (!ctx
->Depth
.Mask
)
208 mask
&= ~GL_DEPTH_BUFFER_BIT
;
210 /* Build the bitmask to send to device driver's Clear function.
211 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
212 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
213 * BUFFER_BIT_COLORn flags.
216 if (mask
& GL_COLOR_BUFFER_BIT
) {
218 for (i
= 0; i
< ctx
->DrawBuffer
->_NumColorDrawBuffers
; i
++) {
219 bufferMask
|= (1 << ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[i
]);
223 if ((mask
& GL_DEPTH_BUFFER_BIT
)
224 && ctx
->DrawBuffer
->Visual
.haveDepthBuffer
) {
225 bufferMask
|= BUFFER_BIT_DEPTH
;
228 if ((mask
& GL_STENCIL_BUFFER_BIT
)
229 && ctx
->DrawBuffer
->Visual
.haveStencilBuffer
) {
230 bufferMask
|= BUFFER_BIT_STENCIL
;
233 if ((mask
& GL_ACCUM_BUFFER_BIT
)
234 && ctx
->DrawBuffer
->Visual
.haveAccumBuffer
) {
235 bufferMask
|= BUFFER_BIT_ACCUM
;
238 ASSERT(ctx
->Driver
.Clear
);
239 ctx
->Driver
.Clear(ctx
, bufferMask
);
244 /** Returned by make_color_buffer_mask() for errors */
245 #define INVALID_MASK ~0x0
249 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
250 * BUFFER_BIT_x values.
251 * Return INVALID_MASK if the drawbuffer value is invalid.
254 make_color_buffer_mask(struct gl_context
*ctx
, GLint drawbuffer
)
256 const struct gl_renderbuffer_attachment
*att
= ctx
->DrawBuffer
->Attachment
;
257 GLbitfield mask
= 0x0;
259 switch (drawbuffer
) {
261 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
262 mask
|= BUFFER_BIT_FRONT_LEFT
;
263 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
264 mask
|= BUFFER_BIT_FRONT_RIGHT
;
267 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
268 mask
|= BUFFER_BIT_BACK_LEFT
;
269 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
270 mask
|= BUFFER_BIT_BACK_RIGHT
;
273 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
274 mask
|= BUFFER_BIT_FRONT_LEFT
;
275 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
276 mask
|= BUFFER_BIT_BACK_LEFT
;
279 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
280 mask
|= BUFFER_BIT_FRONT_RIGHT
;
281 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
282 mask
|= BUFFER_BIT_BACK_RIGHT
;
284 case GL_FRONT_AND_BACK
:
285 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
286 mask
|= BUFFER_BIT_FRONT_LEFT
;
287 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
288 mask
|= BUFFER_BIT_BACK_LEFT
;
289 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
290 mask
|= BUFFER_BIT_FRONT_RIGHT
;
291 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
292 mask
|= BUFFER_BIT_BACK_RIGHT
;
295 if (drawbuffer
< 0 || drawbuffer
>= (GLint
)ctx
->Const
.MaxDrawBuffers
) {
298 else if (att
[BUFFER_COLOR0
+ drawbuffer
].Renderbuffer
) {
299 mask
|= (BUFFER_BIT_COLOR0
<< drawbuffer
);
310 * Clear signed integer color buffer or stencil buffer (not depth).
313 _mesa_ClearBufferiv(GLenum buffer
, GLint drawbuffer
, const GLint
*value
)
315 GET_CURRENT_CONTEXT(ctx
);
316 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
318 FLUSH_CURRENT(ctx
, 0);
321 _mesa_update_state( ctx
);
326 if (drawbuffer
!= 0) {
327 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
332 /* Save current stencil clear value, set to 'value', do the
333 * stencil clear and restore the clear value.
334 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
337 const GLuint clearSave
= ctx
->Stencil
.Clear
;
338 ctx
->Stencil
.Clear
= *value
;
339 if (ctx
->Driver
.ClearStencil
)
340 ctx
->Driver
.ClearStencil(ctx
, *value
);
341 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_STENCIL
);
342 ctx
->Stencil
.Clear
= clearSave
;
343 if (ctx
->Driver
.ClearStencil
)
344 ctx
->Driver
.ClearStencil(ctx
, clearSave
);
349 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
350 if (mask
== INVALID_MASK
) {
351 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
356 union gl_color_union clearSave
;
359 clearSave
= ctx
->Color
.ClearColor
;
361 COPY_4V(ctx
->Color
.ClearColor
.i
, value
);
362 if (ctx
->Driver
.ClearColor
)
363 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
364 /* clear buffer(s) */
365 ctx
->Driver
.Clear(ctx
, mask
);
367 ctx
->Color
.ClearColor
= clearSave
;
368 if (ctx
->Driver
.ClearColor
)
369 ctx
->Driver
.ClearColor(ctx
, clearSave
);
374 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferiv(buffer=%s)",
375 _mesa_lookup_enum_by_nr(buffer
));
383 * Clear unsigned integer color buffer (not depth, not stencil).
386 _mesa_ClearBufferuiv(GLenum buffer
, GLint drawbuffer
, const GLuint
*value
)
388 GET_CURRENT_CONTEXT(ctx
);
389 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
391 FLUSH_CURRENT(ctx
, 0);
394 _mesa_update_state( ctx
);
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)",
407 union gl_color_union clearSave
;
410 clearSave
= ctx
->Color
.ClearColor
;
412 COPY_4V(ctx
->Color
.ClearColor
.ui
, value
);
413 if (ctx
->Driver
.ClearColor
)
414 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
415 /* clear buffer(s) */
416 ctx
->Driver
.Clear(ctx
, mask
);
418 ctx
->Color
.ClearColor
= clearSave
;
419 if (ctx
->Driver
.ClearColor
)
420 ctx
->Driver
.ClearColor(ctx
, clearSave
);
425 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferuiv(buffer=%s)",
426 _mesa_lookup_enum_by_nr(buffer
));
434 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
437 _mesa_ClearBufferfv(GLenum buffer
, GLint drawbuffer
, const GLfloat
*value
)
439 GET_CURRENT_CONTEXT(ctx
);
440 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
442 FLUSH_CURRENT(ctx
, 0);
445 _mesa_update_state( ctx
);
450 if (drawbuffer
!= 0) {
451 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfv(drawbuffer=%d)",
456 /* Save current depth clear value, set to 'value', do the
457 * depth clear and restore the clear value.
458 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
461 const GLclampd clearSave
= ctx
->Depth
.Clear
;
462 ctx
->Depth
.Clear
= *value
;
463 if (ctx
->Driver
.ClearDepth
)
464 ctx
->Driver
.ClearDepth(ctx
, *value
);
465 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_DEPTH
);
466 ctx
->Depth
.Clear
= clearSave
;
467 if (ctx
->Driver
.ClearDepth
)
468 ctx
->Driver
.ClearDepth(ctx
, clearSave
);
470 /* clear depth buffer to value */
474 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
475 if (mask
== INVALID_MASK
) {
476 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfv(drawbuffer=%d)",
481 union gl_color_union clearSave
;
484 clearSave
= ctx
->Color
.ClearColor
;
486 COPY_4V_CAST(ctx
->Color
.ClearColor
.f
, value
, GLclampf
);
487 if (ctx
->Driver
.ClearColor
)
488 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
489 /* clear buffer(s) */
490 ctx
->Driver
.Clear(ctx
, mask
);
492 ctx
->Color
.ClearColor
= clearSave
;
493 if (ctx
->Driver
.ClearColor
)
494 ctx
->Driver
.ClearColor(ctx
, clearSave
);
499 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfv(buffer=%s)",
500 _mesa_lookup_enum_by_nr(buffer
));
508 * Clear depth/stencil buffer only.
511 _mesa_ClearBufferfi(GLenum buffer
, GLint drawbuffer
,
512 GLfloat depth
, GLint stencil
)
514 GET_CURRENT_CONTEXT(ctx
);
515 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
517 FLUSH_CURRENT(ctx
, 0);
519 if (buffer
!= GL_DEPTH_STENCIL
) {
520 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfi(buffer=%s)",
521 _mesa_lookup_enum_by_nr(buffer
));
525 if (drawbuffer
!= 0) {
526 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfi(drawbuffer=%d)",
532 _mesa_update_state( ctx
);
536 /* save current clear values */
537 const GLclampd clearDepthSave
= ctx
->Depth
.Clear
;
538 const GLuint clearStencilSave
= ctx
->Stencil
.Clear
;
540 /* set new clear values */
541 ctx
->Depth
.Clear
= depth
;
542 ctx
->Stencil
.Clear
= stencil
;
543 if (ctx
->Driver
.ClearDepth
)
544 ctx
->Driver
.ClearDepth(ctx
, depth
);
545 if (ctx
->Driver
.ClearStencil
)
546 ctx
->Driver
.ClearStencil(ctx
, stencil
);
549 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_DEPTH
| BUFFER_BIT_STENCIL
);
552 ctx
->Depth
.Clear
= clearDepthSave
;
553 ctx
->Stencil
.Clear
= clearStencilSave
;
554 if (ctx
->Driver
.ClearDepth
)
555 ctx
->Driver
.ClearDepth(ctx
, clearDepthSave
);
556 if (ctx
->Driver
.ClearStencil
)
557 ctx
->Driver
.ClearStencil(ctx
, clearStencilSave
);