summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@ubuntu.com>2014-10-22 11:04:16 +0200
committerMaarten Lankhorst <maarten.lankhorst@ubuntu.com>2014-10-22 11:04:50 +0200
commit241e7289f25a342a457952b9b0e539c2f0b81d99 (patch)
treeccc6f04ac6436d1fe62422c669718b996dc1d13c
parent762b22f5a2b9deed1c6b18d7098f8fddf2f4b759 (diff)
enable dri3 support without glamor
-rw-r--r--src/nouveau_dri2.c127
-rw-r--r--src/nouveau_present.c17
-rw-r--r--src/nouveau_present.h2
-rw-r--r--src/nv_driver.c4
-rw-r--r--src/nv_proto.h1
-rw-r--r--src/nv_type.h2
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))