diff options
-rw-r--r-- | src/mesa/drivers/dri/i915/intel_batchbuffer.c | 192 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915/intel_context.h | 9 |
2 files changed, 122 insertions, 79 deletions
diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.c b/src/mesa/drivers/dri/i915/intel_batchbuffer.c index dd754c67d44..8b1c1c5b980 100644 --- a/src/mesa/drivers/dri/i915/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.c @@ -368,6 +368,7 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv, const drm_clip_rect_t *rect) { intelContextPtr intel; + const intelScreenPrivate *intelScreen; GLboolean missed_target; int64_t ust; @@ -382,97 +383,130 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv, intelFlush( &intel->ctx ); - intelWaitForFrameCompletion( intel ); - LOCK_HARDWARE( intel ); - - if (!rect) - { - UNLOCK_HARDWARE( intel ); - driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target ); - LOCK_HARDWARE( intel ); - } - { - const intelScreenPrivate *intelScreen = intel->intelScreen; - const __DRIdrawablePrivate *dPriv = intel->driDrawable; - const int nbox = dPriv->numClipRects; - const drm_clip_rect_t *pbox = dPriv->pClipRects; - drm_clip_rect_t box; - const int cpp = intelScreen->cpp; - const int pitch = intelScreen->front.pitch; /* in bytes */ - int i; - GLuint CMD, BR13; - BATCH_LOCALS; - - switch(cpp) { - case 2: - BR13 = (pitch) | (0xCC << 16) | (1<<24); - CMD = XY_SRC_COPY_BLT_CMD; - break; - case 4: - BR13 = (pitch) | (0xCC << 16) | (1<<24) | (1<<25); - CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - break; - default: - BR13 = (pitch) | (0xCC << 16) | (1<<24); - CMD = XY_SRC_COPY_BLT_CMD; - break; + 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 (0) - intel_draw_performance_boxes( intel ); - for (i = 0 ; i < nbox; i++, pbox++) - { - if (pbox->x1 > pbox->x2 || - pbox->y1 > pbox->y2 || - pbox->x2 > intelScreen->width || - pbox->y2 > intelScreen->height) { - _mesa_warning(&intel->ctx, "Bad cliprect in intelCopyBuffer()"); - continue; - } + 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: - box = *pbox; + if (!intel->swap_scheduled) { + intelWaitForFrameCompletion( intel ); + LOCK_HARDWARE( intel ); - 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; + if (!rect) + { + UNLOCK_HARDWARE( intel ); + driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target ); + LOCK_HARDWARE( intel ); + } + { + const intelScreenPrivate *intelScreen = intel->intelScreen; + const __DRIdrawablePrivate *dPriv = intel->driDrawable; + const int nbox = dPriv->numClipRects; + const drm_clip_rect_t *pbox = dPriv->pClipRects; + drm_clip_rect_t box; + const int cpp = intelScreen->cpp; + const int pitch = intelScreen->front.pitch; /* in bytes */ + int i; + GLuint CMD, BR13; + BATCH_LOCALS; + + switch(cpp) { + case 2: + BR13 = (pitch) | (0xCC << 16) | (1<<24); + CMD = XY_SRC_COPY_BLT_CMD; + break; + case 4: + BR13 = (pitch) | (0xCC << 16) | (1<<24) | (1<<25); + CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + break; + default: + BR13 = (pitch) | (0xCC << 16) | (1<<24); + CMD = XY_SRC_COPY_BLT_CMD; + break; } + + if (0) + intel_draw_performance_boxes( intel ); - BEGIN_BATCH( 8); - OUT_BATCH( CMD ); - OUT_BATCH( BR13 ); - OUT_BATCH( (box.y1 << 16) | box.x1 ); - OUT_BATCH( (box.y2 << 16) | box.x2 ); + for (i = 0 ; i < nbox; i++, pbox++) + { + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + pbox->x2 > intelScreen->width || + pbox->y2 > intelScreen->height) { + _mesa_warning(&intel->ctx, "Bad cliprect in intelCopyBuffer()"); + continue; + } + + 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); + OUT_BATCH( CMD ); + OUT_BATCH( BR13 ); + OUT_BATCH( (box.y1 << 16) | box.x1 ); + OUT_BATCH( (box.y2 << 16) | box.x2 ); - if (intel->sarea->pf_current_page == 0) - OUT_BATCH( intelScreen->front.offset ); - else - OUT_BATCH( intelScreen->back.offset ); + if (intel->sarea->pf_current_page == 0) + OUT_BATCH( intelScreen->front.offset ); + else + OUT_BATCH( intelScreen->back.offset ); - OUT_BATCH( (box.y1 << 16) | box.x1 ); - OUT_BATCH( BR13 & 0xffff ); + OUT_BATCH( (box.y1 << 16) | box.x1 ); + OUT_BATCH( BR13 & 0xffff ); - if (intel->sarea->pf_current_page == 0) - OUT_BATCH( intelScreen->back.offset ); - else - OUT_BATCH( intelScreen->front.offset ); + if (intel->sarea->pf_current_page == 0) + OUT_BATCH( intelScreen->back.offset ); + else + OUT_BATCH( intelScreen->front.offset ); - ADVANCE_BATCH(); + ADVANCE_BATCH(); + } } + intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE ); + UNLOCK_HARDWARE( intel ); } - intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE ); - UNLOCK_HARDWARE( intel ); if (!rect) { diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h index 0ca8ff268de..6cd6272053f 100644 --- a/src/mesa/drivers/dri/i915/intel_context.h +++ b/src/mesa/drivers/dri/i915/intel_context.h @@ -261,6 +261,8 @@ struct intel_context GLuint swap_count; GLuint swap_missed_count; + + GLuint swap_scheduled; }; @@ -321,6 +323,13 @@ do { \ char __ret=0; \ DEBUG_CHECK_LOCK(); \ assert(!(intel)->locked); \ + if ((intel)->swap_scheduled) { \ + drmVBlank vbl; \ + vbl.request.type = DRM_VBLANK_ABSOLUTE; \ + vbl.request.sequence = (intel)->vbl_seq; \ + drmWaitVBlank((intel)->driFd, &vbl); \ + (intel)->swap_scheduled = 0; \ + } \ DRM_CAS((intel)->driHwLock, (intel)->hHWContext, \ (DRM_LOCK_HELD|(intel)->hHWContext), __ret); \ if (__ret) \ |