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 45 void 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 */ 74 void 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 */ 97 void 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 */ 120 void 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 */ 150 void 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 /* Accumulation buffers were removed in core contexts, and they never 171 * existed in OpenGL ES. 172 */ 173 if ((mask & GL_ACCUM_BUFFER_BIT) != 0 174 && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) { 175 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)"); 176 return; 177 } 178 179 if (ctx->NewState) { 180 _mesa_update_state( ctx ); /* update _Xmin, etc */ 181 } 182 183 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 184 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 185 "glClear(incomplete framebuffer)"); 186 return; 187 } 188 189 if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 || 190 ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax || 191 ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax) 192 return; 193 194 if (ctx->RasterDiscard) 195 return; 196 197 if (ctx->RenderMode == GL_RENDER) { 198 GLbitfield bufferMask; 199 200 /* don't clear depth buffer if depth writing disabled */ 201 if (!ctx->Depth.Mask) 202 mask &= ~GL_DEPTH_BUFFER_BIT; 203 204 /* Build the bitmask to send to device driver's Clear function. 205 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 206 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 207 * BUFFER_BIT_COLORn flags. 208 */ 209 bufferMask = 0; 210 if (mask & GL_COLOR_BUFFER_BIT) { 211 GLuint i; 212 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { 213 bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]); 214 } 215 } 216 217 if ((mask & GL_DEPTH_BUFFER_BIT) 218 && ctx->DrawBuffer->Visual.haveDepthBuffer) { 219 bufferMask |= BUFFER_BIT_DEPTH; 220 } 221 222 if ((mask & GL_STENCIL_BUFFER_BIT) 223 && ctx->DrawBuffer->Visual.haveStencilBuffer) { 224 bufferMask |= BUFFER_BIT_STENCIL; 225 } 226 227 if ((mask & GL_ACCUM_BUFFER_BIT) 228 && ctx->DrawBuffer->Visual.haveAccumBuffer) { 229 bufferMask |= BUFFER_BIT_ACCUM; 230 } 231 232 ASSERT(ctx->Driver.Clear); 233 ctx->Driver.Clear(ctx, bufferMask); 234 } 235 } 236 237 238 /** Returned by make_color_buffer_mask() for errors */ 239 #define INVALID_MASK ~0x0 240 241 242 /** 243 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of 244 * BUFFER_BIT_x values. 245 * Return INVALID_MASK if the drawbuffer value is invalid. 246 */ 247 static GLbitfield 248 make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) 249 { 250 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; 251 GLbitfield mask = 0x0; 252 253 switch (drawbuffer) { 254 case GL_FRONT: 255 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 256 mask |= BUFFER_BIT_FRONT_LEFT; 257 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 258 mask |= BUFFER_BIT_FRONT_RIGHT; 259 break; 260 case GL_BACK: 261 if (att[BUFFER_BACK_LEFT].Renderbuffer) 262 mask |= BUFFER_BIT_BACK_LEFT; 263 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 264 mask |= BUFFER_BIT_BACK_RIGHT; 265 break; 266 case GL_LEFT: 267 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 268 mask |= BUFFER_BIT_FRONT_LEFT; 269 if (att[BUFFER_BACK_LEFT].Renderbuffer) 270 mask |= BUFFER_BIT_BACK_LEFT; 271 break; 272 case GL_RIGHT: 273 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 274 mask |= BUFFER_BIT_FRONT_RIGHT; 275 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 276 mask |= BUFFER_BIT_BACK_RIGHT; 277 break; 278 case GL_FRONT_AND_BACK: 279 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 280 mask |= BUFFER_BIT_FRONT_LEFT; 281 if (att[BUFFER_BACK_LEFT].Renderbuffer) 282 mask |= BUFFER_BIT_BACK_LEFT; 283 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 284 mask |= BUFFER_BIT_FRONT_RIGHT; 285 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 286 mask |= BUFFER_BIT_BACK_RIGHT; 287 break; 288 default: 289 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { 290 mask = INVALID_MASK; 291 } 292 else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) { 293 mask |= (BUFFER_BIT_COLOR0 << drawbuffer); 294 } 295 } 296 297 return mask; 298 } 299 300 301 302 /** 303 * New in GL 3.0 304 * Clear signed integer color buffer or stencil buffer (not depth). 305 */ 306 void GLAPIENTRY 307 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) 308 { 309 GET_CURRENT_CONTEXT(ctx); 310 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 311 312 FLUSH_CURRENT(ctx, 0); 313 314 if (ctx->NewState) { 315 _mesa_update_state( ctx ); 316 } 317 318 switch (buffer) { 319 case GL_STENCIL: 320 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 321 * 322 * "ClearBuffer generates an INVALID VALUE error if buffer is 323 * COLOR and drawbuffer is less than zero, or greater than the 324 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 325 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 326 */ 327 if (drawbuffer != 0) { 328 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 329 drawbuffer); 330 return; 331 } 332 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer && !ctx->RasterDiscard) { 333 /* Save current stencil clear value, set to 'value', do the 334 * stencil clear and restore the clear value. 335 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 336 * hook instead. 337 */ 338 const GLuint clearSave = ctx->Stencil.Clear; 339 ctx->Stencil.Clear = *value; 340 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL); 341 ctx->Stencil.Clear = clearSave; 342 } 343 break; 344 case GL_COLOR: 345 { 346 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 347 if (mask == INVALID_MASK) { 348 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 349 drawbuffer); 350 return; 351 } 352 else if (mask && !ctx->RasterDiscard) { 353 union gl_color_union clearSave; 354 355 /* save color */ 356 clearSave = ctx->Color.ClearColor; 357 /* set color */ 358 COPY_4V(ctx->Color.ClearColor.i, value); 359 /* clear buffer(s) */ 360 ctx->Driver.Clear(ctx, mask); 361 /* restore color */ 362 ctx->Color.ClearColor = clearSave; 363 } 364 } 365 break; 366 case GL_DEPTH: 367 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 368 * 369 * "The result of ClearBuffer is undefined if no conversion between 370 * the type of the specified value and the type of the buffer being 371 * cleared is defined (for example, if ClearBufferiv is called for a 372 * fixed- or floating-point buffer, or if ClearBufferfv is called 373 * for a signed or unsigned integer buffer). This is not an error." 374 * 375 * In this case we take "undefined" and "not an error" to mean "ignore." 376 * Note that we still need to generate an error for the invalid 377 * drawbuffer case (see the GL_STENCIL case above). 378 */ 379 if (drawbuffer != 0) { 380 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 381 drawbuffer); 382 return; 383 } 384 return; 385 default: 386 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", 387 _mesa_lookup_enum_by_nr(buffer)); 388 return; 389 } 390 } 391 392 393 /** 394 * New in GL 3.0 395 * Clear unsigned integer color buffer (not depth, not stencil). 396 */ 397 void GLAPIENTRY 398 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) 399 { 400 GET_CURRENT_CONTEXT(ctx); 401 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 402 403 FLUSH_CURRENT(ctx, 0); 404 405 if (ctx->NewState) { 406 _mesa_update_state( ctx ); 407 } 408 409 switch (buffer) { 410 case GL_COLOR: 411 { 412 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 413 if (mask == INVALID_MASK) { 414 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 415 drawbuffer); 416 return; 417 } 418 else if (mask && !ctx->RasterDiscard) { 419 union gl_color_union clearSave; 420 421 /* save color */ 422 clearSave = ctx->Color.ClearColor; 423 /* set color */ 424 COPY_4V(ctx->Color.ClearColor.ui, value); 425 /* clear buffer(s) */ 426 ctx->Driver.Clear(ctx, mask); 427 /* restore color */ 428 ctx->Color.ClearColor = clearSave; 429 } 430 } 431 break; 432 case GL_DEPTH: 433 case GL_STENCIL: 434 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 435 * 436 * "The result of ClearBuffer is undefined if no conversion between 437 * the type of the specified value and the type of the buffer being 438 * cleared is defined (for example, if ClearBufferiv is called for a 439 * fixed- or floating-point buffer, or if ClearBufferfv is called 440 * for a signed or unsigned integer buffer). This is not an error." 441 * 442 * In this case we take "undefined" and "not an error" to mean "ignore." 443 * Even though we could do something sensible for GL_STENCIL, page 263 444 * (page 279 of the PDF) says: 445 * 446 * "Only ClearBufferiv should be used to clear stencil buffers." 447 * 448 * Note that we still need to generate an error for the invalid 449 * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv). 450 */ 451 if (drawbuffer != 0) { 452 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 453 drawbuffer); 454 return; 455 } 456 return; 457 default: 458 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", 459 _mesa_lookup_enum_by_nr(buffer)); 460 return; 461 } 462 } 463 464 465 /** 466 * New in GL 3.0 467 * Clear fixed-pt or float color buffer or depth buffer (not stencil). 468 */ 469 void GLAPIENTRY 470 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) 471 { 472 GET_CURRENT_CONTEXT(ctx); 473 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 474 475 FLUSH_CURRENT(ctx, 0); 476 477 if (ctx->NewState) { 478 _mesa_update_state( ctx ); 479 } 480 481 switch (buffer) { 482 case GL_DEPTH: 483 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 484 * 485 * "ClearBuffer generates an INVALID VALUE error if buffer is 486 * COLOR and drawbuffer is less than zero, or greater than the 487 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 488 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 489 */ 490 if (drawbuffer != 0) { 491 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 492 drawbuffer); 493 return; 494 } 495 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) { 496 /* Save current depth clear value, set to 'value', do the 497 * depth clear and restore the clear value. 498 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 499 * hook instead. 500 */ 501 const GLclampd clearSave = ctx->Depth.Clear; 502 ctx->Depth.Clear = *value; 503 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH); 504 ctx->Depth.Clear = clearSave; 505 } 506 /* clear depth buffer to value */ 507 break; 508 case GL_COLOR: 509 { 510 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 511 if (mask == INVALID_MASK) { 512 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 513 drawbuffer); 514 return; 515 } 516 else if (mask && !ctx->RasterDiscard) { 517 union gl_color_union clearSave; 518 519 /* save color */ 520 clearSave = ctx->Color.ClearColor; 521 /* set color */ 522 COPY_4V(ctx->Color.ClearColor.f, value); 523 /* clear buffer(s) */ 524 ctx->Driver.Clear(ctx, mask); 525 /* restore color */ 526 ctx->Color.ClearColor = clearSave; 527 } 528 } 529 break; 530 case GL_STENCIL: 531 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 532 * 533 * "The result of ClearBuffer is undefined if no conversion between 534 * the type of the specified value and the type of the buffer being 535 * cleared is defined (for example, if ClearBufferiv is called for a 536 * fixed- or floating-point buffer, or if ClearBufferfv is called 537 * for a signed or unsigned integer buffer). This is not an error." 538 * 539 * In this case we take "undefined" and "not an error" to mean "ignore." 540 * Note that we still need to generate an error for the invalid 541 * drawbuffer case (see the GL_DEPTH case above). 542 */ 543 if (drawbuffer != 0) { 544 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 545 drawbuffer); 546 return; 547 } 548 return; 549 default: 550 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", 551 _mesa_lookup_enum_by_nr(buffer)); 552 return; 553 } 554 } 555 556 557 /** 558 * New in GL 3.0 559 * Clear depth/stencil buffer only. 560 */ 561 void GLAPIENTRY 562 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, 563 GLfloat depth, GLint stencil) 564 { 565 GET_CURRENT_CONTEXT(ctx); 566 GLbitfield mask = 0; 567 568 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 569 570 FLUSH_CURRENT(ctx, 0); 571 572 if (buffer != GL_DEPTH_STENCIL) { 573 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", 574 _mesa_lookup_enum_by_nr(buffer)); 575 return; 576 } 577 578 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 579 * 580 * "ClearBuffer generates an INVALID VALUE error if buffer is 581 * COLOR and drawbuffer is less than zero, or greater than the 582 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 583 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 584 */ 585 if (drawbuffer != 0) { 586 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", 587 drawbuffer); 588 return; 589 } 590 591 if (ctx->RasterDiscard) 592 return; 593 594 if (ctx->NewState) { 595 _mesa_update_state( ctx ); 596 } 597 598 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) 599 mask |= BUFFER_BIT_DEPTH; 600 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) 601 mask |= BUFFER_BIT_STENCIL; 602 603 if (mask) { 604 /* save current clear values */ 605 const GLclampd clearDepthSave = ctx->Depth.Clear; 606 const GLuint clearStencilSave = ctx->Stencil.Clear; 607 608 /* set new clear values */ 609 ctx->Depth.Clear = depth; 610 ctx->Stencil.Clear = stencil; 611 612 /* clear buffers */ 613 ctx->Driver.Clear(ctx, mask); 614 615 /* restore */ 616 ctx->Depth.Clear = clearDepthSave; 617 ctx->Stencil.Clear = clearStencilSave; 618 } 619 } 620