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 "context.h" 36#include "enums.h" 37#include "fbobject.h" 38#include "get.h" 39#include "macros.h" 40#include "mtypes.h" 41#include "state.h" 42#include "api_exec_decl.h" 43 44#include "state_tracker/st_cb_clear.h" 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 st_Clear(ctx, bufferMask); 225 } 226} 227 228 229void GLAPIENTRY 230_mesa_Clear_no_error(GLbitfield mask) 231{ 232 GET_CURRENT_CONTEXT(ctx); 233 clear(ctx, mask, true); 234} 235 236 237void GLAPIENTRY 238_mesa_Clear(GLbitfield mask) 239{ 240 GET_CURRENT_CONTEXT(ctx); 241 242 if (MESA_VERBOSE & VERBOSE_API) 243 _mesa_debug(ctx, "glClear 0x%x\n", mask); 244 245 clear(ctx, mask, false); 246} 247 248 249/** Returned by make_color_buffer_mask() for errors */ 250#define INVALID_MASK ~0x0U 251 252 253/** 254 * Convert the glClearBuffer 'drawbuffer' parameter into a bitmask of 255 * BUFFER_BIT_x values. 256 * Return INVALID_MASK if the drawbuffer value is invalid. 257 */ 258static GLbitfield 259make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) 260{ 261 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; 262 GLbitfield mask = 0x0; 263 264 /* From the GL 4.0 specification: 265 * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is 266 * specified by passing i as the parameter drawbuffer, and value 267 * points to a four-element vector specifying the R, G, B, and A 268 * color to clear that draw buffer to. If the draw buffer is one 269 * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying 270 * multiple buffers, each selected buffer is cleared to the same 271 * value. 272 * 273 * Note that "drawbuffer" and "draw buffer" have different meaning. 274 * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's 275 * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK, 276 * etc. 277 */ 278 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { 279 return INVALID_MASK; 280 } 281 282 switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) { 283 case GL_FRONT: 284 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 285 mask |= BUFFER_BIT_FRONT_LEFT; 286 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 287 mask |= BUFFER_BIT_FRONT_RIGHT; 288 break; 289 case GL_BACK: 290 /* For GLES contexts with a single buffered configuration, we actually 291 * only have a front renderbuffer, so any clear calls to GL_BACK should 292 * affect that buffer. See draw_buffer_enum_to_bitmask for details. 293 */ 294 if (_mesa_is_gles(ctx)) 295 if (!ctx->DrawBuffer->Visual.doubleBufferMode) 296 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 297 mask |= BUFFER_BIT_FRONT_LEFT; 298 if (att[BUFFER_BACK_LEFT].Renderbuffer) 299 mask |= BUFFER_BIT_BACK_LEFT; 300 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 301 mask |= BUFFER_BIT_BACK_RIGHT; 302 break; 303 case GL_LEFT: 304 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 305 mask |= BUFFER_BIT_FRONT_LEFT; 306 if (att[BUFFER_BACK_LEFT].Renderbuffer) 307 mask |= BUFFER_BIT_BACK_LEFT; 308 break; 309 case GL_RIGHT: 310 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 311 mask |= BUFFER_BIT_FRONT_RIGHT; 312 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 313 mask |= BUFFER_BIT_BACK_RIGHT; 314 break; 315 case GL_FRONT_AND_BACK: 316 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 317 mask |= BUFFER_BIT_FRONT_LEFT; 318 if (att[BUFFER_BACK_LEFT].Renderbuffer) 319 mask |= BUFFER_BIT_BACK_LEFT; 320 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 321 mask |= BUFFER_BIT_FRONT_RIGHT; 322 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 323 mask |= BUFFER_BIT_BACK_RIGHT; 324 break; 325 default: 326 { 327 gl_buffer_index buf = 328 ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; 329 330 if (buf != BUFFER_NONE && att[buf].Renderbuffer) { 331 mask |= 1 << buf; 332 } 333 } 334 } 335 336 return mask; 337} 338 339 340 341/** 342 * New in GL 3.0 343 * Clear signed integer color buffer or stencil buffer (not depth). 344 */ 345static ALWAYS_INLINE void 346clear_bufferiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 347 const GLint *value, bool no_error) 348{ 349 FLUSH_VERTICES(ctx, 0, 0); 350 351 if (ctx->NewState) { 352 _mesa_update_state( ctx ); 353 } 354 355 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 356 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 357 "glClearBufferiv(incomplete framebuffer)"); 358 return; 359 } 360 361 switch (buffer) { 362 case GL_STENCIL: 363 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 364 * 365 * "ClearBuffer generates an INVALID VALUE error if buffer is 366 * COLOR and drawbuffer is less than zero, or greater than the 367 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 368 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 369 */ 370 if (!no_error && drawbuffer != 0) { 371 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 372 drawbuffer); 373 return; 374 } 375 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer 376 && !ctx->RasterDiscard) { 377 /* Save current stencil clear value, set to 'value', do the 378 * stencil clear and restore the clear value. 379 * XXX in the future we may have a new st_ClearBuffer() 380 * hook instead. 381 */ 382 const GLuint clearSave = ctx->Stencil.Clear; 383 ctx->Stencil.Clear = *value; 384 st_Clear(ctx, BUFFER_BIT_STENCIL); 385 ctx->Stencil.Clear = clearSave; 386 } 387 break; 388 case GL_COLOR: 389 { 390 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 391 if (!no_error && mask == INVALID_MASK) { 392 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 393 drawbuffer); 394 return; 395 } 396 else if (mask && !ctx->RasterDiscard) { 397 union gl_color_union clearSave; 398 399 /* save color */ 400 clearSave = ctx->Color.ClearColor; 401 /* set color */ 402 COPY_4V(ctx->Color.ClearColor.i, value); 403 /* clear buffer(s) */ 404 st_Clear(ctx, mask); 405 /* restore color */ 406 ctx->Color.ClearColor = clearSave; 407 } 408 } 409 break; 410 default: 411 if (!no_error) { 412 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 413 * of the OpenGL 4.5 spec states: 414 * 415 * "An INVALID_ENUM error is generated by ClearBufferiv and 416 * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL." 417 */ 418 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", 419 _mesa_enum_to_string(buffer)); 420 } 421 return; 422 } 423} 424 425 426void GLAPIENTRY 427_mesa_ClearBufferiv_no_error(GLenum buffer, GLint drawbuffer, const GLint *value) 428{ 429 GET_CURRENT_CONTEXT(ctx); 430 clear_bufferiv(ctx, buffer, drawbuffer, value, true); 431} 432 433 434void GLAPIENTRY 435_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) 436{ 437 GET_CURRENT_CONTEXT(ctx); 438 clear_bufferiv(ctx, buffer, drawbuffer, value, false); 439} 440 441 442/** 443 * The ClearBuffer framework is so complicated and so riddled with the 444 * assumption that the framebuffer is bound that, for now, we will just fake 445 * direct state access clearing for the user. 446 */ 447void GLAPIENTRY 448_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, 449 GLint drawbuffer, const GLint *value) 450{ 451 GLint oldfb; 452 453 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 454 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 455 _mesa_ClearBufferiv(buffer, drawbuffer, value); 456 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 457} 458 459 460/** 461 * New in GL 3.0 462 * Clear unsigned integer color buffer (not depth, not stencil). 463 */ 464static ALWAYS_INLINE void 465clear_bufferuiv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 466 const GLuint *value, bool no_error) 467{ 468 FLUSH_VERTICES(ctx, 0, 0); 469 470 if (ctx->NewState) { 471 _mesa_update_state( ctx ); 472 } 473 474 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) { 475 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, 476 "glClearBufferuiv(incomplete framebuffer)"); 477 return; 478 } 479 480 switch (buffer) { 481 case GL_COLOR: 482 { 483 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 484 if (!no_error && mask == INVALID_MASK) { 485 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 486 drawbuffer); 487 return; 488 } 489 else if (mask && !ctx->RasterDiscard) { 490 union gl_color_union clearSave; 491 492 /* save color */ 493 clearSave = ctx->Color.ClearColor; 494 /* set color */ 495 COPY_4V(ctx->Color.ClearColor.ui, value); 496 /* clear buffer(s) */ 497 st_Clear(ctx, mask); 498 /* restore color */ 499 ctx->Color.ClearColor = clearSave; 500 } 501 } 502 break; 503 default: 504 if (!no_error) { 505 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 506 * of the OpenGL 4.5 spec states: 507 * 508 * "An INVALID_ENUM error is generated by ClearBufferuiv and 509 * ClearNamedFramebufferuiv if buffer is not COLOR." 510 */ 511 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", 512 _mesa_enum_to_string(buffer)); 513 } 514 return; 515 } 516} 517 518 519void GLAPIENTRY 520_mesa_ClearBufferuiv_no_error(GLenum buffer, GLint drawbuffer, 521 const GLuint *value) 522{ 523 GET_CURRENT_CONTEXT(ctx); 524 clear_bufferuiv(ctx, buffer, drawbuffer, value, true); 525} 526 527 528void GLAPIENTRY 529_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) 530{ 531 GET_CURRENT_CONTEXT(ctx); 532 clear_bufferuiv(ctx, buffer, drawbuffer, value, false); 533} 534 535 536/** 537 * The ClearBuffer framework is so complicated and so riddled with the 538 * assumption that the framebuffer is bound that, for now, we will just fake 539 * direct state access clearing for the user. 540 */ 541void GLAPIENTRY 542_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, 543 GLint drawbuffer, const GLuint *value) 544{ 545 GLint oldfb; 546 547 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 548 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 549 _mesa_ClearBufferuiv(buffer, drawbuffer, value); 550 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 551} 552 553 554/** 555 * New in GL 3.0 556 * Clear fixed-pt or float color buffer or depth buffer (not stencil). 557 */ 558static ALWAYS_INLINE void 559clear_bufferfv(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 560 const GLfloat *value, bool no_error) 561{ 562 FLUSH_VERTICES(ctx, 0, 0); 563 564 if (ctx->NewState) { 565 _mesa_update_state( ctx ); 566 } 567 568 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE) { 569 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, 570 "glClearBufferfv(incomplete framebuffer)"); 571 return; 572 } 573 574 switch (buffer) { 575 case GL_DEPTH: 576 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 577 * 578 * "ClearBuffer generates an INVALID VALUE error if buffer is 579 * COLOR and drawbuffer is less than zero, or greater than the 580 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 581 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 582 */ 583 if (!no_error && drawbuffer != 0) { 584 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 585 drawbuffer); 586 return; 587 } 588 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer 589 && !ctx->RasterDiscard) { 590 /* Save current depth clear value, set to 'value', do the 591 * depth clear and restore the clear value. 592 * XXX in the future we may have a new st_ClearBuffer() 593 * hook instead. 594 */ 595 const GLclampd clearSave = ctx->Depth.Clear; 596 597 /* Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says: 598 * 599 * "If buffer is DEPTH, drawbuffer must be zero, and value points 600 * to the single depth value to clear the depth buffer to. 601 * Clamping and type conversion for fixed-point depth buffers are 602 * performed in the same fashion as for ClearDepth." 603 */ 604 const struct gl_renderbuffer *rb = 605 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 606 const bool is_float_depth = 607 _mesa_has_depth_float_channel(rb->InternalFormat); 608 ctx->Depth.Clear = is_float_depth ? *value : SATURATE(*value); 609 610 st_Clear(ctx, BUFFER_BIT_DEPTH); 611 ctx->Depth.Clear = clearSave; 612 } 613 /* clear depth buffer to value */ 614 break; 615 case GL_COLOR: 616 { 617 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 618 if (!no_error && mask == INVALID_MASK) { 619 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 620 drawbuffer); 621 return; 622 } 623 else if (mask && !ctx->RasterDiscard) { 624 union gl_color_union clearSave; 625 626 /* save color */ 627 clearSave = ctx->Color.ClearColor; 628 /* set color */ 629 COPY_4V(ctx->Color.ClearColor.f, value); 630 /* clear buffer(s) */ 631 st_Clear(ctx, mask); 632 /* restore color */ 633 ctx->Color.ClearColor = clearSave; 634 } 635 } 636 break; 637 default: 638 if (!no_error) { 639 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 640 * of the OpenGL 4.5 spec states: 641 * 642 * "An INVALID_ENUM error is generated by ClearBufferfv and 643 * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH." 644 */ 645 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", 646 _mesa_enum_to_string(buffer)); 647 } 648 return; 649 } 650} 651 652 653void GLAPIENTRY 654_mesa_ClearBufferfv_no_error(GLenum buffer, GLint drawbuffer, 655 const GLfloat *value) 656{ 657 GET_CURRENT_CONTEXT(ctx); 658 clear_bufferfv(ctx, buffer, drawbuffer, value, true); 659} 660 661 662void GLAPIENTRY 663_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) 664{ 665 GET_CURRENT_CONTEXT(ctx); 666 clear_bufferfv(ctx, buffer, drawbuffer, value, false); 667} 668 669 670/** 671 * The ClearBuffer framework is so complicated and so riddled with the 672 * assumption that the framebuffer is bound that, for now, we will just fake 673 * direct state access clearing for the user. 674 */ 675void GLAPIENTRY 676_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, 677 GLint drawbuffer, const GLfloat *value) 678{ 679 GLint oldfb; 680 681 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 682 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 683 _mesa_ClearBufferfv(buffer, drawbuffer, value); 684 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 685} 686 687 688/** 689 * New in GL 3.0 690 * Clear depth/stencil buffer only. 691 */ 692static ALWAYS_INLINE void 693clear_bufferfi(struct gl_context *ctx, GLenum buffer, GLint drawbuffer, 694 GLfloat depth, GLint stencil, bool no_error) 695{ 696 GLbitfield mask = 0; 697 698 FLUSH_VERTICES(ctx, 0, 0); 699 700 if (!no_error) { 701 if (buffer != GL_DEPTH_STENCIL) { 702 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", 703 _mesa_enum_to_string(buffer)); 704 return; 705 } 706 707 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 708 * 709 * "ClearBuffer generates an INVALID VALUE error if buffer is 710 * COLOR and drawbuffer is less than zero, or greater than the 711 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 712 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 713 */ 714 if (drawbuffer != 0) { 715 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", 716 drawbuffer); 717 return; 718 } 719 } 720 721 if (ctx->RasterDiscard) 722 return; 723 724 if (ctx->NewState) { 725 _mesa_update_state( ctx ); 726 } 727 728 if (!no_error && ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 729 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 730 "glClearBufferfi(incomplete framebuffer)"); 731 return; 732 } 733 734 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) 735 mask |= BUFFER_BIT_DEPTH; 736 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) 737 mask |= BUFFER_BIT_STENCIL; 738 739 if (mask) { 740 /* save current clear values */ 741 const GLclampd clearDepthSave = ctx->Depth.Clear; 742 const GLuint clearStencilSave = ctx->Stencil.Clear; 743 744 /* set new clear values 745 * 746 * Page 263 (page 279 of the PDF) of the OpenGL 3.0 spec says: 747 * 748 * "depth and stencil are the values to clear the depth and stencil 749 * buffers to, respectively. Clamping and type conversion for 750 * fixed-point depth buffers are performed in the same fashion as 751 * for ClearDepth." 752 */ 753 const struct gl_renderbuffer *rb = 754 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 755 const bool has_float_depth = rb && 756 _mesa_has_depth_float_channel(rb->InternalFormat); 757 ctx->Depth.Clear = has_float_depth ? depth : SATURATE(depth); 758 ctx->Stencil.Clear = stencil; 759 760 /* clear buffers */ 761 st_Clear(ctx, mask); 762 763 /* restore */ 764 ctx->Depth.Clear = clearDepthSave; 765 ctx->Stencil.Clear = clearStencilSave; 766 } 767} 768 769 770void GLAPIENTRY 771_mesa_ClearBufferfi_no_error(GLenum buffer, GLint drawbuffer, 772 GLfloat depth, GLint stencil) 773{ 774 GET_CURRENT_CONTEXT(ctx); 775 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, true); 776} 777 778 779void GLAPIENTRY 780_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, 781 GLfloat depth, GLint stencil) 782{ 783 GET_CURRENT_CONTEXT(ctx); 784 clear_bufferfi(ctx, buffer, drawbuffer, depth, stencil, false); 785} 786 787 788/** 789 * The ClearBuffer framework is so complicated and so riddled with the 790 * assumption that the framebuffer is bound that, for now, we will just fake 791 * direct state access clearing for the user. 792 */ 793void GLAPIENTRY 794_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, 795 GLint drawbuffer, GLfloat depth, GLint stencil) 796{ 797 GLint oldfb; 798 799 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 800 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 801 _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil); 802 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 803} 804