buffers.c revision a1bc0d0f51c2aa248a349283c3b86ae2c72af4aa
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2007 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 (for drawing or reading). 188 * This depends on the type of framebuffer. For window system framebuffers 189 * we look at the framebuffer's visual. But for user-create framebuffers we 190 * look at the number of supported color attachments. 191 * \param fb the framebuffer to draw to, or read from 192 * \return bitmask of BUFFER_BIT_* flags 193 */ 194static GLbitfield 195supported_buffer_bitmask(const GLcontext *ctx, const struct gl_framebuffer *fb) 196{ 197 GLbitfield mask = 0x0; 198 199 if (fb->Name > 0) { 200 /* A user-created renderbuffer */ 201 GLuint i; 202 ASSERT(ctx->Extensions.EXT_framebuffer_object); 203 for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { 204 mask |= (BUFFER_BIT_COLOR0 << i); 205 } 206 } 207 else { 208 /* A window system framebuffer */ 209 GLint i; 210 mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ 211 if (fb->Visual.stereoMode) { 212 mask |= BUFFER_BIT_FRONT_RIGHT; 213 if (fb->Visual.doubleBufferMode) { 214 mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 215 } 216 } 217 else if (fb->Visual.doubleBufferMode) { 218 mask |= BUFFER_BIT_BACK_LEFT; 219 } 220 221 for (i = 0; i < fb->Visual.numAuxBuffers; i++) { 222 mask |= (BUFFER_BIT_AUX0 << i); 223 } 224 } 225 226 return mask; 227} 228 229 230/** 231 * Helper routine used by glDrawBuffer and glDrawBuffersARB. 232 * Given a GLenum naming one or more color buffers (such as 233 * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. 234 */ 235static GLbitfield 236draw_buffer_enum_to_bitmask(GLenum buffer) 237{ 238 switch (buffer) { 239 case GL_NONE: 240 return 0; 241 case GL_FRONT: 242 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; 243 case GL_BACK: 244 return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 245 case GL_RIGHT: 246 return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 247 case GL_FRONT_RIGHT: 248 return BUFFER_BIT_FRONT_RIGHT; 249 case GL_BACK_RIGHT: 250 return BUFFER_BIT_BACK_RIGHT; 251 case GL_BACK_LEFT: 252 return BUFFER_BIT_BACK_LEFT; 253 case GL_FRONT_AND_BACK: 254 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT 255 | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 256 case GL_LEFT: 257 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; 258 case GL_FRONT_LEFT: 259 return BUFFER_BIT_FRONT_LEFT; 260 case GL_AUX0: 261 return BUFFER_BIT_AUX0; 262 case GL_AUX1: 263 return BUFFER_BIT_AUX1; 264 case GL_AUX2: 265 return BUFFER_BIT_AUX2; 266 case GL_AUX3: 267 return BUFFER_BIT_AUX3; 268 case GL_COLOR_ATTACHMENT0_EXT: 269 return BUFFER_BIT_COLOR0; 270 case GL_COLOR_ATTACHMENT1_EXT: 271 return BUFFER_BIT_COLOR1; 272 case GL_COLOR_ATTACHMENT2_EXT: 273 return BUFFER_BIT_COLOR2; 274 case GL_COLOR_ATTACHMENT3_EXT: 275 return BUFFER_BIT_COLOR3; 276 default: 277 /* error */ 278 return BAD_MASK; 279 } 280} 281 282 283/** 284 * Helper routine used by glReadBuffer. 285 * Given a GLenum naming a color buffer, return the index of the corresponding 286 * renderbuffer (a BUFFER_* value). 287 * return -1 for an invalid buffer. 288 */ 289static GLint 290read_buffer_enum_to_index(GLenum buffer) 291{ 292 switch (buffer) { 293 case GL_FRONT: 294 return BUFFER_FRONT_LEFT; 295 case GL_BACK: 296 return BUFFER_BACK_LEFT; 297 case GL_RIGHT: 298 return BUFFER_FRONT_RIGHT; 299 case GL_FRONT_RIGHT: 300 return BUFFER_FRONT_RIGHT; 301 case GL_BACK_RIGHT: 302 return BUFFER_BACK_RIGHT; 303 case GL_BACK_LEFT: 304 return BUFFER_BACK_LEFT; 305 case GL_LEFT: 306 return BUFFER_FRONT_LEFT; 307 case GL_FRONT_LEFT: 308 return BUFFER_FRONT_LEFT; 309 case GL_AUX0: 310 return BUFFER_AUX0; 311 case GL_AUX1: 312 return BUFFER_AUX1; 313 case GL_AUX2: 314 return BUFFER_AUX2; 315 case GL_AUX3: 316 return BUFFER_AUX3; 317 case GL_COLOR_ATTACHMENT0_EXT: 318 return BUFFER_COLOR0; 319 case GL_COLOR_ATTACHMENT1_EXT: 320 return BUFFER_COLOR1; 321 case GL_COLOR_ATTACHMENT2_EXT: 322 return BUFFER_COLOR2; 323 case GL_COLOR_ATTACHMENT3_EXT: 324 return BUFFER_COLOR3; 325 default: 326 /* error */ 327 return -1; 328 } 329} 330 331 332/** 333 * Called by glDrawBuffer(). 334 * Specify which renderbuffer(s) to draw into for the first color output. 335 * <buffer> can name zero, one, two or four renderbuffers! 336 * \sa _mesa_DrawBuffersARB 337 * 338 * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. 339 */ 340void GLAPIENTRY 341_mesa_DrawBuffer(GLenum buffer) 342{ 343 GLbitfield destMask; 344 GET_CURRENT_CONTEXT(ctx); 345 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ 346 347 if (MESA_VERBOSE & VERBOSE_API) { 348 _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 349 } 350 351 if (buffer == GL_NONE) { 352 destMask = 0x0; 353 } 354 else { 355 const GLbitfield supportedMask 356 = supported_buffer_bitmask(ctx, ctx->DrawBuffer); 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 * Call device driver function. 376 */ 377 if (ctx->Driver.DrawBuffers) 378 ctx->Driver.DrawBuffers(ctx, 1, &buffer); 379 else if (ctx->Driver.DrawBuffer) 380 ctx->Driver.DrawBuffer(ctx, buffer); 381} 382 383 384/** 385 * Called by glDrawBuffersARB; specifies the destination color renderbuffers 386 * for N fragment program color outputs. 387 * \sa _mesa_DrawBuffer 388 * \param n number of outputs 389 * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the 390 * names cannot specify more than one buffer. For example, 391 * GL_FRONT_AND_BACK is illegal. 392 */ 393void GLAPIENTRY 394_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) 395{ 396 GLint output; 397 GLbitfield usedBufferMask, supportedMask; 398 GLbitfield destMask[MAX_DRAW_BUFFERS]; 399 GET_CURRENT_CONTEXT(ctx); 400 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 401 402 if (!ctx->Extensions.ARB_draw_buffers) { 403 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB"); 404 return; 405 } 406 if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { 407 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); 408 return; 409 } 410 411 supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); 412 usedBufferMask = 0x0; 413 414 /* complicated error checking... */ 415 for (output = 0; output < n; output++) { 416 if (buffers[output] == GL_NONE) { 417 destMask[output] = 0x0; 418 } 419 else { 420 destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 421 if (destMask[output] == BAD_MASK 422 || _mesa_bitcount(destMask[output]) > 1) { 423 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); 424 return; 425 } 426 destMask[output] &= supportedMask; 427 if (destMask[output] == 0) { 428 _mesa_error(ctx, GL_INVALID_OPERATION, 429 "glDrawBuffersARB(unsupported buffer)"); 430 return; 431 } 432 if (destMask[output] & usedBufferMask) { 433 /* can't specify a dest buffer more than once! */ 434 _mesa_error(ctx, GL_INVALID_OPERATION, 435 "glDrawBuffersARB(duplicated buffer)"); 436 return; 437 } 438 439 /* update bitmask */ 440 usedBufferMask |= destMask[output]; 441 } 442 } 443 444 /* OK, if we get here, there were no errors so set the new state */ 445 _mesa_drawbuffers(ctx, n, buffers, destMask); 446 447 /* 448 * Call device driver function. 449 */ 450 if (ctx->Driver.DrawBuffers) 451 ctx->Driver.DrawBuffers(ctx, n, buffers); 452 else if (ctx->Driver.DrawBuffer) 453 ctx->Driver.DrawBuffer(ctx, buffers[0]); 454} 455 456 457/** 458 * Set color output state. Traditionally, there was only one color 459 * output, but fragment programs can now have several distinct color 460 * outputs (see GL_ARB_draw_buffers). This function sets the state 461 * for one such color output. 462 * \param ctx current context 463 * \param output which fragment program output 464 * \param buffer buffer to write to (like GL_LEFT) 465 * \param destMask BUFFER_* bitmask 466 * (like BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). 467 */ 468static void 469set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, 470 GLbitfield destMask) 471{ 472 struct gl_framebuffer *fb = ctx->DrawBuffer; 473 474 ASSERT(output < ctx->Const.MaxDrawBuffers); 475 476 /* Set per-FBO state */ 477 fb->ColorDrawBuffer[output] = buffer; 478 fb->_ColorDrawBufferMask[output] = destMask; 479 /* not really needed, will be set later */ 480 fb->_NumColorDrawBuffers[output] = 0; 481 482 if (fb->Name == 0) 483 /* Set traditional state var */ 484 ctx->Color.DrawBuffer[output] = buffer; 485} 486 487 488/** 489 * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and 490 * other places (window fbo fixup) to set fbo (and the old ctx) fields. 491 * All error checking will have been done prior to calling this function 492 * so nothing should go wrong at this point. 493 * \param ctx current context 494 * \param n number of color outputs to set 495 * \param buffers array[n] of colorbuffer names, like GL_LEFT. 496 * \param destMask array[n] of BUFFER_* bitmasks which correspond to the 497 * colorbuffer names. (i.e. GL_FRONT_AND_BACK => 498 * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). 499 * \param callDriver call driver or not (bad idea sometimes this is called) 500 */ 501void 502_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, 503 const GLbitfield *destMask) 504{ 505 GLbitfield mask[MAX_DRAW_BUFFERS]; 506 GLuint output; 507 508 if (!destMask) { 509 /* compute destMask values now */ 510 const GLbitfield supportedMask 511 = supported_buffer_bitmask(ctx, ctx->DrawBuffer); 512 for (output = 0; output < n; output++) { 513 mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 514 ASSERT(mask[output] != BAD_MASK); 515 mask[output] &= supportedMask; 516 } 517 destMask = mask; 518 } 519 520 for (output = 0; output < n; output++) { 521 set_color_output(ctx, output, buffers[output], destMask[output]); 522 } 523 524 /* set remaining color outputs to NONE */ 525 for (output = n; output < ctx->Const.MaxDrawBuffers; output++) { 526 set_color_output(ctx, output, GL_NONE, 0x0); 527 } 528 529 ctx->NewState |= _NEW_COLOR; 530} 531 532 533GLboolean 534_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer) 535{ 536 struct gl_framebuffer *fb; 537 GLbitfield supportedMask; 538 GLint srcBuffer; 539 540 fb = ctx->ReadBuffer; 541 542 if (MESA_VERBOSE & VERBOSE_API) 543 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 544 545 if (fb->Name > 0 && buffer == GL_NONE) { 546 /* This is legal for user-created framebuffer objects */ 547 srcBuffer = -1; 548 } 549 else { 550 /* general case / window-system framebuffer */ 551 srcBuffer = read_buffer_enum_to_index(buffer); 552 if (srcBuffer == -1) { 553 _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer); 554 return GL_FALSE; 555 } 556 supportedMask = supported_buffer_bitmask(ctx, fb); 557 if (((1 << srcBuffer) & supportedMask) == 0) { 558 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer); 559 return GL_FALSE; 560 } 561 } 562 563 if (fb->Name == 0) { 564 ctx->Pixel.ReadBuffer = buffer; 565 } 566 fb->ColorReadBuffer = buffer; 567 fb->_ColorReadBufferIndex = srcBuffer; 568 569 return GL_TRUE; 570} 571 572 573 574/** 575 * Called by glReadBuffer to set the source renderbuffer for reading pixels. 576 * \param mode color buffer such as GL_FRONT, GL_BACK, etc. 577 * \param callDriver call driver or not (bad idea sometimes this is called) 578 */ 579void GLAPIENTRY 580_mesa_ReadBuffer(GLenum buffer) 581{ 582 GET_CURRENT_CONTEXT(ctx); 583 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 584 585 if (MESA_VERBOSE & VERBOSE_API) 586 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 587 588 if (!_mesa_readbuffer_update_fields(ctx, buffer)) 589 return; 590 591 ctx->NewState |= _NEW_PIXEL; 592 593 /* 594 * Call device driver function. 595 */ 596 if (ctx->Driver.ReadBuffer) 597 (*ctx->Driver.ReadBuffer)(ctx, buffer); 598} 599 600 601#if _HAVE_FULL_GL 602 603/** 604 * XXX THIS IS OBSOLETE - drivers should take care of detecting window 605 * size changes and act accordingly, likely calling _mesa_resize_framebuffer(). 606 * 607 * GL_MESA_resize_buffers extension. 608 * 609 * When this function is called, we'll ask the window system how large 610 * the current window is. If it's a new size, we'll call the driver's 611 * ResizeBuffers function. The driver will then resize its color buffers 612 * as needed, and maybe call the swrast's routine for reallocating 613 * swrast-managed depth/stencil/accum/etc buffers. 614 * \note This function should only be called through the GL API, not 615 * from device drivers (as was done in the past). 616 */ 617 618void _mesa_resizebuffers( GLcontext *ctx ) 619{ 620 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 621 622 if (MESA_VERBOSE & VERBOSE_API) 623 _mesa_debug(ctx, "glResizeBuffersMESA\n"); 624 625 if (!ctx->Driver.GetBufferSize) { 626 return; 627 } 628 629 if (ctx->WinSysDrawBuffer) { 630 GLuint newWidth, newHeight; 631 GLframebuffer *buffer = ctx->WinSysDrawBuffer; 632 633 assert(buffer->Name == 0); 634 635 /* ask device driver for size of output buffer */ 636 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 637 638 /* see if size of device driver's color buffer (window) has changed */ 639 if (buffer->Width != newWidth || buffer->Height != newHeight) { 640 if (ctx->Driver.ResizeBuffers) 641 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 642 } 643 } 644 645 if (ctx->WinSysReadBuffer 646 && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) { 647 GLuint newWidth, newHeight; 648 GLframebuffer *buffer = ctx->WinSysReadBuffer; 649 650 assert(buffer->Name == 0); 651 652 /* ask device driver for size of read buffer */ 653 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 654 655 /* see if size of device driver's color buffer (window) has changed */ 656 if (buffer->Width != newWidth || buffer->Height != newHeight) { 657 if (ctx->Driver.ResizeBuffers) 658 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 659 } 660 } 661 662 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 663} 664 665 666/* 667 * XXX THIS IS OBSOLETE 668 */ 669void GLAPIENTRY 670_mesa_ResizeBuffersMESA( void ) 671{ 672 GET_CURRENT_CONTEXT(ctx); 673 674 if (ctx->Extensions.MESA_resize_buffers) 675 _mesa_resizebuffers( ctx ); 676} 677 678 679/* 680 * XXX move somewhere else someday? 681 */ 682void GLAPIENTRY 683_mesa_SampleCoverageARB(GLclampf value, GLboolean invert) 684{ 685 GET_CURRENT_CONTEXT(ctx); 686 687 if (!ctx->Extensions.ARB_multisample) { 688 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB"); 689 return; 690 } 691 692 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 693 ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0); 694 ctx->Multisample.SampleCoverageInvert = invert; 695 ctx->NewState |= _NEW_MULTISAMPLE; 696} 697 698#endif /* _HAVE_FULL_GL */ 699 700 701 702/** 703 * Define the scissor box. 704 * 705 * \param x, y coordinates of the scissor box lower-left corner. 706 * \param width width of the scissor box. 707 * \param height height of the scissor box. 708 * 709 * \sa glScissor(). 710 * 711 * Verifies the parameters and updates __GLcontextRec::Scissor. On a 712 * change flushes the vertices and notifies the driver via 713 * the dd_function_table::Scissor callback. 714 */ 715void 716_mesa_set_scissor(GLcontext *ctx, 717 GLint x, GLint y, GLsizei width, GLsizei height) 718{ 719 if (x == ctx->Scissor.X && 720 y == ctx->Scissor.Y && 721 width == ctx->Scissor.Width && 722 height == ctx->Scissor.Height) 723 return; 724 725 FLUSH_VERTICES(ctx, _NEW_SCISSOR); 726 ctx->Scissor.X = x; 727 ctx->Scissor.Y = y; 728 ctx->Scissor.Width = width; 729 ctx->Scissor.Height = height; 730 731 if (ctx->Driver.Scissor) 732 ctx->Driver.Scissor( ctx, x, y, width, height ); 733} 734 735 736void GLAPIENTRY 737_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height ) 738{ 739 GET_CURRENT_CONTEXT(ctx); 740 ASSERT_OUTSIDE_BEGIN_END(ctx); 741 742 if (width < 0 || height < 0) { 743 _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" ); 744 return; 745 } 746 747 if (MESA_VERBOSE & VERBOSE_API) 748 _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height); 749 750 _mesa_set_scissor(ctx, x, y, width, height); 751} 752 753 754 755/**********************************************************************/ 756/** \name Initialization */ 757/*@{*/ 758 759/** 760 * Initialize the context's scissor state. 761 * \param ctx the GL context. 762 */ 763void 764_mesa_init_scissor(GLcontext *ctx) 765{ 766 /* Scissor group */ 767 ctx->Scissor.Enabled = GL_FALSE; 768 ctx->Scissor.X = 0; 769 ctx->Scissor.Y = 0; 770 ctx->Scissor.Width = 0; 771 ctx->Scissor.Height = 0; 772} 773 774 775/** 776 * Initialize the context's multisample state. 777 * \param ctx the GL context. 778 */ 779void 780_mesa_init_multisample(GLcontext *ctx) 781{ 782 ctx->Multisample.Enabled = GL_FALSE; 783 ctx->Multisample.SampleAlphaToCoverage = GL_FALSE; 784 ctx->Multisample.SampleAlphaToOne = GL_FALSE; 785 ctx->Multisample.SampleCoverage = GL_FALSE; 786 ctx->Multisample.SampleCoverageValue = 1.0; 787 ctx->Multisample.SampleCoverageInvert = GL_FALSE; 788} 789 790/*@}*/ 791