[RFC v2 10/13] modesetting: Add support for multi-plane pixmaps when page-flipping

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Fri Jul 14 04:47:57 UTC 2017


This allows the uses of CCS compressed or tiled pixmaps as BOs.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 hw/xfree86/drivers/modesetting/drmmode_display.c | 51 +++++++++++++++++++++++-
 hw/xfree86/drivers/modesetting/drmmode_display.h | 10 +++++
 hw/xfree86/drivers/modesetting/pageflip.c        | 50 ++++++++++++++++++-----
 3 files changed, 100 insertions(+), 11 deletions(-)

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index de5f26078..c1c0b48f8 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -317,13 +317,16 @@ drmmode_crtc_set_fb(xf86CrtcPtr crtc, uint32_t fb_id,
 int
 drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
 {
-    int ret;
+    int i, ret;
 
 #ifdef GLAMOR_HAS_GBM
     if (bo->gbm) {
         gbm_bo_destroy(bo->gbm);
         bo->gbm = NULL;
     }
+    for (i = 0; i < bo->num_planes; i++)
+        close(bo->fds[i]);
+    bo->num_planes = 0;
 #endif
 
     if (bo->dumb) {
@@ -388,10 +391,56 @@ drmmode_bo_map(drmmode_ptr drmmode, drmmode_bo *bo)
     return bo->dumb->ptr;
 }
 
+int
+drmmode_bo_import(drmmode_ptr drmmode, drmmode_bo *bo,
+                  uint32_t *fb_id)
+{
+    if (bo->num_planes > 0) {
+#ifdef GBM_BO_WITH_MODIFIERS
+        int i, ret;
+        uint32_t handles[4];
+
+        memset(handles, 0, sizeof(handles));
+
+        for (i = 0; i < bo->num_planes; i++) {
+            ret = drmPrimeFDToHandle(drmmode->fd, bo->fds[i], &handles[i]);
+            if (ret != 0) //XXX close handles on error
+                return ret;
+        }
+        ret = drmModeAddFB2WithModifiers(drmmode->fd, bo->width, bo->height,
+                                         bo->format, handles, bo->strides,
+                                         bo->offsets, bo->modifiers, fb_id,
+                                         DRM_MODE_FB_MODIFIERS);
+
+        for (i = 0; i < bo->num_planes; i++) {
+            struct drm_gem_close gem_close = { .handle = handles[i] };
+            if (!gem_close.handle)
+                continue;
+            (void) drmIoctl(drmmode->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+        }
+
+        return ret;
+#else
+        xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
+                   "Multi-plane and modified buffers are not supported\n");
+#endif
+    } else {
+        return drmModeAddFB(drmmode->fd, bo->width, bo->height,
+                            drmmode->scrn->depth, drmmode->scrn->bitsPerPixel,
+                            drmmode_bo_get_pitch(bo),
+                            drmmode_bo_get_handle(bo), fb_id);
+    }
+
+    return -1;
+}
+
 static Bool
 drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
                   unsigned width, unsigned height, unsigned bpp)
 {
+    bo->width = width;
+    bo->height = height;
+
 #ifdef GLAMOR_HAS_GBM
     if (drmmode->glamor) {
         bo->gbm = gbm_bo_create(drmmode->gbm, width, height,
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index fadc381db..24e2f6607 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -51,9 +51,17 @@ enum drmmode_plane_type {
 };
 
 typedef struct {
+    uint32_t width;
+    uint32_t height;
     struct dumb_bo *dumb;
 #ifdef GLAMOR_HAS_GBM
     struct gbm_bo *gbm;
+    int num_planes;
+    int fds[4];
+    uint32_t format;
+    uint32_t strides[4];
+    uint32_t offsets[4];
+    uint64_t modifiers[4];
 #endif
 } drmmode_bo;
 
@@ -193,6 +201,8 @@ extern DevPrivateKeyRec msPixmapPrivateKeyRec;
 
 #define msGetPixmapPriv(drmmode, p) ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &(drmmode)->pixmapPrivateKeyRec))
 
+int drmmode_bo_import(drmmode_ptr drmmode, drmmode_bo *bo,
+                      uint32_t *fb_id);
 int drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo);
 uint32_t drmmode_bo_get_pitch(drmmode_bo *bo);
 uint32_t drmmode_bo_get_handle(drmmode_bo *bo);
diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c
index dd296cd12..0ec95ae2e 100644
--- a/hw/xfree86/drivers/modesetting/pageflip.c
+++ b/hw/xfree86/drivers/modesetting/pageflip.c
@@ -253,14 +253,43 @@ ms_do_pageflip(ScreenPtr screen,
     drmmode_bo new_front_bo;
     uint32_t flags;
     int i;
+    uint64_t modifier;
     struct ms_flipdata *flipdata;
     glamor_block_handler(screen);
 
-    new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
+    new_front_bo.num_planes = 0;
+    new_front_bo.gbm = NULL;
+    for (i = 0; i < 4; i++) {
+        new_front_bo.strides[i] = 0;
+        new_front_bo.offsets[i] = 0;
+        new_front_bo.modifiers[i] = 0;
+    }
+
+#ifdef GBM_BO_WITH_MODIFIERS
+    new_front_bo.num_planes = glamor_dmabuf_from_pixmap(new_front,
+                                                        new_front_bo.fds,
+                                                        new_front_bo.strides,
+                                                        new_front_bo.offsets,
+                                                        &new_front_bo.format,
+                                                        &modifier);
+    for (i = 0; i < new_front_bo.num_planes; i++) {
+        new_front_bo.modifiers[i] = modifier;
+        new_front_bo.fds[i] = dup(new_front_bo.fds[i]);
+    }
+#endif
+
+    if (new_front_bo.num_planes == 0)
+        new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
+
     new_front_bo.dumb = NULL;
-    if (!new_front_bo.gbm) {
+
+    /*
+     * At this point there should be a GBM buffer set or
+     * num_planes should be set if we're using DMA buffers
+     */
+    if (!new_front_bo.gbm && new_front_bo.num_planes == 0) {
         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
-                   "Failed to get GBM bo for flip to new front.\n");
+                   "Failed to get buffer for flip to new front.\n");
         return FALSE;
     }
 
@@ -288,14 +317,12 @@ ms_do_pageflip(ScreenPtr screen,
 
     /* 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);
+    new_front_bo.width = new_front->drawable.width;
+    new_front_bo.height = new_front->drawable.height;
+    if (drmmode_bo_import(&ms->drmmode, &new_front_bo,
+                          &ms->drmmode.fb_id))
+        goto error_out;
 
     flags = DRM_MODE_PAGE_FLIP_EVENT;
     if (async)
@@ -323,6 +350,8 @@ ms_do_pageflip(ScreenPtr screen,
         }
     }
 
+    drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
+
     /*
      * Do we have more than our local reference,
      * if so and no errors, then drop our local
@@ -348,6 +377,7 @@ error_undo:
 error_out:
     xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
                strerror(errno));
+    drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
     /* if only the local reference - free the structure,
      * else drop the local reference and return */
     if (flipdata->flip_count == 1)
-- 
2.13.0



More information about the xorg-devel mailing list