diff options
author | Louis-Francis Ratté-Boulianne <lfrb@collabora.com> | 2017-08-30 00:45:39 -0400 |
---|---|---|
committer | Jason Ekstrand <jason.ekstrand@intel.com> | 2017-09-05 12:40:14 -0700 |
commit | 9f979f8d85679ca2c2b5159615e057ba8c9f83a0 (patch) | |
tree | aacfdb8cac7550024f1a22fea74799ce4eeb62ad | |
parent | d3392f15e382cb27702dbafa66687af50d470b0b (diff) |
modesetting: Add support for multi-plane pixmaps when page-flipping
This allows the uses of CCS compressed or tiled pixmaps as BOs when
page-flipping.
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
-rw-r--r-- | hw/xfree86/drivers/modesetting/drmmode_display.c | 46 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/drmmode_display.h | 4 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/pageflip.c | 16 |
3 files changed, 59 insertions, 7 deletions
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index 4fed593ba..536274f3f 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -39,6 +39,8 @@ #include "micmap.h" #include "xf86cmap.h" #include "xf86DDC.h" +#include <drm_fourcc.h> +#include <drm_mode.h> #include <xf86drm.h> #include "xf86Crtc.h" @@ -388,10 +390,54 @@ 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) +{ +#ifdef GBM_BO_WITH_MODIFIERS + if (bo->gbm) { + int num_fds; + + num_fds = gbm_bo_get_plane_count(bo->gbm); + if (num_fds > 0) { + int i; + uint32_t handles[4]; + uint32_t strides[4]; + uint32_t offsets[4]; + uint64_t modifiers[4]; + + memset(handles, 0, sizeof(handles)); + memset(strides, 0, sizeof(strides)); + memset(offsets, 0, sizeof(offsets)); + memset(modifiers, 0, sizeof(modifiers)); + + for (i = 0; i < num_fds; i++) { + handles[i] = gbm_bo_get_handle_for_plane(bo->gbm, i).u32; + strides[i] = gbm_bo_get_stride_for_plane(bo->gbm, i); + offsets[i] = gbm_bo_get_offset(bo->gbm, i); + modifiers[i] = gbm_bo_get_modifier(bo->gbm); + } + + return drmModeAddFB2WithModifiers(drmmode->fd, bo->width, bo->height, + DRM_FORMAT_ARGB8888, handles, strides, + offsets, modifiers, fb_id, + DRM_MODE_FB_MODIFIERS); + } + } +#endif + 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); +} + 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..0a4452e7b 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -51,6 +51,8 @@ enum drmmode_plane_type { }; typedef struct { + uint32_t width; + uint32_t height; struct dumb_bo *dumb; #ifdef GLAMOR_HAS_GBM struct gbm_bo *gbm; @@ -193,6 +195,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..027ebfe42 100644 --- a/hw/xfree86/drivers/modesetting/pageflip.c +++ b/hw/xfree86/drivers/modesetting/pageflip.c @@ -258,6 +258,7 @@ ms_do_pageflip(ScreenPtr 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"); @@ -288,14 +289,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 +322,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 +349,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) |