buffers.c revision 28b014ee256290eb0494b967e40c475c0c895f57
1/** 2 * \file buffers.c 3 * Frame buffer management. 4 */ 5 6/* 7 * Mesa 3-D graphics library 8 * Version: 6.5 9 * 10 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a 13 * copy of this software and associated documentation files (the "Software"), 14 * to deal in the Software without restriction, including without limitation 15 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 * and/or sell copies of the Software, and to permit persons to whom the 17 * Software is furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included 20 * in all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 */ 29 30 31#include "glheader.h" 32#include "buffers.h" 33#include "colormac.h" 34#include "context.h" 35#include "enums.h" 36#include "fbobject.h" 37#include "state.h" 38 39 40#define BAD_MASK ~0u 41 42 43#if _HAVE_FULL_GL 44void GLAPIENTRY 45_mesa_ClearIndex( GLfloat c ) 46{ 47 GET_CURRENT_CONTEXT(ctx); 48 ASSERT_OUTSIDE_BEGIN_END(ctx); 49 50 if (ctx->Color.ClearIndex == (GLuint) c) 51 return; 52 53 FLUSH_VERTICES(ctx, _NEW_COLOR); 54 ctx->Color.ClearIndex = (GLuint) c; 55 56 if (!ctx->Visual.rgbMode && ctx->Driver.ClearIndex) { 57 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */ 58 (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex ); 59 } 60} 61#endif 62 63 64/** 65 * Specify the clear values for the color buffers. 66 * 67 * \param red red color component. 68 * \param green green color component. 69 * \param blue blue color component. 70 * \param alpha alpha component. 71 * 72 * \sa glClearColor(). 73 * 74 * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a 75 * change, flushes the vertices and notifies the driver via the 76 * dd_function_table::ClearColor callback. 77 */ 78void GLAPIENTRY 79_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 80{ 81 GLfloat tmp[4]; 82 GET_CURRENT_CONTEXT(ctx); 83 ASSERT_OUTSIDE_BEGIN_END(ctx); 84 85 tmp[0] = CLAMP(red, 0.0F, 1.0F); 86 tmp[1] = CLAMP(green, 0.0F, 1.0F); 87 tmp[2] = CLAMP(blue, 0.0F, 1.0F); 88 tmp[3] = CLAMP(alpha, 0.0F, 1.0F); 89 90 if (TEST_EQ_4V(tmp, ctx->Color.ClearColor)) 91 return; /* no change */ 92 93 FLUSH_VERTICES(ctx, _NEW_COLOR); 94 COPY_4V(ctx->Color.ClearColor, tmp); 95 96 if (ctx->Visual.rgbMode && ctx->Driver.ClearColor) { 97 /* it's OK to call glClearColor in CI mode but it should be a NOP */ 98 (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor); 99 } 100} 101 102 103/** 104 * Clear buffers. 105 * 106 * \param mask bit-mask indicating the buffers to be cleared. 107 * 108 * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState 109 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin, 110 * etc. If the rasterization mode is set to GL_RENDER then requests the driver 111 * to clear the buffers, via the dd_function_table::Clear callback. 112 */ 113void GLAPIENTRY 114_mesa_Clear( GLbitfield mask ) 115{ 116 GET_CURRENT_CONTEXT(ctx); 117 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 118 119 if (MESA_VERBOSE & VERBOSE_API) 120 _mesa_debug(ctx, "glClear 0x%x\n", mask); 121 122 if (mask & ~(GL_COLOR_BUFFER_BIT | 123 GL_DEPTH_BUFFER_BIT | 124 GL_STENCIL_BUFFER_BIT | 125 GL_ACCUM_BUFFER_BIT)) { 126 /* invalid bit set */ 127 _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); 128 return; 129 } 130 131 if (ctx->NewState) { 132 _mesa_update_state( ctx ); /* update _Xmin, etc */ 133 } 134 135 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 136 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 137 "glClear(incomplete framebuffer)"); 138 return; 139 } 140 141 if (ctx->RenderMode == GL_RENDER) { 142 const GLint x = ctx->DrawBuffer->_Xmin; 143 const GLint y = ctx->DrawBuffer->_Ymin; 144 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 145 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 146 GLbitfield bufferMask; 147 148 /* don't clear depth buffer if depth writing disabled */ 149 if (!ctx->Depth.Mask) 150 mask &= ~GL_DEPTH_BUFFER_BIT; 151 152 /* Build the bitmask to send to device driver's Clear function. 153 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 154 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 155 * BUFFER_BIT_COLORn flags. 156 */ 157 bufferMask = 0; 158 if (mask & GL_COLOR_BUFFER_BIT) { 159 bufferMask |= ctx->DrawBuffer->_ColorDrawBufferMask[0]; 160 } 161 162 if ((mask & GL_DEPTH_BUFFER_BIT) 163 && ctx->DrawBuffer->Visual.haveDepthBuffer) { 164 bufferMask |= BUFFER_BIT_DEPTH; 165 } 166 167 if ((mask & GL_STENCIL_BUFFER_BIT) 168 && ctx->DrawBuffer->Visual.haveStencilBuffer) { 169 bufferMask |= BUFFER_BIT_STENCIL; 170 } 171 172 if ((mask & GL_ACCUM_BUFFER_BIT) 173 && ctx->DrawBuffer->Visual.haveAccumBuffer) { 174 bufferMask |= BUFFER_BIT_ACCUM; 175 } 176 177 ASSERT(ctx->Driver.Clear); 178 ctx->Driver.Clear( ctx, bufferMask, (GLboolean) !ctx->Scissor.Enabled, 179 x, y, width, height ); 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 default: 275 /* error */ 276 return BAD_MASK; 277 } 278} 279 280 281/** 282 * Helper routine used by glReadBuffer. 283 * Given a GLenum naming a color buffer, return the index of the corresponding 284 * renderbuffer (a BUFFER_* value). 285 * return -1 for an invalid buffer. 286 */ 287static GLint 288read_buffer_enum_to_index(GLenum buffer) 289{ 290 switch (buffer) { 291 case GL_FRONT: 292 return BUFFER_FRONT_LEFT; 293 case GL_BACK: 294 return BUFFER_BACK_LEFT; 295 case GL_RIGHT: 296 return BUFFER_FRONT_RIGHT; 297 case GL_FRONT_RIGHT: 298 return BUFFER_FRONT_RIGHT; 299 case GL_BACK_RIGHT: 300 return BUFFER_BACK_RIGHT; 301 case GL_BACK_LEFT: 302 return BUFFER_BACK_LEFT; 303 case GL_LEFT: 304 return BUFFER_FRONT_LEFT; 305 case GL_FRONT_LEFT: 306 return BUFFER_FRONT_LEFT; 307 case GL_AUX0: 308 return BUFFER_AUX0; 309 case GL_AUX1: 310 return BUFFER_AUX1; 311 case GL_AUX2: 312 return BUFFER_AUX2; 313 case GL_AUX3: 314 return BUFFER_AUX3; 315 case GL_COLOR_ATTACHMENT0_EXT: 316 return BUFFER_COLOR0; 317 case GL_COLOR_ATTACHMENT1_EXT: 318 return BUFFER_COLOR1; 319 case GL_COLOR_ATTACHMENT2_EXT: 320 return BUFFER_COLOR2; 321 case GL_COLOR_ATTACHMENT3_EXT: 322 return BUFFER_COLOR3; 323 default: 324 /* error */ 325 return -1; 326 } 327} 328 329 330/** 331 * Called by glDrawBuffer(). 332 * Specify which renderbuffer(s) to draw into for the first color output. 333 * <buffer> can name zero, one, two or four renderbuffers! 334 * \sa _mesa_DrawBuffersARB 335 * 336 * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. 337 */ 338void GLAPIENTRY 339_mesa_DrawBuffer(GLenum buffer) 340{ 341 GLuint bufferID; 342 GLbitfield destMask; 343 GET_CURRENT_CONTEXT(ctx); 344 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ 345 346 if (MESA_VERBOSE & VERBOSE_API) { 347 _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 348 } 349 350 bufferID = ctx->DrawBuffer->Name; 351 352 if (buffer == GL_NONE) { 353 destMask = 0x0; 354 } 355 else { 356 const GLbitfield supportedMask = supported_buffer_bitmask(ctx, bufferID); 357 destMask = draw_buffer_enum_to_bitmask(buffer); 358 if (destMask == BAD_MASK) { 359 /* totally bogus buffer */ 360 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer)"); 361 return; 362 } 363 destMask &= supportedMask; 364 if (destMask == 0x0) { 365 /* none of the named color buffers exist! */ 366 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffer(buffer)"); 367 return; 368 } 369 } 370 371 /* if we get here, there's no error so set new state */ 372 _mesa_drawbuffers(ctx, 1, &buffer, &destMask); 373} 374 375 376/** 377 * Called by glDrawBuffersARB; specifies the destination color renderbuffers 378 * for N fragment program color outputs. 379 * \sa _mesa_DrawBuffer 380 * \param n number of outputs 381 * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the 382 * names cannot specify more than one buffer. For example, 383 * GL_FRONT_AND_BACK is illegal. 384 */ 385void GLAPIENTRY 386_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) 387{ 388 GLint output; 389 GLuint bufferID; 390 GLbitfield usedBufferMask, supportedMask; 391 GLbitfield destMask[MAX_DRAW_BUFFERS]; 392 GET_CURRENT_CONTEXT(ctx); 393 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 394 395 if (!ctx->Extensions.ARB_draw_buffers) { 396 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB"); 397 return; 398 } 399 if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { 400 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); 401 return; 402 } 403 404 bufferID = ctx->DrawBuffer->Name; 405 406 supportedMask = supported_buffer_bitmask(ctx, bufferID); 407 usedBufferMask = 0x0; 408 409 /* complicated error checking... */ 410 for (output = 0; output < n; output++) { 411 if (buffers[output] == GL_NONE) { 412 destMask[output] = 0x0; 413 } 414 else { 415 destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 416 if (destMask[output] == BAD_MASK 417 || _mesa_bitcount(destMask[output]) > 1) { 418 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); 419 return; 420 } 421 destMask[output] &= supportedMask; 422 if (destMask[output] == 0) { 423 _mesa_error(ctx, GL_INVALID_OPERATION, 424 "glDrawBuffersARB(unsupported buffer)"); 425 return; 426 } 427 if (destMask[output] & usedBufferMask) { 428 /* can't specify a dest buffer more than once! */ 429 _mesa_error(ctx, GL_INVALID_OPERATION, 430 "glDrawBuffersARB(duplicated buffer)"); 431 return; 432 } 433 434 /* update bitmask */ 435 usedBufferMask |= destMask[output]; 436 } 437 } 438 439 /* OK, if we get here, there were no errors so set the new state */ 440 _mesa_drawbuffers(ctx, n, buffers, destMask); 441} 442 443 444/** 445 * Set color output state. Traditionally, there was only one color 446 * output, but fragment programs can now have several distinct color 447 * outputs (see GL_ARB_draw_buffers). This function sets the state 448 * for one such color output. 449 * \param ctx current context 450 * \param output which fragment program output 451 * \param buffer buffer to write to (like GL_LEFT) 452 * \param destMask BUFFER_* bitmask 453 * (like BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). 454 */ 455static void 456set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, 457 GLbitfield destMask) 458{ 459 struct gl_framebuffer *fb = ctx->DrawBuffer; 460 461 ASSERT(output < ctx->Const.MaxDrawBuffers); 462 463 fb->ColorDrawBuffer[output] = buffer; 464 fb->_ColorDrawBufferMask[output] = destMask; 465 466 if (fb->Name == 0) { 467 /* Set traditional state var */ 468 ctx->Color.DrawBuffer[output] = buffer; 469 } 470 471 /* not really needed, will be set later */ 472 fb->_NumColorDrawBuffers[output] = 0; 473} 474 475 476/** 477 * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and 478 * _mesa_PopAttrib to set drawbuffer state. 479 * All error checking will have been done prior to calling this function 480 * so nothing should go wrong at this point. 481 * \param ctx current context 482 * \param n number of color outputs to set 483 * \param buffers array[n] of colorbuffer names, like GL_LEFT. 484 * \param destMask array[n] of BUFFER_* bitmasks which correspond to the 485 * colorbuffer names. (i.e. GL_FRONT_AND_BACK => 486 * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). 487 */ 488void 489_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, 490 const GLbitfield *destMask) 491{ 492 GLbitfield mask[MAX_DRAW_BUFFERS]; 493 GLuint output; 494 495 if (!destMask) { 496 /* compute destMask values now */ 497 const GLuint bufferID = ctx->DrawBuffer->Name; 498 const GLbitfield supportedMask = supported_buffer_bitmask(ctx, bufferID); 499 for (output = 0; output < n; output++) { 500 mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 501 ASSERT(mask[output] != BAD_MASK); 502 mask[output] &= supportedMask; 503 } 504 destMask = mask; 505 } 506 507 for (output = 0; output < n; output++) { 508 set_color_output(ctx, output, buffers[output], destMask[output]); 509 } 510 511 /* set remaining color outputs to NONE */ 512 for (output = n; output < ctx->Const.MaxDrawBuffers; output++) { 513 set_color_output(ctx, output, GL_NONE, 0x0); 514 } 515 516 ctx->NewState |= _NEW_COLOR; 517 518 /* 519 * Call device driver function. 520 */ 521 if (ctx->Driver.DrawBuffers) 522 ctx->Driver.DrawBuffers(ctx, n, buffers); 523 else if (ctx->Driver.DrawBuffer) 524 ctx->Driver.DrawBuffer(ctx, buffers[0]); 525} 526 527 528 529/** 530 * Called by glReadBuffer to set the source renderbuffer for reading pixels. 531 * \param mode color buffer such as GL_FRONT, GL_BACK, etc. 532 */ 533void GLAPIENTRY 534_mesa_ReadBuffer(GLenum buffer) 535{ 536 struct gl_framebuffer *fb; 537 GLbitfield supportedMask; 538 GLint srcBuffer; 539 GLuint bufferID; 540 GET_CURRENT_CONTEXT(ctx); 541 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 542 543 fb = ctx->ReadBuffer; 544 bufferID = fb->Name; 545 546 if (MESA_VERBOSE & VERBOSE_API) 547 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 548 549 if (bufferID > 0 && buffer == GL_NONE) { 550 /* This is legal for user-created framebuffer objects */ 551 srcBuffer = -1; 552 } 553 else { 554 /* general case / window-system framebuffer */ 555 srcBuffer = read_buffer_enum_to_index(buffer); 556 if (srcBuffer == -1) { 557 _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer); 558 return; 559 } 560 supportedMask = supported_buffer_bitmask(ctx, bufferID); 561 if (((1 << srcBuffer) & supportedMask) == 0) { 562 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer); 563 return; 564 } 565 } 566 567 if (bufferID == 0) { 568 ctx->Pixel.ReadBuffer = buffer; 569 } 570 fb->ColorReadBuffer = buffer; 571 fb->_ColorReadBufferIndex = srcBuffer; 572 573 ctx->NewState |= _NEW_PIXEL; 574 575 /* 576 * Call device driver function. 577 */ 578 if (ctx->Driver.ReadBuffer) 579 (*ctx->Driver.ReadBuffer)(ctx, buffer); 580} 581 582 583#if _HAVE_FULL_GL 584 585/** 586 * GL_MESA_resize_buffers extension. 587 * 588 * When this function is called, we'll ask the window system how large 589 * the current window is. If it's a new size, we'll call the driver's 590 * ResizeBuffers function. The driver will then resize its color buffers 591 * as needed, and maybe call the swrast's routine for reallocating 592 * swrast-managed depth/stencil/accum/etc buffers. 593 * \note This function should only be called through the GL API, not 594 * from device drivers (as was done in the past). 595 */ 596void GLAPIENTRY 597_mesa_ResizeBuffersMESA( void ) 598{ 599 GET_CURRENT_CONTEXT(ctx); 600 601 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 602 603 if (MESA_VERBOSE & VERBOSE_API) 604 _mesa_debug(ctx, "glResizeBuffersMESA\n"); 605 606 if (ctx->WinSysDrawBuffer) { 607 GLuint newWidth, newHeight; 608 GLframebuffer *buffer = ctx->WinSysDrawBuffer; 609 610 assert(buffer->Name == 0); 611 612 /* ask device driver for size of output buffer */ 613 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 614 615 /* see if size of device driver's color buffer (window) has changed */ 616 if (buffer->Width != newWidth || buffer->Height != newHeight) { 617 if (ctx->Driver.ResizeBuffers) 618 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 619 } 620 } 621 622 if (ctx->WinSysReadBuffer 623 && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) { 624 GLuint newWidth, newHeight; 625 GLframebuffer *buffer = ctx->WinSysReadBuffer; 626 627 assert(buffer->Name == 0); 628 629 /* ask device driver for size of read buffer */ 630 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 631 632 /* see if size of device driver's color buffer (window) has changed */ 633 if (buffer->Width != newWidth || buffer->Height != newHeight) { 634 if (ctx->Driver.ResizeBuffers) 635 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 636 } 637 } 638 639 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 640} 641 642 643/* 644 * XXX move somewhere else someday? 645 */ 646void GLAPIENTRY 647_mesa_SampleCoverageARB(GLclampf value, GLboolean invert) 648{ 649 GET_CURRENT_CONTEXT(ctx); 650 651 if (!ctx->Extensions.ARB_multisample) { 652 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB"); 653 return; 654 } 655 656 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 657 ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0); 658 ctx->Multisample.SampleCoverageInvert = invert; 659 ctx->NewState |= _NEW_MULTISAMPLE; 660} 661 662#endif /* _HAVE_FULL_GL */ 663 664 665 666/** 667 * Define the scissor box. 668 * 669 * \param x, y coordinates of the scissor box lower-left corner. 670 * \param width width of the scissor box. 671 * \param height height of the scissor box. 672 * 673 * \sa glScissor(). 674 * 675 * Verifies the parameters and updates __GLcontextRec::Scissor. On a 676 * change flushes the vertices and notifies the driver via 677 * the dd_function_table::Scissor callback. 678 */ 679void 680_mesa_set_scissor(GLcontext *ctx, 681 GLint x, GLint y, GLsizei width, GLsizei height) 682{ 683 if (x == ctx->Scissor.X && 684 y == ctx->Scissor.Y && 685 width == ctx->Scissor.Width && 686 height == ctx->Scissor.Height) 687 return; 688 689 FLUSH_VERTICES(ctx, _NEW_SCISSOR); 690 ctx->Scissor.X = x; 691 ctx->Scissor.Y = y; 692 ctx->Scissor.Width = width; 693 ctx->Scissor.Height = height; 694 695 if (ctx->Driver.Scissor) 696 ctx->Driver.Scissor( ctx, x, y, width, height ); 697} 698 699 700void GLAPIENTRY 701_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height ) 702{ 703 GET_CURRENT_CONTEXT(ctx); 704 ASSERT_OUTSIDE_BEGIN_END(ctx); 705 706 if (width < 0 || height < 0) { 707 _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" ); 708 return; 709 } 710 711 if (MESA_VERBOSE & VERBOSE_API) 712 _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height); 713 714 _mesa_set_scissor(ctx, x, y, width, height); 715} 716 717 718 719/**********************************************************************/ 720/** \name Initialization */ 721/*@{*/ 722 723/** 724 * Initialize the context's scissor state. 725 * \param ctx the GL context. 726 */ 727void 728_mesa_init_scissor(GLcontext *ctx) 729{ 730 /* Scissor group */ 731 ctx->Scissor.Enabled = GL_FALSE; 732 ctx->Scissor.X = 0; 733 ctx->Scissor.Y = 0; 734 ctx->Scissor.Width = 0; 735 ctx->Scissor.Height = 0; 736} 737 738 739/** 740 * Initialize the context's multisample state. 741 * \param ctx the GL context. 742 */ 743void 744_mesa_init_multisample(GLcontext *ctx) 745{ 746 ctx->Multisample.Enabled = GL_FALSE; 747 ctx->Multisample.SampleAlphaToCoverage = GL_FALSE; 748 ctx->Multisample.SampleAlphaToOne = GL_FALSE; 749 ctx->Multisample.SampleCoverage = GL_FALSE; 750 ctx->Multisample.SampleCoverageValue = 1.0; 751 ctx->Multisample.SampleCoverageInvert = GL_FALSE; 752} 753 754/*@}*/ 755