/*
 * Queue a flip back to the normal frame buffer
 */
static void
intel_present_unflip(ScreenPtr screen, uint64_t event_id)
{
	ScrnInfoPtr                             scrn = xf86ScreenToScrn(screen);
	intel_screen_private                    *intel = intel_get_screen_private(scrn);
	PixmapPtr                               pixmap = screen->GetScreenPixmap(screen);
	struct intel_present_vblank_event       *event = NULL;
	dri_bo                                  *bo;

	if (!intel_present_check_flip(NULL, screen->root, pixmap, true))
		goto fail;

	bo = intel_get_pixmap_bo(pixmap);
	if (!bo)
		goto fail;

	event = calloc(1, sizeof(struct intel_present_vblank_event));
	if (!event)
		goto fail;

	event->event_id = event_id;

	if (!intel_do_pageflip(intel, bo, -1, FALSE, event,
			       intel_present_flip_event,
			       intel_present_flip_abort))
		goto fail;

	return;
fail:
	xf86SetDesiredModes(scrn);
	present_event_notify(event_id, 0, 0);
	free(event);
}
static void
sna_present_unflip(ScreenPtr screen, uint64_t event_id)
{
	struct sna *sna = to_sna_from_screen(screen);
	struct kgem_bo *bo;

	DBG(("%s(event=%lld)\n", __FUNCTION__, (long long)event_id));
	if (sna->mode.front_active == 0 || sna->mode.shadow_active) {
		const struct ust_msc *swap;

		DBG(("%s: no CRTC active, perform no-op flip\n", __FUNCTION__));

notify:
		swap = sna_crtc_last_swap(sna_mode_first_crtc(sna));
		DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
		     -1,
		     swap->tv_sec, swap->tv_usec, (long long)swap->msc,
		     (long long)event_id));
		present_event_notify(event_id,
				     ust64(swap->tv_sec, swap->tv_usec),
				     swap->msc);
		return;
	}

	bo = get_flip_bo(screen->GetScreenPixmap(screen));
	if (bo == NULL || !page_flip(screen, NULL, event_id, bo)) {
		DBG(("%s: failed, trying to restore original mode\n", __FUNCTION__));
		xf86SetDesiredModes(sna->scrn);
		goto notify;
	}
}
static Bool
page_flip__async(RRCrtcPtr crtc,
		 uint64_t event_id,
		 uint64_t target_msc,
		 struct kgem_bo *bo)
{
	DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
	     __FUNCTION__,
	     pipe_from_crtc(crtc),
	     (long long)event_id,
	     bo->handle));

	if (!sna_page_flip(to_sna_from_screen(crtc->pScreen), bo, NULL, NULL)) {
		DBG(("%s: async pageflip failed\n", __FUNCTION__));
		present_info.capabilities &= ~PresentCapabilityAsync;
		return FALSE;
	}

	DBG(("%s: pipe=%d tv=%d.%06d msc=%d, event %lld complete\n", __FUNCTION__,
	     pipe_from_crtc(crtc),
	     gettime_ust64() / 1000000, gettime_ust64() % 1000000,
	     sna_crtc_last_swap(crtc->devPrivate)->msc,
	     (long long)event_id));
	present_event_notify(event_id, gettime_ust64(), target_msc);
	return TRUE;
}
/*
 * Once the flip has been completed on all pipes, notify the
 * extension code telling it when that happened
 */
static void
intel_present_flip_event(uint64_t msc, uint64_t ust, void *pageflip_data)
{
	struct intel_present_vblank_event *event = pageflip_data;

	present_event_notify(event->event_id, ust, msc);
	free(event);
}
/*
 * Called when the queued vblank event has occurred
 */
static void
intel_present_vblank_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t msc, uint64_t usec, void *data)
{
	struct intel_present_vblank_event       *event = data;

	present_event_notify(event->event_id, usec, msc);
	free(event);
}
static void
nouveau_present_vblank(void *priv, uint64_t name, uint64_t ust, uint32_t msc_lo)
{
	struct nouveau_present_vblank *event = priv;
	uint64_t msc;

	msc = (event->msc & 0xffffffff00000000ULL) | msc_lo;
	if (msc < event->msc)
		event->msc += 1ULL << 32;

	present_event_notify(name, ust, msc);
}
static void
nouveau_present_flip(void *priv, uint64_t name, uint64_t ust, uint32_t msc_lo)
{
	struct nouveau_present_flip *flip = priv;
	uint64_t msc;

	msc = (flip->msc & ~0xffffffffULL) | msc_lo;
	if (msc < flip->msc)
		msc += 1ULL << 32;

	present_event_notify(name, ust, msc);
	drmModeRmFB(flip->fd, flip->old);
}
Exemple #8
0
void
sna_present_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
{
	struct sna_present_event *info = to_present_event(event->user_data);

	DBG(("%s: pipe=%d event=%lld, tv=%d.%06d msc=%d\n", __FUNCTION__,
	     sna_crtc_to_pipe(info->crtc), (long long)info->event_id,
	     event->tv_sec, event->tv_usec, event->sequence));
	present_event_notify(info->event_id,
			     ust64(event->tv_sec, event->tv_usec),
			     sna_crtc_record_event(info->crtc, event));
	free(info);
}
Exemple #9
0
/*
 * Queue a flip back to the normal frame buffer
 */
static void
ms_present_unflip(ScreenPtr screen, uint64_t event_id)
{
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
    PixmapPtr pixmap = screen->GetScreenPixmap(screen);
    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
    int i;
    struct ms_present_vblank_event *event;

    event = calloc(1, sizeof(struct ms_present_vblank_event));
    if (!event)
        return;

    event->event_id = event_id;

    if (ms_present_check_flip(NULL, screen->root, pixmap, TRUE) &&
        ms_do_pageflip(screen, pixmap, event, -1, FALSE)) {
        return;
    }

    for (i = 0; i < config->num_crtc; i++) {
        xf86CrtcPtr crtc = config->crtc[i];
	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;

	if (!crtc->enabled)
	    continue;

	/* info->drmmode.fb_id still points to the FB for the last flipped BO.
	 * Clear it, drmmode_set_mode_major will re-create it
	 */
	if (drmmode_crtc->drmmode->fb_id) {
		drmModeRmFB(drmmode_crtc->drmmode->fd,
			    drmmode_crtc->drmmode->fb_id);
		drmmode_crtc->drmmode->fb_id = 0;
	}

	if (drmmode_crtc->dpms_mode == DPMSModeOn)
	    crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
					crtc->x, crtc->y);
	else
	    drmmode_crtc->need_modeset = TRUE;
    }

    present_event_notify(event_id, 0, 0);
}
Exemple #10
0
static void
present_flip_handler(struct drm_event_vblank *event, void *data)
{
	struct sna_present_event *info = data;
	struct ust_msc swap;

	DBG(("%s(sequence=%d)\n", __FUNCTION__, event->sequence));

	if (info->crtc == NULL) {
		swap.tv_sec = event->tv_sec;
		swap.tv_usec = event->tv_usec;
		swap.msc = event->sequence;
	} else
		swap = *sna_crtc_last_swap(info->crtc);

	DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
	     info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
	     swap.tv_sec, swap.tv_usec, (long long)swap.msc,
	     (long long)info->event_id));
	present_event_notify(info->event_id, ust64(swap.tv_sec, swap.tv_usec), swap.msc);
	free(info);
}
Exemple #11
0
/*
 * Flush the DRM event queue when full; makes space for new events.
 *
 * Returns a negative value on error, 0 if there was nothing to process,
 * or 1 if we handled any events.
 */
static int
ms_flush_drm_events(ScreenPtr screen)
{
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
    modesettingPtr ms = modesettingPTR(scrn);

    struct pollfd p = { .fd = ms->fd, .events = POLLIN };
    int r;

    do {
            r = poll(&p, 1, 0);
    } while (r == -1 && (errno == EINTR || errno == EAGAIN));

    /* If there was an error, r will be < 0.  Return that.  If there was
     * nothing to process, r == 0.  Return that.
     */
    if (r <= 0)
        return r;

    /* Try to handle the event.  If there was an error, return it. */
    r = drmHandleEvent(ms->fd, &ms->event_context);
    if (r < 0)
        return r;

    /* Otherwise return 1 to indicate that we handled an event. */
    return 1;
}

/*
 * Called when the queued vblank event has occurred
 */
static void
ms_present_vblank_handler(uint64_t msc, uint64_t usec, void *data)
{
    struct ms_present_vblank_event *event = data;

    DebugPresent(("\t\tmh %lld msc %llu\n",
                 (long long) event->event_id, (long long) msc));

    present_event_notify(event->event_id, usec, msc);
    free(event);
}

/*
 * Called when the queued vblank is aborted
 */
static void
ms_present_vblank_abort(void *data)
{
    struct ms_present_vblank_event *event = data;

    DebugPresent(("\t\tma %lld\n", (long long) event->event_id));

    free(event);
}

/*
 * Queue an event to report back to the Present extension when the specified
 * MSC has past
 */
static int
ms_present_queue_vblank(RRCrtcPtr crtc,
                        uint64_t event_id,
                        uint64_t msc)
{
    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
    ScreenPtr screen = crtc->pScreen;
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
    modesettingPtr ms = modesettingPTR(scrn);
    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
    struct ms_present_vblank_event *event;
    drmVBlank vbl;
    int ret;
    uint32_t seq;

    event = calloc(sizeof(struct ms_present_vblank_event), 1);
    if (!event)
        return BadAlloc;
    event->event_id = event_id;
    seq = ms_drm_queue_alloc(xf86_crtc, event,
                             ms_present_vblank_handler,
                             ms_present_vblank_abort);
    if (!seq) {
        free(event);
        return BadAlloc;
    }

    vbl.request.type =
        DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;
    vbl.request.sequence = ms_crtc_msc_to_kernel_msc(xf86_crtc, msc);
    vbl.request.signal = seq;
    for (;;) {
        ret = drmWaitVBlank(ms->fd, &vbl);
        if (!ret)
            break;
        /* If we hit EBUSY, then try to flush events.  If we can't, then
         * this is an error.
         */
        if (errno != EBUSY || ms_flush_drm_events(screen) < 0) {
	    ms_drm_abort_seq(scrn, seq);
            return BadAlloc;
        }
    }
    DebugPresent(("\t\tmq %lld seq %u msc %llu (hw msc %u)\n",
                 (long long) event_id, seq, (long long) msc,
                 vbl.request.sequence));
    return Success;
}