buffers.c revision 7117f1b4
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.2 4 * 5 * Copyright (C) 1999-2006 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 buffers.c 28 * General framebuffer-related functions, like glClear, glScissor, etc. 29 */ 30 31 32 33#include "glheader.h" 34#include "buffers.h" 35#include "colormac.h" 36#include "context.h" 37#include "enums.h" 38#include "fbobject.h" 39#include "state.h" 40 41 42#define BAD_MASK ~0u 43 44 45#if _HAVE_FULL_GL 46void GLAPIENTRY 47_mesa_ClearIndex( GLfloat c ) 48{ 49 GET_CURRENT_CONTEXT(ctx); 50 ASSERT_OUTSIDE_BEGIN_END(ctx); 51 52 if (ctx->Color.ClearIndex == (GLuint) c) 53 return; 54 55 FLUSH_VERTICES(ctx, _NEW_COLOR); 56 ctx->Color.ClearIndex = (GLuint) c; 57 58 if (!ctx->Visual.rgbMode && ctx->Driver.ClearIndex) { 59 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */ 60 (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex ); 61 } 62} 63#endif 64 65 66/** 67 * Specify the clear values for the color buffers. 68 * 69 * \param red red color component. 70 * \param green green color component. 71 * \param blue blue color component. 72 * \param alpha alpha component. 73 * 74 * \sa glClearColor(). 75 * 76 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a 77 * change, flushes the vertices and notifies the driver via the 78 * dd_function_table::ClearColor callback. 79 */ 80void GLAPIENTRY 81_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 82{ 83 GLfloat tmp[4]; 84 GET_CURRENT_CONTEXT(ctx); 85 ASSERT_OUTSIDE_BEGIN_END(ctx); 86 87 tmp[0] = CLAMP(red, 0.0F, 1.0F); 88 tmp[1] = CLAMP(green, 0.0F, 1.0F); 89 tmp[2] = CLAMP(blue, 0.0F, 1.0F); 90 tmp[3] = CLAMP(alpha, 0.0F, 1.0F); 91 92 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor)) 93 return; /* no change */ 94 95 FLUSH_VERTICES(ctx, _NEW_COLOR); 96 COPY_4V(ctx->Color.ClearColor, tmp); 97 98 if (ctx->Visual.rgbMode && ctx->Driver.ClearColor) { 99 /* it's OK to call glClearColor in CI mode but it should be a NOP */ 100 (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor); 101 } 102} 103 104 105/** 106 * Clear buffers. 107 * 108 * \param mask bit-mask indicating the buffers to be cleared. 109 * 110 * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState 111 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin, 112 * etc. If the rasterization mode is set to GL_RENDER then requests the driver 113 * to clear the buffers, via the dd_function_table::Clear callback. 114 */ 115void GLAPIENTRY 116_mesa_Clear( GLbitfield mask ) 117{ 118 GET_CURRENT_CONTEXT(ctx); 119 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 120 121 if (MESA_VERBOSE & VERBOSE_API) 122 _mesa_debug(ctx, "glClear 0x%x\n", mask); 123 124 if (mask & ~(GL_COLOR_BUFFER_BIT | 125 GL_DEPTH_BUFFER_BIT | 126 GL_STENCIL_BUFFER_BIT | 127 GL_ACCUM_BUFFER_BIT)) { 128 /* invalid bit set */ 129 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); 130 return; 131 } 132 133 if (ctx->NewState) { 134 _mesa_update_state( ctx ); /* update _Xmin, etc */ 135 } 136 137 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 138 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 139 "glClear(incomplete framebuffer)"); 140 return; 141 } 142 143 if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0) 144 return; 145 146 if (ctx->RenderMode == GL_RENDER) { 147 GLbitfield bufferMask; 148 149 /* don't clear depth buffer if depth writing disabled */ 150 if (!ctx->Depth.Mask) 151 mask &= ~GL_DEPTH_BUFFER_BIT; 152 153 /* Build the bitmask to send to device driver's Clear function. 154 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 155 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 156 * BUFFER_BIT_COLORn flags. 157 */ 158 bufferMask = 0; 159 if (mask & GL_COLOR_BUFFER_BIT) { 160 bufferMask |= ctx->DrawBuffer->_ColorDrawBufferMask[0]; 161 } 162 163 if ((mask & GL_DEPTH_BUFFER_BIT) 164 && ctx->DrawBuffer->Visual.haveDepthBuffer) { 165 bufferMask |= BUFFER_BIT_DEPTH; 166 } 167 168 if ((mask & GL_STENCIL_BUFFER_BIT) 169 && ctx->DrawBuffer->Visual.haveStencilBuffer) { 170 bufferMask |= BUFFER_BIT_STENCIL; 171 } 172 173 if ((mask & GL_ACCUM_BUFFER_BIT) 174 && ctx->DrawBuffer->Visual.haveAccumBuffer) { 175 bufferMask |= BUFFER_BIT_ACCUM; 176 } 177 178 ASSERT(ctx->Driver.Clear); 179 ctx->Driver.Clear(ctx, bufferMask); 180 } 181} 182 183 184 185/** 186 * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are 187 * available to the rendering context. 188 * This depends on the framebuffer we're writing to. For window system 189 * framebuffers we look at the framebuffer's visual. But for user- 190 * create framebuffers we look at the number of supported color attachments. 191 */ 192static GLbitfield 193supported_buffer_bitmask(const GLcontext *ctx, GLuint framebufferID) 194{ 195 GLbitfield mask = 0x0; 196 197 if (framebufferID > 0) { 198 /* A user-created renderbuffer */ 199 GLuint i; 200 ASSERT(ctx->Extensions.EXT_framebuffer_object); 201 for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { 202 mask |= (BUFFER_BIT_COLOR0 << i); 203 } 204 } 205 else { 206 /* A window system renderbuffer */ 207 GLint i; 208 mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ 209 if (ctx->Visual.stereoMode) { 210 mask |= BUFFER_BIT_FRONT_RIGHT; 211 if (ctx->Visual.doubleBufferMode) { 212 mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 213 } 214 } 215 else if (ctx->Visual.doubleBufferMode) { 216 mask |= BUFFER_BIT_BACK_LEFT; 217 } 218 219 for (i = 0; i < ctx->Visual.numAuxBuffers; i++) { 220 mask |= (BUFFER_BIT_AUX0 << i); 221 } 222 } 223 224 return mask; 225} 226 227 228/** 229 * Helper routine used by glDrawBuffer and glDrawBuffersARB. 230 * Given a GLenum naming one or more color buffers (such as 231 * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. 232 */ 233static GLbitfield 234draw_buffer_enum_to_bitmask(GLenum buffer) 235{ 236 switch (buffer) { 237 case GL_NONE: 238 return 0; 239 case GL_FRONT: 240 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; 241 case GL_BACK: 242 return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 243 case GL_RIGHT: 244 return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 245 case GL_FRONT_RIGHT: 246 return BUFFER_BIT_FRONT_RIGHT; 247 case GL_BACK_RIGHT: 248 return BUFFER_BIT_BACK_RIGHT; 249 case GL_BACK_LEFT: 250 return BUFFER_BIT_BACK_LEFT; 251 case GL_FRONT_AND_BACK: 252 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT 253 | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 254 case GL_LEFT: 255 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; 256 case GL_FRONT_LEFT: 257 return BUFFER_BIT_FRONT_LEFT; 258 case GL_AUX0: 259 return BUFFER_BIT_AUX0; 260 case GL_AUX1: 261 return BUFFER_BIT_AUX1; 262 case GL_AUX2: 263 return BUFFER_BIT_AUX2; 264 case GL_AUX3: 265 return BUFFER_BIT_AUX3; 266 case GL_COLOR_ATTACHMENT0_EXT: 267 return BUFFER_BIT_COLOR0; 268 case GL_COLOR_ATTACHMENT1_EXT: 269 return BUFFER_BIT_COLOR1; 270 case GL_COLOR_ATTACHMENT2_EXT: 271 return BUFFER_BIT_COLOR2; 272 case GL_COLOR_ATTACHMENT3_EXT: 273 return BUFFER_BIT_COLOR3; 274 case GL_COLOR_ATTACHMENT4_EXT: 275 return BUFFER_BIT_COLOR4; 276 case GL_COLOR_ATTACHMENT5_EXT: 277 return BUFFER_BIT_COLOR5; 278 case GL_COLOR_ATTACHMENT6_EXT: 279 return BUFFER_BIT_COLOR6; 280 case GL_COLOR_ATTACHMENT7_EXT: 281 return BUFFER_BIT_COLOR7; 282 default: 283 /* error */ 284 return BAD_MASK; 285 } 286} 287 288 289/** 290 * Helper routine used by glReadBuffer. 291 * Given a GLenum naming a color buffer, return the index of the corresponding 292 * renderbuffer (a BUFFER_* value). 293 * return -1 for an invalid buffer. 294 */ 295static GLint 296read_buffer_enum_to_index(GLenum buffer) 297{ 298 switch (buffer) { 299 case GL_FRONT: 300 return BUFFER_FRONT_LEFT; 301 case GL_BACK: 302 return BUFFER_BACK_LEFT; 303 case GL_RIGHT: 304 return BUFFER_FRONT_RIGHT; 305 case GL_FRONT_RIGHT: 306 return BUFFER_FRONT_RIGHT; 307 case GL_BACK_RIGHT: 308 return BUFFER_BACK_RIGHT; 309 case GL_BACK_LEFT: 310 return BUFFER_BACK_LEFT; 311 case GL_LEFT: 312 return BUFFER_FRONT_LEFT; 313 case GL_FRONT_LEFT: 314 return BUFFER_FRONT_LEFT; 315 case GL_AUX0: 316 return BUFFER_AUX0; 317 case GL_AUX1: 318 return BUFFER_AUX1; 319 case GL_AUX2: 320 return BUFFER_AUX2; 321 case GL_AUX3: 322 return BUFFER_AUX3; 323 case GL_COLOR_ATTACHMENT0_EXT: 324 return BUFFER_COLOR0; 325 case GL_COLOR_ATTACHMENT1_EXT: 326 return BUFFER_COLOR1; 327 case GL_COLOR_ATTACHMENT2_EXT: 328 return BUFFER_COLOR2; 329 case GL_COLOR_ATTACHMENT3_EXT: 330 return BUFFER_COLOR3; 331 case GL_COLOR_ATTACHMENT4_EXT: 332 return BUFFER_COLOR4; 333 case GL_COLOR_ATTACHMENT5_EXT: 334 return BUFFER_COLOR5; 335 case GL_COLOR_ATTACHMENT6_EXT: 336 return BUFFER_COLOR6; 337 case GL_COLOR_ATTACHMENT7_EXT: 338 return BUFFER_COLOR7; 339 default: 340 /* error */ 341 return -1; 342 } 343} 344 345 346/** 347 * Called by glDrawBuffer(). 348 * Specify which renderbuffer(s) to draw into for the first color output. 349 * <buffer> can name zero, one, two or four renderbuffers! 350 * \sa _mesa_DrawBuffersARB 351 * 352 * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. 353 */ 354void GLAPIENTRY 355_mesa_DrawBuffer(GLenum buffer) 356{ 357 GLuint bufferID; 358 GLbitfield destMask; 359 GET_CURRENT_CONTEXT(ctx); 360 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ 361 362 if (MESA_VERBOSE & VERBOSE_API) { 363 _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 364 } 365 366 bufferID = ctx->DrawBuffer->Name; 367 368 if (buffer == GL_NONE) { 369 destMask = 0x0; 370 } 371 else { 372 const GLbitfield supportedMask = supported_buffer_bitmask(ctx, bufferID); 373 destMask = draw_buffer_enum_to_bitmask(buffer); 374 if (destMask == BAD_MASK) { 375 /* totally bogus buffer */ 376 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer)"); 377 return; 378 } 379 destMask &= supportedMask; 380 if (destMask == 0x0) { 381 /* none of the named color buffers exist! */ 382 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffer(buffer)"); 383 return; 384 } 385 } 386 387 /* if we get here, there's no error so set new state */ 388 _mesa_drawbuffers(ctx, 1, &buffer, &destMask); 389} 390 391 392/** 393 * Called by glDrawBuffersARB; specifies the destination color renderbuffers 394 * for N fragment program color outputs. 395 * \sa _mesa_DrawBuffer 396 * \param n number of outputs 397 * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the 398 * names cannot specify more than one buffer. For example, 399 * GL_FRONT_AND_BACK is illegal. 400 */ 401void GLAPIENTRY 402_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) 403{ 404 GLint output; 405 GLuint bufferID; 406 GLbitfield usedBufferMask, supportedMask; 407 GLbitfield destMask[MAX_DRAW_BUFFERS]; 408 GET_CURRENT_CONTEXT(ctx); 409 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 410 411 if (!ctx->Extensions.ARB_draw_buffers) { 412 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB"); 413 return; 414 } 415 if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { 416 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); 417 return; 418 } 419 420 bufferID = ctx->DrawBuffer->Name; 421 422 supportedMask = supported_buffer_bitmask(ctx, bufferID); 423 usedBufferMask = 0x0; 424 425 /* complicated error checking... */ 426 for (output = 0; output < n; output++) { 427 if (buffers[output] == GL_NONE) { 428 destMask[output] = 0x0; 429 } 430 else { 431 destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 432 if (destMask[output] == BAD_MASK 433 || _mesa_bitcount(destMask[output]) > 1) { 434 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); 435 return; 436 } 437 destMask[output] &= supportedMask; 438 if (destMask[output] == 0) { 439 _mesa_error(ctx, GL_INVALID_OPERATION, 440 "glDrawBuffersARB(unsupported buffer)"); 441 return; 442 } 443 if (destMask[output] & usedBufferMask) { 444 /* can't specify a dest buffer more than once! */ 445 _mesa_error(ctx, GL_INVALID_OPERATION, 446 "glDrawBuffersARB(duplicated buffer)"); 447 return; 448 } 449 450 /* update bitmask */ 451 usedBufferMask |= destMask[output]; 452 } 453 } 454 455 /* OK, if we get here, there were no errors so set the new state */ 456 _mesa_drawbuffers(ctx, n, buffers, destMask); 457} 458 459 460/** 461 * Set color output state. Traditionally, there was only one color 462 * output, but fragment programs can now have several distinct color 463 * outputs (see GL_ARB_draw_buffers). This function sets the state 464 * for one such color output. 465 * \param ctx current context 466 * \param output which fragment program output 467 * \param buffer buffer to write to (like GL_LEFT) 468 * \param destMask BUFFER_* bitmask 469 * (like BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). 470 */ 471static void 472set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, 473 GLbitfield destMask) 474{ 475 struct gl_framebuffer *fb = ctx->DrawBuffer; 476 477 ASSERT(output < ctx->Const.MaxDrawBuffers); 478 479 /* Set per-FBO state */ 480 fb->ColorDrawBuffer[output] = buffer; 481 fb->_ColorDrawBufferMask[output] = destMask; 482 /* not really needed, will be set later */ 483 fb->_NumColorDrawBuffers[output] = 0; 484 485 /* Set traditional state var */ 486 ctx->Color.DrawBuffer[output] = buffer; 487} 488 489 490/** 491 * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and 492 * _mesa_PopAttrib to set drawbuffer state. 493 * All error checking will have been done prior to calling this function 494 * so nothing should go wrong at this point. 495 * \param ctx current context 496 * \param n number of color outputs to set 497 * \param buffers array[n] of colorbuffer names, like GL_LEFT. 498 * \param destMask array[n] of BUFFER_* bitmasks which correspond to the 499 * colorbuffer names. (i.e. GL_FRONT_AND_BACK => 500 * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). 501 */ 502void 503_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, 504 const GLbitfield *destMask) 505{ 506 GLbitfield mask[MAX_DRAW_BUFFERS]; 507 GLuint output; 508 509 if (!destMask) { 510 /* compute destMask values now */ 511 const GLuint bufferID = ctx->DrawBuffer->Name; 512 const GLbitfield supportedMask = supported_buffer_bitmask(ctx, bufferID); 513 for (output = 0; output < n; output++) { 514 mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 515 ASSERT(mask[output] != BAD_MASK); 516 mask[output] &= supportedMask; 517 } 518 destMask = mask; 519 } 520 521 for (output = 0; output < n; output++) { 522 set_color_output(ctx, output, buffers[output], destMask[output]); 523 } 524 525 /* set remaining color outputs to NONE */ 526 for (output = n; output < ctx->Const.MaxDrawBuffers; output++) { 527 set_color_output(ctx, output, GL_NONE, 0x0); 528 } 529 530 ctx->NewState |= _NEW_COLOR; 531 532 /* 533 * Call device driver function. 534 */ 535 if (ctx->Driver.DrawBuffers) 536 ctx->Driver.DrawBuffers(ctx, n, buffers); 537 else if (ctx->Driver.DrawBuffer) 538 ctx->Driver.DrawBuffer(ctx, buffers[0]); 539} 540 541 542 543/** 544 * Called by glReadBuffer to set the source renderbuffer for reading pixels. 545 * \param mode color buffer such as GL_FRONT, GL_BACK, etc. 546 */ 547void GLAPIENTRY 548_mesa_ReadBuffer(GLenum buffer) 549{ 550 struct gl_framebuffer *fb; 551 GLbitfield supportedMask; 552 GLint srcBuffer; 553 GLuint bufferID; 554 GET_CURRENT_CONTEXT(ctx); 555 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 556 557 fb = ctx->ReadBuffer; 558 bufferID = fb->Name; 559 560 if (MESA_VERBOSE & VERBOSE_API) 561 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 562 563 if (bufferID > 0 && buffer == GL_NONE) { 564 /* This is legal for user-created framebuffer objects */ 565 srcBuffer = -1; 566 } 567 else { 568 /* general case / window-system framebuffer */ 569 srcBuffer = read_buffer_enum_to_index(buffer); 570 if (srcBuffer == -1) { 571 _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer); 572 return; 573 } 574 supportedMask = supported_buffer_bitmask(ctx, bufferID); 575 if (((1 << srcBuffer) & supportedMask) == 0) { 576 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer); 577 return; 578 } 579 } 580 581 if (bufferID == 0) { 582 ctx->Pixel.ReadBuffer = buffer; 583 } 584 fb->ColorReadBuffer = buffer; 585 fb->_ColorReadBufferIndex = srcBuffer; 586 587 ctx->NewState |= _NEW_PIXEL; 588 589 /* 590 * Call device driver function. 591 */ 592 if (ctx->Driver.ReadBuffer) 593 (*ctx->Driver.ReadBuffer)(ctx, buffer); 594} 595 596 597#if _HAVE_FULL_GL 598 599/** 600 * XXX THIS IS OBSOLETE - drivers should take care of detecting window 601 * size changes and act accordingly, likely calling _mesa_resize_framebuffer(). 602 * 603 * GL_MESA_resize_buffers extension. 604 * 605 * When this function is called, we'll ask the window system how large 606 * the current window is. If it's a new size, we'll call the driver's 607 * ResizeBuffers function. The driver will then resize its color buffers 608 * as needed, and maybe call the swrast's routine for reallocating 609 * swrast-managed depth/stencil/accum/etc buffers. 610 * \note This function should only be called through the GL API, not 611 * from device drivers (as was done in the past). 612 */ 613 614void _mesa_resizebuffers( GLcontext *ctx ) 615{ 616 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 617 618 if (MESA_VERBOSE & VERBOSE_API) 619 _mesa_debug(ctx, "glResizeBuffersMESA\n"); 620 621 if (!ctx->Driver.GetBufferSize) { 622 return; 623 } 624 625 if (ctx->WinSysDrawBuffer) { 626 GLuint newWidth, newHeight; 627 GLframebuffer *buffer = ctx->WinSysDrawBuffer; 628 629 assert(buffer->Name == 0); 630 631 /* ask device driver for size of output buffer */ 632 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 633 634 /* see if size of device driver's color buffer (window) has changed */ 635 if (buffer->Width != newWidth || buffer->Height != newHeight) { 636 if (ctx->Driver.ResizeBuffers) 637 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 638 } 639 } 640 641 if (ctx->WinSysReadBuffer 642 && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) { 643 GLuint newWidth, newHeight; 644 GLframebuffer *buffer = ctx->WinSysReadBuffer; 645 646 assert(buffer->Name == 0); 647 648 /* ask device driver for size of read buffer */ 649 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 650 651 /* see if size of device driver's color buffer (window) has changed */ 652 if (buffer->Width != newWidth || buffer->Height != newHeight) { 653 if (ctx->Driver.ResizeBuffers) 654 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 655 } 656 } 657 658 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 659} 660 661 662/* 663 * XXX THIS IS OBSOLETE 664 */ 665void GLAPIENTRY 666_mesa_ResizeBuffersMESA( void ) 667{ 668 GET_CURRENT_CONTEXT(ctx); 669 670 if (ctx->Extensions.MESA_resize_buffers) 671 _mesa_resizebuffers( ctx ); 672} 673 674 675/* 676 * XXX move somewhere else someday? 677 */ 678void GLAPIENTRY 679_mesa_SampleCoverageARB(GLclampf value, GLboolean invert) 680{ 681 GET_CURRENT_CONTEXT(ctx); 682 683 if (!ctx->Extensions.ARB_multisample) { 684 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB"); 685 return; 686 } 687 688 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 689 ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0); 690 ctx->Multisample.SampleCoverageInvert = invert; 691 ctx->NewState |= _NEW_MULTISAMPLE; 692} 693 694#endif /* _HAVE_FULL_GL */ 695 696 697 698/** 699 * Define the scissor box. 700 * 701 * \param x, y coordinates of the scissor box lower-left corner. 702 * \param width width of the scissor box. 703 * \param height height of the scissor box. 704 * 705 * \sa glScissor(). 706 * 707 * Verifies the parameters and updates __GLcontextRec::Scissor. On a 708 * change flushes the vertices and notifies the driver via 709 * the dd_function_table::Scissor callback. 710 */ 711void 712_mesa_set_scissor(GLcontext *ctx, 713 GLint x, GLint y, GLsizei width, GLsizei height) 714{ 715 if (x == ctx->Scissor.X && 716 y == ctx->Scissor.Y && 717 width == ctx->Scissor.Width && 718 height == ctx->Scissor.Height) 719 return; 720 721 FLUSH_VERTICES(ctx, _NEW_SCISSOR); 722 ctx->Scissor.X = x; 723 ctx->Scissor.Y = y; 724 ctx->Scissor.Width = width; 725 ctx->Scissor.Height = height; 726 727 if (ctx->Driver.Scissor) 728 ctx->Driver.Scissor( ctx, x, y, width, height ); 729} 730 731 732void GLAPIENTRY 733_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height ) 734{ 735 GET_CURRENT_CONTEXT(ctx); 736 ASSERT_OUTSIDE_BEGIN_END(ctx); 737 738 if (width < 0 || height < 0) { 739 _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" ); 740 return; 741 } 742 743 if (MESA_VERBOSE & VERBOSE_API) 744 _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height); 745 746 _mesa_set_scissor(ctx, x, y, width, height); 747} 748 749 750 751/**********************************************************************/ 752/** \name Initialization */ 753/*@{*/ 754 755/** 756 * Initialize the context's scissor state. 757 * \param ctx the GL context. 758 */ 759void 760_mesa_init_scissor(GLcontext *ctx) 761{ 762 /* Scissor group */ 763 ctx->Scissor.Enabled = GL_FALSE; 764 ctx->Scissor.X = 0; 765 ctx->Scissor.Y = 0; 766 ctx->Scissor.Width = 0; 767 ctx->Scissor.Height = 0; 768} 769 770 771/** 772 * Initialize the context's multisample state. 773 * \param ctx the GL context. 774 */ 775void 776_mesa_init_multisample(GLcontext *ctx) 777{ 778 ctx->Multisample.Enabled = GL_FALSE; 779 ctx->Multisample.SampleAlphaToCoverage = GL_FALSE; 780 ctx->Multisample.SampleAlphaToOne = GL_FALSE; 781 ctx->Multisample.SampleCoverage = GL_FALSE; 782 ctx->Multisample.SampleCoverageValue = 1.0; 783 ctx->Multisample.SampleCoverageInvert = GL_FALSE; 784} 785 786/*@}*/ 787