Browse Source

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.
tags/mesa_6_5_2
Michel Dänzer 19 years ago
parent
commit
c2f1a1857e

+ 113
- 79
src/mesa/drivers/dri/i915/intel_batchbuffer.c View File

const drm_clip_rect_t *rect) const drm_clip_rect_t *rect)
{ {
intelContextPtr intel; intelContextPtr intel;
const intelScreenPrivate *intelScreen;
GLboolean missed_target; GLboolean missed_target;
int64_t ust; int64_t ust;




intelFlush( &intel->ctx ); 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) if (!rect)
{ {

+ 9
- 0
src/mesa/drivers/dri/i915/intel_context.h View File



GLuint swap_count; GLuint swap_count;
GLuint swap_missed_count; GLuint swap_missed_count;

GLuint swap_scheduled;
}; };




char __ret=0; \ char __ret=0; \
DEBUG_CHECK_LOCK(); \ DEBUG_CHECK_LOCK(); \
assert(!(intel)->locked); \ 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_CAS((intel)->driHwLock, (intel)->hHWContext, \
(DRM_LOCK_HELD|(intel)->hHWContext), __ret); \ (DRM_LOCK_HELD|(intel)->hHWContext), __ret); \
if (__ret) \ if (__ret) \

Loading…
Cancel
Save