clear.c revision cf41d7c63aab2289d739c0f9df116caf2cc410e3
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 "macros.h" 39#include "mtypes.h" 40#include "state.h" 41 42 43 44#if _HAVE_FULL_GL 45void GLAPIENTRY 46_mesa_ClearIndex( GLfloat c ) 47{ 48 GET_CURRENT_CONTEXT(ctx); 49 ASSERT_OUTSIDE_BEGIN_END(ctx); 50 51 if (ctx->Color.ClearIndex == (GLuint) c) 52 return; 53 54 FLUSH_VERTICES(ctx, _NEW_COLOR); 55 ctx->Color.ClearIndex = (GLuint) c; 56} 57#endif 58 59 60/** 61 * Specify the clear values for the color buffers. 62 * 63 * \param red red color component. 64 * \param green green color component. 65 * \param blue blue color component. 66 * \param alpha alpha component. 67 * 68 * \sa glClearColor(). 69 * 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. 73 */ 74void GLAPIENTRY 75_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 76{ 77 GLfloat tmp[4]; 78 GET_CURRENT_CONTEXT(ctx); 79 ASSERT_OUTSIDE_BEGIN_END(ctx); 80 81 tmp[0] = red; 82 tmp[1] = green; 83 tmp[2] = blue; 84 tmp[3] = alpha; 85 86 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.f)) 87 return; /* no change */ 88 89 FLUSH_VERTICES(ctx, _NEW_COLOR); 90 COPY_4V(ctx->Color.ClearColor.f, tmp); 91} 92 93 94/** 95 * GL_EXT_texture_integer 96 */ 97void GLAPIENTRY 98_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a) 99{ 100 GLint tmp[4]; 101 GET_CURRENT_CONTEXT(ctx); 102 ASSERT_OUTSIDE_BEGIN_END(ctx); 103 104 tmp[0] = r; 105 tmp[1] = g; 106 tmp[2] = b; 107 tmp[3] = a; 108 109 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.i)) 110 return; /* no change */ 111 112 FLUSH_VERTICES(ctx, _NEW_COLOR); 113 COPY_4V(ctx->Color.ClearColor.i, tmp); 114} 115 116 117/** 118 * GL_EXT_texture_integer 119 */ 120void GLAPIENTRY 121_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a) 122{ 123 GLuint tmp[4]; 124 GET_CURRENT_CONTEXT(ctx); 125 ASSERT_OUTSIDE_BEGIN_END(ctx); 126 127 tmp[0] = r; 128 tmp[1] = g; 129 tmp[2] = b; 130 tmp[3] = a; 131 132 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.ui)) 133 return; /* no change */ 134 135 FLUSH_VERTICES(ctx, _NEW_COLOR); 136 COPY_4V(ctx->Color.ClearColor.ui, tmp); 137} 138 139 140/** 141 * Clear buffers. 142 * 143 * \param mask bit-mask indicating the buffers to be cleared. 144 * 145 * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState 146 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin, 147 * etc. If the rasterization mode is set to GL_RENDER then requests the driver 148 * to clear the buffers, via the dd_function_table::Clear callback. 149 */ 150void GLAPIENTRY 151_mesa_Clear( GLbitfield mask ) 152{ 153 GET_CURRENT_CONTEXT(ctx); 154 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 155 156 FLUSH_CURRENT(ctx, 0); 157 158 if (MESA_VERBOSE & VERBOSE_API) 159 _mesa_debug(ctx, "glClear 0x%x\n", mask); 160 161 if (mask & ~(GL_COLOR_BUFFER_BIT | 162 GL_DEPTH_BUFFER_BIT | 163 GL_STENCIL_BUFFER_BIT | 164 GL_ACCUM_BUFFER_BIT)) { 165 /* invalid bit set */ 166 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); 167 return; 168 } 169 170 if (ctx->NewState) { 171 _mesa_update_state( ctx ); /* update _Xmin, etc */ 172 } 173 174 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 175 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 176 "glClear(incomplete framebuffer)"); 177 return; 178 } 179 180 if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 || 181 ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax || 182 ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax) 183 return; 184 185 if (ctx->RasterDiscard) 186 return; 187 188 if (ctx->RenderMode == GL_RENDER) { 189 GLbitfield bufferMask; 190 191 /* don't clear depth buffer if depth writing disabled */ 192 if (!ctx->Depth.Mask) 193 mask &= ~GL_DEPTH_BUFFER_BIT; 194 195 /* Build the bitmask to send to device driver's Clear function. 196 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 197 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 198 * BUFFER_BIT_COLORn flags. 199 */ 200 bufferMask = 0; 201 if (mask & GL_COLOR_BUFFER_BIT) { 202 GLuint i; 203 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { 204 bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]); 205 } 206 } 207 208 if ((mask & GL_DEPTH_BUFFER_BIT) 209 && ctx->DrawBuffer->Visual.haveDepthBuffer) { 210 bufferMask |= BUFFER_BIT_DEPTH; 211 } 212 213 if ((mask & GL_STENCIL_BUFFER_BIT) 214 && ctx->DrawBuffer->Visual.haveStencilBuffer) { 215 bufferMask |= BUFFER_BIT_STENCIL; 216 } 217 218 if ((mask & GL_ACCUM_BUFFER_BIT) 219 && ctx->DrawBuffer->Visual.haveAccumBuffer) { 220 bufferMask |= BUFFER_BIT_ACCUM; 221 } 222 223 ASSERT(ctx->Driver.Clear); 224 ctx->Driver.Clear(ctx, bufferMask); 225 } 226} 227 228 229/** Returned by make_color_buffer_mask() for errors */ 230#define INVALID_MASK ~0x0 231 232 233/** 234 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of 235 * BUFFER_BIT_x values. 236 * Return INVALID_MASK if the drawbuffer value is invalid. 237 */ 238static GLbitfield 239make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) 240{ 241 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; 242 GLbitfield mask = 0x0; 243 244 switch (drawbuffer) { 245 case GL_FRONT: 246 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 247 mask |= BUFFER_BIT_FRONT_LEFT; 248 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 249 mask |= BUFFER_BIT_FRONT_RIGHT; 250 break; 251 case GL_BACK: 252 if (att[BUFFER_BACK_LEFT].Renderbuffer) 253 mask |= BUFFER_BIT_BACK_LEFT; 254 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 255 mask |= BUFFER_BIT_BACK_RIGHT; 256 break; 257 case GL_LEFT: 258 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 259 mask |= BUFFER_BIT_FRONT_LEFT; 260 if (att[BUFFER_BACK_LEFT].Renderbuffer) 261 mask |= BUFFER_BIT_BACK_LEFT; 262 break; 263 case GL_RIGHT: 264 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 265 mask |= BUFFER_BIT_FRONT_RIGHT; 266 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 267 mask |= BUFFER_BIT_BACK_RIGHT; 268 break; 269 case GL_FRONT_AND_BACK: 270 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 271 mask |= BUFFER_BIT_FRONT_LEFT; 272 if (att[BUFFER_BACK_LEFT].Renderbuffer) 273 mask |= BUFFER_BIT_BACK_LEFT; 274 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 275 mask |= BUFFER_BIT_FRONT_RIGHT; 276 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 277 mask |= BUFFER_BIT_BACK_RIGHT; 278 break; 279 default: 280 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { 281 mask = INVALID_MASK; 282 } 283 else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) { 284 mask |= (BUFFER_BIT_COLOR0 << drawbuffer); 285 } 286 } 287 288 return mask; 289} 290 291 292 293/** 294 * New in GL 3.0 295 * Clear signed integer color buffer or stencil buffer (not depth). 296 */ 297void GLAPIENTRY 298_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) 299{ 300 GET_CURRENT_CONTEXT(ctx); 301 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 302 303 FLUSH_CURRENT(ctx, 0); 304 305 if (ctx->NewState) { 306 _mesa_update_state( ctx ); 307 } 308 309 switch (buffer) { 310 case GL_STENCIL: 311 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 312 * 313 * "ClearBuffer generates an INVALID VALUE error if buffer is 314 * COLOR and drawbuffer is less than zero, or greater than the 315 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 316 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 317 */ 318 if (drawbuffer != 0) { 319 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 320 drawbuffer); 321 return; 322 } 323 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer && !ctx->RasterDiscard) { 324 /* Save current stencil clear value, set to 'value', do the 325 * stencil clear and restore the clear value. 326 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 327 * hook instead. 328 */ 329 const GLuint clearSave = ctx->Stencil.Clear; 330 ctx->Stencil.Clear = *value; 331 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL); 332 ctx->Stencil.Clear = clearSave; 333 } 334 break; 335 case GL_COLOR: 336 { 337 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 338 if (mask == INVALID_MASK) { 339 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 340 drawbuffer); 341 return; 342 } 343 else if (mask && !ctx->RasterDiscard) { 344 union gl_color_union clearSave; 345 346 /* save color */ 347 clearSave = ctx->Color.ClearColor; 348 /* set color */ 349 COPY_4V(ctx->Color.ClearColor.i, value); 350 /* clear buffer(s) */ 351 ctx->Driver.Clear(ctx, mask); 352 /* restore color */ 353 ctx->Color.ClearColor = clearSave; 354 } 355 } 356 break; 357 case GL_DEPTH: 358 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 359 * 360 * "The result of ClearBuffer is undefined if no conversion between 361 * the type of the specified value and the type of the buffer being 362 * cleared is defined (for example, if ClearBufferiv is called for a 363 * fixed- or floating-point buffer, or if ClearBufferfv is called 364 * for a signed or unsigned integer buffer). This is not an error." 365 * 366 * In this case we take "undefined" and "not an error" to mean "ignore." 367 * Note that we still need to generate an error for the invalid 368 * drawbuffer case (see the GL_STENCIL case above). 369 */ 370 if (drawbuffer != 0) { 371 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 372 drawbuffer); 373 return; 374 } 375 return; 376 default: 377 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", 378 _mesa_lookup_enum_by_nr(buffer)); 379 return; 380 } 381} 382 383 384/** 385 * New in GL 3.0 386 * Clear unsigned integer color buffer (not depth, not stencil). 387 */ 388void GLAPIENTRY 389_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) 390{ 391 GET_CURRENT_CONTEXT(ctx); 392 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 393 394 FLUSH_CURRENT(ctx, 0); 395 396 if (ctx->NewState) { 397 _mesa_update_state( ctx ); 398 } 399 400 switch (buffer) { 401 case GL_COLOR: 402 { 403 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 404 if (mask == INVALID_MASK) { 405 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 406 drawbuffer); 407 return; 408 } 409 else if (mask && !ctx->RasterDiscard) { 410 union gl_color_union clearSave; 411 412 /* save color */ 413 clearSave = ctx->Color.ClearColor; 414 /* set color */ 415 COPY_4V(ctx->Color.ClearColor.ui, value); 416 /* clear buffer(s) */ 417 ctx->Driver.Clear(ctx, mask); 418 /* restore color */ 419 ctx->Color.ClearColor = clearSave; 420 } 421 } 422 break; 423 case GL_DEPTH: 424 case GL_STENCIL: 425 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 426 * 427 * "The result of ClearBuffer is undefined if no conversion between 428 * the type of the specified value and the type of the buffer being 429 * cleared is defined (for example, if ClearBufferiv is called for a 430 * fixed- or floating-point buffer, or if ClearBufferfv is called 431 * for a signed or unsigned integer buffer). This is not an error." 432 * 433 * In this case we take "undefined" and "not an error" to mean "ignore." 434 * Even though we could do something sensible for GL_STENCIL, page 263 435 * (page 279 of the PDF) says: 436 * 437 * "Only ClearBufferiv should be used to clear stencil buffers." 438 * 439 * Note that we still need to generate an error for the invalid 440 * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv). 441 */ 442 if (drawbuffer != 0) { 443 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 444 drawbuffer); 445 return; 446 } 447 return; 448 default: 449 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", 450 _mesa_lookup_enum_by_nr(buffer)); 451 return; 452 } 453} 454 455 456/** 457 * New in GL 3.0 458 * Clear fixed-pt or float color buffer or depth buffer (not stencil). 459 */ 460void GLAPIENTRY 461_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) 462{ 463 GET_CURRENT_CONTEXT(ctx); 464 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 465 466 FLUSH_CURRENT(ctx, 0); 467 468 if (ctx->NewState) { 469 _mesa_update_state( ctx ); 470 } 471 472 switch (buffer) { 473 case GL_DEPTH: 474 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 475 * 476 * "ClearBuffer generates an INVALID VALUE error if buffer is 477 * COLOR and drawbuffer is less than zero, or greater than the 478 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 479 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 480 */ 481 if (drawbuffer != 0) { 482 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 483 drawbuffer); 484 return; 485 } 486 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) { 487 /* Save current depth clear value, set to 'value', do the 488 * depth clear and restore the clear value. 489 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 490 * hook instead. 491 */ 492 const GLclampd clearSave = ctx->Depth.Clear; 493 ctx->Depth.Clear = *value; 494 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH); 495 ctx->Depth.Clear = clearSave; 496 } 497 /* clear depth buffer to value */ 498 break; 499 case GL_COLOR: 500 { 501 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 502 if (mask == INVALID_MASK) { 503 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 504 drawbuffer); 505 return; 506 } 507 else if (mask && !ctx->RasterDiscard) { 508 union gl_color_union clearSave; 509 510 /* save color */ 511 clearSave = ctx->Color.ClearColor; 512 /* set color */ 513 COPY_4V(ctx->Color.ClearColor.f, value); 514 /* clear buffer(s) */ 515 ctx->Driver.Clear(ctx, mask); 516 /* restore color */ 517 ctx->Color.ClearColor = clearSave; 518 } 519 } 520 break; 521 case GL_STENCIL: 522 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 523 * 524 * "The result of ClearBuffer is undefined if no conversion between 525 * the type of the specified value and the type of the buffer being 526 * cleared is defined (for example, if ClearBufferiv is called for a 527 * fixed- or floating-point buffer, or if ClearBufferfv is called 528 * for a signed or unsigned integer buffer). This is not an error." 529 * 530 * In this case we take "undefined" and "not an error" to mean "ignore." 531 * Note that we still need to generate an error for the invalid 532 * drawbuffer case (see the GL_DEPTH case above). 533 */ 534 if (drawbuffer != 0) { 535 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 536 drawbuffer); 537 return; 538 } 539 return; 540 default: 541 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", 542 _mesa_lookup_enum_by_nr(buffer)); 543 return; 544 } 545} 546 547 548/** 549 * New in GL 3.0 550 * Clear depth/stencil buffer only. 551 */ 552void GLAPIENTRY 553_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, 554 GLfloat depth, GLint stencil) 555{ 556 GET_CURRENT_CONTEXT(ctx); 557 GLbitfield mask = 0; 558 559 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 560 561 FLUSH_CURRENT(ctx, 0); 562 563 if (buffer != GL_DEPTH_STENCIL) { 564 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", 565 _mesa_lookup_enum_by_nr(buffer)); 566 return; 567 } 568 569 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 570 * 571 * "ClearBuffer generates an INVALID VALUE error if buffer is 572 * COLOR and drawbuffer is less than zero, or greater than the 573 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 574 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 575 */ 576 if (drawbuffer != 0) { 577 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", 578 drawbuffer); 579 return; 580 } 581 582 if (ctx->RasterDiscard) 583 return; 584 585 if (ctx->NewState) { 586 _mesa_update_state( ctx ); 587 } 588 589 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) 590 mask |= BUFFER_BIT_DEPTH; 591 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) 592 mask |= BUFFER_BIT_STENCIL; 593 594 if (mask) { 595 /* save current clear values */ 596 const GLclampd clearDepthSave = ctx->Depth.Clear; 597 const GLuint clearStencilSave = ctx->Stencil.Clear; 598 599 /* set new clear values */ 600 ctx->Depth.Clear = depth; 601 ctx->Stencil.Clear = stencil; 602 603 /* clear buffers */ 604 ctx->Driver.Clear(ctx, mask); 605 606 /* restore */ 607 ctx->Depth.Clear = clearDepthSave; 608 ctx->Stencil.Clear = clearStencilSave; 609 } 610} 611