1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26/** 27 * \file clear.c 28 * glClearColor, glClearIndex, glClear() functions. 29 */ 30 31 32 33#include "glformats.h" 34#include "glheader.h" 35#include "clear.h" 36#include "context.h" 37#include "enums.h" 38#include "fbobject.h" 39#include "get.h" 40#include "macros.h" 41#include "mtypes.h" 42#include "state.h" 43 44 45 46void GLAPIENTRY 47_mesa_ClearIndex( GLfloat c ) 48{ 49 GET_CURRENT_CONTEXT(ctx); 50 51 ctx->PopAttribState |= GL_COLOR_BUFFER_BIT; 52 ctx->Color.ClearIndex = (GLuint) c; 53} 54 55 56/** 57 * Specify the clear values for the color buffers. 58 * 59 * \param red red color component. 60 * \param green green color component. 61 * \param blue blue color component. 62 * \param alpha alpha component. 63 * 64 * \sa glClearColor(). 65 */ 66void GLAPIENTRY 67_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 68{ 69 GET_CURRENT_CONTEXT(ctx); 70 71 ctx->PopAttribState |= GL_COLOR_BUFFER_BIT; 72 ctx->Color.ClearColor.f[0] = red; 73 ctx->Color.ClearColor.f[1] = green; 74 ctx->Color.ClearColor.f[2] = blue; 75 ctx->Color.ClearColor.f[3] = alpha; 76} 77 78 79/** 80 * GL_EXT_texture_integer 81 */ 82void GLAPIENTRY 83_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a) 84{ 85 GET_CURRENT_CONTEXT(ctx); 86 87 ctx->PopAttribState |= GL_COLOR_BUFFER_BIT; 88 ctx->Color.ClearColor.i[0] = r; 89 ctx->Color.ClearColor.i[1] = g; 90 ctx->Color.ClearColor.i[2] = b; 91 ctx->Color.ClearColor.i[3] = a; 92} 93 94 95/** 96 * GL_EXT_texture_integer 97 */ 98void GLAPIENTRY 99_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a) 100{ 101 GET_CURRENT_CONTEXT(ctx); 102 103 ctx->PopAttribState |= GL_COLOR_BUFFER_BIT; 104 ctx->Color.ClearColor.ui[0] = r; 105 ctx->Color.ClearColor.ui[1] = g; 106 ctx->Color.ClearColor.ui[2] = b; 107 ctx->Color.ClearColor.ui[3] = a; 108} 109 110 111/** 112 * Returns true if color writes are enabled for the given color attachment. 113 * 114 * Beyond checking ColorMask, this uses _mesa_format_has_color_component to 115 * ignore components that don't actually exist in the format (such as X in 116 * XRGB). 117 */ 118static bool 119color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx) 120{ 121 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx]; 122 GLuint c; 123 124 if (rb) { 125 for (c = 0; c < 4; c++) { 126 if (GET_COLORMASK_BIT(ctx->Color.ColorMask, idx, c) && 127 _mesa_format_has_color_component(rb->Format, c)) { 128 return true; 129 } 130 } 131 } 132 133 return false; 134} 135 136 137/** 138 * Clear buffers. 139 * 140 * \param mask bit-mask indicating the buffers to be cleared. 141 * 142 * Flushes the vertices and verifies the parameter. 143 * If __struct gl_contextRec::NewState is set then calls _mesa_update_state() 144 * to update gl_frame_buffer::_Xmin, etc. If the rasterization mode is set to 145 * GL_RENDER then requests the driver to clear the buffers, via the 146 * dd_function_table::Clear callback. 147 */ 148static ALWAYS_INLINE void 149clear(struct gl_context *ctx, GLbitfield mask, bool no_error) 150{ 151 FLUSH_VERTICES(ctx, 0, 0); 152 153 if (!no_error) { 154 if (mask & ~(GL_COLOR_BUFFER_BIT | 155 GL_DEPTH_BUFFER_BIT | 156 GL_STENCIL_BUFFER_BIT | 157 GL_ACCUM_BUFFER_BIT)) { 158 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); 159 return; 160 } 161 162 /* Accumulation buffers were removed in core contexts, and they never 163 * existed in OpenGL ES. 164 */ 165 if ((mask & GL_ACCUM_BUFFER_BIT) != 0 166 && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) { 167 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)"); 168 return; 169 } 170 } 171 172 if (ctx->NewState) { 173 _mesa_update_state( ctx ); /* update _Xmin, etc */ 174 } 175 176 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 177 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 178 "glClear(incomplete framebuffer)"); 179 return; 180 } 181 182 if (ctx->RasterDiscard) 183 return; 184 185 if (ctx->RenderMode == GL_RENDER) { 186 GLbitfield bufferMask; 187 188 /* don't clear depth buffer if depth writing disabled */ 189 if (!ctx->Depth.Mask) 190 mask &= ~GL_DEPTH_BUFFER_BIT; 191 192 /* Build the bitmask to send to device driver's Clear function. 193 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 194 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 195 * BUFFER_BIT_COLORn flags. 196 */ 197 bufferMask = 0; 198 if (mask & GL_COLOR_BUFFER_BIT) { 199 GLuint i; 200 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { 201 gl_buffer_index buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; 202 203 if (buf != BUFFER_NONE && color_buffer_writes_enabled(ctx, i)) { 204 bufferMask |= 1 << buf; 205 } 206 } 207 } 208 209 if ((mask & GL_DEPTH_BUFFER_BIT) 210 && ctx->DrawBuffer->Visual.depthBits > 0) { 211 bufferMask |= BUFFER_BIT_DEPTH; 212 } 213 214 if ((mask & GL_STENCIL_BUFFER_BIT) 215 && ctx->DrawBuffer->Visual.stencilBits > 0) { 216 bufferMask |= BUFFER_BIT_STENCIL; 217 } 218 219 if ((mask & GL_ACCUM_BUFFER_BIT) 220 && ctx->DrawBuffer->Visual.accumRedBits > 0) { 221 bufferMask |= BUFFER_BIT_ACCUM; 222 } 223 224 assert(ctx->Driver.Clear); 225 ctx->Driver.Clear(ctx, bufferMask); 226 } 227} 228 229 230void GLAPIENTRY 231_mesa_Clear_no_error(GLbitfield mask) 232{ 233 GET_CURRENT_CONTEXT(ctx); 234 clear(ctx, mask, true); 235} 236 237 238void GLAPIENTRY 239_mesa_Clear(GLbitfield mask) 240{ 241 GET_CURRENT_CONTEXT(ctx); 242 243 if (MESA_VERBOSE & VERBOSE_API) 244 _mesa_debug(ctx, "glClear 0x%x\n", mask); 245 246 clear(ctx, mask, false); 247} 248 249 250/** Returned by make_color_buffer_mask() for errors */ 251#define INVALID_MASK ~0x0U 252 253 254/** 255 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of 256 * BUFFER_BIT_x values. 257 * Return INVALID_MASK if the drawbuffer value is invalid. 258 */ 259static GLbitfield 260make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) 261{ 262 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; 263 GLbitfield mask = 0x0; 264 265 /* From the GL 4.0 specification: 266 * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is 267 * specified by passing i as the parameter drawbuffer, and value 268 * points to a four-element vector specifying the R, G, B, and A 269 * color to clear that draw buffer to. If the draw buffer is one 270 * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying 271 * multiple buffers, each selected buffer is cleared to the same 272 * value. 273 * 274 * Note that "drawbuffer" and "draw buffer" have different meaning. 275 * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's 276 * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK, 277 * etc. 278 */ 279 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { 280 return INVALID_MASK; 281 } 282 283 switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) { 284 case GL_FRONT: 285 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 286 mask |= BUFFER_BIT_FRONT_LEFT; 287 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 288 mask |= BUFFER_BIT_FRONT_RIGHT; 289 break; 290 case GL_BACK: 291 /* For GLES contexts with a single buffered configuration, we actually 292 * only have a front renderbuffer, so any clear calls to GL_BACK should 293 * affect that buffer. See draw_buffer_enum_to_bitmask for details. 294 */ 295 if (_mesa_is_gles(ctx)) 296 if (!ctx->DrawBuffer->Visual.doubleBufferMode) 297 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 298 mask |= BUFFER_BIT_FRONT_LEFT; 299 if (att[BUFFER_BACK_LEFT].Renderbuffer) 300 mask |= BUFFER_BIT_BACK_LEFT; 301 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 302 mask |= BUFFER_BIT_BACK_RIGHT; 303 break; 304 case GL_LEFT: 305 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 306 mask |= BUFFER_BIT_FRONT_LEFT; 307 if (att[BUFFER_BACK_LEFT].Renderbuffer) 308 mask |= BUFFER_BIT_BACK_LEFT; 309 break; 310 case GL_RIGHT: 311 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 312 mask |= BUFFER_BIT_FRONT_RIGHT; 313 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 314 mask |= BUFFER_BIT_BACK_RIGHT; 315 break; 316 case GL_FRONT_AND_BACK: 317 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 318 mask |= BUFFER_BIT_FRONT_LEFT; 319 if (att[BUFFER_BACK_LEFT].Renderbuffer) 320 mask |= BUFFER_BIT_BACK_LEFT; 321 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 322 mask |= BUFFER_BIT_FRONT_RIGHT; 323 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 324 mask |= BUFFER_BIT_BACK_RIGHT; 325 break; 326 default: 327 { 328 gl_buffer_index buf = 329 ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; 330 331 if (buf != BUFFER_NONE && att[buf].Renderbuffer) { 332 mask |= 1 << buf; 333 } 334 } 335 } 336 337 return mask; 338} 339 340 341 342/** 343 * New in GL 3.0 344 * Clear signed integer color buffer or stencil buffer (not depth). 345 */ 346static ALWAYS_INLINE void 347clear_bufferiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 348 const GLint *value, bool no_error) 349{ 350 FLUSH_VERTICES(ctx, 0, 0); 351 352 if (ctx->NewState) { 353 _mesa_update_state( ctx ); 354 } 355 356 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 357 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 358 "glClearBufferiv(incomplete framebuffer)"); 359 return; 360 } 361 362 switch (buffer) { 363 case GL_STENCIL: 364 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 365 * 366 * "ClearBuffer generates an INVALID VALUE error if buffer is 367 * COLOR and drawbuffer is less than zero, or greater than the 368 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 369 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 370 */ 371 if (!no_error && drawbuffer != 0) { 372 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 373 drawbuffer); 374 return; 375 } 376 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer 377 && !ctx->RasterDiscard) { 378 /* Save current stencil clear value, set to 'value', do the 379 * stencil clear and restore the clear value. 380 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 381 * hook instead. 382 */ 383 const GLuint clearSave = ctx->Stencil.Clear; 384 ctx->Stencil.Clear = *value; 385 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL); 386 ctx->Stencil.Clear = clearSave; 387 } 388 break; 389 case GL_COLOR: 390 { 391 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 392 if (!no_error && mask == INVALID_MASK) { 393 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 394 drawbuffer); 395 return; 396 } 397 else if (mask && !ctx->RasterDiscard) { 398 union gl_color_union clearSave; 399 400 /* save color */ 401 clearSave = ctx->Color.ClearColor; 402 /* set color */ 403 COPY_4V(ctx->Color.ClearColor.i, value); 404 /* clear buffer(s) */ 405 ctx->Driver.Clear(ctx, mask); 406 /* restore color */ 407 ctx->Color.ClearColor = clearSave; 408 } 409 } 410 break; 411 default: 412 if (!no_error) { 413 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 414 * of the OpenGL 4.5 spec states: 415 * 416 * "An INVALID_ENUM error is generated by ClearBufferiv and 417 * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL." 418 */ 419 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", 420 _mesa_enum_to_string(buffer)); 421 } 422 return; 423 } 424} 425 426 427void GLAPIENTRY 428_mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value) 429{ 430 GET_CURRENT_CONTEXT(ctx); 431 clear_bufferiv(ctx, buffer, drawbuffer, value, true); 432} 433 434 435void GLAPIENTRY 436_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) 437{ 438 GET_CURRENT_CONTEXT(ctx); 439 clear_bufferiv(ctx, buffer, drawbuffer, value, false); 440} 441 442 443/** 444 * The ClearBuffer framework is so complicated and so riddled with the 445 * assumption that the framebuffer is bound that, for now, we will just fake 446 * direct state access clearing for the user. 447 */ 448void GLAPIENTRY 449_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, 450 GLint drawbuffer, const GLint *value) 451{ 452 GLint oldfb; 453 454 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 455 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 456 _mesa_ClearBufferiv(buffer, drawbuffer, value); 457 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 458} 459 460 461/** 462 * New in GL 3.0 463 * Clear unsigned integer color buffer (not depth, not stencil). 464 */ 465static ALWAYS_INLINE void 466clear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 467 const GLuint *value, bool no_error) 468{ 469 FLUSH_VERTICES(ctx, 0, 0); 470 471 if (ctx->NewState) { 472 _mesa_update_state( ctx ); 473 } 474 475 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) { 476 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, 477 "glClearBufferuiv(incomplete framebuffer)"); 478 return; 479 } 480 481 switch (buffer) { 482 case GL_COLOR: 483 { 484 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 485 if (!no_error && mask == INVALID_MASK) { 486 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 487 drawbuffer); 488 return; 489 } 490 else if (mask && !ctx->RasterDiscard) { 491 union gl_color_union clearSave; 492 493 /* save color */ 494 clearSave = ctx->Color.ClearColor; 495 /* set color */ 496 COPY_4V(ctx->Color.ClearColor.ui, value); 497 /* clear buffer(s) */ 498 ctx->Driver.Clear(ctx, mask); 499 /* restore color */ 500 ctx->Color.ClearColor = clearSave; 501 } 502 } 503 break; 504 default: 505 if (!no_error) { 506 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 507 * of the OpenGL 4.5 spec states: 508 * 509 * "An INVALID_ENUM error is generated by ClearBufferuiv and 510 * ClearNamedFramebufferuiv if buffer is not COLOR." 511 */ 512 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", 513 _mesa_enum_to_string(buffer)); 514 } 515 return; 516 } 517} 518 519 520void GLAPIENTRY 521_mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer, 522 const GLuint *value) 523{ 524 GET_CURRENT_CONTEXT(ctx); 525 clear_bufferuiv(ctx, buffer, drawbuffer, value, true); 526} 527 528 529void GLAPIENTRY 530_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) 531{ 532 GET_CURRENT_CONTEXT(ctx); 533 clear_bufferuiv(ctx, buffer, drawbuffer, value, false); 534} 535 536 537/** 538 * The ClearBuffer framework is so complicated and so riddled with the 539 * assumption that the framebuffer is bound that, for now, we will just fake 540 * direct state access clearing for the user. 541 */ 542void GLAPIENTRY 543_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, 544 GLint drawbuffer, const GLuint *value) 545{ 546 GLint oldfb; 547 548 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 549 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 550 _mesa_ClearBufferuiv(buffer, drawbuffer, value); 551 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 552} 553 554 555/** 556 * New in GL 3.0 557 * Clear fixed-pt or float color buffer or depth buffer (not stencil). 558 */ 559static ALWAYS_INLINE void 560clear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 561 const GLfloat *value, bool no_error) 562{ 563 FLUSH_VERTICES(ctx, 0, 0); 564 565 if (ctx->NewState) { 566 _mesa_update_state( ctx ); 567 } 568 569 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) { 570 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, 571 "glClearBufferfv(incomplete framebuffer)"); 572 return; 573 } 574 575 switch (buffer) { 576 case GL_DEPTH: 577 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 578 * 579 * "ClearBuffer generates an INVALID VALUE error if buffer is 580 * COLOR and drawbuffer is less than zero, or greater than the 581 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 582 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 583 */ 584 if (!no_error && drawbuffer != 0) { 585 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 586 drawbuffer); 587 return; 588 } 589 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer 590 && !ctx->RasterDiscard) { 591 /* Save current depth clear value, set to 'value', do the 592 * depth clear and restore the clear value. 593 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 594 * hook instead. 595 */ 596 const GLclampd clearSave = ctx->Depth.Clear; 597 598 /* Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says: 599 * 600 * "If buffer is DEPTH, drawbuffer must be zero, and value points 601 * to the single depth value to clear the depth buffer to. 602 * Clamping and type conversion for fixed-point depth buffers are 603 * performed in the same fashion as for ClearDepth." 604 */ 605 const struct gl_renderbuffer *rb = 606 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 607 const bool is_float_depth = 608 _mesa_has_depth_float_channel(rb->InternalFormat); 609 ctx->Depth.Clear = is_float_depth ? *value : SATURATE(*value); 610 611 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH); 612 ctx->Depth.Clear = clearSave; 613 } 614 /* clear depth buffer to value */ 615 break; 616 case GL_COLOR: 617 { 618 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 619 if (!no_error && mask == INVALID_MASK) { 620 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 621 drawbuffer); 622 return; 623 } 624 else if (mask && !ctx->RasterDiscard) { 625 union gl_color_union clearSave; 626 627 /* save color */ 628 clearSave = ctx->Color.ClearColor; 629 /* set color */ 630 COPY_4V(ctx->Color.ClearColor.f, value); 631 /* clear buffer(s) */ 632 ctx->Driver.Clear(ctx, mask); 633 /* restore color */ 634 ctx->Color.ClearColor = clearSave; 635 } 636 } 637 break; 638 default: 639 if (!no_error) { 640 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 641 * of the OpenGL 4.5 spec states: 642 * 643 * "An INVALID_ENUM error is generated by ClearBufferfv and 644 * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH." 645 */ 646 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", 647 _mesa_enum_to_string(buffer)); 648 } 649 return; 650 } 651} 652 653 654void GLAPIENTRY 655_mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer, 656 const GLfloat *value) 657{ 658 GET_CURRENT_CONTEXT(ctx); 659 clear_bufferfv(ctx, buffer, drawbuffer, value, true); 660} 661 662 663void GLAPIENTRY 664_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) 665{ 666 GET_CURRENT_CONTEXT(ctx); 667 clear_bufferfv(ctx, buffer, drawbuffer, value, false); 668} 669 670 671/** 672 * The ClearBuffer framework is so complicated and so riddled with the 673 * assumption that the framebuffer is bound that, for now, we will just fake 674 * direct state access clearing for the user. 675 */ 676void GLAPIENTRY 677_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, 678 GLint drawbuffer, const GLfloat *value) 679{ 680 GLint oldfb; 681 682 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 683 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 684 _mesa_ClearBufferfv(buffer, drawbuffer, value); 685 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 686} 687 688 689/** 690 * New in GL 3.0 691 * Clear depth/stencil buffer only. 692 */ 693static ALWAYS_INLINE void 694clear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 695 GLfloat depth, GLint stencil, bool no_error) 696{ 697 GLbitfield mask = 0; 698 699 FLUSH_VERTICES(ctx, 0, 0); 700 701 if (!no_error) { 702 if (buffer != GL_DEPTH_STENCIL) { 703 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", 704 _mesa_enum_to_string(buffer)); 705 return; 706 } 707 708 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 709 * 710 * "ClearBuffer generates an INVALID VALUE error if buffer is 711 * COLOR and drawbuffer is less than zero, or greater than the 712 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 713 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 714 */ 715 if (drawbuffer != 0) { 716 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", 717 drawbuffer); 718 return; 719 } 720 } 721 722 if (ctx->RasterDiscard) 723 return; 724 725 if (ctx->NewState) { 726 _mesa_update_state( ctx ); 727 } 728 729 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 730 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 731 "glClearBufferfi(incomplete framebuffer)"); 732 return; 733 } 734 735 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) 736 mask |= BUFFER_BIT_DEPTH; 737 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) 738 mask |= BUFFER_BIT_STENCIL; 739 740 if (mask) { 741 /* save current clear values */ 742 const GLclampd clearDepthSave = ctx->Depth.Clear; 743 const GLuint clearStencilSave = ctx->Stencil.Clear; 744 745 /* set new clear values 746 * 747 * Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says: 748 * 749 * "depth and stencil are the values to clear the depth and stencil 750 * buffers to, respectively. Clamping and type conversion for 751 * fixed-point depth buffers are performed in the same fashion as 752 * for ClearDepth." 753 */ 754 const struct gl_renderbuffer *rb = 755 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 756 const bool has_float_depth = rb && 757 _mesa_has_depth_float_channel(rb->InternalFormat); 758 ctx->Depth.Clear = has_float_depth ? depth : SATURATE(depth); 759 ctx->Stencil.Clear = stencil; 760 761 /* clear buffers */ 762 ctx->Driver.Clear(ctx, mask); 763 764 /* restore */ 765 ctx->Depth.Clear = clearDepthSave; 766 ctx->Stencil.Clear = clearStencilSave; 767 } 768} 769 770 771void GLAPIENTRY 772_mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer, 773 GLfloat depth, GLint stencil) 774{ 775 GET_CURRENT_CONTEXT(ctx); 776 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true); 777} 778 779 780void GLAPIENTRY 781_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, 782 GLfloat depth, GLint stencil) 783{ 784 GET_CURRENT_CONTEXT(ctx); 785 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false); 786} 787 788 789/** 790 * The ClearBuffer framework is so complicated and so riddled with the 791 * assumption that the framebuffer is bound that, for now, we will just fake 792 * direct state access clearing for the user. 793 */ 794void GLAPIENTRY 795_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, 796 GLint drawbuffer, GLfloat depth, GLint stencil) 797{ 798 GLint oldfb; 799 800 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 801 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 802 _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil); 803 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 804} 805