r300/compiler: Remove unnecessary header.
[mesa.git] / src / mesa / main / clear.c
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 "state.h"
39
40
41
42 #if _HAVE_FULL_GL
43 void GLAPIENTRY
44 _mesa_ClearIndex( GLfloat c )
45 {
46 GET_CURRENT_CONTEXT(ctx);
47 ASSERT_OUTSIDE_BEGIN_END(ctx);
48
49 if (ctx->Color.ClearIndex == (GLuint) c)
50 return;
51
52 FLUSH_VERTICES(ctx, _NEW_COLOR);
53 ctx->Color.ClearIndex = (GLuint) c;
54 }
55 #endif
56
57
58 /**
59 * Specify the clear values for the color buffers.
60 *
61 * \param red red color component.
62 * \param green green color component.
63 * \param blue blue color component.
64 * \param alpha alpha component.
65 *
66 * \sa glClearColor().
67 *
68 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a
69 * change, flushes the vertices and notifies the driver via the
70 * dd_function_table::ClearColor callback.
71 */
72 void GLAPIENTRY
73 _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
74 {
75 GLfloat tmp[4];
76 GET_CURRENT_CONTEXT(ctx);
77 ASSERT_OUTSIDE_BEGIN_END(ctx);
78
79 tmp[0] = CLAMP(red, 0.0F, 1.0F);
80 tmp[1] = CLAMP(green, 0.0F, 1.0F);
81 tmp[2] = CLAMP(blue, 0.0F, 1.0F);
82 tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
83
84 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
85 return; /* no change */
86
87 FLUSH_VERTICES(ctx, _NEW_COLOR);
88 COPY_4V(ctx->Color.ClearColor, tmp);
89
90 if (ctx->Driver.ClearColor) {
91 /* it's OK to call glClearColor in CI mode but it should be a NOP */
92 (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor);
93 }
94 }
95
96
97 /**
98 * Clear buffers.
99 *
100 * \param mask bit-mask indicating the buffers to be cleared.
101 *
102 * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState
103 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
104 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
105 * to clear the buffers, via the dd_function_table::Clear callback.
106 */
107 void GLAPIENTRY
108 _mesa_Clear( GLbitfield mask )
109 {
110 GET_CURRENT_CONTEXT(ctx);
111 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
112
113 FLUSH_CURRENT(ctx, 0);
114
115 if (MESA_VERBOSE & VERBOSE_API)
116 _mesa_debug(ctx, "glClear 0x%x\n", mask);
117
118 if (mask & ~(GL_COLOR_BUFFER_BIT |
119 GL_DEPTH_BUFFER_BIT |
120 GL_STENCIL_BUFFER_BIT |
121 GL_ACCUM_BUFFER_BIT)) {
122 /* invalid bit set */
123 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
124 return;
125 }
126
127 if (ctx->NewState) {
128 _mesa_update_state( ctx ); /* update _Xmin, etc */
129 }
130
131 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
132 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
133 "glClear(incomplete framebuffer)");
134 return;
135 }
136
137 if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 ||
138 ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax ||
139 ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax)
140 return;
141
142 if (ctx->RenderMode == GL_RENDER) {
143 GLbitfield bufferMask;
144
145 /* don't clear depth buffer if depth writing disabled */
146 if (!ctx->Depth.Mask)
147 mask &= ~GL_DEPTH_BUFFER_BIT;
148
149 /* Build the bitmask to send to device driver's Clear function.
150 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
151 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
152 * BUFFER_BIT_COLORn flags.
153 */
154 bufferMask = 0;
155 if (mask & GL_COLOR_BUFFER_BIT) {
156 GLuint i;
157 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
158 bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]);
159 }
160 }
161
162 if ((mask & GL_DEPTH_BUFFER_BIT)
163 && ctx->DrawBuffer->Visual.haveDepthBuffer) {
164 bufferMask |= BUFFER_BIT_DEPTH;
165 }
166
167 if ((mask & GL_STENCIL_BUFFER_BIT)
168 && ctx->DrawBuffer->Visual.haveStencilBuffer) {
169 bufferMask |= BUFFER_BIT_STENCIL;
170 }
171
172 if ((mask & GL_ACCUM_BUFFER_BIT)
173 && ctx->DrawBuffer->Visual.haveAccumBuffer) {
174 bufferMask |= BUFFER_BIT_ACCUM;
175 }
176
177 ASSERT(ctx->Driver.Clear);
178 ctx->Driver.Clear(ctx, bufferMask);
179 }
180 }
181
182
183 /** Returned by make_color_buffer_mask() for errors */
184 #define INVALID_MASK ~0x0
185
186
187 /**
188 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of
189 * BUFFER_BIT_x values.
190 * Return INVALID_MASK if the drawbuffer value is invalid.
191 */
192 static GLbitfield
193 make_color_buffer_mask(GLcontext *ctx, GLint drawbuffer)
194 {
195 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
196 GLbitfield mask = 0x0;
197
198 switch (drawbuffer) {
199 case GL_FRONT:
200 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
201 mask |= BUFFER_BIT_FRONT_LEFT;
202 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
203 mask |= BUFFER_BIT_FRONT_RIGHT;
204 break;
205 case GL_BACK:
206 if (att[BUFFER_BACK_LEFT].Renderbuffer)
207 mask |= BUFFER_BIT_BACK_LEFT;
208 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
209 mask |= BUFFER_BIT_BACK_RIGHT;
210 break;
211 case GL_LEFT:
212 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
213 mask |= BUFFER_BIT_FRONT_LEFT;
214 if (att[BUFFER_BACK_LEFT].Renderbuffer)
215 mask |= BUFFER_BIT_BACK_LEFT;
216 break;
217 case GL_RIGHT:
218 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
219 mask |= BUFFER_BIT_FRONT_RIGHT;
220 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
221 mask |= BUFFER_BIT_BACK_RIGHT;
222 break;
223 case GL_FRONT_AND_BACK:
224 if (att[BUFFER_FRONT_LEFT].Renderbuffer)
225 mask |= BUFFER_BIT_FRONT_LEFT;
226 if (att[BUFFER_BACK_LEFT].Renderbuffer)
227 mask |= BUFFER_BIT_BACK_LEFT;
228 if (att[BUFFER_FRONT_RIGHT].Renderbuffer)
229 mask |= BUFFER_BIT_FRONT_RIGHT;
230 if (att[BUFFER_BACK_RIGHT].Renderbuffer)
231 mask |= BUFFER_BIT_BACK_RIGHT;
232 break;
233 default:
234 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) {
235 mask = INVALID_MASK;
236 }
237 else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) {
238 mask |= (BUFFER_BIT_COLOR0 << drawbuffer);
239 }
240 }
241
242 return mask;
243 }
244
245
246
247 /**
248 * New in GL 3.0
249 * Clear signed integer color buffer or stencil buffer (not depth).
250 */
251 void GLAPIENTRY
252 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
253 {
254 GET_CURRENT_CONTEXT(ctx);
255 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
256
257 FLUSH_CURRENT(ctx, 0);
258
259 if (ctx->NewState) {
260 _mesa_update_state( ctx );
261 }
262
263 switch (buffer) {
264 case GL_STENCIL:
265 if (drawbuffer != 0) {
266 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
267 drawbuffer);
268 return;
269 }
270 else {
271 /* Save current stencil clear value, set to 'value', do the
272 * stencil clear and restore the clear value.
273 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
274 * hook instead.
275 */
276 const GLuint clearSave = ctx->Stencil.Clear;
277 ctx->Stencil.Clear = *value;
278 if (ctx->Driver.ClearStencil)
279 ctx->Driver.ClearStencil(ctx, *value);
280 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL);
281 ctx->Stencil.Clear = clearSave;
282 if (ctx->Driver.ClearStencil)
283 ctx->Driver.ClearStencil(ctx, clearSave);
284 }
285 break;
286 case GL_COLOR:
287 {
288 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
289 if (mask == INVALID_MASK) {
290 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
291 drawbuffer);
292 return;
293 }
294 else if (mask) {
295 /* XXX note: we're putting the integer clear values into the
296 * floating point state var. This will not always work. We'll
297 * need a new ctx->Driver.ClearBuffer() hook....
298 */
299 GLclampf clearSave[4];
300 /* save color */
301 COPY_4V(clearSave, ctx->Color.ClearColor);
302 /* set color */
303 COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
304 if (ctx->Driver.ClearColor)
305 ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
306 /* clear buffer(s) */
307 ctx->Driver.Clear(ctx, mask);
308 /* restore color */
309 COPY_4V(ctx->Color.ClearColor, clearSave);
310 if (ctx->Driver.ClearColor)
311 ctx->Driver.ClearColor(ctx, clearSave);
312 }
313 }
314 break;
315 default:
316 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
317 _mesa_lookup_enum_by_nr(buffer));
318 return;
319 }
320 }
321
322
323 /**
324 * New in GL 3.0
325 * Clear unsigned integer color buffer (not depth, not stencil).
326 */
327 void GLAPIENTRY
328 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
329 {
330 GET_CURRENT_CONTEXT(ctx);
331 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
332
333 FLUSH_CURRENT(ctx, 0);
334
335 if (ctx->NewState) {
336 _mesa_update_state( ctx );
337 }
338
339 switch (buffer) {
340 case GL_COLOR:
341 {
342 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
343 if (mask == INVALID_MASK) {
344 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)",
345 drawbuffer);
346 return;
347 }
348 else if (mask) {
349 /* XXX note: we're putting the uint clear values into the
350 * floating point state var. This will not always work. We'll
351 * need a new ctx->Driver.ClearBuffer() hook....
352 */
353 GLclampf clearSave[4];
354 /* save color */
355 COPY_4V(clearSave, ctx->Color.ClearColor);
356 /* set color */
357 COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
358 if (ctx->Driver.ClearColor)
359 ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
360 /* clear buffer(s) */
361 ctx->Driver.Clear(ctx, mask);
362 /* restore color */
363 COPY_4V(ctx->Color.ClearColor, clearSave);
364 if (ctx->Driver.ClearColor)
365 ctx->Driver.ClearColor(ctx, clearSave);
366 }
367 }
368 break;
369 default:
370 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
371 _mesa_lookup_enum_by_nr(buffer));
372 return;
373 }
374 }
375
376
377 /**
378 * New in GL 3.0
379 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
380 */
381 void GLAPIENTRY
382 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
383 {
384 GET_CURRENT_CONTEXT(ctx);
385 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
386
387 FLUSH_CURRENT(ctx, 0);
388
389 if (ctx->NewState) {
390 _mesa_update_state( ctx );
391 }
392
393 switch (buffer) {
394 case GL_DEPTH:
395 if (drawbuffer != 0) {
396 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
397 drawbuffer);
398 return;
399 }
400 else {
401 /* Save current depth clear value, set to 'value', do the
402 * depth clear and restore the clear value.
403 * XXX in the future we may have a new ctx->Driver.ClearBuffer()
404 * hook instead.
405 */
406 const GLclampd clearSave = ctx->Depth.Clear;
407 ctx->Depth.Clear = *value;
408 if (ctx->Driver.ClearDepth)
409 ctx->Driver.ClearDepth(ctx, *value);
410 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
411 ctx->Depth.Clear = clearSave;
412 if (ctx->Driver.ClearDepth)
413 ctx->Driver.ClearDepth(ctx, clearSave);
414 }
415 /* clear depth buffer to value */
416 break;
417 case GL_COLOR:
418 {
419 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
420 if (mask == INVALID_MASK) {
421 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
422 drawbuffer);
423 return;
424 }
425 else if (mask) {
426 GLclampf clearSave[4];
427 /* save color */
428 COPY_4V(clearSave, ctx->Color.ClearColor);
429 /* set color */
430 COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
431 if (ctx->Driver.ClearColor)
432 ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
433 /* clear buffer(s) */
434 ctx->Driver.Clear(ctx, mask);
435 /* restore color */
436 COPY_4V(ctx->Color.ClearColor, clearSave);
437 if (ctx->Driver.ClearColor)
438 ctx->Driver.ClearColor(ctx, clearSave);
439 }
440 }
441 break;
442 default:
443 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
444 _mesa_lookup_enum_by_nr(buffer));
445 return;
446 }
447 }
448
449
450 /**
451 * New in GL 3.0
452 * Clear depth/stencil buffer only.
453 */
454 void GLAPIENTRY
455 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
456 GLfloat depth, GLint stencil)
457 {
458 GET_CURRENT_CONTEXT(ctx);
459 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
460
461 FLUSH_CURRENT(ctx, 0);
462
463 if (buffer != GL_DEPTH_STENCIL) {
464 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
465 _mesa_lookup_enum_by_nr(buffer));
466 return;
467 }
468
469 if (drawbuffer != 0) {
470 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)",
471 drawbuffer);
472 return;
473 }
474
475 if (ctx->NewState) {
476 _mesa_update_state( ctx );
477 }
478
479 {
480 /* save current clear values */
481 const GLclampd clearDepthSave = ctx->Depth.Clear;
482 const GLuint clearStencilSave = ctx->Stencil.Clear;
483
484 /* set new clear values */
485 ctx->Depth.Clear = depth;
486 ctx->Stencil.Clear = stencil;
487 if (ctx->Driver.ClearDepth)
488 ctx->Driver.ClearDepth(ctx, depth);
489 if (ctx->Driver.ClearStencil)
490 ctx->Driver.ClearStencil(ctx, stencil);
491
492 /* clear buffers */
493 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
494
495 /* restore */
496 ctx->Depth.Clear = clearDepthSave;
497 ctx->Stencil.Clear = clearStencilSave;
498 if (ctx->Driver.ClearDepth)
499 ctx->Driver.ClearDepth(ctx, clearDepthSave);
500 if (ctx->Driver.ClearStencil)
501 ctx->Driver.ClearStencil(ctx, clearStencilSave);
502 }
503 }