From af64dd2ae0aa31261002335f10d46492000f552b Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 2 Feb 2007 17:10:25 +0100 Subject: i915tex: Make page flipping work again. --- src/mesa/drivers/dri/i915tex/intel_blit.c | 40 +++++++++++----------- src/mesa/drivers/dri/i915tex/intel_buffers.c | 50 ++++++++++++++++------------ src/mesa/drivers/dri/i915tex/intel_context.c | 14 +++++++- src/mesa/drivers/dri/i915tex/intel_context.h | 4 +++ src/mesa/drivers/dri/i915tex/intel_fbo.c | 19 +++++++++-- src/mesa/drivers/dri/i915tex/intel_reg.h | 3 ++ src/mesa/drivers/dri/i915tex/intel_tris.c | 10 ++++++ 7 files changed, 94 insertions(+), 46 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c index 550669ab0c..c08c45a936 100644 --- a/src/mesa/drivers/dri/i915tex/intel_blit.c +++ b/src/mesa/drivers/dri/i915tex/intel_blit.c @@ -453,16 +453,6 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch; clear.x2 = clear.x1 + cw; clear.y2 = clear.y1 + ch; - - /* adjust for page flipping */ - if (intel->sarea->pf_current_page == 1) { - const GLuint tmp = mask; - mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); - if (tmp & BUFFER_BIT_FRONT_LEFT) - mask |= BUFFER_BIT_BACK_LEFT; - if (tmp & BUFFER_BIT_BACK_LEFT) - mask |= BUFFER_BIT_FRONT_LEFT; - } } else { /* clearing FBO */ @@ -499,11 +489,10 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) const GLbitfield bufBit = 1 << buf; if ((clearMask & bufBit) && !(bufBit & skipBuffers)) { /* OK, clear this renderbuffer */ - const struct intel_renderbuffer *irb - = intel_renderbuffer(ctx->DrawBuffer-> - Attachment[buf].Renderbuffer); + struct intel_region *irb_region = + intel_get_rb_region(ctx->DrawBuffer, buf); struct _DriBufferObject *write_buffer = - intel_region_buffer(intel->intelScreen, irb->region, + intel_region_buffer(intel->intelScreen, irb_region, all ? INTEL_WRITE_FULL : INTEL_WRITE_PART); @@ -511,16 +500,15 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) GLint pitch, cpp; GLuint BR13, CMD; - ASSERT(irb); - ASSERT(irb->region); + ASSERT(irb_region); - pitch = irb->region->pitch; - cpp = irb->region->cpp; + pitch = irb_region->pitch; + cpp = irb_region->cpp; DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", __FUNCTION__, - irb->region->buffer, (pitch * cpp), - irb->region->draw_offset, + irb_region->buffer, (pitch * cpp), + irb_region->draw_offset, b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1); @@ -558,6 +546,16 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n", buf, irb->Base.Name); */ + if (intel->flip_pending) { + /* Wait for a pending flip to take effect */ + BEGIN_BATCH(2, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); + OUT_BATCH(0); + ADVANCE_BATCH(); + + intel->flip_pending = GL_FALSE; + } + BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH(CMD); OUT_BATCH(BR13); @@ -565,7 +563,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) OUT_BATCH((b.y2 << 16) | b.x2); OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - irb->region->draw_offset); + irb_region->draw_offset); OUT_BATCH(clearVal); ADVANCE_BATCH(); clearMask &= ~bufBit; /* turn off bit, for faster loop exit */ diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 1ded0b5417..a8fb0b14a1 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -159,7 +159,7 @@ intelSetBackClipRects(struct intel_context *intel) if (!dPriv) return; - if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { + if (intel->sarea->pf_active || dPriv->numBackClipRects == 0) { /* use the front clip rects */ intel->numClipRects = dPriv->numClipRects; intel->pClipRects = dPriv->pClipRects; @@ -421,7 +421,8 @@ intelRotateWindow(struct intel_context *intel, intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL); /* ? */ - if (srcBuf == BUFFER_BIT_FRONT_LEFT) { + if ((srcBuf == BUFFER_BIT_BACK_LEFT && intel->sarea->pf_current_page) || + (srcBuf == BUFFER_BIT_FRONT_LEFT && !intel->sarea->pf_current_page)) { src = intel->intelScreen->front_region; clipRects = dPriv->pClipRects; numClipRects = dPriv->numClipRects; @@ -592,9 +593,9 @@ intelClear(GLcontext *ctx, GLbitfield mask) static void intelPageFlip(const __DRIdrawablePrivate * dPriv) { -#if 0 struct intel_context *intel; - int tmp, ret; + GLboolean missed_target; + int ret; if (INTEL_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s\n", __FUNCTION__); @@ -606,27 +607,36 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv) intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; intelFlush(&intel->ctx); - LOCK_HARDWARE(intel); - if (dPriv->pClipRects) { - *(drm_clip_rect_t *) intel->sarea->boxes = dPriv->pClipRects[0]; - intel->sarea->nbox = 1; + driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags, &missed_target); + + if (missed_target) { + intel->swap_missed_count++; + (void)(*dri_interface->getUST) (&intel->swap_missed_ust); } - ret = drmCommandNone(intel->driFd, DRM_I830_FLIP); - if (ret) { - fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); + LOCK_HARDWARE(intel); + + if (!dPriv->numClipRects) { UNLOCK_HARDWARE(intel); - exit(1); + usleep(10000); /* throttle invisible client 10ms */ + return; } - tmp = intel->sarea->last_enqueue; - intelRefillBatchLocked(intel); + ret = drmCommandNone(intel->driFd, DRM_I830_FLIP); UNLOCK_HARDWARE(intel); + if (ret) { + _mesa_error(&intel->ctx, GL_INVALID_OPERATION, "DRM_I830_FLIP: %d\n", + ret); + return; + } - intelSetDrawBuffer(&intel->ctx, intel->ctx.Color.DriverDrawBuffer); -#endif + driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, + intel->sarea->pf_current_page); + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + + intel->flip_pending = GL_TRUE; } #if 0 @@ -641,7 +651,7 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv) if (ctx && ctx->DrawBuffer == fb) { _mesa_notifySwapBuffers(ctx); /* flush pending rendering */ } - if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */ + if (intel->doPageFlip) { intelPageFlip(dPriv); } else { @@ -672,7 +682,7 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv) if (ctx->Visual.doubleBufferMode) { intelScreenPrivate *screen = intel->intelScreen; _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ - if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */ + if (screen->current_rotation == 0 && intel->doPageFlip) { intelPageFlip(dPriv); } else { @@ -788,10 +798,6 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) */ if (fb->Name == 0) { /* drawing to window system buffer */ - if (intel->sarea->pf_current_page == 1) { - /* page flipped back/front */ - front ^= 1; - } if (front) { intelSetFrontClipRects(intel); colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index a5ce08b170..7eb209cf5f 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -59,6 +59,7 @@ #include "intel_buffer_objects.h" #include "intel_fbo.h" +#include "drirenderbuffer.h" #include "vblank.h" #include "utils.h" #include "xmlpool.h" /* for symbolic values of enum-type options */ @@ -683,13 +684,24 @@ intelContendedLock(struct intel_context *intel, GLuint flags) intel->current_rotation = sarea->rotation; } - /* Drawable changed? */ if (dPriv && intel->lastStamp != dPriv->lastStamp) { intelWindowMoved(intel); intel->lastStamp = dPriv->lastStamp; } + + /* Update page flipping info + */ + if (INTEL_DEBUG & DEBUG_LOCK) + if (intel->doPageFlip != intel->sarea->pf_active) + _mesa_printf("%s - age flipping %sactive\n", __progname, + intel->sarea->pf_active ? "" : "in"); + + intel->doPageFlip = intel->sarea->pf_active; + driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, + intel->sarea->pf_current_page); + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); } diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index 96b911501f..321a945c05 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -295,6 +295,10 @@ struct intel_context int height; int current_rotation; + /* Page flipping + */ + GLboolean doPageFlip; + GLboolean flip_pending; }; /* These are functions now: diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c index ab0e569bd9..b739e22cca 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.c +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.c @@ -78,8 +78,23 @@ intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) struct intel_region * intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) { - struct intel_renderbuffer *irb - = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); + GET_CURRENT_CONTEXT(ctx); + struct intel_context *intel = intel_context(ctx); + struct intel_renderbuffer *irb; + + if (intel->sarea->pf_current_page) { + switch (attIndex) { + case BUFFER_BACK_LEFT: + attIndex = BUFFER_FRONT_LEFT; + break; + case BUFFER_FRONT_LEFT: + attIndex = BUFFER_BACK_LEFT; + break; + } + } + + irb = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); + if (irb) return irb->region; else diff --git a/src/mesa/drivers/dri/i915tex/intel_reg.h b/src/mesa/drivers/dri/i915tex/intel_reg.h index 1ec153266c..126d2ea7ff 100644 --- a/src/mesa/drivers/dri/i915tex/intel_reg.h +++ b/src/mesa/drivers/dri/i915tex/intel_reg.h @@ -81,4 +81,7 @@ #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define MI_WAIT_FOR_EVENT ((0x3<<23)) +#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) + #endif diff --git a/src/mesa/drivers/dri/i915tex/intel_tris.c b/src/mesa/drivers/dri/i915tex/intel_tris.c index 1ba49d8f6e..4e0ca70c1e 100644 --- a/src/mesa/drivers/dri/i915tex/intel_tris.c +++ b/src/mesa/drivers/dri/i915tex/intel_tris.c @@ -102,6 +102,16 @@ intelStartInlinePrimitive(struct intel_context *intel, /* _mesa_printf("%s *", __progname); */ + if (intel->flip_pending) { + /* Wait for a pending flip to take effect */ + BEGIN_BATCH(2, batch_flags); + OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); + OUT_BATCH(0); + ADVANCE_BATCH(); + + intel->flip_pending = GL_FALSE; + } + /* Emit a slot which will be filled with the inline primitive * command later. */ -- cgit v1.2.3 From 6b99cafd69a791d03ce749d0fd2b9f59ca265677 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 15 Feb 2007 16:30:40 +0100 Subject: i915tex: Support page flipping on both CRTCs independently. No longer track page flipping state per context but per window, via struct intel_framebuffer which wraps struct gl_framebuffer for windows. --- src/mesa/drivers/dri/i915tex/intel_blit.c | 45 ++++---- src/mesa/drivers/dri/i915tex/intel_buffers.c | 156 +++++++++++++++++++++------ src/mesa/drivers/dri/i915tex/intel_buffers.h | 3 + src/mesa/drivers/dri/i915tex/intel_context.c | 13 +-- src/mesa/drivers/dri/i915tex/intel_context.h | 5 - src/mesa/drivers/dri/i915tex/intel_fbo.c | 36 ++++--- src/mesa/drivers/dri/i915tex/intel_fbo.h | 14 +++ src/mesa/drivers/dri/i915tex/intel_reg.h | 1 + src/mesa/drivers/dri/i915tex/intel_screen.c | 37 ++++--- src/mesa/drivers/dri/i915tex/intel_tris.c | 10 +- 10 files changed, 203 insertions(+), 117 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c index c08c45a936..e33d283076 100644 --- a/src/mesa/drivers/dri/i915tex/intel_blit.c +++ b/src/mesa/drivers/dri/i915tex/intel_blit.c @@ -123,14 +123,13 @@ noschedule: */ LOCK_HARDWARE(intel); - if (intel->driDrawable && intel->driDrawable->numClipRects) { + if (dPriv && dPriv->numClipRects) { const intelScreenPrivate *intelScreen = intel->intelScreen; - struct gl_framebuffer *fb - = (struct gl_framebuffer *) dPriv->driverPrivate; + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; const struct intel_region *frontRegion - = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); + = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); const struct intel_region *backRegion - = intel_get_rb_region(fb, BUFFER_BACK_LEFT); + = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); const int nbox = dPriv->numClipRects; const drm_clip_rect_t *pbox = dPriv->pClipRects; const int pitch = frontRegion->pitch; @@ -138,8 +137,8 @@ noschedule: int BR13, CMD; int i; - ASSERT(fb); - ASSERT(fb->Name == 0); /* Not a user-created FBO */ + ASSERT(intel_fb); + ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ ASSERT(frontRegion); ASSERT(backRegion); ASSERT(frontRegion->pitch == backRegion->pitch); @@ -185,7 +184,7 @@ noschedule: OUT_BATCH((pbox->y1 << 16) | pbox->x1); OUT_BATCH((pbox->y2 << 16) | pbox->x2); - if (intel->sarea->pf_current_page == 0) + if (intel_fb->pf_current_page == 0) OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); @@ -196,7 +195,7 @@ noschedule: OUT_BATCH((pbox->y1 << 16) | pbox->x1); OUT_BATCH(BR13 & 0xffff); - if (intel->sarea->pf_current_page == 0) + if (intel_fb->pf_current_page == 0) OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); @@ -406,6 +405,7 @@ void intelClearWithBlit(GLcontext * ctx, GLbitfield mask) { struct intel_context *intel = intel_context(ctx); + struct gl_framebuffer *fb = ctx->DrawBuffer; GLuint clear_depth; GLbitfield skipBuffers = 0; BATCH_LOCALS; @@ -417,7 +417,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) */ clear_depth = 0; if (mask & BUFFER_BIT_DEPTH) { - clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear); + clear_depth = (GLuint) (fb->_DepthMax * ctx->Depth.Clear); } if (mask & BUFFER_BIT_STENCIL) { clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; @@ -440,12 +440,12 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) int i; /* Get clear bounds after locking */ - cx = ctx->DrawBuffer->_Xmin; - cy = ctx->DrawBuffer->_Ymin; - cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + cx = fb->_Xmin; + cy = fb->_Ymin; + cw = fb->_Xmax - cx; + ch = fb->_Ymax - cy; - if (intel->ctx.DrawBuffer->Name == 0) { + if (fb->Name == 0) { /* clearing a window */ /* flip top to bottom */ @@ -470,8 +470,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) drm_clip_rect_t b; GLuint buf; GLuint clearMask = mask; /* use copy, since we modify it below */ - GLboolean all = (cw == ctx->DrawBuffer->Width && - ch == ctx->DrawBuffer->Height); + GLboolean all = (cw == fb->Width && ch == fb->Height); if (!all) { intel_intersect_cliprects(&b, &clear, box); @@ -490,7 +489,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) if ((clearMask & bufBit) && !(bufBit & skipBuffers)) { /* OK, clear this renderbuffer */ struct intel_region *irb_region = - intel_get_rb_region(ctx->DrawBuffer, buf); + intel_get_rb_region(fb, buf); struct _DriBufferObject *write_buffer = intel_region_buffer(intel->intelScreen, irb_region, all ? INTEL_WRITE_FULL : @@ -546,15 +545,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n", buf, irb->Base.Name); */ - if (intel->flip_pending) { - /* Wait for a pending flip to take effect */ - BEGIN_BATCH(2, INTEL_BATCH_NO_CLIPRECTS); - OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); - OUT_BATCH(0); - ADVANCE_BATCH(); - - intel->flip_pending = GL_FALSE; - } + intel_wait_flips(intel, INTEL_BATCH_NO_CLIPRECTS); BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH(CMD); diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index a8fb0b14a1..fdb6ea9444 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -34,6 +34,7 @@ #include "intel_tris.h" #include "intel_regions.h" #include "intel_batchbuffer.h" +#include "intel_reg.h" #include "context.h" #include "utils.h" #include "drirenderbuffer.h" @@ -155,11 +156,14 @@ static void intelSetBackClipRects(struct intel_context *intel) { __DRIdrawablePrivate *dPriv = intel->driDrawable; + struct intel_framebuffer *intel_fb; if (!dPriv) return; - if (intel->sarea->pf_active || dPriv->numBackClipRects == 0) { + intel_fb = dPriv->driverPrivate; + + if (intel_fb->pf_active || dPriv->numBackClipRects == 0) { /* use the front clip rects */ intel->numClipRects = dPriv->numClipRects; intel->pClipRects = dPriv->pClipRects; @@ -185,7 +189,7 @@ intelWindowMoved(struct intel_context *intel) { GLcontext *ctx = &intel->ctx; __DRIdrawablePrivate *dPriv = intel->driDrawable; - GLframebuffer *drawFb = (GLframebuffer *) dPriv->driverPrivate; + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; if (!intel->ctx.DrawBuffer) { /* when would this happen? -BP */ @@ -197,7 +201,7 @@ intelWindowMoved(struct intel_context *intel) } else { /* drawing to a window */ - switch (drawFb->_ColorDrawBufferMask[0]) { + switch (intel_fb->Base._ColorDrawBufferMask[0]) { case BUFFER_BIT_FRONT_LEFT: intelSetFrontClipRects(intel); break; @@ -212,7 +216,7 @@ intelWindowMoved(struct intel_context *intel) /* Update Mesa's notion of window size */ driUpdateFramebufferSize(ctx, dPriv); - drawFb->Initialized = GL_TRUE; /* XXX remove someday */ + intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */ if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) { drmI830Sarea *sarea = intel->sarea; @@ -227,7 +231,50 @@ intelWindowMoved(struct intel_context *intel) GLint areaA = driIntersectArea( drw_rect, pipeA_rect ); GLint areaB = driIntersectArea( drw_rect, pipeB_rect ); GLuint flags = intel->vblank_flags; + GLboolean pf_active; + GLint pf_pipes; + + /* Update page flipping info + */ + pf_pipes = 0; + + if (areaA > 0) + pf_pipes |= 1; + + if (areaB > 0) + pf_pipes |= 2; + + intel_fb->pf_current_page = (intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3; + + pf_active = (pf_pipes & intel->sarea->pf_active) == pf_pipes; + + if (1 /*INTEL_DEBUG & DEBUG_LOCK*/) + if (pf_active != intel_fb->pf_active) + _mesa_printf("%s - Page flipping %sactive\n", __progname, + pf_active ? "" : "in"); + + if (pf_active) { + if (pf_pipes != intel_fb->pf_pipes && intel_fb->pf_pipes == 0x3 && + (intel->sarea->pf_current_page & 0x3) != + ((intel->sarea->pf_current_page) >> 2 & 0x3)) { + drm_i915_flip_t flip; + + flip.pipes = (intel_fb->pf_current_page == + (intel->sarea->pf_current_page & 0x3)) ? 0x2 : 0x1; + + drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); + } + + intel_fb->pf_pipes = pf_pipes; + } + + intel_fb->pf_active = pf_active; + driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, intel_fb->pf_current_page); + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + /* Update vblank info + */ if (areaB > areaA || (areaA == areaB && areaB > 0)) { flags = intel->vblank_flags | VBLANK_FLAG_SECONDARY; } else { @@ -259,6 +306,7 @@ static void intelClearWithTris(struct intel_context *intel, GLbitfield mask) { GLcontext *ctx = &intel->ctx; + struct gl_framebuffer *fb = ctx->DrawBuffer; drm_clip_rect_t clear; if (INTEL_DEBUG & DEBUG_BLIT) @@ -274,10 +322,10 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask) intel->vtbl.install_meta_state(intel); /* Get clear bounds after locking */ - cx = ctx->DrawBuffer->_Xmin; - cy = ctx->DrawBuffer->_Ymin; - ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; - cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + cx = fb->_Xmin; + cy = fb->_Ymin; + ch = fb->_Ymax - cx; + cw = fb->_Xmax - cy; /* note: regardless of 'all', cx, cy, cw, ch are now correct */ clear.x1 = cx; @@ -291,9 +339,9 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask) if (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) { struct intel_region *backRegion = - intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT); + intel_get_rb_region(fb, BUFFER_BACK_LEFT); struct intel_region *depthRegion = - intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH); + intel_get_rb_region(fb, BUFFER_DEPTH); const GLuint clearColor = (backRegion && backRegion->cpp == 4) ? intel->ClearColor8888 : intel->ClearColor565; @@ -330,8 +378,7 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask) const GLuint bufBit = 1 << buf; if (mask & bufBit) { struct intel_renderbuffer *irbColor = - intel_renderbuffer(ctx->DrawBuffer-> - Attachment[buf].Renderbuffer); + intel_renderbuffer(fb->Attachment[buf].Renderbuffer); GLuint color = (irbColor->region->cpp == 4) ? intel->ClearColor8888 : intel->ClearColor565; @@ -372,6 +419,7 @@ intelRotateWindow(struct intel_context *intel, { intelScreenPrivate *screen = intel->intelScreen; drm_clip_rect_t fullRect; + struct intel_framebuffer *intel_fb; struct intel_region *src; const drm_clip_rect_t *clipRects; int numClipRects; @@ -421,8 +469,10 @@ intelRotateWindow(struct intel_context *intel, intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL); /* ? */ - if ((srcBuf == BUFFER_BIT_BACK_LEFT && intel->sarea->pf_current_page) || - (srcBuf == BUFFER_BIT_FRONT_LEFT && !intel->sarea->pf_current_page)) { + intel_fb = dPriv->driverPrivate; + + if ((srcBuf == BUFFER_BIT_BACK_LEFT && intel_fb->pf_current_page) || + (srcBuf == BUFFER_BIT_FRONT_LEFT && !intel_fb->pf_current_page)) { src = intel->intelScreen->front_region; clipRects = dPriv->pClipRects; numClipRects = dPriv->numClipRects; @@ -517,6 +567,7 @@ intelClear(GLcontext *ctx, GLbitfield mask) GLbitfield tri_mask = 0; GLbitfield blit_mask = 0; GLbitfield swrast_mask = 0; + struct gl_framebuffer *fb = ctx->DrawBuffer; GLuint i; if (0) @@ -536,7 +587,7 @@ intelClear(GLcontext *ctx, GLbitfield mask) /* HW stencil */ if (mask & BUFFER_BIT_STENCIL) { const struct intel_region *stencilRegion - = intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL); + = intel_get_rb_region(fb, BUFFER_STENCIL); if (stencilRegion) { /* have hw stencil */ if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { @@ -565,7 +616,7 @@ intelClear(GLcontext *ctx, GLbitfield mask) for (i = 0; i < BUFFER_COUNT; i++) { GLuint bufBit = 1 << i; if ((blit_mask | tri_mask) & bufBit) { - if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) { + if (!fb->Attachment[i].Renderbuffer->ClassID) { blit_mask &= ~bufBit; tri_mask &= ~bufBit; swrast_mask |= bufBit; @@ -587,15 +638,44 @@ intelClear(GLcontext *ctx, GLbitfield mask) } +/* Emit wait for pending flips */ +void +intel_wait_flips(struct intel_context *intel, GLuint batch_flags) +{ + struct intel_framebuffer *intel_fb = + (struct intel_framebuffer *) intel->ctx.DrawBuffer; + + if (intel_fb->Base.Name == 0 && intel_fb->flip_pending) { + GLuint mi_wait = MI_WAIT_FOR_EVENT; + GLint pf_pipes = intel_fb->pf_pipes; + BATCH_LOCALS; + + if (pf_pipes & 0x1) + mi_wait |= MI_WAIT_FOR_PLANE_A_FLIP; + + if (pf_pipes & 0x2) + mi_wait |= MI_WAIT_FOR_PLANE_B_FLIP; + + /* Wait for pending flips to take effect */ + BEGIN_BATCH(2, batch_flags); + OUT_BATCH(mi_wait); + OUT_BATCH(0); + ADVANCE_BATCH(); + + intel_fb->flip_pending = GL_FALSE; + } +} + /* Flip the front & back buffers */ -static void +static GLboolean intelPageFlip(const __DRIdrawablePrivate * dPriv) { struct intel_context *intel; GLboolean missed_target; int ret; + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; if (INTEL_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s\n", __FUNCTION__); @@ -606,6 +686,9 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv) intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; + if (intel->intelScreen->drmMinor < 9) + return GL_FALSE; + intelFlush(&intel->ctx); driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags, &missed_target); @@ -615,28 +698,36 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv) (void)(*dri_interface->getUST) (&intel->swap_missed_ust); } + ret = 0; + LOCK_HARDWARE(intel); - if (!dPriv->numClipRects) { - UNLOCK_HARDWARE(intel); - usleep(10000); /* throttle invisible client 10ms */ - return; + if (dPriv->numClipRects && intel_fb->pf_active) { + drm_i915_flip_t flip; + + flip.pipes = intel_fb->pf_pipes; + + ret = drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); } - ret = drmCommandNone(intel->driFd, DRM_I830_FLIP); UNLOCK_HARDWARE(intel); - if (ret) { - _mesa_error(&intel->ctx, GL_INVALID_OPERATION, "DRM_I830_FLIP: %d\n", - ret); - return; + if (ret || !intel_fb->pf_active) + return GL_FALSE; + + if (!dPriv->numClipRects) { + usleep(10000); /* throttle invisible client 10ms */ } - driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, - intel->sarea->pf_current_page); - intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + intel_fb->pf_current_page = (intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3; + + driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, intel_fb->pf_current_page); + intel_draw_buffer(&intel->ctx, &intel_fb->Base); - intel->flip_pending = GL_TRUE; + intel_fb->flip_pending = dPriv->numClipRects != 0; + + return GL_TRUE; } #if 0 @@ -682,10 +773,7 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv) if (ctx->Visual.doubleBufferMode) { intelScreenPrivate *screen = intel->intelScreen; _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ - if (screen->current_rotation == 0 && intel->doPageFlip) { - intelPageFlip(dPriv); - } - else { + if (screen->current_rotation != 0 || !intelPageFlip(dPriv)) { intelCopyBuffer(dPriv, NULL); } if (screen->current_rotation != 0) { diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.h b/src/mesa/drivers/dri/i915tex/intel_buffers.h index 0faf055347..3b686cb5c1 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.h +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.h @@ -30,6 +30,7 @@ struct intel_context; +struct intel_framebuffer; extern GLboolean @@ -41,6 +42,8 @@ extern struct intel_region *intel_readbuf_region(struct intel_context *intel); extern struct intel_region *intel_drawbuf_region(struct intel_context *intel); +extern void intel_wait_flips(struct intel_context *intel, GLuint batch_flags); + extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); extern void intelWindowMoved(struct intel_context *intel); diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index 7eb209cf5f..8d90489b4e 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -690,21 +690,10 @@ intelContendedLock(struct intel_context *intel, GLuint flags) intelWindowMoved(intel); intel->lastStamp = dPriv->lastStamp; } - - /* Update page flipping info - */ - if (INTEL_DEBUG & DEBUG_LOCK) - if (intel->doPageFlip != intel->sarea->pf_active) - _mesa_printf("%s - age flipping %sactive\n", __progname, - intel->sarea->pf_active ? "" : "in"); - - intel->doPageFlip = intel->sarea->pf_active; - driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, - intel->sarea->pf_current_page); - intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); } + /* Lock the hardware and validate our state. */ void LOCK_HARDWARE( struct intel_context *intel ) diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index 321a945c05..8f78597ba0 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -294,11 +294,6 @@ struct intel_context int width; int height; int current_rotation; - - /* Page flipping - */ - GLboolean doPageFlip; - GLboolean flip_pending; }; /* These are functions now: diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c index b739e22cca..104cf1d9bb 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.c +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.c @@ -71,6 +71,21 @@ intel_renderbuffer(struct gl_renderbuffer *rb) struct intel_renderbuffer * intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) { + if (fb->Name == 0) { + struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb; + + if (intel_fb->pf_current_page) { + switch (attIndex) { + case BUFFER_BACK_LEFT: + attIndex = BUFFER_FRONT_LEFT; + break; + case BUFFER_FRONT_LEFT: + attIndex = BUFFER_BACK_LEFT; + break; + } + } + } + return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); } @@ -78,22 +93,7 @@ intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) struct intel_region * intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) { - GET_CURRENT_CONTEXT(ctx); - struct intel_context *intel = intel_context(ctx); - struct intel_renderbuffer *irb; - - if (intel->sarea->pf_current_page) { - switch (attIndex) { - case BUFFER_BACK_LEFT: - attIndex = BUFFER_FRONT_LEFT; - break; - case BUFFER_FRONT_LEFT: - attIndex = BUFFER_BACK_LEFT; - break; - } - } - - irb = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); + struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); if (irb) return irb->region; @@ -109,7 +109,9 @@ intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) static struct gl_framebuffer * intel_new_framebuffer(GLcontext * ctx, GLuint name) { - /* there's no intel_framebuffer at this time, just use Mesa's class */ + /* Only drawable state in intel_framebuffer at this time, just use Mesa's + * class + */ return _mesa_new_framebuffer(ctx, name); } diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.h b/src/mesa/drivers/dri/i915tex/intel_fbo.h index 221f09b39a..d55f02967f 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.h +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.h @@ -32,6 +32,20 @@ struct intel_context; struct intel_region; +/** + * Intel framebuffer, derived from gl_framebuffer. + */ +struct intel_framebuffer +{ + struct gl_framebuffer Base; + + /* Drawable page flipping state */ + GLboolean pf_active; + GLboolean flip_pending; + GLint pf_pipes; + GLint pf_current_page; +}; + /** * Intel renderbuffer, derived from gl_renderbuffer. diff --git a/src/mesa/drivers/dri/i915tex/intel_reg.h b/src/mesa/drivers/dri/i915tex/intel_reg.h index 126d2ea7ff..7828ba6ad3 100644 --- a/src/mesa/drivers/dri/i915tex/intel_reg.h +++ b/src/mesa/drivers/dri/i915tex/intel_reg.h @@ -82,6 +82,7 @@ #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) #define MI_WAIT_FOR_EVENT ((0x3<<23)) +#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) #endif diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c index efa1b014a6..f26b3f33ad 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.c +++ b/src/mesa/drivers/dri/i915tex/intel_screen.c @@ -541,7 +541,12 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, mesaVis->depthBits != 24); GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8); - struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); + struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer); + + if (!intel_fb) + return GL_FALSE; + + _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis); /* setup the hardware-based renderbuffers */ { @@ -553,7 +558,8 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, screen->cpp, screen->front.map); intel_set_span_functions(&frontRb->Base); - _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, + &frontRb->Base); } if (mesaVis->doubleBufferMode) { @@ -565,7 +571,8 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, screen->cpp, screen->back.map); intel_set_span_functions(&backRb->Base); - _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, + &backRb->Base); } if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { @@ -579,8 +586,10 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, screen->depth.map); intel_set_span_functions(&depthStencilRb->Base); /* note: bind RB to two attachment points */ - _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); - _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, + &depthStencilRb->Base); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, + &depthStencilRb->Base); } else if (mesaVis->depthBits == 16) { /* just 16-bit depth buffer, no hw stencil */ @@ -592,17 +601,19 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, screen->cpp, /* 2! */ screen->depth.map); intel_set_span_functions(&depthRb->Base); - _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); } /* now add any/all software-based renderbuffers we may need */ - _mesa_add_soft_renderbuffers(fb, GL_FALSE, /* never sw color */ - GL_FALSE, /* never sw depth */ - swStencil, mesaVis->accumRedBits > 0, GL_FALSE, /* never sw alpha */ - GL_FALSE /* never sw aux */ ); - driDrawPriv->driverPrivate = (void *) fb; - - return (driDrawPriv->driverPrivate != NULL); + _mesa_add_soft_renderbuffers(&intel_fb->Base, + GL_FALSE, /* never sw color */ + GL_FALSE, /* never sw depth */ + swStencil, mesaVis->accumRedBits > 0, + GL_FALSE, /* never sw alpha */ + GL_FALSE /* never sw aux */ ); + driDrawPriv->driverPrivate = (void *) intel_fb; + + return GL_TRUE; } } diff --git a/src/mesa/drivers/dri/i915tex/intel_tris.c b/src/mesa/drivers/dri/i915tex/intel_tris.c index 4e0ca70c1e..9ac8c32f60 100644 --- a/src/mesa/drivers/dri/i915tex/intel_tris.c +++ b/src/mesa/drivers/dri/i915tex/intel_tris.c @@ -102,15 +102,7 @@ intelStartInlinePrimitive(struct intel_context *intel, /* _mesa_printf("%s *", __progname); */ - if (intel->flip_pending) { - /* Wait for a pending flip to take effect */ - BEGIN_BATCH(2, batch_flags); - OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); - OUT_BATCH(0); - ADVANCE_BATCH(); - - intel->flip_pending = GL_FALSE; - } + intel_wait_flips(intel, batch_flags); /* Emit a slot which will be filled with the inline primitive * command later. -- cgit v1.2.3 From 6f2bf34748c2dfcff09216132c48377db7d6f17d Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 15 Feb 2007 18:33:53 +0100 Subject: intelCopyBuffer: Remove incorrect intel_fb->pf_current_page tests. intel_get_rb_region already takes the current page into account. This would result in broken rendering when multiple 3D windows are visible and the pages are reversed. --- src/mesa/drivers/dri/i915tex/intel_blit.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c index e33d283076..640c73e355 100644 --- a/src/mesa/drivers/dri/i915tex/intel_blit.c +++ b/src/mesa/drivers/dri/i915tex/intel_blit.c @@ -184,25 +184,12 @@ noschedule: OUT_BATCH((pbox->y1 << 16) | pbox->x1); OUT_BATCH((pbox->y2 << 16) | pbox->x2); - if (intel_fb->pf_current_page == 0) - OUT_RELOC(frontRegion->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); - else - OUT_RELOC(backRegion->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); + OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); OUT_BATCH((pbox->y1 << 16) | pbox->x1); OUT_BATCH(BR13 & 0xffff); - - if (intel_fb->pf_current_page == 0) - OUT_RELOC(backRegion->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); - else - OUT_RELOC(frontRegion->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); + OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, + DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); ADVANCE_BATCH(); } -- cgit v1.2.3 From bfbc1de02ea5a26dc9c05bdd267aa933f04891c8 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 15 Feb 2007 18:41:40 +0100 Subject: intelRotateWindow: Only use back buffer and cliprects in very specific cases. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index fdb6ea9444..f51b0af164 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -471,17 +471,16 @@ intelRotateWindow(struct intel_context *intel, intel_fb = dPriv->driverPrivate; - if ((srcBuf == BUFFER_BIT_BACK_LEFT && intel_fb->pf_current_page) || - (srcBuf == BUFFER_BIT_FRONT_LEFT && !intel_fb->pf_current_page)) { - src = intel->intelScreen->front_region; - clipRects = dPriv->pClipRects; - numClipRects = dPriv->numClipRects; - } - else { + if ((srcBuf == BUFFER_BIT_BACK_LEFT && !intel_fb->pf_active)) { src = intel->intelScreen->back_region; clipRects = dPriv->pBackClipRects; numClipRects = dPriv->numBackClipRects; } + else { + src = intel->intelScreen->front_region; + clipRects = dPriv->pClipRects; + numClipRects = dPriv->numClipRects; + } if (src->cpp == 4) { format = GL_BGRA; -- cgit v1.2.3 From 356bf9563ed145de5ba4a14c9f23c379293f273a Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 15 Feb 2007 18:43:46 +0100 Subject: intelWindowMoved: Some debugging output was accidentally left always enabled. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index f51b0af164..ec2150d27b 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -249,7 +249,7 @@ intelWindowMoved(struct intel_context *intel) pf_active = (pf_pipes & intel->sarea->pf_active) == pf_pipes; - if (1 /*INTEL_DEBUG & DEBUG_LOCK*/) + if (INTEL_DEBUG & DEBUG_LOCK) if (pf_active != intel_fb->pf_active) _mesa_printf("%s - Page flipping %sactive\n", __progname, pf_active ? "" : "in"); -- cgit v1.2.3 From e33a9d689415e00bded306699abdf93b96c0b9ad Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 20 Feb 2007 19:14:23 +0100 Subject: i915tex: Triple buffering support, only effective with page flipping so far. Pending flips are tracked per renderbuffer and the colour renderbuffer attachments of window framebuffer objects are rotated on flips to avoid stalling the pipeline for pending flips unnecessarily. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 47 ++++++++++------ src/mesa/drivers/dri/i915tex/intel_context.c | 51 +++++++++--------- src/mesa/drivers/dri/i915tex/intel_fbo.c | 49 ++++++++++++----- src/mesa/drivers/dri/i915tex/intel_fbo.h | 9 +++- src/mesa/drivers/dri/i915tex/intel_screen.c | 65 ++++++++++++++++++++--- src/mesa/drivers/dri/i915tex/intel_screen.h | 2 + src/mesa/drivers/dri/i915tex/server/i830_common.h | 6 +++ 7 files changed, 166 insertions(+), 63 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index ec2150d27b..7db5ccfc26 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -214,10 +214,6 @@ intelWindowMoved(struct intel_context *intel) } } - /* Update Mesa's notion of window size */ - driUpdateFramebufferSize(ctx, dPriv); - intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */ - if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) { drmI830Sarea *sarea = intel->sarea; drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w, @@ -247,7 +243,9 @@ intelWindowMoved(struct intel_context *intel) intel_fb->pf_current_page = (intel->sarea->pf_current_page >> (intel_fb->pf_pipes & 0x2)) & 0x3; - pf_active = (pf_pipes & intel->sarea->pf_active) == pf_pipes; + intel_fb->pf_num_pages = intel->intelScreen->third.handle ? 3 : 2; + + pf_active = pf_pipes && (pf_pipes & intel->sarea->pf_active) == pf_pipes; if (INTEL_DEBUG & DEBUG_LOCK) if (pf_active != intel_fb->pf_active) @@ -255,9 +253,13 @@ intelWindowMoved(struct intel_context *intel) pf_active ? "" : "in"); if (pf_active) { - if (pf_pipes != intel_fb->pf_pipes && intel_fb->pf_pipes == 0x3 && - (intel->sarea->pf_current_page & 0x3) != - ((intel->sarea->pf_current_page) >> 2 & 0x3)) { + int i; + + /* Sync pages between pipes if we're flipping on both at the same time */ + for (i = 0; i < 2 && pf_pipes != intel_fb->pf_pipes && + intel_fb->pf_pipes == 0x3 && + (intel->sarea->pf_current_page & 0x3) != + ((intel->sarea->pf_current_page) >> 2 & 0x3); i++) { drm_i915_flip_t flip; flip.pipes = (intel_fb->pf_current_page == @@ -270,7 +272,7 @@ intelWindowMoved(struct intel_context *intel) } intel_fb->pf_active = pf_active; - driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, intel_fb->pf_current_page); + intel_flip_renderbuffers(intel_fb); intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); /* Update vblank info @@ -289,6 +291,10 @@ intelWindowMoved(struct intel_context *intel) intel->vblank_flags &= ~VBLANK_FLAG_SECONDARY; } + /* Update Mesa's notion of window size */ + driUpdateFramebufferSize(ctx, dPriv); + intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */ + /* Update hardware scissor */ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, ctx->Scissor.Width, ctx->Scissor.Height); @@ -472,12 +478,12 @@ intelRotateWindow(struct intel_context *intel, intel_fb = dPriv->driverPrivate; if ((srcBuf == BUFFER_BIT_BACK_LEFT && !intel_fb->pf_active)) { - src = intel->intelScreen->back_region; + src = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); clipRects = dPriv->pBackClipRects; numClipRects = dPriv->numBackClipRects; } else { - src = intel->intelScreen->front_region; + src = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); clipRects = dPriv->pClipRects; numClipRects = dPriv->numClipRects; } @@ -643,8 +649,13 @@ intel_wait_flips(struct intel_context *intel, GLuint batch_flags) { struct intel_framebuffer *intel_fb = (struct intel_framebuffer *) intel->ctx.DrawBuffer; + struct intel_renderbuffer *intel_rb = + intel_get_renderbuffer(&intel_fb->Base, + intel_fb->Base._ColorDrawBufferMask[0] == + BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : + BUFFER_BACK_LEFT); - if (intel_fb->Base.Name == 0 && intel_fb->flip_pending) { + if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) { GLuint mi_wait = MI_WAIT_FOR_EVENT; GLint pf_pipes = intel_fb->pf_pipes; BATCH_LOCALS; @@ -661,7 +672,7 @@ intel_wait_flips(struct intel_context *intel, GLuint batch_flags) OUT_BATCH(0); ADVANCE_BATCH(); - intel_fb->flip_pending = GL_FALSE; + intel_rb->pf_pending--; } } @@ -721,10 +732,14 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv) intel_fb->pf_current_page = (intel->sarea->pf_current_page >> (intel_fb->pf_pipes & 0x2)) & 0x3; - driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, intel_fb->pf_current_page); - intel_draw_buffer(&intel->ctx, &intel_fb->Base); + if (dPriv->numClipRects != 0) { + intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->pf_pending = + intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->pf_pending = + ++intel_fb->pf_seq; + } - intel_fb->flip_pending = dPriv->numClipRects != 0; + intel_flip_renderbuffers(intel_fb); + intel_draw_buffer(&intel->ctx, &intel_fb->Base); return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index 8d90489b4e..649fe549bf 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -551,27 +551,30 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, if (driContextPriv) { struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; - GLframebuffer *drawFb = (GLframebuffer *) driDrawPriv->driverPrivate; + struct intel_framebuffer *intel_fb = + (struct intel_framebuffer *) driDrawPriv->driverPrivate; GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate; /* XXX FBO temporary fix-ups! */ /* if the renderbuffers don't have regions, init them from the context */ { - struct intel_renderbuffer *irbFront - = intel_get_renderbuffer(drawFb, BUFFER_FRONT_LEFT); - struct intel_renderbuffer *irbBack - = intel_get_renderbuffer(drawFb, BUFFER_BACK_LEFT); struct intel_renderbuffer *irbDepth - = intel_get_renderbuffer(drawFb, BUFFER_DEPTH); + = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH); struct intel_renderbuffer *irbStencil - = intel_get_renderbuffer(drawFb, BUFFER_STENCIL); + = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL); - if (irbFront && !irbFront->region) { - intel_region_reference(&irbFront->region, intel->intelScreen->front_region); + if (intel_fb->color_rb[0] && !intel_fb->color_rb[0]->region) { + intel_region_reference(&intel_fb->color_rb[0]->region, + intel->intelScreen->front_region); } - if (irbBack && !irbBack->region) { - intel_region_reference(&irbBack->region, intel->intelScreen->back_region); + if (intel_fb->color_rb[1] && !intel_fb->color_rb[1]->region) { + intel_region_reference(&intel_fb->color_rb[1]->region, + intel->intelScreen->back_region); + } + if (intel_fb->color_rb[2] && !intel_fb->color_rb[2]->region) { + intel_region_reference(&intel_fb->color_rb[2]->region, + intel->intelScreen->third_region); } if (irbDepth && !irbDepth->region) { intel_region_reference(&irbDepth->region, intel->intelScreen->depth_region); @@ -581,21 +584,11 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, } } - /* set initial GLframebuffer size to match window, if needed */ - if (drawFb->Width == 0 && driDrawPriv->w) { - _mesa_resize_framebuffer(&intel->ctx, drawFb, - driDrawPriv->w, driDrawPriv->h); - } - if (readFb->Width == 0 && driReadPriv->w) { - _mesa_resize_framebuffer(&intel->ctx, readFb, - driReadPriv->w, driReadPriv->h); - } - - _mesa_make_current(&intel->ctx, drawFb, readFb); + _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb); /* The drawbuffer won't always be updated by _mesa_make_current: */ - if (intel->ctx.DrawBuffer == drawFb) { + if (intel->ctx.DrawBuffer == &intel_fb->Base) { if (intel->driDrawable != driDrawPriv) { driDrawableInitVBlank(driDrawPriv, intel->vblank_flags, &intel->vbl_seq); @@ -603,8 +596,18 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, intelWindowMoved(intel); } - intel_draw_buffer(&intel->ctx, drawFb); + intel_draw_buffer(&intel->ctx, &intel_fb->Base); } + + /* set initial GLframebuffer size to match window, if needed */ + if (&intel_fb->Base.Width == 0 && driDrawPriv->w) { + _mesa_resize_framebuffer(&intel->ctx, &intel_fb->Base, + driDrawPriv->w, driDrawPriv->h); + } + if (readFb->Width == 0 && driReadPriv->w) { + _mesa_resize_framebuffer(&intel->ctx, readFb, + driReadPriv->w, driReadPriv->h); + } } else { _mesa_make_current(NULL, NULL, NULL); diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c index 104cf1d9bb..ad078451bf 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.c +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.c @@ -71,22 +71,29 @@ intel_renderbuffer(struct gl_renderbuffer *rb) struct intel_renderbuffer * intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) { - if (fb->Name == 0) { - struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb; - - if (intel_fb->pf_current_page) { - switch (attIndex) { - case BUFFER_BACK_LEFT: - attIndex = BUFFER_FRONT_LEFT; - break; - case BUFFER_FRONT_LEFT: - attIndex = BUFFER_BACK_LEFT; - break; - } - } + return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); +} + + +void +intel_flip_renderbuffers(struct intel_framebuffer *intel_fb) +{ + int current_page = intel_fb->pf_current_page; + int next_page = (current_page + 1) % intel_fb->pf_num_pages; + + if (intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer != + &intel_fb->color_rb[current_page]->Base) { + _mesa_remove_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, + &intel_fb->color_rb[current_page]->Base); } - return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); + if (intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer != + &intel_fb->color_rb[next_page]->Base) { + _mesa_remove_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, + &intel_fb->color_rb[next_page]->Base); + } } @@ -288,10 +295,24 @@ static GLboolean intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { + struct intel_context *intel = intel_context(ctx); + struct intel_framebuffer *intel_fb; + ASSERT(rb->Name == 0); rb->Width = width; rb->Height = height; rb->_ActualFormat = internalFormat; + + if (intel && intel->driDrawable && + (intel_fb = intel->driDrawable->driverPrivate) && + intel_fb->pf_num_pages == 3 && + rb == &intel_fb->color_rb[intel_fb->pf_current_page]->Base && + (rb = &intel_fb->color_rb[(intel_fb->pf_current_page + 2) % 3]->Base)) { + rb->Width = width; + rb->Height = height; + rb->_ActualFormat = internalFormat; + } + return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.h b/src/mesa/drivers/dri/i915tex/intel_fbo.h index d55f02967f..0446d681c6 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.h +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.h @@ -39,11 +39,14 @@ struct intel_framebuffer { struct gl_framebuffer Base; + struct intel_renderbuffer *color_rb[3]; + /* Drawable page flipping state */ GLboolean pf_active; - GLboolean flip_pending; + GLuint pf_seq; GLint pf_pipes; GLint pf_current_page; + GLint pf_num_pages; }; @@ -63,6 +66,8 @@ struct intel_renderbuffer GLuint PairedDepth; /**< only used if this is a depth renderbuffer */ GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */ + + GLuint pf_pending; /**< sequence number of pending flip */ }; @@ -83,6 +88,8 @@ extern struct intel_renderbuffer *intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex); +extern void intel_flip_renderbuffers(struct intel_framebuffer *intel_fb); + /* XXX make inline or macro */ extern struct intel_region *intel_get_rb_region(struct gl_framebuffer *fb, diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c index f26b3f33ad..4763d14f4f 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.c +++ b/src/mesa/drivers/dri/i915tex/intel_screen.c @@ -98,6 +98,18 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv) return GL_FALSE; } + if (intelScreen->third.handle) { + if (0) + _mesa_printf("Third 0x%08x ", intelScreen->third.handle); + if (drmMap(sPriv->fd, + intelScreen->third.handle, + intelScreen->third.size, + (drmAddress *) & intelScreen->third.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + } + if (0) _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle); if (drmMap(sPriv->fd, @@ -119,9 +131,9 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv) } #endif if (0) - printf("Mappings: front: %p back: %p depth: %p tex: %p\n", + printf("Mappings: front: %p back: %p third: %p depth: %p tex: %p\n", intelScreen->front.map, - intelScreen->back.map, + intelScreen->back.map, intelScreen->third.map, intelScreen->depth.map, intelScreen->tex.map); return GL_TRUE; } @@ -191,6 +203,18 @@ intel_recreate_static_regions(intelScreenPrivate *intelScreen) intelScreen->back.pitch / intelScreen->cpp, intelScreen->height); + if (intelScreen->third.handle) { + intelScreen->third_region = + intel_recreate_static(intelScreen, + intelScreen->third_region, + DRM_BO_FLAG_MEM_TT, + intelScreen->third.offset, + intelScreen->third.map, + intelScreen->cpp, + intelScreen->third.pitch / intelScreen->cpp, + intelScreen->height); + } + /* Still assuming front.cpp == depth.cpp */ intelScreen->depth_region = @@ -240,6 +264,13 @@ intelUnmapScreenRegions(intelScreenPrivate * intelScreen) #endif intelScreen->back.map = NULL; } + if (intelScreen->third.map) { +#if REALLY_UNMAP + if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0) + printf("drmUnmap third failed!\n"); +#endif + intelScreen->third.map = NULL; + } if (intelScreen->depth.map) { #if REALLY_UNMAP drmUnmap(intelScreen->depth.map, intelScreen->depth.size); @@ -325,6 +356,13 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen, intelScreen->back.handle = sarea->back_handle; intelScreen->back.size = sarea->back_size; + if (intelScreen->driScrnPriv->ddxMinor >= 8) { + intelScreen->third.offset = sarea->third_offset; + intelScreen->third.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->third.handle = sarea->third_handle; + intelScreen->third.size = sarea->third_size; + } + intelScreen->depth.offset = sarea->depth_offset; intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp; intelScreen->depth.handle = sarea->depth_handle; @@ -550,29 +588,40 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, /* setup the hardware-based renderbuffers */ { - struct intel_renderbuffer *frontRb + intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat, screen->width, screen->height, screen->front.offset, screen->front.pitch, screen->cpp, screen->front.map); - intel_set_span_functions(&frontRb->Base); + intel_set_span_functions(&intel_fb->color_rb[0]->Base); _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, - &frontRb->Base); + &intel_fb->color_rb[0]->Base); } if (mesaVis->doubleBufferMode) { - struct intel_renderbuffer *backRb + intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat, screen->width, screen->height, screen->back.offset, screen->back.pitch, screen->cpp, screen->back.map); - intel_set_span_functions(&backRb->Base); + intel_set_span_functions(&intel_fb->color_rb[1]->Base); _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, - &backRb->Base); + &intel_fb->color_rb[1]->Base); + + if (screen->third.handle) { + intel_fb->color_rb[2] + = intel_create_renderbuffer(rgbFormat, + screen->width, screen->height, + screen->third.offset, + screen->third.pitch, + screen->cpp, + screen->third.map); + intel_set_span_functions(&intel_fb->color_rb[2]->Base); + } } if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.h b/src/mesa/drivers/dri/i915tex/intel_screen.h index 17698773f3..05e2f1f2ea 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.h +++ b/src/mesa/drivers/dri/i915tex/intel_screen.h @@ -51,12 +51,14 @@ typedef struct { intelRegion front; intelRegion back; + intelRegion third; intelRegion rotated; intelRegion depth; intelRegion tex; struct intel_region *front_region; struct intel_region *back_region; + struct intel_region *third_region; struct intel_region *depth_region; struct intel_region *rotated_region; diff --git a/src/mesa/drivers/dri/i915tex/server/i830_common.h b/src/mesa/drivers/dri/i915tex/server/i830_common.h index 06f28ed19a..d4d58886ce 100644 --- a/src/mesa/drivers/dri/i915tex/server/i830_common.h +++ b/src/mesa/drivers/dri/i915tex/server/i830_common.h @@ -129,6 +129,12 @@ typedef struct { int pipeB_y; int pipeB_w; int pipeB_h; + + /* Triple buffering */ + drm_handle_t third_handle; + int third_offset; + int third_size; + unsigned int third_tiled; } drmI830Sarea; /* Flags for perf_boxes -- cgit v1.2.3 From 641c966e3de192eba17c693f00d6654742c72eb6 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 22 Feb 2007 17:24:09 +0100 Subject: i915tex: Schedule flips when possible. Also move vsync related state from context to window, so it's possible to schedule several flips ahead of time with triple buffering. --- src/mesa/drivers/dri/i915tex/intel_blit.c | 195 ++++++++++----------------- src/mesa/drivers/dri/i915tex/intel_buffers.c | 134 +++++++++++++++--- src/mesa/drivers/dri/i915tex/intel_context.c | 36 +++-- src/mesa/drivers/dri/i915tex/intel_context.h | 13 -- src/mesa/drivers/dri/i915tex/intel_fbo.h | 14 ++ src/mesa/drivers/dri/i915tex/intel_screen.c | 15 +-- 6 files changed, 228 insertions(+), 179 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c index 640c73e355..dbe4ba2ac5 100644 --- a/src/mesa/drivers/dri/i915tex/intel_blit.c +++ b/src/mesa/drivers/dri/i915tex/intel_blit.c @@ -55,8 +55,6 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, struct intel_context *intel; const intelScreenPrivate *intelScreen; - GLboolean missed_target; - int64_t ust; DBG("%s\n", __FUNCTION__); @@ -68,41 +66,6 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, intelScreen = intel->intelScreen; - if (!rect && !intel->swap_scheduled && intelScreen->drmMinor >= 6 && - !(intel->vblank_flags & VBLANK_FLAG_NO_IRQ) && - intelScreen->current_rotation == 0) { - unsigned int interval = driGetVBlankInterval(dPriv, intel->vblank_flags); - unsigned int target; - drm_i915_vblank_swap_t swap; - - swap.drawable = dPriv->hHWDrawable; - swap.seqtype = DRM_VBLANK_ABSOLUTE; - target = swap.sequence = intel->vbl_seq + interval; - - if (intel->vblank_flags & VBLANK_FLAG_SYNC) { - swap.seqtype |= DRM_VBLANK_NEXTONMISS; - } else if (interval == 0) { - goto noschedule; - } - - if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) { - swap.seqtype |= DRM_VBLANK_SECONDARY; - } - - intel_batchbuffer_flush(intel->batch); - - if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap, - sizeof(swap))) { - intel->swap_scheduled = 1; - intel->vbl_seq = swap.sequence; - swap.sequence -= target; - missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23); - } - } else { - intel->swap_scheduled = 0; - } -noschedule: - if (intel->last_swap_fence) { driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); driFenceUnReference(intel->last_swap_fence); @@ -111,108 +74,88 @@ noschedule: intel->last_swap_fence = intel->first_swap_fence; intel->first_swap_fence = NULL; - if (!intel->swap_scheduled) { - if (!rect) { - driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags, - &missed_target); + /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets + * should work regardless. + */ + LOCK_HARDWARE(intel); + + if (dPriv && dPriv->numClipRects) { + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + const struct intel_region *frontRegion + = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); + const struct intel_region *backRegion + = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); + const int nbox = dPriv->numClipRects; + const drm_clip_rect_t *pbox = dPriv->pClipRects; + const int pitch = frontRegion->pitch; + const int cpp = frontRegion->cpp; + int BR13, CMD; + int i; + + ASSERT(intel_fb); + ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ + ASSERT(frontRegion); + ASSERT(backRegion); + ASSERT(frontRegion->pitch == backRegion->pitch); + ASSERT(frontRegion->cpp == backRegion->cpp); + + if (cpp == 2) { + BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); + CMD = XY_SRC_COPY_BLT_CMD; + } + else { + BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); + CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); } + for (i = 0; i < nbox; i++, pbox++) { + drm_clip_rect_t box; - /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets - * should work regardless. - */ - LOCK_HARDWARE(intel); - - if (dPriv && dPriv->numClipRects) { - const intelScreenPrivate *intelScreen = intel->intelScreen; - struct intel_framebuffer *intel_fb = dPriv->driverPrivate; - const struct intel_region *frontRegion - = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); - const struct intel_region *backRegion - = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); - const int nbox = dPriv->numClipRects; - const drm_clip_rect_t *pbox = dPriv->pClipRects; - const int pitch = frontRegion->pitch; - const int cpp = frontRegion->cpp; - int BR13, CMD; - int i; - - ASSERT(intel_fb); - ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ - ASSERT(frontRegion); - ASSERT(backRegion); - ASSERT(frontRegion->pitch == backRegion->pitch); - ASSERT(frontRegion->cpp == backRegion->cpp); - - if (cpp == 2) { - BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); - CMD = XY_SRC_COPY_BLT_CMD; - } - else { - BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); - CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - } + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height) + continue; - for (i = 0; i < nbox; i++, pbox++) { - drm_clip_rect_t box; + box = *pbox; - if (pbox->x1 > pbox->x2 || - pbox->y1 > pbox->y2 || - pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height) - continue; + if (rect) { + if (rect->x1 > box.x1) + box.x1 = rect->x1; + if (rect->y1 > box.y1) + box.y1 = rect->y1; + if (rect->x2 < box.x2) + box.x2 = rect->x2; + if (rect->y2 < box.y2) + box.y2 = rect->y2; - box = *pbox; - - if (rect) { - if (rect->x1 > box.x1) - box.x1 = rect->x1; - if (rect->y1 > box.y1) - box.y1 = rect->y1; - if (rect->x2 < box.x2) - box.x2 = rect->x2; - if (rect->y2 < box.y2) - box.y2 = rect->y2; - - if (box.x1 > box.x2 || box.y1 > box.y2) - continue; - } - - BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); - OUT_BATCH(CMD); - OUT_BATCH(BR13); - OUT_BATCH((pbox->y1 << 16) | pbox->x1); - OUT_BATCH((pbox->y2 << 16) | pbox->x2); - - OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); - OUT_BATCH((pbox->y1 << 16) | pbox->x1); - OUT_BATCH(BR13 & 0xffff); - OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); - - ADVANCE_BATCH(); + if (box.x1 > box.x2 || box.y1 > box.y2) + continue; } - if (intel->first_swap_fence) - driFenceUnReference(intel->first_swap_fence); - intel->first_swap_fence = intel_batchbuffer_flush(intel->batch); - driFenceReference(intel->first_swap_fence); - } + BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH(CMD); + OUT_BATCH(BR13); + OUT_BATCH((pbox->y1 << 16) | pbox->x1); + OUT_BATCH((pbox->y2 << 16) | pbox->x2); - UNLOCK_HARDWARE(intel); - } + OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); + OUT_BATCH((pbox->y1 << 16) | pbox->x1); + OUT_BATCH(BR13 & 0xffff); + OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, + DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); - if (!rect) { - intel->swap_count++; - (*dri_interface->getUST) (&ust); - if (missed_target) { - intel->swap_missed_count++; - intel->swap_missed_ust = ust - intel->swap_ust; + ADVANCE_BATCH(); } - intel->swap_ust = ust; + if (intel->first_swap_fence) + driFenceUnReference(intel->first_swap_fence); + intel->first_swap_fence = intel_batchbuffer_flush(intel->batch); + driFenceReference(intel->first_swap_fence); } + + UNLOCK_HARDWARE(intel); } diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 7db5ccfc26..8054d98646 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -226,7 +226,7 @@ intelWindowMoved(struct intel_context *intel) .y2 = sarea->pipeB_y + sarea->pipeB_h }; GLint areaA = driIntersectArea( drw_rect, pipeA_rect ); GLint areaB = driIntersectArea( drw_rect, pipeB_rect ); - GLuint flags = intel->vblank_flags; + GLuint flags = intel_fb->vblank_flags; GLboolean pf_active; GLint pf_pipes; @@ -278,17 +278,17 @@ intelWindowMoved(struct intel_context *intel) /* Update vblank info */ if (areaB > areaA || (areaA == areaB && areaB > 0)) { - flags = intel->vblank_flags | VBLANK_FLAG_SECONDARY; + flags = intel_fb->vblank_flags | VBLANK_FLAG_SECONDARY; } else { - flags = intel->vblank_flags & ~VBLANK_FLAG_SECONDARY; + flags = intel_fb->vblank_flags & ~VBLANK_FLAG_SECONDARY; } - if (flags != intel->vblank_flags) { - intel->vblank_flags = flags; - driGetCurrentVBlank(dPriv, intel->vblank_flags, &intel->vbl_seq); + if (flags != intel_fb->vblank_flags) { + intel_fb->vblank_flags = flags; + driGetCurrentVBlank(dPriv, intel_fb->vblank_flags, &intel_fb->vbl_seq); } } else { - intel->vblank_flags &= ~VBLANK_FLAG_SECONDARY; + intel_fb->vblank_flags &= ~VBLANK_FLAG_SECONDARY; } /* Update Mesa's notion of window size */ @@ -683,7 +683,6 @@ static GLboolean intelPageFlip(const __DRIdrawablePrivate * dPriv) { struct intel_context *intel; - GLboolean missed_target; int ret; struct intel_framebuffer *intel_fb = dPriv->driverPrivate; @@ -701,13 +700,6 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv) intelFlush(&intel->ctx); - driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags, &missed_target); - - if (missed_target) { - intel->swap_missed_count++; - (void)(*dri_interface->getUST) (&intel->swap_missed_ust); - } - ret = 0; LOCK_HARDWARE(intel); @@ -772,6 +764,83 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv) #else /* Trunk version: */ + +static GLboolean +intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target) +{ + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + unsigned int interval = driGetVBlankInterval(dPriv, intel_fb->vblank_flags); + struct intel_context *intel = + intelScreenContext(dPriv->driScreenPriv->private); + const intelScreenPrivate *intelScreen = intel->intelScreen; + unsigned int target; + drm_i915_vblank_swap_t swap; + GLboolean ret; + + if ((intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) || + intelScreen->current_rotation != 0 || + intelScreen->drmMinor < (intel_fb->pf_active ? 9 : 6)) + return GL_FALSE; + + swap.seqtype = DRM_VBLANK_ABSOLUTE; + + if (intel_fb->vblank_flags & VBLANK_FLAG_SYNC) { + swap.seqtype |= DRM_VBLANK_NEXTONMISS; + } else if (interval == 0) { + return GL_FALSE; + } + + swap.drawable = dPriv->hHWDrawable; + target = swap.sequence = intel_fb->vbl_seq + interval; + + if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { + swap.seqtype |= DRM_VBLANK_SECONDARY; + } + + LOCK_HARDWARE(intel); + + intel_batchbuffer_flush(intel->batch); + + if ( intel_fb->pf_active ) { + swap.seqtype |= DRM_VBLANK_FLIP; + + intel_fb->pf_current_page = (((intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3) + 1) % + intel_fb->pf_num_pages; + } + + if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap, + sizeof(swap))) { + intel_fb->vbl_seq = swap.sequence; + swap.sequence -= target; + *missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23); + + if (swap.seqtype & DRM_VBLANK_FLIP) { + intel_get_renderbuffer(&intel_fb->Base, + BUFFER_FRONT_LEFT)->vbl_pending = + intel_get_renderbuffer(&intel_fb->Base, + BUFFER_BACK_LEFT)->vbl_pending = intel_fb->vbl_seq; + + intel_flip_renderbuffers(intel_fb); + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + } + + ret = GL_TRUE; + } else { + if (swap.seqtype & DRM_VBLANK_FLIP) { + intel_fb->pf_current_page = ((intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3) % + intel_fb->pf_num_pages; + } + + ret = GL_FALSE; + } + + UNLOCK_HARDWARE(intel); + + return ret; +} + void intelSwapBuffers(__DRIdrawablePrivate * dPriv) { @@ -786,13 +855,34 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv) if (ctx->Visual.doubleBufferMode) { intelScreenPrivate *screen = intel->intelScreen; - _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ - if (screen->current_rotation != 0 || !intelPageFlip(dPriv)) { - intelCopyBuffer(dPriv, NULL); - } - if (screen->current_rotation != 0) { - intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); - } + GLboolean missed_target; + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + int64_t ust; + + _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ + + if (screen->current_rotation != 0 || + !intelScheduleSwap(dPriv, &missed_target)) { + driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags, + &missed_target); + + if (screen->current_rotation != 0 || !intelPageFlip(dPriv)) { + intelCopyBuffer(dPriv, NULL); + } + + if (screen->current_rotation != 0) { + intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); + } + } + + intel_fb->swap_count++; + (*dri_interface->getUST) (&ust); + if (missed_target) { + intel_fb->swap_missed_count++; + intel_fb->swap_missed_ust = ust - intel_fb->swap_ust; + } + + intel_fb->swap_ust = ust; } } else { diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index 649fe549bf..b1352a766e 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -443,10 +443,6 @@ intelInitContext(struct intel_context *intel, intel->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS); - intel->vblank_flags = (intel->intelScreen->irq_active != 0) - ? driGetDefaultVBlankFlags(&intel->optionCache) : VBLANK_FLAG_NO_IRQ; - - (*dri_interface->getUST) (&intel->swap_ust); _math_matrix_ctr(&intel->ViewportMatrix); /* Disable imaging extension until convolution is working in @@ -591,7 +587,12 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, if (intel->ctx.DrawBuffer == &intel_fb->Base) { if (intel->driDrawable != driDrawPriv) { - driDrawableInitVBlank(driDrawPriv, intel->vblank_flags, &intel->vbl_seq); + intel_fb->vblank_flags = (intel->intelScreen->irq_active != 0) + ? driGetDefaultVBlankFlags(&intel->optionCache) + : VBLANK_FLAG_NO_IRQ; + (*dri_interface->getUST) (&intel_fb->swap_ust); + driDrawableInitVBlank(driDrawPriv, intel_fb->vblank_flags, + &intel_fb->vbl_seq); intel->driDrawable = driDrawPriv; intelWindowMoved(intel); } @@ -702,19 +703,34 @@ intelContendedLock(struct intel_context *intel, GLuint flags) void LOCK_HARDWARE( struct intel_context *intel ) { char __ret=0; - + struct intel_framebuffer *intel_fb = NULL; + struct intel_renderbuffer *intel_rb = NULL; _glthread_LOCK_MUTEX(lockMutex); assert(!intel->locked); - if (intel->swap_scheduled) { + if (intel->driDrawable) { + intel_fb = intel->driDrawable->driverPrivate; + + if (intel_fb) + intel_rb = + intel_get_renderbuffer(&intel_fb->Base, + intel_fb->Base._ColorDrawBufferMask[0] == + BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : + BUFFER_BACK_LEFT); + } + + if (intel_rb && (intel_fb->vbl_waited - intel_rb->vbl_pending) > (1<<23)) { drmVBlank vbl; + vbl.request.type = DRM_VBLANK_ABSOLUTE; - if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) { + + if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { vbl.request.type |= DRM_VBLANK_SECONDARY; } - vbl.request.sequence = intel->vbl_seq; + + vbl.request.sequence = intel_rb->vbl_pending; drmWaitVBlank(intel->driFd, &vbl); - intel->swap_scheduled = 0; + intel_fb->vbl_waited = intel_rb->vbl_pending; } DRM_CAS(intel->driHwLock, intel->hHWContext, diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index 8f78597ba0..44c20af7f8 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -274,19 +274,6 @@ struct intel_context */ driOptionCache optionCache; - /* VBI - */ - GLuint vbl_seq; - GLuint vblank_flags; - - int64_t swap_ust; - int64_t swap_missed_ust; - - GLuint swap_count; - GLuint swap_missed_count; - - GLuint swap_scheduled; - /* Rotation. Need to match that of the * current screen. */ diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.h b/src/mesa/drivers/dri/i915tex/intel_fbo.h index 0446d681c6..963f5e706f 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.h +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.h @@ -47,6 +47,18 @@ struct intel_framebuffer GLint pf_pipes; GLint pf_current_page; GLint pf_num_pages; + + /* VBI + */ + GLuint vbl_seq; + GLuint vblank_flags; + GLuint vbl_waited; + + int64_t swap_ust; + int64_t swap_missed_ust; + + GLuint swap_count; + GLuint swap_missed_count; }; @@ -68,6 +80,8 @@ struct intel_renderbuffer GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */ GLuint pf_pending; /**< sequence number of pending flip */ + + GLuint vbl_pending; /**< vblank sequence number of pending flip */ }; diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c index 4763d14f4f..86a3d79266 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.c +++ b/src/mesa/drivers/dri/i915tex/intel_screen.c @@ -679,21 +679,20 @@ intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) static int intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) { - struct intel_context *intel; + struct intel_framebuffer *intel_fb; - if ((dPriv == NULL) || (dPriv->driContextPriv == NULL) - || (dPriv->driContextPriv->driverPrivate == NULL) + if ((dPriv == NULL) || (dPriv->driverPrivate == NULL) || (sInfo == NULL)) { return -1; } - intel = dPriv->driContextPriv->driverPrivate; - sInfo->swap_count = intel->swap_count; - sInfo->swap_ust = intel->swap_ust; - sInfo->swap_missed_count = intel->swap_missed_count; + intel_fb = dPriv->driverPrivate; + sInfo->swap_count = intel_fb->swap_count; + sInfo->swap_ust = intel_fb->swap_ust; + sInfo->swap_missed_count = intel_fb->swap_missed_count; sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) - ? driCalculateSwapUsage(dPriv, 0, intel->swap_missed_ust) + ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust) : 0.0; return 0; -- cgit v1.2.3 From edf676cc5af26d8f82625a94788d4f27c464ab38 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Wed, 28 Feb 2007 16:05:49 +0100 Subject: i915tex: Also update intel_rb->vbl_pending when scheduled swap is not a flip. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 8054d98646..5eb2a8e5d0 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -815,12 +815,12 @@ intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target) swap.sequence -= target; *missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23); - if (swap.seqtype & DRM_VBLANK_FLIP) { + intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending = intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->vbl_pending = - intel_get_renderbuffer(&intel_fb->Base, - BUFFER_BACK_LEFT)->vbl_pending = intel_fb->vbl_seq; + intel_fb->vbl_seq; + if (swap.seqtype & DRM_VBLANK_FLIP) { intel_flip_renderbuffers(intel_fb); intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); } -- cgit v1.2.3 From 3c578455e103664e6f93a7792999da7c06dd9a3f Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Wed, 28 Feb 2007 17:42:54 +0100 Subject: i915tex: Check that intel_rb is valid before trying to add it to an fbo. --- src/mesa/drivers/dri/i915tex/intel_fbo.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c index ad078451bf..8d43055382 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.c +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.c @@ -81,14 +81,16 @@ intel_flip_renderbuffers(struct intel_framebuffer *intel_fb) int current_page = intel_fb->pf_current_page; int next_page = (current_page + 1) % intel_fb->pf_num_pages; - if (intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer != + if (intel_fb->color_rb[current_page] && + intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer != &intel_fb->color_rb[current_page]->Base) { _mesa_remove_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT); _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, &intel_fb->color_rb[current_page]->Base); } - if (intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer != + if (intel_fb->color_rb[next_page] && + intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer != &intel_fb->color_rb[next_page]->Base) { _mesa_remove_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT); _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, -- cgit v1.2.3 From 0609b6afa8117893d7b36468158ac6ec2f5642bc Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Wed, 28 Feb 2007 17:46:07 +0100 Subject: i915tex: Sync pages differently when crossing pipe borders. Don't flip (up to twice) immediately but just arrange things such that the pages will be in sync on both pipes on the next flip. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 30 +++++++++++++++++----------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 5eb2a8e5d0..9f1b25ef38 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -253,19 +253,25 @@ intelWindowMoved(struct intel_context *intel) pf_active ? "" : "in"); if (pf_active) { - int i; - /* Sync pages between pipes if we're flipping on both at the same time */ - for (i = 0; i < 2 && pf_pipes != intel_fb->pf_pipes && - intel_fb->pf_pipes == 0x3 && - (intel->sarea->pf_current_page & 0x3) != - ((intel->sarea->pf_current_page) >> 2 & 0x3); i++) { - drm_i915_flip_t flip; - - flip.pipes = (intel_fb->pf_current_page == - (intel->sarea->pf_current_page & 0x3)) ? 0x2 : 0x1; - - drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); + if (pf_pipes == 0x3 && pf_pipes != intel_fb->pf_pipes && + (intel->sarea->pf_current_page & 0x3) != + (((intel->sarea->pf_current_page) >> 2) & 0x3)) { + if (intel_fb->pf_current_page == + (intel->sarea->pf_current_page & 0x3)) { + /* XXX: This is ugly, but emitting two flips 'in a row' can cause + * lockups for unknown reasons. + */ + intel->sarea->pf_current_page = + intel->sarea->pf_current_page & 0x3; + intel->sarea->pf_current_page |= + intel->sarea->pf_current_page << 2; + } else { + intel->sarea->pf_current_page = + intel->sarea->pf_current_page & (0x3 << 2); + intel->sarea->pf_current_page |= + intel->sarea->pf_current_page >> 2; + } } intel_fb->pf_pipes = pf_pipes; -- cgit v1.2.3 From fb3410297bb21a0eeda4d32698c2612f4e3cf40e Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Wed, 7 Mar 2007 18:01:39 +0100 Subject: i915tex: Set framebuffer size to match window before calling _mesa_make_current. Fixes issues with apps that don't call glViewport by default. --- src/mesa/drivers/dri/i915tex/intel_context.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index b1352a766e..b8515fe9b8 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -580,6 +580,16 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, } } + /* set GLframebuffer size to match window, if needed */ + if (intel_fb->Base.Width != driDrawPriv->w) { + _mesa_resize_framebuffer(&intel->ctx, &intel_fb->Base, + driDrawPriv->w, driDrawPriv->h); + } + if (readFb->Width != driReadPriv->w) { + _mesa_resize_framebuffer(&intel->ctx, readFb, + driReadPriv->w, driReadPriv->h); + } + _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb); /* The drawbuffer won't always be updated by _mesa_make_current: @@ -599,16 +609,6 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, intel_draw_buffer(&intel->ctx, &intel_fb->Base); } - - /* set initial GLframebuffer size to match window, if needed */ - if (&intel_fb->Base.Width == 0 && driDrawPriv->w) { - _mesa_resize_framebuffer(&intel->ctx, &intel_fb->Base, - driDrawPriv->w, driDrawPriv->h); - } - if (readFb->Width == 0 && driReadPriv->w) { - _mesa_resize_framebuffer(&intel->ctx, readFb, - driReadPriv->w, driReadPriv->h); - } } else { _mesa_make_current(NULL, NULL, NULL); -- cgit v1.2.3 From 81536789d2d2d92c687e9037cbb6f86b633ef839 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 9 Mar 2007 17:41:04 +0100 Subject: i915tex: Do not wait for pending flips on both pipes at the same time. The MI_WAIT_FOR_EVENT instruction does not support waiting for several events at once, so this should fix the lockups with page flipping when both pipes are enabled. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 9f1b25ef38..35236edc0c 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -662,20 +662,15 @@ intel_wait_flips(struct intel_context *intel, GLuint batch_flags) BUFFER_BACK_LEFT); if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) { - GLuint mi_wait = MI_WAIT_FOR_EVENT; GLint pf_pipes = intel_fb->pf_pipes; BATCH_LOCALS; - if (pf_pipes & 0x1) - mi_wait |= MI_WAIT_FOR_PLANE_A_FLIP; - - if (pf_pipes & 0x2) - mi_wait |= MI_WAIT_FOR_PLANE_B_FLIP; - /* Wait for pending flips to take effect */ BEGIN_BATCH(2, batch_flags); - OUT_BATCH(mi_wait); - OUT_BATCH(0); + OUT_BATCH(pf_pipes & 0x1 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP) + : 0); + OUT_BATCH(pf_pipes & 0x2 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP) + : 0); ADVANCE_BATCH(); intel_rb->pf_pending--; -- cgit v1.2.3 From 36b4e25da34691dffd6b147c8cf3d2598ec11ac7 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 9 Mar 2007 17:52:29 +0100 Subject: i915tex: Sync pages between pipes immediately again. This should be safe now that we no longer use the MI_WAIT_FOR_EVENT instruction incorrectly and should also work correctly with applications that render to the front buffer. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 35236edc0c..174f3c6351 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -257,6 +257,8 @@ intelWindowMoved(struct intel_context *intel) if (pf_pipes == 0x3 && pf_pipes != intel_fb->pf_pipes && (intel->sarea->pf_current_page & 0x3) != (((intel->sarea->pf_current_page) >> 2) & 0x3)) { + drm_i915_flip_t flip; + if (intel_fb->pf_current_page == (intel->sarea->pf_current_page & 0x3)) { /* XXX: This is ugly, but emitting two flips 'in a row' can cause @@ -265,13 +267,21 @@ intelWindowMoved(struct intel_context *intel) intel->sarea->pf_current_page = intel->sarea->pf_current_page & 0x3; intel->sarea->pf_current_page |= - intel->sarea->pf_current_page << 2; + ((intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % + intel_fb->pf_num_pages) << 2; + + flip.pipes = 0x2; } else { intel->sarea->pf_current_page = intel->sarea->pf_current_page & (0x3 << 2); intel->sarea->pf_current_page |= - intel->sarea->pf_current_page >> 2; + (intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % + intel_fb->pf_num_pages; + + flip.pipes = 0x1; } + + drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); } intel_fb->pf_pipes = pf_pipes; -- cgit v1.2.3 From bb0760ca4f1759eb3c237045f464da4ad60eef83 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 9 Mar 2007 19:56:55 +0100 Subject: i915tex: Set intel_fb->vbl_waited to current instead of what we aimed for. --- src/mesa/drivers/dri/i915tex/intel_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index b8515fe9b8..5c2cdf0c7d 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -730,7 +730,7 @@ void LOCK_HARDWARE( struct intel_context *intel ) vbl.request.sequence = intel_rb->vbl_pending; drmWaitVBlank(intel->driFd, &vbl); - intel_fb->vbl_waited = intel_rb->vbl_pending; + intel_fb->vbl_waited = vbl.reply.sequence; } DRM_CAS(intel->driHwLock, intel->hHWContext, -- cgit v1.2.3 From 6e0878becfbf211e5bbd141cd3441dfbdb206cc8 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 9 Mar 2007 20:00:13 +0100 Subject: i915tex: Wait for pending scheduled flips before switching vsync pipe. This avoids hangs when the vblank sequence numbers are not in sync between pipes, in particular when they run at different refresh rates. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 174f3c6351..164395719c 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -300,8 +300,27 @@ intelWindowMoved(struct intel_context *intel) } if (flags != intel_fb->vblank_flags) { + drmVBlank vbl; + int i; + + vbl.request.type = DRM_VBLANK_ABSOLUTE; + + if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { + vbl.request.type |= DRM_VBLANK_SECONDARY; + } + + for (i = 0; i < intel_fb->pf_num_pages; i++) { + vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending; + drmWaitVBlank(intel->driFd, &vbl); + } + intel_fb->vblank_flags = flags; driGetCurrentVBlank(dPriv, intel_fb->vblank_flags, &intel_fb->vbl_seq); + intel_fb->vbl_waited = intel_fb->vbl_seq; + + for (i = 0; i < intel_fb->pf_num_pages; i++) { + intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited; + } } } else { intel_fb->vblank_flags &= ~VBLANK_FLAG_SECONDARY; -- cgit v1.2.3