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.
45 _mesa_ClearIndex( GLfloat c
)
47 GET_CURRENT_CONTEXT(ctx
);
48 ASSERT_OUTSIDE_BEGIN_END(ctx
);
50 if (ctx
->Color
.ClearIndex
== (GLuint
) c
)
53 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
54 ctx
->Color
.ClearIndex
= (GLuint
) c
;
60 * Specify the clear values for the color buffers.
62 * \param red red color component.
63 * \param green green color component.
64 * \param blue blue color component.
65 * \param alpha alpha component.
69 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a
70 * change, flushes the vertices and notifies the driver via the
71 * dd_function_table::ClearColor callback.
74 _mesa_ClearColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
77 GET_CURRENT_CONTEXT(ctx
);
78 ASSERT_OUTSIDE_BEGIN_END(ctx
);
80 tmp
[0] = CLAMP(red
, 0.0F
, 1.0F
);
81 tmp
[1] = CLAMP(green
, 0.0F
, 1.0F
);
82 tmp
[2] = CLAMP(blue
, 0.0F
, 1.0F
);
83 tmp
[3] = CLAMP(alpha
, 0.0F
, 1.0F
);
85 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
))
86 return; /* no change */
88 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
89 COPY_4V(ctx
->Color
.ClearColor
, tmp
);
91 if (ctx
->Driver
.ClearColor
) {
92 /* it's OK to call glClearColor in CI mode but it should be a NOP */
93 (*ctx
->Driver
.ClearColor
)(ctx
, ctx
->Color
.ClearColor
);
99 * GL_EXT_texture_integer
102 _mesa_ClearColorIiEXT(GLint r
, GLint g
, GLint b
, GLint a
)
105 GET_CURRENT_CONTEXT(ctx
);
106 ASSERT_OUTSIDE_BEGIN_END(ctx
);
108 tmp
[0] = (GLfloat
) r
;
109 tmp
[1] = (GLfloat
) g
;
110 tmp
[2] = (GLfloat
) b
;
111 tmp
[3] = (GLfloat
) a
;
113 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
))
114 return; /* no change */
116 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
118 /* XXX we should eventually have a float/int/uint union for
119 * the ctx->Color.ClearColor state.
121 COPY_4V(ctx
->Color
.ClearColor
, tmp
);
123 if (ctx
->Driver
.ClearColor
) {
124 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
130 * GL_EXT_texture_integer
133 _mesa_ClearColorIuiEXT(GLuint r
, GLuint g
, GLuint b
, GLuint a
)
136 GET_CURRENT_CONTEXT(ctx
);
137 ASSERT_OUTSIDE_BEGIN_END(ctx
);
139 tmp
[0] = (GLfloat
) r
;
140 tmp
[1] = (GLfloat
) g
;
141 tmp
[2] = (GLfloat
) b
;
142 tmp
[3] = (GLfloat
) a
;
144 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
))
145 return; /* no change */
147 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
149 /* XXX we should eventually have a float/int/uint union for
150 * the ctx->Color.ClearColor state.
152 COPY_4V(ctx
->Color
.ClearColor
, tmp
);
154 if (ctx
->Driver
.ClearColor
) {
155 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
163 * \param mask bit-mask indicating the buffers to be cleared.
165 * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState
166 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
167 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
168 * to clear the buffers, via the dd_function_table::Clear callback.
171 _mesa_Clear( GLbitfield mask
)
173 GET_CURRENT_CONTEXT(ctx
);
174 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
176 FLUSH_CURRENT(ctx
, 0);
178 if (MESA_VERBOSE
& VERBOSE_API
)
179 _mesa_debug(ctx
, "glClear 0x%x\n", mask
);
181 if (mask
& ~(GL_COLOR_BUFFER_BIT
|
182 GL_DEPTH_BUFFER_BIT
|
183 GL_STENCIL_BUFFER_BIT
|
184 GL_ACCUM_BUFFER_BIT
)) {
185 /* invalid bit set */
186 _mesa_error( ctx
, GL_INVALID_VALUE
, "glClear(0x%x)", mask
);
191 _mesa_update_state( ctx
); /* update _Xmin, etc */
194 if (ctx
->DrawBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
195 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
196 "glClear(incomplete framebuffer)");
200 if (ctx
->DrawBuffer
->Width
== 0 || ctx
->DrawBuffer
->Height
== 0 ||
201 ctx
->DrawBuffer
->_Xmin
>= ctx
->DrawBuffer
->_Xmax
||
202 ctx
->DrawBuffer
->_Ymin
>= ctx
->DrawBuffer
->_Ymax
)
205 if (ctx
->RenderMode
== GL_RENDER
) {
206 GLbitfield bufferMask
;
208 /* don't clear depth buffer if depth writing disabled */
209 if (!ctx
->Depth
.Mask
)
210 mask
&= ~GL_DEPTH_BUFFER_BIT
;
212 /* Build the bitmask to send to device driver's Clear function.
213 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
214 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
215 * BUFFER_BIT_COLORn flags.
218 if (mask
& GL_COLOR_BUFFER_BIT
) {
220 for (i
= 0; i
< ctx
->DrawBuffer
->_NumColorDrawBuffers
; i
++) {
221 bufferMask
|= (1 << ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[i
]);
225 if ((mask
& GL_DEPTH_BUFFER_BIT
)
226 && ctx
->DrawBuffer
->Visual
.haveDepthBuffer
) {
227 bufferMask
|= BUFFER_BIT_DEPTH
;
230 if ((mask
& GL_STENCIL_BUFFER_BIT
)
231 && ctx
->DrawBuffer
->Visual
.haveStencilBuffer
) {
232 bufferMask
|= BUFFER_BIT_STENCIL
;
235 if ((mask
& GL_ACCUM_BUFFER_BIT
)
236 && ctx
->DrawBuffer
->Visual
.haveAccumBuffer
) {
237 bufferMask
|= BUFFER_BIT_ACCUM
;
240 ASSERT(ctx
->Driver
.Clear
);
241 ctx
->Driver
.Clear(ctx
, bufferMask
);
246 /** Returned by make_color_buffer_mask() for errors */
247 #define INVALID_MASK ~0x0
251 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
252 * BUFFER_BIT_x values.
253 * Return INVALID_MASK if the drawbuffer value is invalid.
256 make_color_buffer_mask(struct gl_context
*ctx
, GLint drawbuffer
)
258 const struct gl_renderbuffer_attachment
*att
= ctx
->DrawBuffer
->Attachment
;
259 GLbitfield mask
= 0x0;
261 switch (drawbuffer
) {
263 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
264 mask
|= BUFFER_BIT_FRONT_LEFT
;
265 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
266 mask
|= BUFFER_BIT_FRONT_RIGHT
;
269 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
270 mask
|= BUFFER_BIT_BACK_LEFT
;
271 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
272 mask
|= BUFFER_BIT_BACK_RIGHT
;
275 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
276 mask
|= BUFFER_BIT_FRONT_LEFT
;
277 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
278 mask
|= BUFFER_BIT_BACK_LEFT
;
281 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
282 mask
|= BUFFER_BIT_FRONT_RIGHT
;
283 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
284 mask
|= BUFFER_BIT_BACK_RIGHT
;
286 case GL_FRONT_AND_BACK
:
287 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
288 mask
|= BUFFER_BIT_FRONT_LEFT
;
289 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
290 mask
|= BUFFER_BIT_BACK_LEFT
;
291 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
292 mask
|= BUFFER_BIT_FRONT_RIGHT
;
293 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
294 mask
|= BUFFER_BIT_BACK_RIGHT
;
297 if (drawbuffer
< 0 || drawbuffer
>= (GLint
)ctx
->Const
.MaxDrawBuffers
) {
300 else if (att
[BUFFER_COLOR0
+ drawbuffer
].Renderbuffer
) {
301 mask
|= (BUFFER_BIT_COLOR0
<< drawbuffer
);
312 * Clear signed integer color buffer or stencil buffer (not depth).
315 _mesa_ClearBufferiv(GLenum buffer
, GLint drawbuffer
, const GLint
*value
)
317 GET_CURRENT_CONTEXT(ctx
);
318 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
320 FLUSH_CURRENT(ctx
, 0);
323 _mesa_update_state( ctx
);
328 if (drawbuffer
!= 0) {
329 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
334 /* Save current stencil clear value, set to 'value', do the
335 * stencil clear and restore the clear value.
336 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
339 const GLuint clearSave
= ctx
->Stencil
.Clear
;
340 ctx
->Stencil
.Clear
= *value
;
341 if (ctx
->Driver
.ClearStencil
)
342 ctx
->Driver
.ClearStencil(ctx
, *value
);
343 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_STENCIL
);
344 ctx
->Stencil
.Clear
= clearSave
;
345 if (ctx
->Driver
.ClearStencil
)
346 ctx
->Driver
.ClearStencil(ctx
, clearSave
);
351 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
352 if (mask
== INVALID_MASK
) {
353 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
358 /* XXX note: we're putting the integer clear values into the
359 * floating point state var. This will not always work. We'll
360 * need a new ctx->Driver.ClearBuffer() hook....
362 GLclampf clearSave
[4];
364 COPY_4V(clearSave
, ctx
->Color
.ClearColor
);
366 COPY_4V_CAST(ctx
->Color
.ClearColor
, value
, GLclampf
);
367 if (ctx
->Driver
.ClearColor
)
368 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
369 /* clear buffer(s) */
370 ctx
->Driver
.Clear(ctx
, mask
);
372 COPY_4V(ctx
->Color
.ClearColor
, clearSave
);
373 if (ctx
->Driver
.ClearColor
)
374 ctx
->Driver
.ClearColor(ctx
, clearSave
);
379 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferiv(buffer=%s)",
380 _mesa_lookup_enum_by_nr(buffer
));
388 * Clear unsigned integer color buffer (not depth, not stencil).
391 _mesa_ClearBufferuiv(GLenum buffer
, GLint drawbuffer
, const GLuint
*value
)
393 GET_CURRENT_CONTEXT(ctx
);
394 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
396 FLUSH_CURRENT(ctx
, 0);
399 _mesa_update_state( ctx
);
405 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
406 if (mask
== INVALID_MASK
) {
407 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
412 /* XXX note: we're putting the uint clear values into the
413 * floating point state var. This will not always work. We'll
414 * need a new ctx->Driver.ClearBuffer() hook....
416 GLclampf clearSave
[4];
418 COPY_4V(clearSave
, ctx
->Color
.ClearColor
);
420 COPY_4V_CAST(ctx
->Color
.ClearColor
, value
, GLclampf
);
421 if (ctx
->Driver
.ClearColor
)
422 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
423 /* clear buffer(s) */
424 ctx
->Driver
.Clear(ctx
, mask
);
426 COPY_4V(ctx
->Color
.ClearColor
, clearSave
);
427 if (ctx
->Driver
.ClearColor
)
428 ctx
->Driver
.ClearColor(ctx
, clearSave
);
433 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferuiv(buffer=%s)",
434 _mesa_lookup_enum_by_nr(buffer
));
442 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
445 _mesa_ClearBufferfv(GLenum buffer
, GLint drawbuffer
, const GLfloat
*value
)
447 GET_CURRENT_CONTEXT(ctx
);
448 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
450 FLUSH_CURRENT(ctx
, 0);
453 _mesa_update_state( ctx
);
458 if (drawbuffer
!= 0) {
459 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfv(drawbuffer=%d)",
464 /* Save current depth clear value, set to 'value', do the
465 * depth clear and restore the clear value.
466 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
469 const GLclampd clearSave
= ctx
->Depth
.Clear
;
470 ctx
->Depth
.Clear
= *value
;
471 if (ctx
->Driver
.ClearDepth
)
472 ctx
->Driver
.ClearDepth(ctx
, *value
);
473 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_DEPTH
);
474 ctx
->Depth
.Clear
= clearSave
;
475 if (ctx
->Driver
.ClearDepth
)
476 ctx
->Driver
.ClearDepth(ctx
, clearSave
);
478 /* clear depth buffer to value */
482 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
483 if (mask
== INVALID_MASK
) {
484 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfv(drawbuffer=%d)",
489 GLclampf clearSave
[4];
491 COPY_4V(clearSave
, ctx
->Color
.ClearColor
);
493 COPY_4V_CAST(ctx
->Color
.ClearColor
, value
, GLclampf
);
494 if (ctx
->Driver
.ClearColor
)
495 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
496 /* clear buffer(s) */
497 ctx
->Driver
.Clear(ctx
, mask
);
499 COPY_4V(ctx
->Color
.ClearColor
, clearSave
);
500 if (ctx
->Driver
.ClearColor
)
501 ctx
->Driver
.ClearColor(ctx
, clearSave
);
506 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfv(buffer=%s)",
507 _mesa_lookup_enum_by_nr(buffer
));
515 * Clear depth/stencil buffer only.
518 _mesa_ClearBufferfi(GLenum buffer
, GLint drawbuffer
,
519 GLfloat depth
, GLint stencil
)
521 GET_CURRENT_CONTEXT(ctx
);
522 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
524 FLUSH_CURRENT(ctx
, 0);
526 if (buffer
!= GL_DEPTH_STENCIL
) {
527 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfi(buffer=%s)",
528 _mesa_lookup_enum_by_nr(buffer
));
532 if (drawbuffer
!= 0) {
533 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfi(drawbuffer=%d)",
539 _mesa_update_state( ctx
);
543 /* save current clear values */
544 const GLclampd clearDepthSave
= ctx
->Depth
.Clear
;
545 const GLuint clearStencilSave
= ctx
->Stencil
.Clear
;
547 /* set new clear values */
548 ctx
->Depth
.Clear
= depth
;
549 ctx
->Stencil
.Clear
= stencil
;
550 if (ctx
->Driver
.ClearDepth
)
551 ctx
->Driver
.ClearDepth(ctx
, depth
);
552 if (ctx
->Driver
.ClearStencil
)
553 ctx
->Driver
.ClearStencil(ctx
, stencil
);
556 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_DEPTH
| BUFFER_BIT_STENCIL
);
559 ctx
->Depth
.Clear
= clearDepthSave
;
560 ctx
->Stencil
.Clear
= clearStencilSave
;
561 if (ctx
->Driver
.ClearDepth
)
562 ctx
->Driver
.ClearDepth(ctx
, clearDepthSave
);
563 if (ctx
->Driver
.ClearStencil
)
564 ctx
->Driver
.ClearStencil(ctx
, clearStencilSave
);