intel_buffers.c revision 39b4061bb9be540dfb51891e22c505bc235ec8a2
1/************************************************************************** 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * 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 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "intel_screen.h" 29#include "intel_context.h" 30#include "intel_blit.h" 31#include "intel_buffers.h" 32#include "intel_chipset.h" 33#include "intel_depthstencil.h" 34#include "intel_fbo.h" 35#include "intel_regions.h" 36#include "intel_batchbuffer.h" 37#include "intel_reg.h" 38#include "main/context.h" 39#include "main/framebuffer.h" 40#include "swrast/swrast.h" 41#include "utils.h" 42#include "drirenderbuffer.h" 43#include "vblank.h" 44#include "i915_drm.h" 45 46#define FILE_DEBUG_FLAG DEBUG_BLIT 47 48/** 49 * XXX move this into a new dri/common/cliprects.c file. 50 */ 51GLboolean 52intel_intersect_cliprects(drm_clip_rect_t * dst, 53 const drm_clip_rect_t * a, 54 const drm_clip_rect_t * b) 55{ 56 GLint bx = b->x1; 57 GLint by = b->y1; 58 GLint bw = b->x2 - bx; 59 GLint bh = b->y2 - by; 60 61 if (bx < a->x1) 62 bw -= a->x1 - bx, bx = a->x1; 63 if (by < a->y1) 64 bh -= a->y1 - by, by = a->y1; 65 if (bx + bw > a->x2) 66 bw = a->x2 - bx; 67 if (by + bh > a->y2) 68 bh = a->y2 - by; 69 if (bw <= 0) 70 return GL_FALSE; 71 if (bh <= 0) 72 return GL_FALSE; 73 74 dst->x1 = bx; 75 dst->y1 = by; 76 dst->x2 = bx + bw; 77 dst->y2 = by + bh; 78 79 return GL_TRUE; 80} 81 82/** 83 * Return pointer to current color drawing region, or NULL. 84 */ 85struct intel_region * 86intel_drawbuf_region(struct intel_context *intel) 87{ 88 struct intel_renderbuffer *irbColor = 89 intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0]); 90 if (irbColor) 91 return irbColor->region; 92 else 93 return NULL; 94} 95 96/** 97 * Return pointer to current color reading region, or NULL. 98 */ 99struct intel_region * 100intel_readbuf_region(struct intel_context *intel) 101{ 102 struct intel_renderbuffer *irb 103 = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); 104 if (irb) 105 return irb->region; 106 else 107 return NULL; 108} 109 110void 111intel_get_cliprects(struct intel_context *intel, 112 struct drm_clip_rect **cliprects, 113 unsigned int *num_cliprects, 114 int *x_off, int *y_off) 115{ 116 __DRIdrawablePrivate *dPriv = intel->driDrawable; 117 struct intel_framebuffer *intel_fb = dPriv->driverPrivate; 118 119 if (intel->constant_cliprect) { 120 /* FBO or DRI2 rendering, which can just use the fb's size. */ 121 intel->fboRect.x1 = 0; 122 intel->fboRect.y1 = 0; 123 intel->fboRect.x2 = intel->ctx.DrawBuffer->Width; 124 intel->fboRect.y2 = intel->ctx.DrawBuffer->Height; 125 126 *cliprects = &intel->fboRect; 127 *num_cliprects = 1; 128 *x_off = 0; 129 *y_off = 0; 130 } else if (intel->front_cliprects || dPriv->numBackClipRects == 0) { 131 /* use the front clip rects */ 132 *cliprects = dPriv->pClipRects; 133 *num_cliprects = dPriv->numClipRects; 134 *x_off = dPriv->x; 135 *y_off = dPriv->y; 136 } 137 else { 138 /* use the back clip rects */ 139 *num_cliprects = dPriv->numBackClipRects; 140 *cliprects = dPriv->pBackClipRects; 141 *x_off = dPriv->backX; 142 *y_off = dPriv->backY; 143 } 144} 145 146/* 147 * Correct a drawablePrivate's set of vblank flags WRT the current context. 148 * When considering multiple crtcs. 149 */ 150GLuint 151intelFixupVblank(struct intel_context *intel, __DRIdrawablePrivate *dPriv) 152{ 153 154 if (!intel->intelScreen->driScrnPriv->dri2.enabled && 155 intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) { 156 volatile drm_i915_sarea_t *sarea = intel->sarea; 157 drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w, 158 .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h }; 159 drm_clip_rect_t planeA_rect = { .x1 = sarea->planeA_x, .y1 = sarea->planeA_y, 160 .x2 = sarea->planeA_x + sarea->planeA_w, 161 .y2 = sarea->planeA_y + sarea->planeA_h }; 162 drm_clip_rect_t planeB_rect = { .x1 = sarea->planeB_x, .y1 = sarea->planeB_y, 163 .x2 = sarea->planeB_x + sarea->planeB_w, 164 .y2 = sarea->planeB_y + sarea->planeB_h }; 165 GLint areaA = driIntersectArea( drw_rect, planeA_rect ); 166 GLint areaB = driIntersectArea( drw_rect, planeB_rect ); 167 GLuint flags = dPriv->vblFlags; 168 169 /* Update vblank info 170 */ 171 if (areaB > areaA || (areaA == areaB && areaB > 0)) { 172 flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY; 173 } else { 174 flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY; 175 } 176 177 return flags; 178 } else { 179 return dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY; 180 } 181} 182 183/** 184 * This will be called whenever the currently bound window is moved/resized. 185 * XXX: actually, it seems to NOT be called when the window is only moved (BP). 186 */ 187void 188intelWindowMoved(struct intel_context *intel) 189{ 190 GLcontext *ctx = &intel->ctx; 191 __DRIdrawablePrivate *dPriv = intel->driDrawable; 192 struct intel_framebuffer *intel_fb = dPriv->driverPrivate; 193 194 if (!intel->intelScreen->driScrnPriv->dri2.enabled && 195 intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) { 196 GLuint flags = intelFixupVblank(intel, dPriv); 197 198 /* Check to see if we changed pipes */ 199 if (flags != dPriv->vblFlags && dPriv->vblFlags && 200 !(dPriv->vblFlags & VBLANK_FLAG_NO_IRQ)) { 201 int64_t count; 202 drmVBlank vbl; 203 int i; 204 205 /* 206 * Deal with page flipping 207 */ 208 vbl.request.type = DRM_VBLANK_ABSOLUTE; 209 210 if ( dPriv->vblFlags & VBLANK_FLAG_SECONDARY ) { 211 vbl.request.type |= DRM_VBLANK_SECONDARY; 212 } 213 214 for (i = 0; i < 2; i++) { 215 if (!intel_fb->color_rb[i] || 216 (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <= 217 (1<<23)) 218 continue; 219 220 vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending; 221 drmWaitVBlank(intel->driFd, &vbl); 222 } 223 224 /* 225 * Update msc_base from old pipe 226 */ 227 driDrawableGetMSC32(dPriv->driScreenPriv, dPriv, &count); 228 dPriv->msc_base = count; 229 /* 230 * Then get new vblank_base and vblSeq values 231 */ 232 dPriv->vblFlags = flags; 233 driGetCurrentVBlank(dPriv); 234 dPriv->vblank_base = dPriv->vblSeq; 235 236 intel_fb->vbl_waited = dPriv->vblSeq; 237 238 for (i = 0; i < 2; i++) { 239 if (intel_fb->color_rb[i]) 240 intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited; 241 } 242 } 243 } else { 244 dPriv->vblFlags &= ~VBLANK_FLAG_SECONDARY; 245 } 246 247 /* Update Mesa's notion of window size */ 248 driUpdateFramebufferSize(ctx, dPriv); 249 intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */ 250 251 /* Update hardware scissor */ 252 if (ctx->Driver.Scissor != NULL) { 253 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, 254 ctx->Scissor.Width, ctx->Scissor.Height); 255 } 256 257 /* Re-calculate viewport related state */ 258 if (ctx->Driver.DepthRange != NULL) 259 ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far ); 260} 261 262 263 264/* A true meta version of this would be very simple and additionally 265 * machine independent. Maybe we'll get there one day. 266 */ 267static void 268intelClearWithTris(struct intel_context *intel, GLbitfield mask) 269{ 270 GLcontext *ctx = &intel->ctx; 271 struct gl_framebuffer *fb = ctx->DrawBuffer; 272 GLuint buf; 273 274 intel->vtbl.install_meta_state(intel); 275 276 /* Back and stencil cliprects are the same. Try and do both 277 * buffers at once: 278 */ 279 if (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) { 280 struct intel_region *backRegion = 281 intel_get_rb_region(fb, BUFFER_BACK_LEFT); 282 struct intel_region *depthRegion = 283 intel_get_rb_region(fb, BUFFER_DEPTH); 284 285 intel->vtbl.meta_draw_region(intel, backRegion, depthRegion); 286 287 if (mask & BUFFER_BIT_BACK_LEFT) 288 intel->vtbl.meta_color_mask(intel, GL_TRUE); 289 else 290 intel->vtbl.meta_color_mask(intel, GL_FALSE); 291 292 if (mask & BUFFER_BIT_STENCIL) 293 intel->vtbl.meta_stencil_replace(intel, 294 intel->ctx.Stencil.WriteMask[0], 295 intel->ctx.Stencil.Clear); 296 else 297 intel->vtbl.meta_no_stencil_write(intel); 298 299 if (mask & BUFFER_BIT_DEPTH) 300 intel->vtbl.meta_depth_replace(intel); 301 else 302 intel->vtbl.meta_no_depth_write(intel); 303 304 intel->vtbl.meta_draw_quad(intel, 305 fb->_Xmin, 306 fb->_Xmax, 307 fb->_Ymin, 308 fb->_Ymax, 309 intel->ctx.Depth.Clear, 310 intel->ClearColor8888, 311 0, 0, 0, 0); /* texcoords */ 312 313 mask &= ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH); 314 } 315 316 /* clear the remaining (color) renderbuffers */ 317 for (buf = 0; buf < BUFFER_COUNT && mask; buf++) { 318 const GLuint bufBit = 1 << buf; 319 if (mask & bufBit) { 320 struct intel_renderbuffer *irbColor = 321 intel_renderbuffer(fb->Attachment[buf].Renderbuffer); 322 323 ASSERT(irbColor); 324 325 intel->vtbl.meta_no_depth_write(intel); 326 intel->vtbl.meta_no_stencil_write(intel); 327 intel->vtbl.meta_color_mask(intel, GL_TRUE); 328 intel->vtbl.meta_draw_region(intel, irbColor->region, NULL); 329 330 intel->vtbl.meta_draw_quad(intel, 331 fb->_Xmin, 332 fb->_Xmax, 333 fb->_Ymin, 334 fb->_Ymax, 335 0, intel->ClearColor8888, 336 0, 0, 0, 0); /* texcoords */ 337 338 mask &= ~bufBit; 339 } 340 } 341 342 intel->vtbl.leave_meta_state(intel); 343} 344 345static const char *buffer_names[] = { 346 [BUFFER_FRONT_LEFT] = "front", 347 [BUFFER_BACK_LEFT] = "back", 348 [BUFFER_FRONT_RIGHT] = "front right", 349 [BUFFER_BACK_RIGHT] = "back right", 350 [BUFFER_AUX0] = "aux0", 351 [BUFFER_AUX1] = "aux1", 352 [BUFFER_AUX2] = "aux2", 353 [BUFFER_AUX3] = "aux3", 354 [BUFFER_DEPTH] = "depth", 355 [BUFFER_STENCIL] = "stencil", 356 [BUFFER_ACCUM] = "accum", 357 [BUFFER_COLOR0] = "color0", 358 [BUFFER_COLOR1] = "color1", 359 [BUFFER_COLOR2] = "color2", 360 [BUFFER_COLOR3] = "color3", 361 [BUFFER_COLOR4] = "color4", 362 [BUFFER_COLOR5] = "color5", 363 [BUFFER_COLOR6] = "color6", 364 [BUFFER_COLOR7] = "color7", 365}; 366 367/** 368 * Called by ctx->Driver.Clear. 369 */ 370static void 371intelClear(GLcontext *ctx, GLbitfield mask) 372{ 373 struct intel_context *intel = intel_context(ctx); 374 const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask); 375 GLbitfield tri_mask = 0; 376 GLbitfield blit_mask = 0; 377 GLbitfield swrast_mask = 0; 378 struct gl_framebuffer *fb = ctx->DrawBuffer; 379 GLuint i; 380 381 if (0) 382 fprintf(stderr, "%s\n", __FUNCTION__); 383 384 /* HW color buffers (front, back, aux, generic FBO, etc) */ 385 if (colorMask == ~0) { 386 /* clear all R,G,B,A */ 387 /* XXX FBO: need to check if colorbuffers are software RBOs! */ 388 blit_mask |= (mask & BUFFER_BITS_COLOR); 389 } 390 else { 391 /* glColorMask in effect */ 392 tri_mask |= (mask & BUFFER_BITS_COLOR); 393 } 394 395 /* HW stencil */ 396 if (mask & BUFFER_BIT_STENCIL) { 397 const struct intel_region *stencilRegion 398 = intel_get_rb_region(fb, BUFFER_STENCIL); 399 if (stencilRegion) { 400 /* have hw stencil */ 401 if (IS_965(intel->intelScreen->deviceID) || 402 (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { 403 /* We have to use the 3D engine if we're clearing a partial mask 404 * of the stencil buffer, or if we're on a 965 which has a tiled 405 * depth/stencil buffer in a layout we can't blit to. 406 */ 407 tri_mask |= BUFFER_BIT_STENCIL; 408 } 409 else { 410 /* clearing all stencil bits, use blitting */ 411 blit_mask |= BUFFER_BIT_STENCIL; 412 } 413 } 414 } 415 416 /* HW depth */ 417 if (mask & BUFFER_BIT_DEPTH) { 418 /* clear depth with whatever method is used for stencil (see above) */ 419 if (IS_965(intel->intelScreen->deviceID) || 420 tri_mask & BUFFER_BIT_STENCIL) 421 tri_mask |= BUFFER_BIT_DEPTH; 422 else 423 blit_mask |= BUFFER_BIT_DEPTH; 424 } 425 426 /* SW fallback clearing */ 427 swrast_mask = mask & ~tri_mask & ~blit_mask; 428 429 for (i = 0; i < BUFFER_COUNT; i++) { 430 GLuint bufBit = 1 << i; 431 if ((blit_mask | tri_mask) & bufBit) { 432 if (!fb->Attachment[i].Renderbuffer->ClassID) { 433 blit_mask &= ~bufBit; 434 tri_mask &= ~bufBit; 435 swrast_mask |= bufBit; 436 } 437 } 438 } 439 440 if (blit_mask) { 441 if (INTEL_DEBUG & DEBUG_BLIT) { 442 DBG("blit clear:"); 443 for (i = 0; i < BUFFER_COUNT; i++) { 444 if (blit_mask & (1 << i)) 445 DBG(" %s", buffer_names[i]); 446 } 447 DBG("\n"); 448 } 449 intelClearWithBlit(ctx, blit_mask); 450 } 451 452 if (tri_mask) { 453 if (INTEL_DEBUG & DEBUG_BLIT) { 454 DBG("tri clear:"); 455 for (i = 0; i < BUFFER_COUNT; i++) { 456 if (tri_mask & (1 << i)) 457 DBG(" %s", buffer_names[i]); 458 } 459 DBG("\n"); 460 } 461 intelClearWithTris(intel, tri_mask); 462 } 463 464 if (swrast_mask) { 465 if (INTEL_DEBUG & DEBUG_BLIT) { 466 DBG("swrast clear:"); 467 for (i = 0; i < BUFFER_COUNT; i++) { 468 if (swrast_mask & (1 << i)) 469 DBG(" %s", buffer_names[i]); 470 } 471 DBG("\n"); 472 } 473 _swrast_Clear(ctx, swrast_mask); 474 } 475} 476 477void 478intelSwapBuffers(__DRIdrawablePrivate * dPriv) 479{ 480 __DRIscreenPrivate *psp = dPriv->driScreenPriv; 481 482 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { 483 GET_CURRENT_CONTEXT(ctx); 484 struct intel_context *intel; 485 486 if (ctx == NULL) 487 return; 488 489 intel = intel_context(ctx); 490 491 if (ctx->Visual.doubleBufferMode) { 492 GLboolean missed_target; 493 struct intel_framebuffer *intel_fb = dPriv->driverPrivate; 494 int64_t ust; 495 496 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ 497 498 /* 499 * The old swapping ioctl was incredibly racy, just wait for vblank 500 * and do the swap ourselves. 501 */ 502 driWaitForVBlank(dPriv, &missed_target); 503 504 /* 505 * Update each buffer's vbl_pending so we don't get too out of 506 * sync 507 */ 508 intel_get_renderbuffer(&intel_fb->Base, 509 BUFFER_BACK_LEFT)->vbl_pending = dPriv->vblSeq; 510 intel_get_renderbuffer(&intel_fb->Base, 511 BUFFER_FRONT_LEFT)->vbl_pending = dPriv->vblSeq; 512 513 intelCopyBuffer(dPriv, NULL); 514 515 intel_fb->swap_count++; 516 (*psp->systemTime->getUST) (&ust); 517 if (missed_target) { 518 intel_fb->swap_missed_count++; 519 intel_fb->swap_missed_ust = ust - intel_fb->swap_ust; 520 } 521 522 intel_fb->swap_ust = ust; 523 } 524 drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE); 525 526 } 527 else { 528 /* XXX this shouldn't be an error but we can't handle it for now */ 529 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); 530 } 531} 532 533void 534intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) 535{ 536 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { 537 struct intel_context *intel = 538 (struct intel_context *) dPriv->driContextPriv->driverPrivate; 539 GLcontext *ctx = &intel->ctx; 540 541 if (ctx->Visual.doubleBufferMode) { 542 drm_clip_rect_t rect; 543 rect.x1 = x + dPriv->x; 544 rect.y1 = (dPriv->h - y - h) + dPriv->y; 545 rect.x2 = rect.x1 + w; 546 rect.y2 = rect.y1 + h; 547 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ 548 intelCopyBuffer(dPriv, &rect); 549 } 550 } 551 else { 552 /* XXX this shouldn't be an error but we can't handle it for now */ 553 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); 554 } 555} 556 557 558/** 559 * Update the hardware state for drawing into a window or framebuffer object. 560 * 561 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other 562 * places within the driver. 563 * 564 * Basically, this needs to be called any time the current framebuffer 565 * changes, the renderbuffers change, or we need to draw into different 566 * color buffers. 567 */ 568void 569intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) 570{ 571 struct intel_context *intel = intel_context(ctx); 572 struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL; 573 struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; 574 575 if (!fb) { 576 /* this can happen during the initial context initialization */ 577 return; 578 } 579 580 /* Do this here, not core Mesa, since this function is called from 581 * many places within the driver. 582 */ 583 if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { 584 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ 585 _mesa_update_framebuffer(ctx); 586 /* this updates the DrawBuffer's Width/Height if it's a FBO */ 587 _mesa_update_draw_buffer_bounds(ctx); 588 } 589 590 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 591 /* this may occur when we're called by glBindFrameBuffer() during 592 * the process of someone setting up renderbuffers, etc. 593 */ 594 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ 595 return; 596 } 597 598 /* 599 * How many color buffers are we drawing into? 600 */ 601 if (fb->_NumColorDrawBuffers == 0) { 602 /* writing to 0 */ 603 colorRegions[0] = NULL; 604 intel->constant_cliprect = GL_TRUE; 605 } 606 else if (fb->_NumColorDrawBuffers > 1) { 607 int i; 608 struct intel_renderbuffer *irb; 609 610 for (i = 0; i < fb->_NumColorDrawBuffers; i++) { 611 irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]); 612 colorRegions[i] = irb ? irb->region : NULL; 613 } 614 intel->constant_cliprect = GL_TRUE; 615 } 616 else { 617 /* Get the intel_renderbuffer for the single colorbuffer we're drawing 618 * into, and set up cliprects if it's . 619 */ 620 if (fb->Name == 0) { 621 intel->constant_cliprect = intel->driScreen->dri2.enabled; 622 /* drawing to window system buffer */ 623 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { 624 if (!intel->constant_cliprect && !intel->front_cliprects) 625 intel_batchbuffer_flush(intel->batch); 626 intel->front_cliprects = GL_TRUE; 627 colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); 628 } 629 else { 630 if (!intel->constant_cliprect && intel->front_cliprects) 631 intel_batchbuffer_flush(intel->batch); 632 intel->front_cliprects = GL_FALSE; 633 colorRegions[0]= intel_get_rb_region(fb, BUFFER_BACK_LEFT); 634 } 635 } 636 else { 637 /* drawing to user-created FBO */ 638 struct intel_renderbuffer *irb; 639 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); 640 colorRegions[0] = (irb && irb->region) ? irb->region : NULL; 641 intel->constant_cliprect = GL_TRUE; 642 } 643 } 644 645 if (!colorRegions[0]) { 646 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); 647 } 648 else { 649 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); 650 } 651 652 /*** 653 *** Get depth buffer region and check if we need a software fallback. 654 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer. 655 ***/ 656 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) { 657 irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped); 658 if (irbDepth && irbDepth->region) { 659 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); 660 depthRegion = irbDepth->region; 661 } 662 else { 663 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE); 664 depthRegion = NULL; 665 } 666 } 667 else { 668 /* not using depth buffer */ 669 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); 670 depthRegion = NULL; 671 } 672 673 /*** 674 *** Stencil buffer 675 *** This can only be hardware accelerated if we're using a 676 *** combined DEPTH_STENCIL buffer. 677 ***/ 678 if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) { 679 irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped); 680 if (irbStencil && irbStencil->region) { 681 ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); 682 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); 683 } 684 else { 685 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE); 686 } 687 } 688 else { 689 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */ 690 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); 691 } 692 693 /* 694 * Update depth and stencil test state 695 */ 696 if (ctx->Driver.Enable) { 697 ctx->Driver.Enable(ctx, GL_DEPTH_TEST, 698 (ctx->Depth.Test && fb->Visual.depthBits > 0)); 699 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, 700 (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0)); 701 } 702 else { 703 ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL); 704 } 705 706 intel->vtbl.set_draw_region(intel, colorRegions, depthRegion, 707 fb->_NumColorDrawBuffers); 708 709 /* update viewport since it depends on window size */ 710 if (ctx->Driver.Viewport) { 711 ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, 712 ctx->Viewport.Width, ctx->Viewport.Height); 713 } 714 else { 715 ctx->NewState |= _NEW_VIEWPORT; 716 } 717 718 /* Set state we know depends on drawable parameters: 719 */ 720 if (ctx->Driver.Scissor) 721 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, 722 ctx->Scissor.Width, ctx->Scissor.Height); 723 intel->NewGLState |= _NEW_SCISSOR; 724 725 if (ctx->Driver.DepthRange) 726 ctx->Driver.DepthRange(ctx, 727 ctx->Viewport.Near, 728 ctx->Viewport.Far); 729 730 /* Update culling direction which changes depending on the 731 * orientation of the buffer: 732 */ 733 if (ctx->Driver.FrontFace) 734 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); 735 else 736 ctx->NewState |= _NEW_POLYGON; 737} 738 739 740static void 741intelDrawBuffer(GLcontext * ctx, GLenum mode) 742{ 743 intel_draw_buffer(ctx, ctx->DrawBuffer); 744} 745 746 747static void 748intelReadBuffer(GLcontext * ctx, GLenum mode) 749{ 750 if (ctx->ReadBuffer == ctx->DrawBuffer) { 751 /* This will update FBO completeness status. 752 * A framebuffer will be incomplete if the GL_READ_BUFFER setting 753 * refers to a missing renderbuffer. Calling glReadBuffer can set 754 * that straight and can make the drawing buffer complete. 755 */ 756 intel_draw_buffer(ctx, ctx->DrawBuffer); 757 } 758 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc) 759 * reference ctx->ReadBuffer and do appropriate state checks. 760 */ 761} 762 763 764void 765intelInitBufferFuncs(struct dd_function_table *functions) 766{ 767 functions->Clear = intelClear; 768 functions->DrawBuffer = intelDrawBuffer; 769 functions->ReadBuffer = intelReadBuffer; 770} 771