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.
44 _mesa_ClearIndex( GLfloat c
)
46 GET_CURRENT_CONTEXT(ctx
);
47 ASSERT_OUTSIDE_BEGIN_END(ctx
);
49 if (ctx
->Color
.ClearIndex
== (GLuint
) c
)
52 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
53 ctx
->Color
.ClearIndex
= (GLuint
) c
;
55 if (!ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearIndex
) {
56 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
57 (*ctx
->Driver
.ClearIndex
)( ctx
, ctx
->Color
.ClearIndex
);
64 * Specify the clear values for the color buffers.
66 * \param red red color component.
67 * \param green green color component.
68 * \param blue blue color component.
69 * \param alpha alpha component.
73 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a
74 * change, flushes the vertices and notifies the driver via the
75 * dd_function_table::ClearColor callback.
78 _mesa_ClearColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
81 GET_CURRENT_CONTEXT(ctx
);
82 ASSERT_OUTSIDE_BEGIN_END(ctx
);
84 tmp
[0] = CLAMP(red
, 0.0F
, 1.0F
);
85 tmp
[1] = CLAMP(green
, 0.0F
, 1.0F
);
86 tmp
[2] = CLAMP(blue
, 0.0F
, 1.0F
);
87 tmp
[3] = CLAMP(alpha
, 0.0F
, 1.0F
);
89 if (TEST_EQ_4V(tmp
, ctx
->Color
.ClearColor
))
90 return; /* no change */
92 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
93 COPY_4V(ctx
->Color
.ClearColor
, tmp
);
95 if (ctx
->Visual
.rgbMode
&& ctx
->Driver
.ClearColor
) {
96 /* it's OK to call glClearColor in CI mode but it should be a NOP */
97 (*ctx
->Driver
.ClearColor
)(ctx
, ctx
->Color
.ClearColor
);
105 * \param mask bit-mask indicating the buffers to be cleared.
107 * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState
108 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
109 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
110 * to clear the buffers, via the dd_function_table::Clear callback.
113 _mesa_Clear( GLbitfield mask
)
115 GET_CURRENT_CONTEXT(ctx
);
116 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
118 FLUSH_CURRENT(ctx
, 0);
120 if (MESA_VERBOSE
& VERBOSE_API
)
121 _mesa_debug(ctx
, "glClear 0x%x\n", mask
);
123 if (mask
& ~(GL_COLOR_BUFFER_BIT
|
124 GL_DEPTH_BUFFER_BIT
|
125 GL_STENCIL_BUFFER_BIT
|
126 GL_ACCUM_BUFFER_BIT
)) {
127 /* invalid bit set */
128 _mesa_error( ctx
, GL_INVALID_VALUE
, "glClear(0x%x)", mask
);
133 _mesa_update_state( ctx
); /* update _Xmin, etc */
136 if (ctx
->DrawBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
137 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
138 "glClear(incomplete framebuffer)");
142 if (ctx
->DrawBuffer
->Width
== 0 || ctx
->DrawBuffer
->Height
== 0 ||
143 ctx
->DrawBuffer
->_Xmin
>= ctx
->DrawBuffer
->_Xmax
||
144 ctx
->DrawBuffer
->_Ymin
>= ctx
->DrawBuffer
->_Ymax
)
147 if (ctx
->RenderMode
== GL_RENDER
) {
148 GLbitfield bufferMask
;
150 /* don't clear depth buffer if depth writing disabled */
151 if (!ctx
->Depth
.Mask
)
152 mask
&= ~GL_DEPTH_BUFFER_BIT
;
154 /* Build the bitmask to send to device driver's Clear function.
155 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
156 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
157 * BUFFER_BIT_COLORn flags.
160 if (mask
& GL_COLOR_BUFFER_BIT
) {
162 for (i
= 0; i
< ctx
->DrawBuffer
->_NumColorDrawBuffers
; i
++) {
163 bufferMask
|= (1 << ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[i
]);
167 if ((mask
& GL_DEPTH_BUFFER_BIT
)
168 && ctx
->DrawBuffer
->Visual
.haveDepthBuffer
) {
169 bufferMask
|= BUFFER_BIT_DEPTH
;
172 if ((mask
& GL_STENCIL_BUFFER_BIT
)
173 && ctx
->DrawBuffer
->Visual
.haveStencilBuffer
) {
174 bufferMask
|= BUFFER_BIT_STENCIL
;
177 if ((mask
& GL_ACCUM_BUFFER_BIT
)
178 && ctx
->DrawBuffer
->Visual
.haveAccumBuffer
) {
179 bufferMask
|= BUFFER_BIT_ACCUM
;
182 ASSERT(ctx
->Driver
.Clear
);
183 ctx
->Driver
.Clear(ctx
, bufferMask
);
188 /** Returned by make_color_buffer_mask() for errors */
189 #define INVALID_MASK ~0x0
193 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
194 * BUFFER_BIT_x values.
195 * Return INVALID_MASK if the drawbuffer value is invalid.
198 make_color_buffer_mask(GLcontext
*ctx
, GLint drawbuffer
)
200 const struct gl_renderbuffer_attachment
*att
= ctx
->DrawBuffer
->Attachment
;
201 GLbitfield mask
= 0x0;
203 switch (drawbuffer
) {
205 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
206 mask
|= BUFFER_BIT_FRONT_LEFT
;
207 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
208 mask
|= BUFFER_BIT_FRONT_RIGHT
;
211 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
212 mask
|= BUFFER_BIT_BACK_LEFT
;
213 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
214 mask
|= BUFFER_BIT_BACK_RIGHT
;
217 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
218 mask
|= BUFFER_BIT_FRONT_LEFT
;
219 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
220 mask
|= BUFFER_BIT_BACK_LEFT
;
223 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
224 mask
|= BUFFER_BIT_FRONT_RIGHT
;
225 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
226 mask
|= BUFFER_BIT_BACK_RIGHT
;
228 case GL_FRONT_AND_BACK
:
229 if (att
[BUFFER_FRONT_LEFT
].Renderbuffer
)
230 mask
|= BUFFER_BIT_FRONT_LEFT
;
231 if (att
[BUFFER_BACK_LEFT
].Renderbuffer
)
232 mask
|= BUFFER_BIT_BACK_LEFT
;
233 if (att
[BUFFER_FRONT_RIGHT
].Renderbuffer
)
234 mask
|= BUFFER_BIT_FRONT_RIGHT
;
235 if (att
[BUFFER_BACK_RIGHT
].Renderbuffer
)
236 mask
|= BUFFER_BIT_BACK_RIGHT
;
239 if (drawbuffer
< 0 || drawbuffer
>= ctx
->Const
.MaxDrawBuffers
) {
242 else if (att
[BUFFER_COLOR0
+ drawbuffer
].Renderbuffer
) {
243 mask
|= (BUFFER_BIT_COLOR0
<< drawbuffer
);
254 * Clear signed integer color buffer or stencil buffer (not depth).
257 _mesa_ClearBufferiv(GLenum buffer
, GLint drawbuffer
, const GLint
*value
)
259 GET_CURRENT_CONTEXT(ctx
);
260 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
262 FLUSH_CURRENT(ctx
, 0);
264 if (!ctx
->DrawBuffer
->Visual
.rgbMode
) {
265 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glClearBufferiv()");
270 _mesa_update_state( ctx
);
275 if (drawbuffer
!= 0) {
276 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
281 /* Save current stencil clear value, set to 'value', do the
282 * stencil clear and restore the clear value.
283 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
286 const GLuint clearSave
= ctx
->Stencil
.Clear
;
287 ctx
->Stencil
.Clear
= *value
;
288 if (ctx
->Driver
.ClearStencil
)
289 ctx
->Driver
.ClearStencil(ctx
, *value
);
290 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_STENCIL
);
291 ctx
->Stencil
.Clear
= clearSave
;
292 if (ctx
->Driver
.ClearStencil
)
293 ctx
->Driver
.ClearStencil(ctx
, clearSave
);
298 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
299 if (mask
== INVALID_MASK
) {
300 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
305 /* XXX note: we're putting the integer clear values into the
306 * floating point state var. This will not always work. We'll
307 * need a new ctx->Driver.ClearBuffer() hook....
309 GLfloat clearSave
[4];
311 COPY_4V(clearSave
, ctx
->Color
.ClearColor
);
313 COPY_4V(ctx
->Color
.ClearColor
, value
);
314 if (ctx
->Driver
.ClearColor
)
315 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
316 /* clear buffer(s) */
317 ctx
->Driver
.Clear(ctx
, mask
);
319 COPY_4V(ctx
->Color
.ClearColor
, clearSave
);
320 if (ctx
->Driver
.ClearColor
)
321 ctx
->Driver
.ClearColor(ctx
, clearSave
);
326 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferiv(buffer=%s)",
327 _mesa_lookup_enum_by_nr(buffer
));
335 * Clear unsigned integer color buffer (not depth, not stencil).
338 _mesa_ClearBufferuiv(GLenum buffer
, GLint drawbuffer
, const GLuint
*value
)
340 GET_CURRENT_CONTEXT(ctx
);
341 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
343 FLUSH_CURRENT(ctx
, 0);
345 if (!ctx
->DrawBuffer
->Visual
.rgbMode
) {
346 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glClearBufferuiv()");
351 _mesa_update_state( ctx
);
357 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
358 if (mask
== INVALID_MASK
) {
359 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferiv(drawbuffer=%d)",
364 /* XXX note: we're putting the uint clear values into the
365 * floating point state var. This will not always work. We'll
366 * need a new ctx->Driver.ClearBuffer() hook....
368 GLfloat clearSave
[4];
370 COPY_4V(clearSave
, ctx
->Color
.ClearColor
);
372 COPY_4V(ctx
->Color
.ClearColor
, value
);
373 if (ctx
->Driver
.ClearColor
)
374 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
375 /* clear buffer(s) */
376 ctx
->Driver
.Clear(ctx
, mask
);
378 COPY_4V(ctx
->Color
.ClearColor
, clearSave
);
379 if (ctx
->Driver
.ClearColor
)
380 ctx
->Driver
.ClearColor(ctx
, clearSave
);
385 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferuiv(buffer=%s)",
386 _mesa_lookup_enum_by_nr(buffer
));
394 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
397 _mesa_ClearBufferfv(GLenum buffer
, GLint drawbuffer
, const GLfloat
*value
)
399 GET_CURRENT_CONTEXT(ctx
);
400 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
402 FLUSH_CURRENT(ctx
, 0);
404 if (!ctx
->DrawBuffer
->Visual
.rgbMode
) {
405 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glClearBufferfv()");
410 _mesa_update_state( ctx
);
415 if (drawbuffer
!= 0) {
416 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfv(drawbuffer=%d)",
421 /* Save current depth clear value, set to 'value', do the
422 * depth clear and restore the clear value.
423 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
426 const GLfloat clearSave
= ctx
->Depth
.Clear
;
427 ctx
->Depth
.Clear
= *value
;
428 if (ctx
->Driver
.ClearDepth
)
429 ctx
->Driver
.ClearDepth(ctx
, *value
);
430 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_DEPTH
);
431 ctx
->Depth
.Clear
= clearSave
;
432 if (ctx
->Driver
.ClearDepth
)
433 ctx
->Driver
.ClearDepth(ctx
, clearSave
);
435 /* clear depth buffer to value */
439 const GLbitfield mask
= make_color_buffer_mask(ctx
, drawbuffer
);
440 if (mask
== INVALID_MASK
) {
441 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfv(drawbuffer=%d)",
446 GLfloat clearSave
[4];
448 COPY_4V(clearSave
, ctx
->Color
.ClearColor
);
450 COPY_4V(ctx
->Color
.ClearColor
, value
);
451 if (ctx
->Driver
.ClearColor
)
452 ctx
->Driver
.ClearColor(ctx
, ctx
->Color
.ClearColor
);
453 /* clear buffer(s) */
454 ctx
->Driver
.Clear(ctx
, mask
);
456 COPY_4V(ctx
->Color
.ClearColor
, clearSave
);
457 if (ctx
->Driver
.ClearColor
)
458 ctx
->Driver
.ClearColor(ctx
, clearSave
);
463 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfv(buffer=%s)",
464 _mesa_lookup_enum_by_nr(buffer
));
472 * Clear depth/stencil buffer only.
475 _mesa_ClearBufferfi(GLenum buffer
, GLint drawbuffer
,
476 GLfloat depth
, GLint stencil
)
478 GET_CURRENT_CONTEXT(ctx
);
479 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
481 FLUSH_CURRENT(ctx
, 0);
483 if (!ctx
->DrawBuffer
->Visual
.rgbMode
) {
484 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glClearBufferfi()");
488 if (buffer
!= GL_DEPTH_STENCIL
) {
489 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfi(buffer=%s)",
490 _mesa_lookup_enum_by_nr(buffer
));
494 if (drawbuffer
!= 0) {
495 _mesa_error(ctx
, GL_INVALID_VALUE
, "glClearBufferfi(drawbuffer=%d)",
501 _mesa_update_state( ctx
);
505 /* save current clear values */
506 const GLfloat clearDepthSave
= ctx
->Depth
.Clear
;
507 const GLuint clearStencilSave
= ctx
->Stencil
.Clear
;
509 /* set new clear values */
510 ctx
->Depth
.Clear
= depth
;
511 ctx
->Stencil
.Clear
= stencil
;
512 if (ctx
->Driver
.ClearDepth
)
513 ctx
->Driver
.ClearDepth(ctx
, depth
);
514 if (ctx
->Driver
.ClearStencil
)
515 ctx
->Driver
.ClearStencil(ctx
, stencil
);
518 ctx
->Driver
.Clear(ctx
, BUFFER_BIT_DEPTH
| BUFFER_BIT_STENCIL
);
521 ctx
->Depth
.Clear
= clearDepthSave
;
522 ctx
->Stencil
.Clear
= clearStencilSave
;
523 if (ctx
->Driver
.ClearDepth
)
524 ctx
->Driver
.ClearDepth(ctx
, clearDepthSave
);
525 if (ctx
->Driver
.ClearStencil
)
526 ctx
->Driver
.ClearStencil(ctx
, clearStencilSave
);