buffers.c revision 2c8524b4fb4aa8e56a6b2646b0a8e21732e7aed4
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-2005 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->RenderMode == GL_RENDER) { 136 const GLint x = ctx->DrawBuffer->_Xmin; 137 const GLint y = ctx->DrawBuffer->_Ymin; 138 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 139 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 140 GLbitfield bufferMask; 141 142 /* don't clear depth buffer if depth writing disabled */ 143 if (!ctx->Depth.Mask) 144 mask &= ~GL_DEPTH_BUFFER_BIT; 145 146 /* Build the bitmask to send to device driver's Clear function. 147 * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 148 * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the 149 * BUFFER_BIT_COLORn flags. 150 */ 151 bufferMask = 0; 152 if (mask & GL_COLOR_BUFFER_BIT) { 153 bufferMask |= ctx->DrawBuffer->_ColorDrawBufferMask[0]; 154 } 155 156 if ((mask & GL_DEPTH_BUFFER_BIT) 157 && ctx->DrawBuffer->Visual.haveDepthBuffer) { 158 bufferMask |= BUFFER_BIT_DEPTH; 159 } 160 161 if ((mask & GL_STENCIL_BUFFER_BIT) 162 && ctx->DrawBuffer->Visual.haveStencilBuffer) { 163 bufferMask |= BUFFER_BIT_STENCIL; 164 } 165 166 if ((mask & GL_ACCUM_BUFFER_BIT) 167 && ctx->DrawBuffer->Visual.haveAccumBuffer) { 168 bufferMask |= BUFFER_BIT_ACCUM; 169 } 170 171 ASSERT(ctx->Driver.Clear); 172 ctx->Driver.Clear( ctx, bufferMask, (GLboolean) !ctx->Scissor.Enabled, 173 x, y, width, height ); 174 } 175} 176 177 178 179/** 180 * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are 181 * available to the rendering context. 182 * This depends on the framebuffer we're writing to. For window system 183 * framebuffers we look at the framebuffer's visual. But for user- 184 * create framebuffers we look at the number of supported color attachments. 185 */ 186static GLuint 187supported_buffer_bitmask(const GLcontext *ctx, GLuint framebufferID) 188{ 189 GLuint mask = 0x0; 190 GLint i; 191 192 if (framebufferID > 0) { 193 /* A user-created renderbuffer */ 194 ASSERT(ctx->Extensions.EXT_framebuffer_object); 195 for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { 196 mask |= (BUFFER_BIT_COLOR0 << i); 197 } 198 } 199 else { 200 /* A window system renderbuffer */ 201 mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ 202 if (ctx->Visual.stereoMode) { 203 mask |= BUFFER_BIT_FRONT_RIGHT; 204 if (ctx->Visual.doubleBufferMode) { 205 mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 206 } 207 } 208 else if (ctx->Visual.doubleBufferMode) { 209 mask |= BUFFER_BIT_BACK_LEFT; 210 } 211 212 for (i = 0; i < ctx->Visual.numAuxBuffers; i++) { 213 mask |= (BUFFER_BIT_AUX0 << i); 214 } 215 } 216 217 return mask; 218} 219 220 221/** 222 * Helper routine used by glDrawBuffer and glDrawBuffersARB. 223 * Given a GLenum naming one or more color buffers (such as 224 * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. 225 */ 226static GLuint 227draw_buffer_enum_to_bitmask(GLenum buffer) 228{ 229 switch (buffer) { 230 case GL_NONE: 231 return 0; 232 case GL_FRONT: 233 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; 234 case GL_BACK: 235 return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 236 case GL_RIGHT: 237 return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 238 case GL_FRONT_RIGHT: 239 return BUFFER_BIT_FRONT_RIGHT; 240 case GL_BACK_RIGHT: 241 return BUFFER_BIT_BACK_RIGHT; 242 case GL_BACK_LEFT: 243 return BUFFER_BIT_BACK_LEFT; 244 case GL_FRONT_AND_BACK: 245 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT 246 | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 247 case GL_LEFT: 248 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; 249 case GL_FRONT_LEFT: 250 return BUFFER_BIT_FRONT_LEFT; 251 case GL_AUX0: 252 return BUFFER_BIT_AUX0; 253 case GL_AUX1: 254 return BUFFER_BIT_AUX1; 255 case GL_AUX2: 256 return BUFFER_BIT_AUX2; 257 case GL_AUX3: 258 return BUFFER_BIT_AUX3; 259 case GL_COLOR_ATTACHMENT0_EXT: 260 return BUFFER_BIT_COLOR0; 261 case GL_COLOR_ATTACHMENT1_EXT: 262 return BUFFER_BIT_COLOR1; 263 case GL_COLOR_ATTACHMENT2_EXT: 264 return BUFFER_BIT_COLOR2; 265 case GL_COLOR_ATTACHMENT3_EXT: 266 return BUFFER_BIT_COLOR3; 267 default: 268 /* error */ 269 return BAD_MASK; 270 } 271} 272 273 274/** 275 * Helper routine used by glReadBuffer. 276 * Given a GLenum naming (a) color buffer(s), return the corresponding 277 * bitmask of DD_* flags. 278 */ 279static GLuint 280read_buffer_enum_to_bitmask(GLenum buffer) 281{ 282 switch (buffer) { 283 case GL_FRONT: 284 return BUFFER_BIT_FRONT_LEFT; 285 case GL_BACK: 286 return BUFFER_BIT_BACK_LEFT; 287 case GL_RIGHT: 288 return BUFFER_BIT_FRONT_RIGHT; 289 case GL_FRONT_RIGHT: 290 return BUFFER_BIT_FRONT_RIGHT; 291 case GL_BACK_RIGHT: 292 return BUFFER_BIT_BACK_RIGHT; 293 case GL_BACK_LEFT: 294 return BUFFER_BIT_BACK_LEFT; 295 case GL_LEFT: 296 return BUFFER_BIT_FRONT_LEFT; 297 case GL_FRONT_LEFT: 298 return BUFFER_BIT_FRONT_LEFT; 299 case GL_AUX0: 300 return BUFFER_BIT_AUX0; 301 case GL_AUX1: 302 return BUFFER_BIT_AUX1; 303 case GL_AUX2: 304 return BUFFER_BIT_AUX2; 305 case GL_AUX3: 306 return BUFFER_BIT_AUX3; 307 case GL_COLOR_ATTACHMENT0_EXT: 308 return BUFFER_BIT_COLOR0; 309 case GL_COLOR_ATTACHMENT1_EXT: 310 return BUFFER_BIT_COLOR1; 311 case GL_COLOR_ATTACHMENT2_EXT: 312 return BUFFER_BIT_COLOR2; 313 case GL_COLOR_ATTACHMENT3_EXT: 314 return BUFFER_BIT_COLOR3; 315 default: 316 /* error */ 317 return BAD_MASK; 318 } 319} 320 321 322/** 323 * Specify which color buffer(s) to draw into for the first color output. 324 * Recall that fragment programs can write to multiple outputs. 325 * \sa _mesa_DrawBuffersARB 326 * 327 * \param buffer color buffer, such as GL_LEFT or GL_FRONT_AND_BACK. 328 */ 329void GLAPIENTRY 330_mesa_DrawBuffer(GLenum buffer) 331{ 332 GLuint bufferID; 333 GLuint destMask; 334 GET_CURRENT_CONTEXT(ctx); 335 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ 336 337 if (MESA_VERBOSE & VERBOSE_API) { 338 _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 339 } 340 341 bufferID = ctx->DrawBuffer->Name; 342 343 if (buffer == GL_NONE) { 344 destMask = 0x0; 345 } 346 else { 347 const GLuint supportedMask = supported_buffer_bitmask(ctx, bufferID); 348 destMask = draw_buffer_enum_to_bitmask(buffer); 349 if (destMask == BAD_MASK) { 350 /* totally bogus buffer */ 351 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer)"); 352 return; 353 } 354 destMask &= supportedMask; 355 if (destMask == 0x0) { 356 /* none of the named color buffers exist! */ 357 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffer(buffer)"); 358 return; 359 } 360 } 361 362 /* if we get here, there's no error so set new state */ 363 _mesa_drawbuffers(ctx, 1, &buffer, &destMask); 364} 365 366 367/** 368 * Called by glDrawBuffersARB; specifies the destination color buffers 369 * for N fragment program color outputs. 370 * \sa _mesa_DrawBuffer 371 */ 372void GLAPIENTRY 373_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) 374{ 375 GLint output; 376 GLuint usedBufferMask, supportedMask; 377 GLuint bufferID; 378 GLuint destMask[MAX_DRAW_BUFFERS]; 379 GET_CURRENT_CONTEXT(ctx); 380 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 381 382 if (!ctx->Extensions.ARB_draw_buffers) { 383 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB"); 384 return; 385 } 386 if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { 387 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); 388 return; 389 } 390 391 bufferID = ctx->DrawBuffer->Name; 392 393 supportedMask = supported_buffer_bitmask(ctx, bufferID); 394 usedBufferMask = 0x0; 395 396 /* complicated error checking... */ 397 for (output = 0; output < n; output++) { 398 if (buffers[output] == GL_NONE) { 399 destMask[output] = 0x0; 400 } 401 else { 402 destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 403 if (destMask[output] == BAD_MASK 404 || _mesa_bitcount(destMask[output]) > 1) { 405 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); 406 return; 407 } 408 destMask[output] &= supportedMask; 409 if (destMask[output] == 0) { 410 _mesa_error(ctx, GL_INVALID_OPERATION, 411 "glDrawBuffersARB(unsupported buffer)"); 412 return; 413 } 414 if (destMask[output] & usedBufferMask) { 415 /* can't specify a dest buffer more than once! */ 416 _mesa_error(ctx, GL_INVALID_OPERATION, 417 "glDrawBuffersARB(duplicated buffer)"); 418 return; 419 } 420 421 /* update bitmask */ 422 usedBufferMask |= destMask[output]; 423 } 424 } 425 426 /* OK, if we get here, there were no errors so set the new state */ 427 _mesa_drawbuffers(ctx, n, buffers, destMask); 428} 429 430 431/** 432 * Set color output state. Traditionally, there was only one color 433 * output, but fragment programs can now have several distinct color 434 * outputs (see GL_ARB_draw_buffers). This function sets the state 435 * for one such color output. 436 */ 437static void 438set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, GLuint destMask) 439{ 440 struct gl_framebuffer *fb = ctx->DrawBuffer; 441 442 ASSERT(output < ctx->Const.MaxDrawBuffers); 443 444 fb->ColorDrawBuffer[output] = buffer; 445 fb->_ColorDrawBufferMask[output] = destMask; 446 447 if (fb->Name == 0) { 448 /* Set traditional state var */ 449 ctx->Color.DrawBuffer[output] = buffer; 450 } 451 452 /* not really needed, will be set later */ 453 fb->_NumColorDrawBuffers[output] = 0; 454} 455 456 457/** 458 * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and 459 * _mesa_PopAttrib to set drawbuffer state. 460 */ 461void 462_mesa_drawbuffers(GLcontext *ctx, GLsizei n, const GLenum *buffers, 463 const GLuint *destMask) 464{ 465 GLuint mask[MAX_DRAW_BUFFERS]; 466 GLint output; 467 468 if (!destMask) { 469 /* compute destMask values now */ 470 const GLuint bufferID = ctx->DrawBuffer->Name; 471 const GLuint supportedMask = supported_buffer_bitmask(ctx, bufferID); 472 for (output = 0; output < n; output++) { 473 mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); 474 ASSERT(mask[output] != BAD_MASK); 475 mask[output] &= supportedMask; 476 } 477 destMask = mask; 478 } 479 480 for (output = 0; output < n; output++) { 481 set_color_output(ctx, output, buffers[output], destMask[output]); 482 } 483 484 /* set remaining color outputs to NONE */ 485 for (output = n; output < ctx->Const.MaxDrawBuffers; output++) { 486 set_color_output(ctx, output, GL_NONE, 0x0); 487 } 488 489 ctx->NewState |= _NEW_COLOR; 490 491 /* 492 * Call device driver function. 493 */ 494 if (ctx->Driver.DrawBuffers) 495 ctx->Driver.DrawBuffers(ctx, n, buffers); 496 else if (ctx->Driver.DrawBuffer) 497 ctx->Driver.DrawBuffer(ctx, buffers[0]); 498} 499 500 501 502/** 503 * Set the color buffer source for reading pixels. 504 * 505 * \param mode color buffer. 506 * 507 * \sa glReadBuffer(). 508 * 509 */ 510void GLAPIENTRY 511_mesa_ReadBuffer(GLenum buffer) 512{ 513 struct gl_framebuffer *fb; 514 GLuint srcMask, supportedMask; 515 GLuint bufferID; 516 GET_CURRENT_CONTEXT(ctx); 517 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 518 519 fb = ctx->ReadBuffer; 520 bufferID = fb->Name; 521 522 if (MESA_VERBOSE & VERBOSE_API) 523 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); 524 525 if (bufferID > 0 && buffer == GL_NONE) { 526 /* legal! */ 527 srcMask = 0x0; 528 } 529 else { 530 /* general case */ 531 srcMask = read_buffer_enum_to_bitmask(buffer); 532 if (srcMask == BAD_MASK) { 533 _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer)"); 534 return; 535 } 536 supportedMask = supported_buffer_bitmask(ctx, bufferID); 537 if ((srcMask & supportedMask) == 0) { 538 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer)"); 539 return; 540 } 541 } 542 543 if (bufferID == 0) { 544 ctx->Pixel.ReadBuffer = buffer; 545 } 546 fb->ColorReadBuffer = buffer; 547 fb->_ColorReadBufferMask = srcMask; 548 549 ctx->NewState |= _NEW_PIXEL; 550 551 /* 552 * Call device driver function. 553 */ 554 if (ctx->Driver.ReadBuffer) 555 (*ctx->Driver.ReadBuffer)(ctx, buffer); 556} 557 558 559#if _HAVE_FULL_GL 560 561/** 562 * GL_MESA_resize_buffers extension. 563 * 564 * When this function is called, we'll ask the window system how large 565 * the current window is. If it's a new size, we'll call the driver's 566 * ResizeBuffers function. The driver will then resize its color buffers 567 * as needed, and maybe call the swrast's routine for reallocating 568 * swrast-managed depth/stencil/accum/etc buffers. 569 * \note This function may be called from within Mesa or called by the 570 * user directly (see the GL_MESA_resize_buffers extension). 571 */ 572void GLAPIENTRY 573_mesa_ResizeBuffersMESA( void ) 574{ 575 GET_CURRENT_CONTEXT(ctx); 576 577 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 578 579 if (MESA_VERBOSE & VERBOSE_API) 580 _mesa_debug(ctx, "glResizeBuffersMESA\n"); 581 582 if (ctx->DrawBuffer && ctx->DrawBuffer->Name == 0) { 583 GLuint newWidth, newHeight; 584 GLframebuffer *buffer = ctx->DrawBuffer; 585 586 /* ask device driver for size of output buffer */ 587 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 588 589 /* see if size of device driver's color buffer (window) has changed */ 590 if (buffer->Width != newWidth || buffer->Height != newHeight) { 591 if (ctx->Driver.ResizeBuffers) 592 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 593 } 594 } 595 596 if (ctx->ReadBuffer && ctx->ReadBuffer != ctx->DrawBuffer 597 && ctx->ReadBuffer->Name == 0) { 598 GLuint newWidth, newHeight; 599 GLframebuffer *buffer = ctx->ReadBuffer; 600 601 /* ask device driver for size of read buffer */ 602 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 603 604 /* see if size of device driver's color buffer (window) has changed */ 605 if (buffer->Width != newWidth || buffer->Height != newHeight) { 606 if (ctx->Driver.ResizeBuffers) 607 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 608 } 609 } 610 611 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 612} 613 614 615/* 616 * XXX move somewhere else someday? 617 */ 618void GLAPIENTRY 619_mesa_SampleCoverageARB(GLclampf value, GLboolean invert) 620{ 621 GET_CURRENT_CONTEXT(ctx); 622 623 if (!ctx->Extensions.ARB_multisample) { 624 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB"); 625 return; 626 } 627 628 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 629 ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0); 630 ctx->Multisample.SampleCoverageInvert = invert; 631 ctx->NewState |= _NEW_MULTISAMPLE; 632} 633 634#endif /* _HAVE_FULL_GL */ 635 636 637 638/** 639 * Define the scissor box. 640 * 641 * \param x, y coordinates of the scissor box lower-left corner. 642 * \param width width of the scissor box. 643 * \param height height of the scissor box. 644 * 645 * \sa glScissor(). 646 * 647 * Verifies the parameters and updates __GLcontextRec::Scissor. On a 648 * change flushes the vertices and notifies the driver via 649 * the dd_function_table::Scissor callback. 650 */ 651void GLAPIENTRY 652_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height ) 653{ 654 GET_CURRENT_CONTEXT(ctx); 655 ASSERT_OUTSIDE_BEGIN_END(ctx); 656 657 if (width < 0 || height < 0) { 658 _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" ); 659 return; 660 } 661 662 if (MESA_VERBOSE & VERBOSE_API) 663 _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height); 664 665 if (x == ctx->Scissor.X && 666 y == ctx->Scissor.Y && 667 width == ctx->Scissor.Width && 668 height == ctx->Scissor.Height) 669 return; 670 671 FLUSH_VERTICES(ctx, _NEW_SCISSOR); 672 ctx->Scissor.X = x; 673 ctx->Scissor.Y = y; 674 ctx->Scissor.Width = width; 675 ctx->Scissor.Height = height; 676 677 if (ctx->Driver.Scissor) 678 ctx->Driver.Scissor( ctx, x, y, width, height ); 679} 680 681 682 683/**********************************************************************/ 684/** \name Initialization */ 685/*@{*/ 686 687/** 688 * Initialize the context's scissor state. 689 * \param ctx the GL context. 690 */ 691void 692_mesa_init_scissor(GLcontext *ctx) 693{ 694 /* Scissor group */ 695 ctx->Scissor.Enabled = GL_FALSE; 696 ctx->Scissor.X = 0; 697 ctx->Scissor.Y = 0; 698 ctx->Scissor.Width = 0; 699 ctx->Scissor.Height = 0; 700} 701 702 703/** 704 * Initialize the context's multisample state. 705 * \param ctx the GL context. 706 */ 707void 708_mesa_init_multisample(GLcontext *ctx) 709{ 710 ctx->Multisample.Enabled = GL_FALSE; 711 ctx->Multisample.SampleAlphaToCoverage = GL_FALSE; 712 ctx->Multisample.SampleAlphaToOne = GL_FALSE; 713 ctx->Multisample.SampleCoverage = GL_FALSE; 714 ctx->Multisample.SampleCoverageValue = 1.0; 715 ctx->Multisample.SampleCoverageInvert = GL_FALSE; 716} 717 718/*@}*/ 719