[PATCH v4 xserver 2/4] modesetting: move ms_do_pageflip to pageflip.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Qiang Yu <Qiang.Yu at amd.com>
Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
---
 hw/xfree86/drivers/modesetting/Makefile.am |   1 +
 hw/xfree86/drivers/modesetting/driver.h    |  48 ++++++
 hw/xfree86/drivers/modesetting/pageflip.c  | 251 ++++++++++++++++++++++++++++
 hw/xfree86/drivers/modesetting/present.c   | 252 -----------------------------
 4 files changed, 300 insertions(+), 252 deletions(-)
 create mode 100644 hw/xfree86/drivers/modesetting/pageflip.c

diff --git a/hw/xfree86/drivers/modesetting/Makefile.am b/hw/xfree86/drivers/modesetting/Makefile.am
index ca7e05a..44823b0 100644
--- a/hw/xfree86/drivers/modesetting/Makefile.am
+++ b/hw/xfree86/drivers/modesetting/Makefile.am
@@ -54,6 +54,7 @@ modesetting_drv_la_SOURCES = \
 	 sh3224.c \
 	 sh3224.h \
 	 vblank.c \
+	 pageflip.c \
 	 $(NULL)
 
 drivermandir = $(DRIVER_MAN_DIR)
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 498b9bf..c0d80a8 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -153,3 +153,51 @@ Bool ms_vblank_screen_init(ScreenPtr screen);
 void ms_vblank_close_screen(ScreenPtr screen);
 
 Bool ms_present_screen_init(ScreenPtr screen);
+
+#ifdef GLAMOR
+
+/*
+ * Event data for an in progress flip.
+ * This contains a pointer to the vblank event,
+ * and information about the flip in progress.
+ * a reference to this is stored in the per-crtc
+ * flips.
+ */
+struct ms_flipdata {
+    ScreenPtr screen;
+    void *event;
+    /* number of CRTC events referencing this */
+    int flip_count;
+    uint64_t fe_msc;
+    uint64_t fe_usec;
+    uint32_t old_fb_id;
+};
+
+/*
+ * Per crtc pageflipping infomation,
+ * These are submitted to the queuing code
+ * one of them per crtc per flip.
+ */
+struct ms_crtc_pageflip {
+    Bool on_reference_crtc;
+    /* reference to the ms_flipdata */
+    struct ms_flipdata *flipdata;
+};
+
+typedef void (*ms_pageflip_handler_proc)(uint64_t frame,
+                                         uint64_t usec,
+                                         void *data);
+
+typedef void (*ms_pageflip_abort_proc)(void *data);
+
+int ms_flush_drm_events(ScreenPtr screen);
+
+Bool ms_do_pageflip(ScreenPtr screen,
+                    PixmapPtr new_front,
+                    void *event,
+                    int ref_crtc_vblank_pipe,
+                    Bool async,
+                    ms_pageflip_handler_proc pageflip_handler,
+                    ms_pageflip_abort_proc pageflip_abort);
+
+#endif
diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c
new file mode 100644
index 0000000..4549792
--- /dev/null
+++ b/hw/xfree86/drivers/modesetting/pageflip.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <xserver_poll.h>
+#include <xf86drm.h>
+
+#include "driver.h"
+
+#ifdef GLAMOR
+
+/*
+ * 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.
+ */
+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 = xserver_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;
+}
+
+static Bool
+queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
+                   struct ms_flipdata *flipdata,
+                   int ref_crtc_vblank_pipe, uint32_t flags,
+                   ms_pageflip_handler_proc pageflip_handler,
+                   ms_pageflip_abort_proc pageflip_abort)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    struct ms_crtc_pageflip *flip;
+    uint32_t seq;
+    int err;
+
+    flip = calloc(1, sizeof(struct ms_crtc_pageflip));
+    if (flip == NULL) {
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                   "flip queue: carrier alloc failed.\n");
+        return FALSE;
+    }
+
+    /* Only the reference crtc will finally deliver its page flip
+     * completion event. All other crtc's events will be discarded.
+     */
+    flip->on_reference_crtc = (drmmode_crtc->vblank_pipe == ref_crtc_vblank_pipe);
+    flip->flipdata = flipdata;
+
+    seq = ms_drm_queue_alloc(crtc, flip, pageflip_handler, pageflip_abort);
+    if (!seq) {
+        free(flip);
+        return FALSE;
+    }
+
+    /* take a reference on flipdata for use in flip */
+    flipdata->flip_count++;
+
+    while (drmModePageFlip(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
+                           ms->drmmode.fb_id, flags, (void *) (uintptr_t) seq)) {
+        err = errno;
+        /* We may have failed because the event queue was full.  Flush it
+         * and retry.  If there was nothing to flush, then we failed for
+         * some other reason and should just return an error.
+         */
+        if (ms_flush_drm_events(screen) <= 0) {
+            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                       "flip queue failed: %s\n", strerror(err));
+            /* Aborting will also decrement flip_count and free(flip). */
+            ms_drm_abort_seq(scrn, seq);
+            return FALSE;
+        }
+
+        /* We flushed some events, so try again. */
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n");
+    }
+
+    /* The page flip succeded. */
+    return TRUE;
+}
+
+
+Bool
+ms_do_pageflip(ScreenPtr screen,
+               PixmapPtr new_front,
+               void *event,
+               int ref_crtc_vblank_pipe,
+               Bool async,
+               ms_pageflip_handler_proc pageflip_handler,
+               ms_pageflip_abort_proc pageflip_abort)
+{
+#ifndef GLAMOR_HAS_GBM
+    return FALSE;
+#else
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+    drmmode_bo new_front_bo;
+    uint32_t flags;
+    int i;
+    struct ms_flipdata *flipdata;
+    glamor_block_handler(screen);
+
+    new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
+    new_front_bo.dumb = NULL;
+    if (!new_front_bo.gbm) {
+        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                   "Failed to get GBM bo for flip to new front.\n");
+        return FALSE;
+    }
+
+    flipdata = calloc(1, sizeof(struct ms_flipdata));
+    if (!flipdata) {
+        drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
+        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                   "Failed to allocate flipdata.\n");
+        return FALSE;
+    }
+
+    flipdata->event = event;
+    flipdata->screen = screen;
+
+    /*
+     * Take a local reference on flipdata.
+     * if the first flip fails, the sequence abort
+     * code will free the crtc flip data, and drop
+     * it's reference which would cause this to be
+     * freed when we still required it.
+     */
+    flipdata->flip_count++;
+
+    /* Create a new handle for the back buffer */
+    flipdata->old_fb_id = ms->drmmode.fb_id;
+    if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY,
+                     scrn->depth, scrn->bitsPerPixel,
+                     drmmode_bo_get_pitch(&new_front_bo),
+                     drmmode_bo_get_handle(&new_front_bo), &ms->drmmode.fb_id)) {
+        goto error_out;
+    }
+
+    drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
+
+    flags = DRM_MODE_PAGE_FLIP_EVENT;
+    if (async)
+        flags |= DRM_MODE_PAGE_FLIP_ASYNC;
+
+    /* Queue flips on all enabled CRTCs.
+     *
+     * Note that if/when we get per-CRTC buffers, we'll have to update this.
+     * Right now it assumes a single shared fb across all CRTCs, with the
+     * kernel fixing up the offset of each CRTC as necessary.
+     *
+     * Also, flips queued on disabled or incorrectly configured displays
+     * may never complete; this is a configuration error.
+     */
+    for (i = 0; i < config->num_crtc; i++) {
+        xf86CrtcPtr crtc = config->crtc[i];
+
+        if (!ms_crtc_on(crtc))
+            continue;
+
+        if (!queue_flip_on_crtc(screen, crtc, flipdata,
+                                ref_crtc_vblank_pipe,
+                                flags, pageflip_handler,
+                                pageflip_abort)) {
+            goto error_undo;
+        }
+    }
+
+    /*
+     * Do we have more than our local reference,
+     * if so and no errors, then drop our local
+     * reference and return now.
+     */
+    if (flipdata->flip_count > 1) {
+        flipdata->flip_count--;
+        return TRUE;
+    }
+
+error_undo:
+
+    /*
+     * Have we just got the local reference?
+     * free the framebuffer if so since nobody successfully
+     * submitted anything
+     */
+    if (flipdata->flip_count == 1) {
+        drmModeRmFB(ms->fd, ms->drmmode.fb_id);
+        ms->drmmode.fb_id = flipdata->old_fb_id;
+    }
+
+error_out:
+    xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
+               strerror(errno));
+    /* if only the local reference - free the structure,
+     * else drop the local reference and return */
+    if (flipdata->flip_count == 1)
+        free(flipdata);
+    else
+        flipdata->flip_count--;
+
+    return FALSE;
+#endif /* GLAMOR_HAS_GBM */
+}
+
+#endif
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index 8b60c07..51f98fe 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -27,7 +27,6 @@
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <xserver_poll.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -72,40 +71,6 @@ ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
 }
 
 /*
- * 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 = xserver_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
@@ -226,40 +191,6 @@ ms_present_flush(WindowPtr window)
 
 #ifdef GLAMOR
 
-/*
- * Event data for an in progress flip.
- * This contains a pointer to the vblank event,
- * and information about the flip in progress.
- * a reference to this is stored in the per-crtc
- * flips.
- */
-struct ms_flipdata {
-    ScreenPtr screen;
-    void *event;
-    /* number of CRTC events referencing this */
-    int flip_count;
-    uint64_t fe_msc;
-    uint64_t fe_usec;
-    uint32_t old_fb_id;
-};
-
-/*
- * Per crtc pageflipping infomation,
- * These are submitted to the queuing code
- * one of them per crtc per flip.
- */
-struct ms_crtc_pageflip {
-    Bool on_reference_crtc;
-    /* reference to the ms_flipdata */
-    struct ms_flipdata *flipdata;
-};
-
-typedef void (*ms_pageflip_handler_proc)(uint64_t frame,
-                                         uint64_t usec,
-                                         void *data);
-
-typedef void (*ms_pageflip_abort_proc)(void *data);
-
 /**
  * Free an ms_crtc_pageflip.
  *
@@ -334,189 +265,6 @@ ms_present_flip_abort(void *data)
     ms_present_flip_free(flip);
 }
 
-static Bool
-queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
-                   struct ms_flipdata *flipdata,
-                   int ref_crtc_vblank_pipe, uint32_t flags,
-                   ms_pageflip_handler_proc pageflip_handler,
-                   ms_pageflip_abort_proc pageflip_abort)
-{
-    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    modesettingPtr ms = modesettingPTR(scrn);
-    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-    struct ms_crtc_pageflip *flip;
-    uint32_t seq;
-    int err;
-
-    flip = calloc(1, sizeof(struct ms_crtc_pageflip));
-    if (flip == NULL) {
-        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-                   "flip queue: carrier alloc failed.\n");
-        return FALSE;
-    }
-
-    /* Only the reference crtc will finally deliver its page flip
-     * completion event. All other crtc's events will be discarded.
-     */
-    flip->on_reference_crtc = (drmmode_crtc->vblank_pipe == ref_crtc_vblank_pipe);
-    flip->flipdata = flipdata;
-
-    seq = ms_drm_queue_alloc(crtc, flip, pageflip_handler, pageflip_abort);
-    if (!seq) {
-        free(flip);
-        return FALSE;
-    }
-
-    /* take a reference on flipdata for use in flip */
-    flipdata->flip_count++;
-
-    while (drmModePageFlip(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
-                           ms->drmmode.fb_id, flags, (void *) (uintptr_t) seq)) {
-        err = errno;
-        /* We may have failed because the event queue was full.  Flush it
-         * and retry.  If there was nothing to flush, then we failed for
-         * some other reason and should just return an error.
-         */
-        if (ms_flush_drm_events(screen) <= 0) {
-            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-                       "flip queue failed: %s\n", strerror(err));
-            /* Aborting will also decrement flip_count and free(flip). */
-            ms_drm_abort_seq(scrn, seq);
-            return FALSE;
-        }
-
-        /* We flushed some events, so try again. */
-        xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n");
-    }
-
-    /* The page flip succeded. */
-    return TRUE;
-}
-
-
-static Bool
-ms_do_pageflip(ScreenPtr screen,
-               PixmapPtr new_front,
-               void *event,
-               int ref_crtc_vblank_pipe,
-               Bool async,
-               ms_pageflip_handler_proc pageflip_handler,
-               ms_pageflip_abort_proc pageflip_abort)
-{
-#ifndef GLAMOR_HAS_GBM
-    return FALSE;
-#else
-    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    modesettingPtr ms = modesettingPTR(scrn);
-    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
-    drmmode_bo new_front_bo;
-    uint32_t flags;
-    int i;
-    struct ms_flipdata *flipdata;
-    glamor_block_handler(screen);
-
-    new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
-    new_front_bo.dumb = NULL;
-    if (!new_front_bo.gbm) {
-        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
-                   "Failed to get GBM bo for flip to new front.\n");
-        return FALSE;
-    }
-
-    flipdata = calloc(1, sizeof(struct ms_flipdata));
-    if (!flipdata) {
-        drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
-        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
-                   "Failed to allocate flipdata.\n");
-        return FALSE;
-    }
-
-    flipdata->event = event;
-    flipdata->screen = screen;
-
-    /*
-     * Take a local reference on flipdata.
-     * if the first flip fails, the sequence abort
-     * code will free the crtc flip data, and drop
-     * it's reference which would cause this to be
-     * freed when we still required it.
-     */
-    flipdata->flip_count++;
-
-    /* Create a new handle for the back buffer */
-    flipdata->old_fb_id = ms->drmmode.fb_id;
-    if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY,
-                     scrn->depth, scrn->bitsPerPixel,
-                     drmmode_bo_get_pitch(&new_front_bo),
-                     drmmode_bo_get_handle(&new_front_bo), &ms->drmmode.fb_id)) {
-        goto error_out;
-    }
-
-    drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
-
-    flags = DRM_MODE_PAGE_FLIP_EVENT;
-    if (async)
-        flags |= DRM_MODE_PAGE_FLIP_ASYNC;
-
-    /* Queue flips on all enabled CRTCs.
-     *
-     * Note that if/when we get per-CRTC buffers, we'll have to update this.
-     * Right now it assumes a single shared fb across all CRTCs, with the
-     * kernel fixing up the offset of each CRTC as necessary.
-     *
-     * Also, flips queued on disabled or incorrectly configured displays
-     * may never complete; this is a configuration error.
-     */
-    for (i = 0; i < config->num_crtc; i++) {
-        xf86CrtcPtr crtc = config->crtc[i];
-
-        if (!ms_crtc_on(crtc))
-            continue;
-
-        if (!queue_flip_on_crtc(screen, crtc, flipdata,
-                                ref_crtc_vblank_pipe,
-                                flags, pageflip_handler,
-                                pageflip_abort)) {
-            goto error_undo;
-        }
-    }
-
-    /*
-     * Do we have more than our local reference,
-     * if so and no errors, then drop our local
-     * reference and return now.
-     */
-    if (flipdata->flip_count > 1) {
-        flipdata->flip_count--;
-        return TRUE;
-    }
-
-error_undo:
-
-    /*
-     * Have we just got the local reference?
-     * free the framebuffer if so since nobody successfully
-     * submitted anything
-     */
-    if (flipdata->flip_count == 1) {
-        drmModeRmFB(ms->fd, ms->drmmode.fb_id);
-        ms->drmmode.fb_id = flipdata->old_fb_id;
-    }
-
-error_out:
-    xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
-               strerror(errno));
-    /* if only the local reference - free the structure,
-     * else drop the local reference and return */
-    if (flipdata->flip_count == 1)
-        free(flipdata);
-    else
-        flipdata->flip_count--;
-
-    return FALSE;
-#endif /* GLAMOR_HAS_GBM */
-}
-
 /*
  * Test to see if page flipping is possible on the target crtc
  */
-- 
2.7.4



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux