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 45 void 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 */ 64 void 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 */ 79 void 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 */ 94 void 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 */ 113 static bool 114 color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx) 115 { 116 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx]; 117 GLuint c; 118 GLubyte colorMask = 0; 119 120 if (rb) { 121 for (c = 0; c < 4; c++) { 122 if (_mesa_format_has_color_component(rb->Format, c)) 123 colorMask |= ctx->Color.ColorMask[idx][c]; 124 } 125 } 126 127 return colorMask != 0; 128 } 129 130 131 /** 132 * Clear buffers. 133 * 134 * \param mask bit-mask indicating the buffers to be cleared. 135 * 136 * Flushes the vertices and verifies the parameter. 137 * If __struct gl_contextRec::NewState is set then calls _mesa_update_state() 138 * to update gl_frame_buffer::_Xmin, etc. If the rasterization mode is set to 139 * GL_RENDER then requests the driver to clear the buffers, via the 140 * dd_function_table::Clear callback. 141 */ 142 void GLAPIENTRY 143 _mesa_Clear( GLbitfield mask ) 144 { 145 GET_CURRENT_CONTEXT(ctx); 146 FLUSH_VERTICES(ctx, 0); 147 148 FLUSH_CURRENT(ctx, 0); 149 150 if (MESA_VERBOSE & VERBOSE_API) 151 _mesa_debug(ctx, "glClear 0x%x\n", mask); 152 153 if (mask & ~(GL_COLOR_BUFFER_BIT | 154 GL_DEPTH_BUFFER_BIT | 155 GL_STENCIL_BUFFER_BIT | 156 GL_ACCUM_BUFFER_BIT)) { 157 /* invalid bit set */ 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 if (ctx->NewState) { 172 _mesa_update_state( ctx ); /* update _Xmin, etc */ 173 } 174 175 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 176 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 177 "glClear(incomplete framebuffer)"); 178 return; 179 } 180 181 if (ctx->RasterDiscard) 182 return; 183 184 if (ctx->RenderMode == GL_RENDER) { 185 GLbitfield bufferMask; 186 187 /* don't clear depth buffer if depth writing disabled */ 188 if (!ctx->Depth.Mask) 189 mask &= ~GL_DEPTH_BUFFER_BIT; 190 191 /* Build the bitmask to send to device driver's Clear function. 192 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 193 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 194 * BUFFER_BIT_COLORn flags. 195 */ 196 bufferMask = 0; 197 if (mask & GL_COLOR_BUFFER_BIT) { 198 GLuint i; 199 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { 200 GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; 201 202 if (buf >= 0 && color_buffer_writes_enabled(ctx, i)) { 203 bufferMask |= 1 << buf; 204 } 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 ~0x0U 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 */ 238 static GLbitfield 239 make_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 /* From the GL 4.0 specification: 245 * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is 246 * specified by passing i as the parameter drawbuffer, and value 247 * points to a four-element vector specifying the R, G, B, and A 248 * color to clear that draw buffer to. If the draw buffer is one 249 * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying 250 * multiple buffers, each selected buffer is cleared to the same 251 * value. 252 * 253 * Note that "drawbuffer" and "draw buffer" have different meaning. 254 * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's 255 * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK, 256 * etc. 257 */ 258 if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { 259 return INVALID_MASK; 260 } 261 262 switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) { 263 case GL_FRONT: 264 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 265 mask |= BUFFER_BIT_FRONT_LEFT; 266 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 267 mask |= BUFFER_BIT_FRONT_RIGHT; 268 break; 269 case GL_BACK: 270 /* For GLES contexts with a single buffered configuration, we actually 271 * only have a front renderbuffer, so any clear calls to GL_BACK should 272 * affect that buffer. See draw_buffer_enum_to_bitmask for details. 273 */ 274 if (_mesa_is_gles(ctx)) 275 if (!ctx->DrawBuffer->Visual.doubleBufferMode) 276 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 277 mask |= BUFFER_BIT_FRONT_LEFT; 278 if (att[BUFFER_BACK_LEFT].Renderbuffer) 279 mask |= BUFFER_BIT_BACK_LEFT; 280 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 281 mask |= BUFFER_BIT_BACK_RIGHT; 282 break; 283 case GL_LEFT: 284 if (att[BUFFER_FRONT_LEFT].Renderbuffer) 285 mask |= BUFFER_BIT_FRONT_LEFT; 286 if (att[BUFFER_BACK_LEFT].Renderbuffer) 287 mask |= BUFFER_BIT_BACK_LEFT; 288 break; 289 case GL_RIGHT: 290 if (att[BUFFER_FRONT_RIGHT].Renderbuffer) 291 mask |= BUFFER_BIT_FRONT_RIGHT; 292 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 293 mask |= BUFFER_BIT_BACK_RIGHT; 294 break; 295 case GL_FRONT_AND_BACK: 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_FRONT_RIGHT].Renderbuffer) 301 mask |= BUFFER_BIT_FRONT_RIGHT; 302 if (att[BUFFER_BACK_RIGHT].Renderbuffer) 303 mask |= BUFFER_BIT_BACK_RIGHT; 304 break; 305 default: 306 { 307 GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; 308 309 if (buf >= 0 && att[buf].Renderbuffer) { 310 mask |= 1 << buf; 311 } 312 } 313 } 314 315 return mask; 316 } 317 318 319 320 /** 321 * New in GL 3.0 322 * Clear signed integer color buffer or stencil buffer (not depth). 323 */ 324 void GLAPIENTRY 325 _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) 326 { 327 GET_CURRENT_CONTEXT(ctx); 328 FLUSH_VERTICES(ctx, 0); 329 330 FLUSH_CURRENT(ctx, 0); 331 332 if (ctx->NewState) { 333 _mesa_update_state( ctx ); 334 } 335 336 switch (buffer) { 337 case GL_STENCIL: 338 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 339 * 340 * "ClearBuffer generates an INVALID VALUE error if buffer is 341 * COLOR and drawbuffer is less than zero, or greater than the 342 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 343 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 344 */ 345 if (drawbuffer != 0) { 346 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 347 drawbuffer); 348 return; 349 } 350 else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer 351 && !ctx->RasterDiscard) { 352 /* Save current stencil clear value, set to 'value', do the 353 * stencil clear and restore the clear value. 354 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 355 * hook instead. 356 */ 357 const GLuint clearSave = ctx->Stencil.Clear; 358 ctx->Stencil.Clear = *value; 359 ctx->Driver.Clear(ctx, BUFFER_BIT_STENCIL); 360 ctx->Stencil.Clear = clearSave; 361 } 362 break; 363 case GL_COLOR: 364 { 365 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 366 if (mask == INVALID_MASK) { 367 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferiv(drawbuffer=%d)", 368 drawbuffer); 369 return; 370 } 371 else if (mask && !ctx->RasterDiscard) { 372 union gl_color_union clearSave; 373 374 /* save color */ 375 clearSave = ctx->Color.ClearColor; 376 /* set color */ 377 COPY_4V(ctx->Color.ClearColor.i, value); 378 /* clear buffer(s) */ 379 ctx->Driver.Clear(ctx, mask); 380 /* restore color */ 381 ctx->Color.ClearColor = clearSave; 382 } 383 } 384 break; 385 default: 386 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 387 * of the OpenGL 4.5 spec states: 388 * 389 * "An INVALID_ENUM error is generated by ClearBufferiv and 390 * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL." 391 */ 392 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)", 393 _mesa_enum_to_string(buffer)); 394 return; 395 } 396 } 397 398 399 /** 400 * The ClearBuffer framework is so complicated and so riddled with the 401 * assumption that the framebuffer is bound that, for now, we will just fake 402 * direct state access clearing for the user. 403 */ 404 void GLAPIENTRY 405 _mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, 406 GLint drawbuffer, const GLint *value) 407 { 408 GLint oldfb; 409 410 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 411 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 412 _mesa_ClearBufferiv(buffer, drawbuffer, value); 413 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 414 } 415 416 417 /** 418 * New in GL 3.0 419 * Clear unsigned integer color buffer (not depth, not stencil). 420 */ 421 void GLAPIENTRY 422 _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) 423 { 424 GET_CURRENT_CONTEXT(ctx); 425 426 FLUSH_VERTICES(ctx, 0); 427 FLUSH_CURRENT(ctx, 0); 428 429 if (ctx->NewState) { 430 _mesa_update_state( ctx ); 431 } 432 433 switch (buffer) { 434 case GL_COLOR: 435 { 436 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 437 if (mask == INVALID_MASK) { 438 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)", 439 drawbuffer); 440 return; 441 } 442 else if (mask && !ctx->RasterDiscard) { 443 union gl_color_union clearSave; 444 445 /* save color */ 446 clearSave = ctx->Color.ClearColor; 447 /* set color */ 448 COPY_4V(ctx->Color.ClearColor.ui, value); 449 /* clear buffer(s) */ 450 ctx->Driver.Clear(ctx, mask); 451 /* restore color */ 452 ctx->Color.ClearColor = clearSave; 453 } 454 } 455 break; 456 default: 457 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 458 * of the OpenGL 4.5 spec states: 459 * 460 * "An INVALID_ENUM error is generated by ClearBufferuiv and 461 * ClearNamedFramebufferuiv if buffer is not COLOR." 462 */ 463 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)", 464 _mesa_enum_to_string(buffer)); 465 return; 466 } 467 } 468 469 470 /** 471 * The ClearBuffer framework is so complicated and so riddled with the 472 * assumption that the framebuffer is bound that, for now, we will just fake 473 * direct state access clearing for the user. 474 */ 475 void GLAPIENTRY 476 _mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, 477 GLint drawbuffer, const GLuint *value) 478 { 479 GLint oldfb; 480 481 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 482 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 483 _mesa_ClearBufferuiv(buffer, drawbuffer, value); 484 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 485 } 486 487 488 /** 489 * New in GL 3.0 490 * Clear fixed-pt or float color buffer or depth buffer (not stencil). 491 */ 492 void GLAPIENTRY 493 _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) 494 { 495 GET_CURRENT_CONTEXT(ctx); 496 497 FLUSH_VERTICES(ctx, 0); 498 FLUSH_CURRENT(ctx, 0); 499 500 if (ctx->NewState) { 501 _mesa_update_state( ctx ); 502 } 503 504 switch (buffer) { 505 case GL_DEPTH: 506 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 507 * 508 * "ClearBuffer generates an INVALID VALUE error if buffer is 509 * COLOR and drawbuffer is less than zero, or greater than the 510 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 511 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 512 */ 513 if (drawbuffer != 0) { 514 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 515 drawbuffer); 516 return; 517 } 518 else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer 519 && !ctx->RasterDiscard) { 520 /* Save current depth clear value, set to 'value', do the 521 * depth clear and restore the clear value. 522 * XXX in the future we may have a new ctx->Driver.ClearBuffer() 523 * hook instead. 524 */ 525 const GLclampd clearSave = ctx->Depth.Clear; 526 ctx->Depth.Clear = *value; 527 ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH); 528 ctx->Depth.Clear = clearSave; 529 } 530 /* clear depth buffer to value */ 531 break; 532 case GL_COLOR: 533 { 534 const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer); 535 if (mask == INVALID_MASK) { 536 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)", 537 drawbuffer); 538 return; 539 } 540 else if (mask && !ctx->RasterDiscard) { 541 union gl_color_union clearSave; 542 543 /* save color */ 544 clearSave = ctx->Color.ClearColor; 545 /* set color */ 546 COPY_4V(ctx->Color.ClearColor.f, value); 547 /* clear buffer(s) */ 548 ctx->Driver.Clear(ctx, mask); 549 /* restore color */ 550 ctx->Color.ClearColor = clearSave; 551 } 552 } 553 break; 554 default: 555 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers' 556 * of the OpenGL 4.5 spec states: 557 * 558 * "An INVALID_ENUM error is generated by ClearBufferfv and 559 * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH." 560 */ 561 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)", 562 _mesa_enum_to_string(buffer)); 563 return; 564 } 565 } 566 567 568 /** 569 * The ClearBuffer framework is so complicated and so riddled with the 570 * assumption that the framebuffer is bound that, for now, we will just fake 571 * direct state access clearing for the user. 572 */ 573 void GLAPIENTRY 574 _mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, 575 GLint drawbuffer, const GLfloat *value) 576 { 577 GLint oldfb; 578 579 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 580 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 581 _mesa_ClearBufferfv(buffer, drawbuffer, value); 582 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 583 } 584 585 586 /** 587 * New in GL 3.0 588 * Clear depth/stencil buffer only. 589 */ 590 void GLAPIENTRY 591 _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, 592 GLfloat depth, GLint stencil) 593 { 594 GET_CURRENT_CONTEXT(ctx); 595 GLbitfield mask = 0; 596 597 FLUSH_VERTICES(ctx, 0); 598 FLUSH_CURRENT(ctx, 0); 599 600 if (buffer != GL_DEPTH_STENCIL) { 601 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)", 602 _mesa_enum_to_string(buffer)); 603 return; 604 } 605 606 /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says: 607 * 608 * "ClearBuffer generates an INVALID VALUE error if buffer is 609 * COLOR and drawbuffer is less than zero, or greater than the 610 * value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH, 611 * STENCIL, or DEPTH STENCIL and drawbuffer is not zero." 612 */ 613 if (drawbuffer != 0) { 614 _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfi(drawbuffer=%d)", 615 drawbuffer); 616 return; 617 } 618 619 if (ctx->RasterDiscard) 620 return; 621 622 if (ctx->NewState) { 623 _mesa_update_state( ctx ); 624 } 625 626 if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) 627 mask |= BUFFER_BIT_DEPTH; 628 if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) 629 mask |= BUFFER_BIT_STENCIL; 630 631 if (mask) { 632 /* save current clear values */ 633 const GLclampd clearDepthSave = ctx->Depth.Clear; 634 const GLuint clearStencilSave = ctx->Stencil.Clear; 635 636 /* set new clear values */ 637 ctx->Depth.Clear = depth; 638 ctx->Stencil.Clear = stencil; 639 640 /* clear buffers */ 641 ctx->Driver.Clear(ctx, mask); 642 643 /* restore */ 644 ctx->Depth.Clear = clearDepthSave; 645 ctx->Stencil.Clear = clearStencilSave; 646 } 647 } 648 649 650 /** 651 * The ClearBuffer framework is so complicated and so riddled with the 652 * assumption that the framebuffer is bound that, for now, we will just fake 653 * direct state access clearing for the user. 654 */ 655 void GLAPIENTRY 656 _mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, 657 GLint drawbuffer, GLfloat depth, GLint stencil) 658 { 659 GLint oldfb; 660 661 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); 662 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); 663 _mesa_ClearBufferfi(buffer, drawbuffer, depth, stencil); 664 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); 665 } 666