From 241e7289f25a342a457952b9b0e539c2f0b81d99 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 22 Oct 2014 11:04:16 +0200 Subject: enable dri3 support without glamor --- src/nouveau_dri2.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++- src/nouveau_present.c | 17 +++---- src/nouveau_present.h | 2 +- src/nv_driver.c | 4 ++ src/nv_proto.h | 1 + src/nv_type.h | 2 + 6 files changed, 143 insertions(+), 10 deletions(-) diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 3361869..6c1260c 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -10,7 +10,9 @@ #else #error "This driver requires a DRI2-enabled X server" #endif - +#ifdef DRI3 +#include "dri3.h" +#endif #include "xf86drmMode.h" struct nouveau_dri2_buffer { @@ -1012,3 +1014,126 @@ nouveau_dri2_fini(ScreenPtr pScreen) if (pNv->AccelMethod == EXA) DRI2CloseScreen(pScreen); } + +#ifdef DRI3 +static int is_render_node(int fd, struct stat *st) +{ + if (fstat(fd, st)) + return 0; + + if (!S_ISCHR(st->st_mode)) + return 0; + + return st->st_rdev & 0x80; + } + +static int +nouveau_dri3_open(ScreenPtr screen, RRProviderPtr provider, int *out) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); + NVPtr pNv = NVPTR(pScrn); + int fd = -1; + struct stat buff; + +#ifdef O_CLOEXEC + fd = open(pNv->render_node, O_RDWR | O_CLOEXEC); +#endif + if (fd < 0) + fd = open(pNv->render_node, O_RDWR); + if (fd < 0) + return -BadAlloc; + + if (fstat(fd, &buff)) { + close(fd); + return -BadMatch; + } + if (!is_render_node(fd, &buff)) { + drm_magic_t magic; + + if (drmGetMagic(fd, &magic) || drmAuthMagic(pNv->dev->fd, magic)) { + close(fd); + return -BadMatch; + } + } + + *out = fd; + return Success; +} + +static PixmapPtr nouveau_dri3_pixmap_from_fd(ScreenPtr screen, int fd, CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); + NVPtr pNv = NVPTR(pScrn); + PixmapPtr pixmap; + struct nouveau_bo *bo = NULL; + struct nouveau_pixmap *nvpix; + + if (depth < 8 || depth > 32 || depth % 8) + return NULL; + + pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); + if (!pixmap) + return NULL; + + if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL)) + goto free_pixmap; + + if (nouveau_bo_prime_handle_ref(pNv->dev, fd, &bo)) + goto free_pixmap; + + nvpix = nouveau_pixmap(pixmap); + nouveau_bo_ref(NULL, &nvpix->bo); + nvpix->bo = bo; + nvpix->shared = (bo->flags & NOUVEAU_BO_APER) == NOUVEAU_BO_GART; + return pixmap; + +free_pixmap: + screen->DestroyPixmap(pixmap); + return NULL; +} + +static int nouveau_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, CARD16 *stride, CARD32 *size) +{ + struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap); + int fd; + + if (nouveau_bo_set_prime(bo, &fd) < 0) + return -1; + + *stride = pixmap->devKind; + *size = bo->size; + return fd; +} + +static dri3_screen_info_rec nouveau_dri3_screen_info = { + .version = DRI3_SCREEN_INFO_VERSION, + + .open = nouveau_dri3_open, + .pixmap_from_fd = nouveau_dri3_pixmap_from_fd, + .fd_from_pixmap = nouveau_dri3_fd_from_pixmap +}; + +Bool +nouveau_dri3_screen_init(ScreenPtr screen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); + NVPtr pNv = NVPTR(pScrn); + struct stat master, render; + char buf[32]; + + if (is_render_node(pNv->dev->fd, &master)) + return TRUE; + + sprintf(buf, "/dev/dri/renderD%d", (int)((master.st_rdev & 0x3f) | 0x80)); + + if (stat(buf, &render) == 0 && + master.st_mode == render.st_mode && + (render.st_rdev & ~0x80) == master.st_rdev) + pNv->render_node = strdup(buf); + + if (!pNv->render_node) + return TRUE; + + return dri3_screen_init(screen, &nouveau_dri3_screen_info); +} +#endif diff --git a/src/nouveau_present.c b/src/nouveau_present.c index ea1686e..4de1e6e 100644 --- a/src/nouveau_present.c +++ b/src/nouveau_present.c @@ -23,7 +23,7 @@ */ #include "nouveau_present.h" -#if defined(DRI3) && defined(HAVE_GLAMOR) +#if defined(DRI3) #include "nv_include.h" #include "nouveau_glamor.h" #include "xf86drmMode.h" @@ -178,7 +178,7 @@ nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync, uint64_t target_msc, PixmapPtr pixmap, Bool vsync) { ScreenPtr screen = scrn->pScreen; - struct nouveau_pixmap *priv; + struct nouveau_pixmap *priv = NULL; NVPtr pNv = NVPTR(scrn); uint32_t next_fb; CARD16 stride; @@ -186,8 +186,9 @@ nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync, void *token; int ret; - priv = nouveau_glamor_pixmap_get(pixmap); - if (priv == NULL) { +#ifdef HAVE_GLAMOR + if (pNv->AccelMethod == GLAMOR && + !(priv = nouveau_glamor_pixmap_get(pixmap))) { int fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size); if (fd < 0) return FALSE; @@ -203,7 +204,10 @@ nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync, } nouveau_glamor_pixmap_set(pixmap, priv); - } + } else +#endif + if (!priv) + priv = nouveau_pixmap(pixmap); ret = drmModeAddFB(pNv->dev->fd, pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth, @@ -298,9 +302,6 @@ nouveau_present_init(ScreenPtr screen) uint64_t value; int ret; - if (pNv->AccelMethod != GLAMOR) - return -ENOSYS; - present = pNv->present = calloc(1, sizeof(*present)); if (!present) return -ENOMEM; diff --git a/src/nouveau_present.h b/src/nouveau_present.h index 958c2f7..e807b6d 100644 --- a/src/nouveau_present.h +++ b/src/nouveau_present.h @@ -8,7 +8,7 @@ #include "config.h" #endif -#if defined(DRI3) && defined(HAVE_GLAMOR) +#if defined(DRI3) #include "present.h" Bool nouveau_present_init(ScreenPtr pScreen); void nouveau_present_fini(ScreenPtr pScreen); diff --git a/src/nv_driver.c b/src/nv_driver.c index 4bad985..6bca141 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -721,6 +721,7 @@ NVCloseDRM(ScrnInfoPtr pScrn) drmFree(pNv->drm_device_name); nouveau_client_del(&pNv->client); nouveau_device_del(&pNv->dev); + free(pNv->render_node); } static void @@ -1468,6 +1469,9 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL) if (pNv->AccelMethod == EXA) { if (!nouveau_exa_init(pScreen)) return FALSE; + + if (!nouveau_dri3_screen_init(pScreen)) + return FALSE; } xf86SetBackingStore(pScreen); diff --git a/src/nv_proto.h b/src/nv_proto.h index cc4fd09..122ede5 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -36,6 +36,7 @@ Bool nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, /* in nouveau_dri2.c */ Bool nouveau_dri2_init(ScreenPtr pScreen); void nouveau_dri2_fini(ScreenPtr pScreen); +Bool nouveau_dri3_screen_init(ScreenPtr pScreen); /* in nouveau_xv.c */ void NVInitVideo(ScreenPtr); diff --git a/src/nv_type.h b/src/nv_type.h index c0517c6..e6ab192 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -140,6 +140,8 @@ typedef struct _NVRec { PixmapPtr pspix, pmpix, pdpix; PicturePtr pspict, pmpict; Pixel fg_colour; + + char *render_node; } NVRec; #define NVPTR(p) ((NVPtr)((p)->driverPrivate)) -- cgit v1.2.3