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(-) (limited to 'src/mesa/drivers') 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