diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-06-11 10:15:14 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-06-12 10:44:18 +0100 |
commit | ff262aca9c46b7616c59d8e8f04d33a5bbc6e324 (patch) | |
tree | 0f77136a1b116aa20971383940994b5c56c5c665 /src/sna | |
parent | b199bc2b415fd0f06e456e0b1f44dd25ba8dbe02 (diff) |
sna/dri: Fix tripple-buffering for vblank_mode=0
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna')
-rw-r--r-- | src/sna/kgem.c | 23 | ||||
-rw-r--r-- | src/sna/kgem.h | 6 | ||||
-rw-r--r-- | src/sna/sna.h | 16 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 2 | ||||
-rw-r--r-- | src/sna/sna_display.c | 203 | ||||
-rw-r--r-- | src/sna/sna_dri.c | 517 | ||||
-rw-r--r-- | src/sna/sna_driver.c | 33 | ||||
-rw-r--r-- | src/sna/sna_video_textured.c | 7 |
8 files changed, 400 insertions, 407 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c index d6009368..8a8bca2a 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -515,6 +515,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo) bo->deleted = 1; } + kgem->need_expire = true; list_move(&bo->list, (bo->rq || bo->needs_flush) ? &kgem->active : inactive(kgem, bo->size)); if (bo->rq == NULL && bo->needs_flush) { assert(list_is_empty(&bo->request)); @@ -943,21 +944,6 @@ void kgem_throttle(struct kgem *kgem) } } -bool kgem_needs_expire(struct kgem *kgem) -{ - int i; - - if (!list_is_empty(&kgem->active)) - return true; - - for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++) { - if (!list_is_empty(&kgem->inactive[i])) - return true; - } - - return false; -} - bool kgem_expire_cache(struct kgem *kgem) { time_t now, expire; @@ -1018,6 +1004,7 @@ bool kgem_expire_cache(struct kgem *kgem) DBG(("%s: purge? %d -- expired %d objects, %d bytes\n", __FUNCTION__, kgem->need_purge, count, size)); + kgem->need_expire = !idle; kgem->need_purge = false; return idle; (void)count; @@ -1539,7 +1526,11 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo) if (ret) return 0; - bo->reusable = false; + /* Ordinarily giving the name aware makes the buffer non-reusable. + * However, we track the lifetime of all clients and their hold + * on the buffer, and *presuming* they do not pass it on to a third + * party, we track the lifetime accurately. + */ return flink.name; } diff --git a/src/sna/kgem.h b/src/sna/kgem.h index fc1c38cc..eb16ceb8 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -97,8 +97,9 @@ struct kgem { uint16_t nreloc; uint16_t nfence; - uint32_t flush; - uint32_t need_purge; + uint32_t flush:1; + uint32_t need_expire:1; + uint32_t need_purge:1; uint32_t has_vmap :1; uint32_t has_relaxed_fencing :1; @@ -312,7 +313,6 @@ struct kgem_bo *kgem_create_buffer(struct kgem *kgem, void kgem_buffer_sync(struct kgem *kgem, struct kgem_bo *bo); void kgem_throttle(struct kgem *kgem); -bool kgem_needs_expire(struct kgem *kgem); bool kgem_expire_cache(struct kgem *kgem); #if HAS_EXTRA_DEBUG diff --git a/src/sna/sna.h b/src/sna/sna.h index 844705d7..1173b7b2 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -120,13 +120,6 @@ static inline void list_add_tail(struct list *new, struct list *head) __list_add(new, head->prev, head); } -enum DRI2FrameEventType { - DRI2_SWAP, - DRI2_ASYNC_SWAP, - DRI2_FLIP, - DRI2_WAITMSC, -}; - #ifndef CREATE_PIXMAP_USAGE_SCRATCH_HEADER #define CREATE_PIXMAP_USAGE_SCRATCH_HEADER -1 #endif @@ -182,7 +175,6 @@ enum { OPTION_PREFER_OVERLAY, OPTION_COLOR_KEY, OPTION_VIDEO_KEY, - OPTION_SWAPBUFFERS_WAIT, OPTION_HOTPLUG, OPTION_THROTTLE, OPTION_RELAXED_FENCING, @@ -201,7 +193,6 @@ struct sna { unsigned flags; #define SNA_NO_THROTTLE 0x1 -#define SNA_SWAP_WAIT 0x2 int timer[NUM_TIMERS]; int timer_active; @@ -222,9 +213,6 @@ struct sna { struct sna_dri { int flip_pending[2]; - unsigned int fe_frame; - unsigned int fe_tv_sec; - unsigned int fe_tv_usec; } dri; unsigned int tiling; @@ -239,7 +227,9 @@ struct sna { struct intel_chipset chipset; ScreenBlockHandlerProcPtr BlockHandler; + void *BlockData; ScreenWakeupHandlerProcPtr WakeupHandler; + void *WakeupData; CloseScreenProcPtr CloseScreen; union { @@ -315,7 +305,7 @@ extern xf86CrtcPtr sna_covering_crtc(ScrnInfoPtr scrn, BoxPtr crtc_box_ret); extern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap, - xf86CrtcPtr crtc, RegionPtr clip); + xf86CrtcPtr crtc, const BoxRec *clip); Bool sna_dri_open(struct sna *sna, ScreenPtr pScreen); void sna_dri_wakeup(struct sna *sna); diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index d84d7031..8a8165e8 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -3131,7 +3131,7 @@ static Bool sna_accel_do_expire(struct sna *sna) return_if_timer_active(EXPIRE_TIMER); - if (!kgem_needs_expire(&sna->kgem)) + if (!sna->kgem.need_expire) return FALSE; if (sna->timer[EXPIRE_TIMER] == -1) diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 6131be19..bf0b98ff 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1310,11 +1310,8 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num) if (xf86IsEntityShared(scrn->entityList[0])) { s = xf86GetOptValString(sna->Options, OPTION_ZAPHOD); - if (s && !sna_zaphod_match(scrn, s, name)) { - ErrorF("output '%s' not matched for zaphod '%s'\n", - name, s); + if (s && !sna_zaphod_match(scrn, s, name)) goto cleanup_encoder; - } } output = xf86OutputCreate(scrn, &sna_output_funcs, name); @@ -1492,7 +1489,8 @@ static int do_page_flip(struct sna *sna, void *data, int ref_crtc_hw_id) struct sna_crtc *crtc = config->crtc[i]->driver_private; uintptr_t evdata; - if (!config->crtc[i]->enabled) + DBG(("%s: crtc %d active? %d\n",__FUNCTION__, i,crtc->active)); + if (!crtc->active) continue; /* Only the reference crtc will finally deliver its page flip @@ -1510,8 +1508,12 @@ static int do_page_flip(struct sna *sna, void *data, int ref_crtc_hw_id) sna->mode.fb_id, DRM_MODE_PAGE_FLIP_EVENT, (void*)evdata)) { + int err = errno; + DBG(("%s: flip [fb=%d] on crtc %d [%d] failed - %d\n", + __FUNCTION__, sna->mode.fb_id, + i, crtc_id(crtc), err)); xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING, - "flip queue failed: %s\n", strerror(errno)); + "flip queue failed: %s\n", strerror(err)); continue; } @@ -1531,11 +1533,12 @@ sna_do_pageflip(struct sna *sna, { ScrnInfoPtr scrn = sna->scrn; struct sna_mode *mode = &sna->mode; - struct kgem_bo *bo = sna_pixmap_pin(pixmap); + struct kgem_bo *bo; int count; assert(pixmap != sna->front); + bo = sna_pixmap_pin(pixmap); if (!bo) return 0; @@ -1574,20 +1577,13 @@ sna_do_pageflip(struct sna *sna, * may never complete; this is a configuration error. */ count = do_page_flip(sna, data, ref_crtc_hw_id); + DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count)); if (count > 0) { - int id = sna->front->drawable.serialNumber; - sna->front = pixmap; pixmap->refcnt++; sna_redirect_screen_pixmap(scrn, *old_front, sna->front); scrn->displayWidth = bo->pitch / sna->mode.cpp; - - /* DRI2 uses the serialNumber as a means for detecting - * when to revoke its buffers after a reconfigureatin event. - * For the ScreenPixmap this means set_size. - */ - pixmap->drawable.serialNumber = id; } else { drmModeRmFB(sna->kgem.fd, mode->fb_id); mode->fb_id = *old_fb; @@ -1683,11 +1679,23 @@ static void sna_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) { if (crtc->enabled) { crtc_box->x1 = crtc->x; - crtc_box->x2 = - crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); crtc_box->y1 = crtc->y; - crtc_box->y2 = - crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + + switch (crtc->rotation & 0xf) { + default: + assert(0); + case RR_Rotate_0: + case RR_Rotate_180: + crtc_box->x2 = crtc->x + crtc->mode.HDisplay; + crtc_box->y2 = crtc->y + crtc->mode.VDisplay; + break; + + case RR_Rotate_90: + case RR_Rotate_270: + crtc_box->x2 = crtc->x + crtc->mode.VDisplay; + crtc_box->y2 = crtc->y + crtc->mode.HDisplay; + break; + } } else crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; } @@ -1781,74 +1789,51 @@ sna_covering_crtc(ScrnInfoPtr scrn, return best_crtc; } -bool -sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap, - xf86CrtcPtr crtc, RegionPtr clip) -{ - pixman_box16_t box, crtc_box; - int pipe, event; - Bool full_height; - int y1, y2; - uint32_t *b; +/* Gen6 wait for scan line support */ +#define MI_LOAD_REGISTER_IMM (0x22<<23) - /* XXX no wait for scanline support on SNB? */ - if (sna->kgem.gen >= 60) - return false; +/* gen6: Scan lines register */ +#define GEN6_PIPEA_SLC (0x7004) +#define GEN6_PIPEB_SLC (0x7104) - if (!pixmap_is_scanout(pixmap)) - return false; +static void sna_emit_wait_for_scanline_gen6(struct sna *sna, + int pipe, int y1, int y2, + bool full_height) +{ + uint32_t event; + uint32_t *b; - if (crtc == NULL) { - if (clip) { - crtc_box = *REGION_EXTENTS(NULL, clip); - } else { - crtc_box.x1 = 0; /* XXX drawable offsets? */ - crtc_box.y1 = 0; - crtc_box.x2 = pixmap->drawable.width; - crtc_box.y2 = pixmap->drawable.height; - } - crtc = sna_covering_crtc(sna->scrn, &crtc_box, NULL, &crtc_box); + /* We just wait until the trace passes the roi */ + if (pipe == 0) { + pipe = GEN6_PIPEA_SLC; + event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW; + } else { + pipe = GEN6_PIPEB_SLC; + event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW; } - if (crtc == NULL) - return false; - - if (clip) { - box = *REGION_EXTENTS(unused, clip); - - if (crtc->transform_in_use) - pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &box); - - /* We could presume the clip was correctly computed... */ - sna_crtc_box(crtc, &crtc_box); - sna_box_intersect(&box, &crtc_box, &box); + kgem_set_mode(&sna->kgem, KGEM_RENDER); + b = kgem_get_batch(&sna->kgem, 4); + b[0] = MI_LOAD_REGISTER_IMM | 1; + b[1] = pipe; + b[2] = y2 - 1; + b[3] = MI_WAIT_FOR_EVENT | event; + kgem_advance_batch(&sna->kgem, 4); +} - /* - * Make sure we don't wait for a scanline that will - * never occur - */ - y1 = (crtc_box.y1 <= box.y1) ? box.y1 - crtc_box.y1 : 0; - y2 = (box.y2 <= crtc_box.y2) ? - box.y2 - crtc_box.y1 : crtc_box.y2 - crtc_box.y1; - if (y2 <= y1) - return false; - - full_height = FALSE; - if (y1 == 0 && y2 == (crtc_box.y2 - crtc_box.y1)) - full_height = TRUE; - } else { - sna_crtc_box(crtc, &crtc_box); - y1 = crtc_box.y1; - y2 = crtc_box.y2; - full_height = TRUE; - } +static void sna_emit_wait_for_scanline_gen2(struct sna *sna, + int pipe, int y1, int y2, + bool full_height) +{ + uint32_t event; + uint32_t *b; /* * Pre-965 doesn't have SVBLANK, so we need a bit * of extra time for the blitter to start up and * do its job for a full height blit */ - if (sna_crtc_to_pipe(crtc) == 0) { + if (pipe == 0) { pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEA; event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW; if (full_height) @@ -1860,11 +1845,8 @@ sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap, event = MI_WAIT_FOR_PIPEB_SVBLANK; } - if (crtc->mode.Flags & V_INTERLACE) { - /* DSL count field lines */ - y1 /= 2; - y2 /= 2; - } + if (sna->kgem.mode == KGEM_NONE) + kgem_set_mode(&sna->kgem, KGEM_BLT); b = kgem_get_batch(&sna->kgem, 5); /* The documentation says that the LOAD_SCAN_LINES command @@ -1875,5 +1857,66 @@ sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap, b[3] = (y1 << 16) | (y2-1); b[4] = MI_WAIT_FOR_EVENT | event; kgem_advance_batch(&sna->kgem, 5); +} + +bool +sna_wait_for_scanline(struct sna *sna, + PixmapPtr pixmap, + xf86CrtcPtr crtc, + const BoxRec *clip) +{ + pixman_box16_t box, crtc_box; + Bool full_height; + int y1, y2, pipe; + + if (sna->kgem.gen >= 60) + return false; + + if (!pixmap_is_scanout(pixmap)) + return false; + + if (crtc == NULL) { + crtc = sna_covering_crtc(sna->scrn, clip, NULL, &crtc_box); + assert(crtc); + } else + sna_crtc_box(crtc, &crtc_box); + + if (crtc->transform_in_use) { + box = *clip; + pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &box); + clip = &box; + } + + /* + * Make sure we don't wait for a scanline that will + * never occur + */ + y1 = clip->y1 - crtc_box.y1; + if (y1 < 0) + y1 = 0; + y2 = clip->y2 - crtc_box.y1; + if (y2 > crtc_box.y2 - crtc_box.y1) + y2 = crtc_box.y2 - crtc_box.y1; + DBG(("%s: clipped range = %d, %d\n", __FUNCTION__, y1, y2)); + if (y2 <= y1) + return false; + + full_height = y1 == 0 && y2 == crtc_box.y2 - crtc_box.y1; + + if (crtc->mode.Flags & V_INTERLACE) { + /* DSL count field lines */ + y1 /= 2; + y2 /= 2; + } + + pipe = sna_crtc_to_pipe(crtc); + DBG(("%s: pipe=%d, y1=%d, y2=%d, full_height?=%d\n", + __FUNCTION__, pipe, y1, y2, full_height)); + + if (sna->kgem.gen >= 60) + sna_emit_wait_for_scanline_gen6(sna, pipe, y1, y2, full_height); + else + sna_emit_wait_for_scanline_gen2(sna, pipe, y1, y2, full_height); + return true; } diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c index 94cd2059..14a2f3d1 100644 --- a/src/sna/sna_dri.c +++ b/src/sna/sna_dri.c @@ -77,6 +77,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define NDEBUG 1 #endif +enum frame_event_type { + DRI2_SWAP, + DRI2_SWAP_THROTTLE, + DRI2_ASYNC_FLIP, + DRI2_FLIP, + DRI2_WAITMSC, +}; + struct sna_dri_private { int refcnt; PixmapPtr pixmap; @@ -88,7 +96,7 @@ struct sna_dri_frame_event { XID drawable_id; XID client_id; /* fake client ID to track client destruction */ ClientPtr client; - enum DRI2FrameEventType type; + enum frame_event_type type; int frame; int pipe; int count; @@ -99,6 +107,10 @@ struct sna_dri_frame_event { DRI2BufferPtr front; DRI2BufferPtr back; + unsigned int fe_frame; + unsigned int fe_tv_sec; + unsigned int fe_tv_usec; + PixmapPtr old_front; uint32_t old_fb; }; @@ -291,13 +303,11 @@ static void sna_dri_reference_buffer(DRI2Buffer2Ptr buffer) } } -static void damage(DrawablePtr drawable, RegionPtr region) +static void damage(DrawablePtr drawable, PixmapPtr pixmap, RegionPtr region) { - PixmapPtr pixmap; struct sna_pixmap *priv; int16_t dx, dy; - pixmap = get_drawable_pixmap(drawable); get_drawable_deltas(drawable, pixmap, &dx, &dy); priv = sna_pixmap(pixmap); @@ -350,51 +360,65 @@ static void damage(DrawablePtr drawable, RegionPtr region) } static void -sna_dri_copy_region(DrawablePtr drawable, RegionPtr region, - DRI2BufferPtr dst_buffer, DRI2BufferPtr src_buffer) +sna_dri_copy_region(DrawablePtr draw, + RegionPtr region, + DRI2BufferPtr dst_buffer, + DRI2BufferPtr src_buffer) { - struct sna *sna = to_sna_from_drawable(drawable); - struct sna_dri_private *srcPrivate = src_buffer->driverPrivate; - struct sna_dri_private *dstPrivate = dst_buffer->driverPrivate; - ScreenPtr screen = drawable->pScreen; - DrawablePtr src = (src_buffer->attachment == DRI2BufferFrontLeft) - ? drawable : &srcPrivate->pixmap->drawable; - DrawablePtr dst = (dst_buffer->attachment == DRI2BufferFrontLeft) - ? drawable : &dstPrivate->pixmap->drawable; - GCPtr gc; - bool flush = false; + struct sna *sna = to_sna_from_drawable(draw); + struct sna_dri_private *src_priv = src_buffer->driverPrivate; + struct sna_dri_private *dst_priv = dst_buffer->driverPrivate; + PixmapPtr src = src_priv->pixmap; + PixmapPtr dst = dst_priv->pixmap; + pixman_region16_t clip; DBG(("%s(region=(%d, %d), (%d, %d)))\n", __FUNCTION__, region ? REGION_EXTENTS(NULL, region)->x1 : 0, region ? REGION_EXTENTS(NULL, region)->y1 : 0, - region ? REGION_EXTENTS(NULL, region)->x2 : dst->width, - region ? REGION_EXTENTS(NULL, region)->y2 : dst->height)); + region ? REGION_EXTENTS(NULL, region)->x2 : draw->width, + region ? REGION_EXTENTS(NULL, region)->y2 : draw->height)); DBG(("%s: dst -- attachment=%d, name=%d, handle=%d\n", __FUNCTION__, dst_buffer->attachment, dst_buffer->name, - dstPrivate->bo->handle)); + dst_priv->bo->handle)); DBG(("%s: src -- attachment=%d, name=%d, handle=%d\n", __FUNCTION__, src_buffer->attachment, src_buffer->name, - srcPrivate->bo->handle)); + src_priv->bo->handle)); - gc = GetScratchGC(dst->depth, screen); - if (!gc) - return; - - if (region) { - RegionPtr clip; + if (draw->type == DRAWABLE_WINDOW) { + WindowPtr win = (WindowPtr)draw; - clip = REGION_CREATE(screen, NULL, 0); - pixman_region_intersect_rect(clip, region, - 0, 0, dst->width, dst->height); - (*gc->funcs->ChangeClip)(gc, CT_REGION, clip, 0); - region = clip; + pixman_region_init(&clip); + pixman_region_intersect(&clip, &win->clipList, region); + if (!pixman_region_not_empty(&clip)) { + DBG(("%s: all clipped\n", __FUNCTION__)); + return; + } + region = &clip; } - ValidateGC(dst, gc); + + assert(sna_pixmap(src)->cpu_damage == NULL); + assert(sna_pixmap(dst)->cpu_damage == NULL); + + /* It's important that this copy gets submitted before the + * direct rendering client submits rendering for the next + * frame, but we don't actually need to submit right now. The + * client will wait for the DRI2CopyRegion reply or the swap + * buffer event before rendering, and we'll hit the flush + * callback chain before those messages are sent. We submit + * our batch buffers from the flush callback chain so we know + * that will happen before the client tries to render + * again. + */ + sna->render.copy_boxes(sna, GXcopy, + src, src_priv->bo, draw->x, draw->y, + dst, dst_priv->bo, draw->x, draw->y, + REGION_RECTS(region), + REGION_NUM_RECTS(region)); /* Invalidate src to reflect unknown modifications made by the client * @@ -402,12 +426,46 @@ sna_dri_copy_region(DrawablePtr drawable, RegionPtr region, * between the last flush and this request? Hopefully nobody will * hit that race window to find out... */ - damage(src, region); + damage(draw, src, region); + damage(draw, dst, region); + if (region == &clip) + pixman_region_fini(&clip); +} + +static void +sna_dri_swap_blit(struct sna *sna, DrawablePtr draw, DRI2BufferPtr back) +{ + struct sna_dri_private *src_priv = back->driverPrivate; + PixmapPtr src = src_priv->pixmap; + PixmapPtr dst = sna->front; + bool flush = false; + BoxRec box, *boxes; + int n; + + DBG(("%s: back -- attachment=%d, name=%d, handle=%d\n", + __FUNCTION__, + back->attachment, + back->name, + src_priv->bo->handle)); + + if (draw->type == DRAWABLE_PIXMAP) { + box.x1 = box.y1 = 0; + box.x2 = draw->width; + box.y2 = draw->height; + + boxes = &box; + n = 1; + } else { + WindowPtr win = (WindowPtr)draw; + + boxes = REGION_RECTS(&win->clipList); + n = REGION_NUM_RECTS(&win->clipList); + if (n == 0) + return; - /* Wait for the scanline to be outside the region to be copied */ - if (sna->flags & SNA_SWAP_WAIT) - flush = sna_wait_for_scanline(sna, get_drawable_pixmap(dst), - NULL, region); + flush = sna_wait_for_scanline(sna, sna->front, + NULL, &win->clipList.extents); + } /* It's important that this copy gets submitted before the * direct rendering client submits rendering for the next @@ -419,11 +477,19 @@ sna_dri_copy_region(DrawablePtr drawable, RegionPtr region, * that will happen before the client tries to render * again. */ - gc->ops->CopyArea(src, dst, gc, - 0, 0, - drawable->width, drawable->height, - 0, 0); - FreeScratchGC(gc); + sna->render.copy_boxes(sna, GXcopy, + src, src_priv->bo, draw->x, draw->y, + dst, sna_pixmap_get_bo(dst), draw->x, draw->y, + boxes, n); + + /* Invalidate src to reflect unknown modifications made by the client + * + * XXX But what about any conflicting shadow writes made by others + * between the last flush and this request? Hopefully nobody will + * hit that race window to find out... + */ + damage(draw, src, NULL); + damage(draw, dst, NULL); DBG(("%s: flushing? %d\n", __FUNCTION__, flush)); if (flush) /* STAT! */ @@ -432,12 +498,10 @@ sna_dri_copy_region(DrawablePtr drawable, RegionPtr region, #if DRI2INFOREC_VERSION >= 4 - static int sna_dri_get_pipe(DrawablePtr pDraw) { - ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum]; BoxRec box, crtcbox; xf86CrtcPtr crtc; int pipe; @@ -533,7 +597,7 @@ sna_dri_add_frame_event(struct sna_dri_frame_event *frame_event) } static void -sna_dri_frame_event_info(struct sna_dri_frame_event *info) +sna_dri_frame_event_info_free(struct sna_dri_frame_event *info) { if (info->client_id) FreeResourceByType(info->client_id, @@ -559,7 +623,8 @@ sna_dri_exchange_buffers(DrawablePtr draw, { int tmp; - DBG(("%s()\n", __FUNCTION__)); + DBG(("%s(%d <--> %d)\n", + __FUNCTION__, front->attachment, back->attachment)); assert(front->format == back->format); @@ -577,83 +642,21 @@ sna_dri_schedule_flip(struct sna *sna, DrawablePtr draw, struct sna_dri_frame_event *info) { - struct sna_dri *dri = &sna->dri; struct sna_dri_private *back_priv; - /* Main crtc for this drawable shall finally deliver pageflip event. */ - int ref_crtc_hw_id = sna_dri_get_pipe(draw); - DBG(("%s()\n", __FUNCTION__)); - dri->fe_frame = 0; - dri->fe_tv_sec = 0; - dri->fe_tv_usec = 0; - /* Page flip the full screen buffer */ back_priv = info->back->driverPrivate; info->count = sna_do_pageflip(sna, back_priv->pixmap, - info, ref_crtc_hw_id, + info, info->pipe, &info->old_front, &info->old_fb); return info->count != 0; } static Bool -can_exchange(DRI2BufferPtr front, - DRI2BufferPtr back) -{ - struct sna_dri_private *front_priv = front->driverPrivate; - struct sna_dri_private *back_priv = back->driverPrivate; - PixmapPtr front_pixmap = front_priv->pixmap; - PixmapPtr back_pixmap = back_priv->pixmap; - struct sna_pixmap *front_sna, *back_sna; - - if (front_pixmap->drawable.width != back_pixmap->drawable.width) { - DBG(("%s -- no, size mismatch: front width=%d, back=%d\n", - __FUNCTION__, - front_pixmap->drawable.width, - back_pixmap->drawable.width)); - return FALSE; - } - - if (front_pixmap->drawable.height != back_pixmap->drawable.height) { - DBG(("%s -- no, size mismatch: front height=%d, back=%d\n", - __FUNCTION__, - front_pixmap->drawable.height, - back_pixmap->drawable.height)); - return FALSE; - } - - if (front_pixmap->drawable.bitsPerPixel != back_pixmap->drawable.bitsPerPixel) { - DBG(("%s -- no, depth mismatch: front bpp=%d, back=%d\n", - __FUNCTION__, - front_pixmap->drawable.bitsPerPixel, - back_pixmap->drawable.bitsPerPixel)); - return FALSE; - } - - /* prevent an implicit tiling mode change */ - front_sna = sna_pixmap(front_pixmap); - back_sna = sna_pixmap(back_pixmap); - if (front_sna->gpu_bo->tiling != back_sna->gpu_bo->tiling) { - DBG(("%s -- no, tiling mismatch: front %d, back=%d\n", - __FUNCTION__, - front_sna->gpu_bo->tiling, - back_sna->gpu_bo->tiling)); - return FALSE; - } - - if (front_sna->gpu_only != back_sna->gpu_only) { - DBG(("%s -- no, mismatch in gpu_only: front %d, back=%d\n", - __FUNCTION__, front_sna->gpu_only, back_sna->gpu_only)); - return FALSE; - } - - return TRUE; -} - -static Bool can_flip(struct sna * sna, DrawablePtr draw, DRI2BufferPtr front, @@ -773,78 +776,59 @@ static void sna_dri_vblank_handle(int fd, unsigned int tv_usec, void *data) { - struct sna_dri_frame_event *swap_info = data; + struct sna_dri_frame_event *info = data; DrawablePtr draw; - ScreenPtr screen; - ScrnInfoPtr scrn; struct sna *sna; int status; DBG(("%s(id=%d, type=%d)\n", __FUNCTION__, - (int)swap_info->drawable_id, swap_info->type)); + (int)info->drawable_id, info->type)); status = BadDrawable; - if (swap_info->drawable_id) + if (info->drawable_id) status = dixLookupDrawable(&draw, - swap_info->drawable_id, + info->drawable_id, serverClient, M_ANY, DixWriteAccess); if (status != Success) goto done; - screen = draw->pScreen; - scrn = xf86Screens[screen->myNum]; - sna = to_sna(scrn); + sna = to_sna_from_drawable(draw); - switch (swap_info->type) { + switch (info->type) { case DRI2_FLIP: /* If we can still flip... */ - if (can_flip(sna, draw, - swap_info->front, swap_info->back) && - sna_dri_schedule_flip(sna, draw, swap_info)) { - sna_dri_exchange_buffers(draw, - swap_info->front, - swap_info->back); + if (can_flip(sna, draw, info->front, info->back) && + sna_dri_schedule_flip(sna, draw, info)) { + sna_dri_exchange_buffers(draw, info->front, info->back); return; } /* else fall through to exchange/blit */ - case DRI2_SWAP: { - int swap_type; - - if (DRI2CanExchange(draw) && - can_exchange(swap_info->front, swap_info->back)) { - sna_dri_exchange_buffers(draw, - swap_info->front, - swap_info->back); - swap_type = DRI2_EXCHANGE_COMPLETE; - } else { - sna_dri_copy_region(draw, NULL, - swap_info->front, - swap_info->back); - swap_type = DRI2_BLIT_COMPLETE; - } - DRI2SwapComplete(swap_info->client, + case DRI2_SWAP: + sna_dri_swap_blit(sna, draw, info->back); + case DRI2_SWAP_THROTTLE: + DRI2SwapComplete(info->client, draw, frame, tv_sec, tv_usec, - swap_type, - swap_info->client ? swap_info->event_complete : NULL, - swap_info->event_data); + DRI2_BLIT_COMPLETE, + info->client ? info->event_complete : NULL, + info->event_data); break; - } + case DRI2_WAITMSC: - if (swap_info->client) - DRI2WaitMSCComplete(swap_info->client, draw, + if (info->client) + DRI2WaitMSCComplete(info->client, draw, frame, tv_sec, tv_usec); break; default: - xf86DrvMsg(scrn->scrnIndex, X_WARNING, + xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__); /* Unknown type */ break; } done: - sna_dri_frame_event_info(swap_info); + sna_dri_frame_event_info_free(info); } static void sna_dri_flip_event(struct sna *sna, @@ -855,9 +839,9 @@ static void sna_dri_flip_event(struct sna *sna, DBG(("%s(frame=%d, tv=%d.%06d, type=%d)\n", __FUNCTION__, - sna->dri.fe_frame, - sna->dri.fe_tv_sec, - sna->dri.fe_tv_usec, + flip->fe_frame, + flip->fe_tv_sec, + flip->fe_tv_usec, flip->type)); if (!flip->drawable_id) @@ -878,8 +862,8 @@ static void sna_dri_flip_event(struct sna *sna, * into account. This usually means some defective kms pageflip completion, * causing wrong (msc, ust) return values and possible visual corruption. */ - if ((sna->dri.fe_frame < flip->frame) && - (flip->frame - sna->dri.fe_frame < 5)) { + if ((flip->fe_frame < flip->frame) && + (flip->frame - flip->fe_frame < 5)) { static int limit = 5; /* XXX we are currently hitting this path with older @@ -888,25 +872,25 @@ static void sna_dri_flip_event(struct sna *sna, if (limit) { xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING, "%s: Pageflip completion has impossible msc %d < target_msc %d\n", - __func__, sna->dri.fe_frame, flip->frame); + __func__, flip->fe_frame, flip->frame); limit--; } /* All-0 values signal timestamping failure. */ - sna->dri.fe_frame = sna->dri.fe_tv_sec = sna->dri.fe_tv_usec = 0; + flip->fe_frame = flip->fe_tv_sec = flip->fe_tv_usec = 0; } DBG(("%s: flip complete\n", __FUNCTION__)); DRI2SwapComplete(flip->client, drawable, - sna->dri.fe_frame, - sna->dri.fe_tv_sec, - sna->dri.fe_tv_usec, + flip->fe_frame, + flip->fe_tv_sec, + flip->fe_tv_usec, DRI2_FLIP_COMPLETE, flip->client ? flip->event_complete : NULL, flip->event_data); break; - case DRI2_ASYNC_SWAP: + case DRI2_ASYNC_FLIP: DBG(("%s: async swap flip completed on pipe %d, pending %d\n", __FUNCTION__, flip->pipe, sna->dri.flip_pending[flip->pipe])); sna->dri.flip_pending[flip->pipe]--; @@ -925,16 +909,15 @@ sna_dri_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *data) { struct sna_dri_frame_event *info = to_frame_event(data); - struct sna_dri *dri = &info->sna->dri; DBG(("%s: pending flip_count=%d\n", __FUNCTION__, info->count)); /* Is this the event whose info shall be delivered to higher level? */ if ((uintptr_t)data & 1) { /* Yes: Cache msc, ust for later delivery. */ - dri->fe_frame = frame; - dri->fe_tv_sec = tv_sec; - dri->fe_tv_usec = tv_usec; + info->fe_frame = frame; + info->fe_tv_sec = tv_sec; + info->fe_tv_usec = tv_usec; } if (--info->count) @@ -943,7 +926,7 @@ sna_dri_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, sna_dri_flip_event(info->sna, info); sna_mode_delete_fb(info->sna, info->old_front, info->old_fb); - sna_dri_frame_event_info(info); + sna_dri_frame_event_info_free(info); } /* @@ -976,16 +959,20 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, struct sna *sna = to_sna(scrn); drmVBlank vbl; int pipe, flip; - struct sna_dri_frame_event *info; - enum DRI2FrameEventType swap_type = DRI2_SWAP; + struct sna_dri_frame_event *info = NULL; + enum frame_event_type swap_type = DRI2_SWAP; CARD64 current_msc; - DBG(("%s(target_msc=%llu)\n", __FUNCTION__, (long long)*target_msc)); + DBG(("%s(target_msc=%llu, divisor=%llu, remainder=%llu)\n", + __FUNCTION__, + (long long)*target_msc, + (long long)divisor, + (long long)remainder)); /* Drawable not displayed... just complete the swap */ pipe = sna_dri_get_pipe(draw); if (pipe == -1) - goto xchg_fallback; + goto blit_fallback; /* Truncate to match kernel interfaces; means occasional overflow * misses, but that's generally not a big deal */ @@ -995,7 +982,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, info = calloc(1, sizeof(struct sna_dri_frame_event)); if (!info) - goto xchg_fallback; + goto blit_fallback; info->sna = sna; info->drawable_id = draw->id; @@ -1004,10 +991,12 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, info->event_data = data; info->front = front; info->back = back; + info->pipe = pipe; if (!sna_dri_add_frame_event(info)) { free(info); - goto xchg_fallback; + info = NULL; + goto blit_fallback; } sna_dri_reference_buffer(front); @@ -1064,8 +1053,23 @@ immediate: return TRUE; } - /* Similarly, the CopyRegion blit is coupled to vsync. */ - goto blit_fallback; + DBG(("%s: emitting immediate vsync'ed blit, throttling client\n")); + + info->type = DRI2_SWAP_THROTTLE; + + vbl.request.type = + DRM_VBLANK_RELATIVE | + DRM_VBLANK_EVENT | + DRM_VBLANK_NEXTONMISS; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = 0; + vbl.request.signal = (unsigned long)info; + if (drmWaitVBlank(sna->kgem.fd, &vbl)) + sna_dri_frame_event_info_free(info); + + sna_dri_swap_blit(sna, draw, back); + return TRUE; } /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP. @@ -1126,15 +1130,10 @@ immediate: blit_fallback: DBG(("%s -- blit\n", __FUNCTION__)); - sna_dri_copy_region(draw, NULL, front, back); - sna_dri_frame_event_info(info); - swap_type = DRI2_BLIT_COMPLETE; - goto fallback; -xchg_fallback: - swap_type = DRI2_EXCHANGE_COMPLETE; - sna_dri_exchange_buffers(draw, front, back); -fallback: - DRI2SwapComplete(client, draw, 0, 0, 0, swap_type, func, data); + sna_dri_swap_blit(sna, draw, back); + if (info) + sna_dri_frame_event_info_free(info); + DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); *target_msc = 0; /* offscreen, so zero out target vblank count */ return TRUE; } @@ -1142,53 +1141,53 @@ fallback: #if DRI2INFOREC_VERSION >= 6 static void sna_dri_async_swap(ClientPtr client, DrawablePtr draw, - DRI2BufferPtr front, DRI2BufferPtr back, - DRI2SwapEventPtr func, void *data) + DRI2BufferPtr front, DRI2BufferPtr back, + DRI2SwapEventPtr func, void *data) { ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct sna *sna = to_sna(scrn); - int pipe = sna_dri_get_pipe(draw); int type = DRI2_EXCHANGE_COMPLETE; + struct sna_dri_private *back_priv = back->driverPrivate; + struct sna_dri_private *front_priv = front->driverPrivate; + PixmapPtr pixmap; + int pipe; DBG(("%s()\n", __FUNCTION__)); /* Drawable not displayed... just complete the swap */ - if (pipe == -1) - goto exchange; - - if (!can_flip(sna, draw, front, back)) { - /* Do an synchronous copy instead */ - struct sna_dri_private *front_priv = front->driverPrivate; - struct sna_dri_private *back_priv = back->driverPrivate; + pipe = sna_dri_get_pipe(draw); + if (pipe == -1 || !can_flip(sna, draw, front, back)) { BoxRec box, *boxes; - PixmapPtr dst; int n; - DBG(("%s: fallback blit: %dx%d\n", - __FUNCTION__, draw->width, draw->height)); - - /* XXX clipping */ if (draw->type == DRAWABLE_PIXMAP) { box.x1 = box.y1 = 0; box.x2 = draw->width; box.y2 = draw->height; - dst = front_priv->pixmap; boxes = &box; n = 1; } else { WindowPtr win = (WindowPtr)draw; - dst = sna->front; boxes = REGION_RECTS(&win->clipList); n = REGION_NUM_RECTS(&win->clipList); } - sna->render.copy_boxes(sna, GXcopy, - back_priv->pixmap, back_priv->bo, 0, 0, - dst, sna_pixmap_get_bo(dst), 0, 0, - boxes, n); + DBG(("%s: fallback blit: %dx%d\n", + __FUNCTION__, draw->width, draw->height)); + + if (n) { + sna->render.copy_boxes(sna, GXcopy, + back_priv->pixmap, + back_priv->bo, + 0, 0, + front_priv->pixmap, + front_priv->bo, + 0, 0, + boxes, n); + } DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); @@ -1197,72 +1196,60 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw, if (!sna->dri.flip_pending[pipe]) { struct sna_dri_frame_event *info; - struct sna_dri_private *back_priv = back->driverPrivate; - struct sna_pixmap *priv; - PixmapPtr src = back_priv->pixmap; - PixmapPtr copy; - BoxRec box; + DRI2BufferPtr t; DBG(("%s: no pending flip on pipe %d, so updating scanout\n", __FUNCTION__, pipe)); - copy = screen->CreatePixmap(screen, - src->drawable.width, - src->drawable.height, - src->drawable.depth, - SNA_CREATE_FB); - if (copy == NullPixmap) - goto exchange; - - priv = sna_pixmap_force_to_gpu(copy); - if (priv == NULL) { - screen->DestroyPixmap(copy); - goto exchange; - } - - box.x1 = box.y1 = 0; - box.x2 = src->drawable.width; - box.y2 = src->drawable.height; - if (!sna->render.copy_boxes(sna, GXcopy, - src, back_priv->bo, 0, 0, - copy, priv->gpu_bo, 0, 0, - &box, 1)) { - screen->DestroyPixmap(copy); - goto exchange; - } - sna_damage_all(&priv->gpu_damage, - src->drawable.width, src->drawable.height); - assert(priv->cpu_damage == NULL); - info = calloc(1, sizeof(struct sna_dri_frame_event)); if (!info) { - screen->DestroyPixmap(copy); goto exchange; } info->sna = sna; info->drawable_id = draw->id; info->client = client; - info->type = DRI2_ASYNC_SWAP; + info->type = DRI2_ASYNC_FLIP; info->pipe = pipe; if (!sna_dri_add_frame_event(info)) { free(info); - screen->DestroyPixmap(copy); goto exchange; } - info->count = sna_do_pageflip(sna, copy, info, pipe, + info->count = sna_do_pageflip(sna, back_priv->pixmap, + info, pipe, &info->old_front, &info->old_fb); - screen->DestroyPixmap(copy); if (info->count == 0) { + DBG(("%s: pageflip failed\n", __FUNCTION__)); free(info); goto exchange; } type = DRI2_FLIP_COMPLETE; sna->dri.flip_pending[pipe]++; + + /* and flip the pointers */ + t = front; + front = back; + back = t; + + front_priv = front->driverPrivate; + back_priv = back->driverPrivate; + } + + if (front_priv->pixmap == sna->front && + (pixmap = screen->CreatePixmap(screen, + draw->width, + draw->height, + draw->depth, + SNA_CREATE_FB))) { + screen->DestroyPixmap(front_priv->pixmap); + front_priv->pixmap = pixmap; + front_priv->bo = sna_pixmap_set_dri(sna, pixmap); + front->name = kgem_bo_flink(&sna->kgem, front_priv->bo); + front->pitch = front_priv->bo->pitch; } exchange: @@ -1278,11 +1265,9 @@ exchange: static int sna_dri_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) { - ScreenPtr screen = draw->pScreen; - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct sna *sna = to_sna(scrn); + struct sna *sna = to_sna_from_drawable(draw); drmVBlank vbl; - int ret, pipe = sna_dri_get_pipe(draw); + int pipe = sna_dri_get_pipe(draw); DBG(("%s()\n", __FUNCTION__)); @@ -1298,22 +1283,21 @@ sna_dri_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) vbl.request.type |= DRM_VBLANK_SECONDARY; vbl.request.sequence = 0; - ret = drmWaitVBlank(sna->kgem.fd, &vbl); - if (ret) { + if (drmWaitVBlank(sna->kgem.fd, &vbl)) { static int limit = 5; if (limit) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, + xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING, "%s:%d get vblank counter failed: %s\n", __FUNCTION__, __LINE__, strerror(errno)); limit--; } + DBG(("%s: failed on pipe %d\n", __FUNCTION__, pipe)); return FALSE; } *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; *msc = vbl.reply.sequence; - return TRUE; } @@ -1330,9 +1314,9 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc, ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct sna *sna = to_sna(scrn); - struct sna_dri_frame_event *wait_info; + struct sna_dri_frame_event *info; drmVBlank vbl; - int ret, pipe = sna_dri_get_pipe(draw); + int pipe = sna_dri_get_pipe(draw); CARD64 current_msc; DBG(("%s(target_msc=%llu, divisor=%llu, rem=%llu)\n", @@ -1351,22 +1335,21 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc, if (pipe == -1) goto out_complete; - wait_info = calloc(1, sizeof(struct sna_dri_frame_event)); - if (!wait_info) + info = calloc(1, sizeof(struct sna_dri_frame_event)); + if (!info) goto out_complete; - wait_info->sna = sna; - wait_info->drawable_id = draw->id; - wait_info->client = client; - wait_info->type = DRI2_WAITMSC; + info->sna = sna; + info->drawable_id = draw->id; + info->client = client; + info->type = DRI2_WAITMSC; /* Get current count */ vbl.request.type = DRM_VBLANK_RELATIVE; if (pipe > 0) vbl.request.type |= DRM_VBLANK_SECONDARY; vbl.request.sequence = 0; - ret = drmWaitVBlank(sna->kgem.fd, &vbl); - if (ret) { + if (drmWaitVBlank(sna->kgem.fd, &vbl)) { static int limit = 5; if (limit) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1398,9 +1381,8 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc, if (pipe > 0) vbl.request.type |= DRM_VBLANK_SECONDARY; vbl.request.sequence = target_msc; - vbl.request.signal = (unsigned long)wait_info; - ret = drmWaitVBlank(sna->kgem.fd, &vbl); - if (ret) { + vbl.request.signal = (unsigned long)info; + if (drmWaitVBlank(sna->kgem.fd, &vbl)) { static int limit = 5; if (limit) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1412,7 +1394,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc, goto out_complete; } - wait_info->frame = vbl.reply.sequence; + info->frame = vbl.reply.sequence; DRI2BlockClient(client, draw); return TRUE; } @@ -1437,9 +1419,8 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc, if ((current_msc % divisor) >= remainder) vbl.request.sequence += divisor; - vbl.request.signal = (unsigned long)wait_info; - ret = drmWaitVBlank(sna->kgem.fd, &vbl); - if (ret) { + vbl.request.signal = (unsigned long)info; + if (drmWaitVBlank(sna->kgem.fd, &vbl)) { static int limit = 5; if (limit) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1451,7 +1432,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc, goto out_complete; } - wait_info->frame = vbl.reply.sequence; + info->frame = vbl.reply.sequence; DRI2BlockClient(client, draw); return TRUE; diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index b9402e75..99701771 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -84,7 +84,6 @@ static OptionInfoRec sna_options[] = { {OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, - {OPTION_SWAPBUFFERS_WAIT, "SwapbuffersWait", OPTV_BOOLEAN, {0}, TRUE}, {OPTION_HOTPLUG, "HotPlug", OPTV_BOOLEAN, {0}, TRUE}, {OPTION_THROTTLE, "Throttle", OPTV_BOOLEAN, {0}, TRUE}, {OPTION_RELAXED_FENCING, "UseRelaxedFencing", OPTV_BOOLEAN, {0}, TRUE}, @@ -502,8 +501,6 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags) sna->flags = 0; if (!xf86ReturnOptValBool(sna->Options, OPTION_THROTTLE, TRUE)) sna->flags |= SNA_NO_THROTTLE; - if (xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE)) - sna->flags |= SNA_SWAP_WAIT; xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Framebuffer %s\n", sna->tiling & SNA_TILING_FB ? "tiled" : "linear"); @@ -511,8 +508,6 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags) sna->tiling & SNA_TILING_2D ? "tiled" : "linear"); xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "3D buffers %s\n", sna->tiling & SNA_TILING_3D ? "tiled" : "linear"); - xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n", - sna->flags & SNA_SWAP_WAIT ? "en" : "dis"); xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Throttling %sabled\n", sna->flags & SNA_NO_THROTTLE ? "dis" : "en"); @@ -558,18 +553,11 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags) static void sna_block_handler(int i, pointer data, pointer timeout, pointer read_mask) { - ScreenPtr screen = screenInfo.screens[i]; - ScrnInfoPtr scrn = xf86Screens[i]; - struct sna *sna = to_sna(scrn); + struct sna *sna = data; DBG(("%s\n", __FUNCTION__)); - screen->BlockHandler = sna->BlockHandler; - - (*screen->BlockHandler) (i, data, timeout, read_mask); - - sna->BlockHandler = screen->BlockHandler; - screen->BlockHandler = sna_block_handler; + sna->BlockHandler(i, sna->BlockData, timeout, read_mask); sna_accel_block_handler(sna); } @@ -577,19 +565,10 @@ sna_block_handler(int i, pointer data, pointer timeout, pointer read_mask) static void sna_wakeup_handler(int i, pointer data, unsigned long result, pointer read_mask) { - ScreenPtr screen = screenInfo.screens[i]; - ScrnInfoPtr scrn = xf86Screens[i]; - struct sna *sna = to_sna(scrn); + struct sna *sna = data; DBG(("%s\n", __FUNCTION__)); - screen->WakeupHandler = sna->WakeupHandler; - - (*screen->WakeupHandler) (i, data, result, read_mask); - - sna->WakeupHandler = screen->WakeupHandler; - screen->WakeupHandler = sna_wakeup_handler; - /* despite all appearances, result is just a signed int */ if ((int)result < 0) return; @@ -597,6 +576,8 @@ sna_wakeup_handler(int i, pointer data, unsigned long result, pointer read_mask) if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask)) sna_dri_wakeup(sna); + sna->WakeupHandler(i, sna->WakeupData, result, read_mask); + sna_accel_wakeup_handler(sna); } @@ -852,10 +833,14 @@ sna_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) scrn->vtSema = TRUE; sna->BlockHandler = screen->BlockHandler; + sna->BlockData = screen->blockData; screen->BlockHandler = sna_block_handler; + screen->blockData = sna; sna->WakeupHandler = screen->WakeupHandler; + sna->WakeupData = screen->wakeupData; screen->WakeupHandler = sna_wakeup_handler; + screen->wakeupData = sna; screen->SaveScreen = xf86SaveScreen; sna->CloseScreen = screen->CloseScreen; diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c index 66c70d4a..a10c6769 100644 --- a/src/sna/sna_video_textured.c +++ b/src/sna/sna_video_textured.c @@ -238,6 +238,7 @@ sna_video_textured_put_image(ScrnInfoPtr scrn, BoxRec dstBox; xf86CrtcPtr crtc; int top, left, npixels, nlines; + Bool flush = false; if (!sna_video_clip_helper(scrn, video, &crtc, &dstBox, src_x, src_y, drw_x, drw_y, @@ -267,7 +268,8 @@ sna_video_textured_put_image(ScrnInfoPtr scrn, } if (crtc && video->SyncToVblank != 0) - sna_wait_for_scanline(sna, pixmap, crtc, clip); + flush = sna_wait_for_scanline(sna, pixmap, crtc, + &clip->extents); sna->render.video(sna, video, &frame, clip, src_w, src_h, @@ -281,7 +283,8 @@ sna_video_textured_put_image(ScrnInfoPtr scrn, /* Push the frame to the GPU as soon as possible so * we can hit the next vsync. */ - kgem_submit(&sna->kgem); + if (flush) + kgem_submit(&sna->kgem); return Success; } |