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