summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel@daenzer.net>2006-09-28 14:07:12 +0000
committerMichel Dänzer <michel@daenzer.net>2006-09-28 14:07:12 +0000
commitc2f1a1857e553f4d11fc0715bb586f69ac147df0 (patch)
treef5f5df3cba64993e27dba88a48c48021f8d7eb25
parent7585fc989de1eabe7b978226b8750f912f06778c (diff)
i915: Attempt to schedule buffer swap on target vertical blank when possible.
This has some advantages over the traditional way of first waiting for the target vertical blank and then emitting the buffer swap, e.g. * glXSwapBuffers returns immediately, only the next time the driver needs the hardware lock will it block until the target vertical blank. This should allow applications that don't intermix rendering and other processing to start processing for the next frame right away. * It's less likely to produce tearing.
-rw-r--r--src/mesa/drivers/dri/i915/intel_batchbuffer.c192
-rw-r--r--src/mesa/drivers/dri/i915/intel_context.h9
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 dd754c67d4..8b1c1c5b98 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 0ca8ff268d..6cd6272053 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) \