summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac19
-rw-r--r--etnaviv/Makefile.am6
-rw-r--r--etnaviv/etnaviv.c134
-rw-r--r--etnaviv/etnaviv_accel.h7
-rw-r--r--etnaviv/etnaviv_dri3.c128
-rw-r--r--etnaviv/etnaviv_dri3.h12
-rw-r--r--man/armada.man4
7 files changed, 279 insertions, 31 deletions
diff --git a/configure.ac b/configure.ac
index b14d4cf..a489334 100644
--- a/configure.ac
+++ b/configure.ac
@@ -205,6 +205,11 @@ AC_ARG_ENABLE(dri2, AC_HELP_STRING([--disable-dri2],
[DRI2="$enableval"],
[DRI2=auto])
+AC_ARG_ENABLE(dri3, AC_HELP_STRING([--disable-dri3],
+ [Disable DRI3 support [[default=auto]]]),
+ [DRI3="$enableval"],
+ [DRI3=auto])
+
AC_ARG_ENABLE(present, AC_HELP_STRING([--disable-present],
[Disable PRESENT support [[default=auto]]]),
[PRESENT="$enableval"],
@@ -247,6 +252,20 @@ if test x$DRI2 = xyes; then
AC_DEFINE(HAVE_DRI2,1,[Enable DRI2 driver support])
fi
+PKG_CHECK_MODULES(DRI3, [dri3proto >= 1.0], , DRI3=no)
+if test x$DRI3 != xno; then
+ save_CFLAGS=$CFLAGS
+ CFLAGS="$XORG_CFLAGS $DRM_CFLAGS $DRI_CFLAGS $DRI2_CFLAGS $DRI3_CFLAGS"
+ AC_CHECK_HEADERS([dri3.h], DRI3=yes, DRI3=no, [#include <dixstruct.h>])
+ CFLAGS=$save_CFLAGS
+fi
+AC_MSG_CHECKING([whether to include DRI3 support])
+AM_CONDITIONAL(HAVE_DRI3, test x$DRI3 = xyes)
+AC_MSG_RESULT([$DRI3])
+if test x$DRI3 = xyes; then
+ AC_DEFINE(HAVE_DRI3,1,[Enable DRI3 driver support])
+fi
+
PKG_CHECK_MODULES(PRESENT, [presentproto >= 1.0], , PRESENT=no)
if test x$PRESENT != xno; then
save_CFLAGS=$CFLAGS
diff --git a/etnaviv/Makefile.am b/etnaviv/Makefile.am
index 5fb6ad5..95e3775 100644
--- a/etnaviv/Makefile.am
+++ b/etnaviv/Makefile.am
@@ -42,6 +42,12 @@ ETNA_COMMON_SOURCES += \
ETNA_COMMON_LIBADD += $(DRI_LIBS)
endif
+if HAVE_DRI3
+ETNA_COMMON_SOURCES += \
+ etnaviv_dri3.c \
+ etnaviv_dri3.h
+endif
+
if HAVE_ACCEL_ETNAVIV
etnaviv_gpu_la_LTLIBRARIES = etnaviv_gpu.la
etnaviv_gpu_la_LDFLAGS = -module -avoid-version
diff --git a/etnaviv/etnaviv.c b/etnaviv/etnaviv.c
index 5aa6f2a..5123b74 100644
--- a/etnaviv/etnaviv.c
+++ b/etnaviv/etnaviv.c
@@ -40,6 +40,7 @@
#include "etnaviv_accel.h"
#include "etnaviv_dri2.h"
+#include "etnaviv_dri3.h"
#include "etnaviv_render.h"
#include "etnaviv_utils.h"
#include "etnaviv_xv.h"
@@ -49,11 +50,13 @@ etnaviv_Key etnaviv_screen_index;
int etnaviv_private_index = -1;
enum {
- OPTION_DRI,
+ OPTION_DRI2,
+ OPTION_DRI3,
};
const OptionInfoRec etnaviv_options[] = {
- { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, TRUE },
+ { OPTION_DRI2, "DRI", OPTV_BOOLEAN, {0}, TRUE },
+ { OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, TRUE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -866,7 +869,17 @@ static Bool etnaviv_pre_init(ScrnInfoPtr pScrn, int drm_fd)
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
#ifdef HAVE_DRI2
- etnaviv->dri2_enabled = xf86ReturnOptValBool(options, OPTION_DRI, TRUE);
+ etnaviv->dri2_enabled = xf86ReturnOptValBool(options, OPTION_DRI2,
+ TRUE);
+#endif
+#ifdef HAVE_DRI3
+ /*
+ * We default to DRI3 disabled, as we are unable to support
+ * flips with etnaviv-allocated buffer objects, whereas DRI2
+ * can (and does) provide support for this.
+ */
+ etnaviv->dri3_enabled = xf86ReturnOptValBool(options, OPTION_DRI3,
+ FALSE);
#endif
etnaviv->scrnIndex = pScrn->scrnIndex;
@@ -910,7 +923,7 @@ static Bool etnaviv_ScreenInit(ScreenPtr pScreen, struct drm_armada_bufmgr *mgr)
#ifdef HAVE_DRI2
if (!etnaviv->dri2_enabled) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
- "direct rendering: disabled\n");
+ "direct rendering: %s %s\n", "DRI2", "disabled");
} else {
const char *name;
drmVersionPtr version;
@@ -939,14 +952,28 @@ static Bool etnaviv_ScreenInit(ScreenPtr pScreen, struct drm_armada_bufmgr *mgr)
"direct rendering: unusuable devices\n");
} else if (!etnaviv_dri2_ScreenInit(pScreen, dri_fd, name)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "direct rendering: failed\n");
+ "direct rendering: %s %s\n", "DRI2",
+ "failed");
etnaviv->dri2_enabled = FALSE;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "direct rendering: DRI2 enabled\n");
+ "direct rendering: %s %s\n", "DRI2",
+ "enabled");
}
}
#endif
+#ifdef HAVE_DRI3
+ if (!etnaviv->dri3_enabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "direct rendering: %s %s\n", "DRI3", "disabled");
+ } else if (!etnaviv_dri3_ScreenInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "direct rendering: %s %s\n", "DRI3", "failed");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "direct rendering: %s %s\n", "DRI3", "enabled");
+ }
+#endif
etnaviv->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = etnaviv_CloseScreen;
@@ -978,48 +1005,98 @@ fail_accel:
return FALSE;
}
-/* Scanout pixmaps are never tiled. */
-static Bool etnaviv_import_dmabuf(ScreenPtr pScreen, PixmapPtr pPixmap, int fd)
+static Bool etnaviv_format(struct etnaviv_format *fmt, unsigned int depth,
+ unsigned int bpp)
{
- struct etnaviv *etnaviv = etnaviv_get_screen_priv(pScreen);
- struct etnaviv_format fmt = { .swizzle = DE_SWIZZLE_ARGB, };
- struct etnaviv_pixmap *vpix;
- struct etna_bo *bo;
-
- etnaviv_free_pixmap(pPixmap);
-
- switch (pPixmap->drawable.bitsPerPixel) {
+ static const struct etnaviv_format template =
+ { .swizzle = DE_SWIZZLE_ARGB, };
+ *fmt = template;
+ switch (bpp) {
case 16:
- if (pPixmap->drawable.depth == 15)
- fmt.format = DE_FORMAT_A1R5G5B5;
+ if (depth == 15)
+ fmt->format = DE_FORMAT_A1R5G5B5;
else
- fmt.format = DE_FORMAT_R5G6B5;
- break;
+ fmt->format = DE_FORMAT_R5G6B5;
+ return TRUE;
case 32:
- fmt.format = DE_FORMAT_A8R8G8B8;
- break;
+ fmt->format = DE_FORMAT_A8R8G8B8;
+ return TRUE;
default:
- return TRUE;
+ return FALSE;
}
+}
+
+static struct etnaviv_pixmap *etnaviv_pixmap_attach_dmabuf(
+ struct etnaviv *etnaviv, PixmapPtr pixmap, struct etnaviv_format fmt,
+ int fd)
+{
+ struct etnaviv_pixmap *vpix;
+ struct etna_bo *bo;
bo = etna_bo_from_dmabuf(etnaviv->conn, fd, PROT_READ | PROT_WRITE);
if (!bo) {
xf86DrvMsg(etnaviv->scrnIndex, X_ERROR,
"etnaviv: gpu dmabuf map failed: %s\n",
strerror(errno));
- return FALSE;
+ return NULL;
}
- vpix = etnaviv_alloc_pixmap(pPixmap, fmt);
+ vpix = etnaviv_alloc_pixmap(pixmap, fmt);
if (!vpix) {
etna_bo_del(etnaviv->conn, bo, NULL);
- return FALSE;
+ return NULL;
}
vpix->etna_bo = bo;
+ etnaviv_set_pixmap_priv(pixmap, vpix);
+
+ return vpix;
+}
+
+PixmapPtr etnaviv_pixmap_from_dmabuf(ScreenPtr pScreen, int fd,
+ CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp)
+{
+ struct etnaviv *etnaviv = etnaviv_get_screen_priv(pScreen);
+ struct etnaviv_format fmt;
+ PixmapPtr pixmap;
+
+ if (!etnaviv_format(&fmt, depth, bpp))
+ return NullPixmap;
+
+ pixmap = etnaviv->CreatePixmap(pScreen, 0, 0, depth, 0);
+ if (pixmap == NullPixmap)
+ return pixmap;
+
+ pScreen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL);
+
+ if (!etnaviv_pixmap_attach_dmabuf(etnaviv, pixmap, fmt, fd)) {
+ etnaviv->DestroyPixmap(pixmap);
+ return NullPixmap;
+ }
+
+ return pixmap;
+}
+
+/* Scanout pixmaps are never tiled. */
+static Bool etnaviv_import_dmabuf(ScreenPtr pScreen, PixmapPtr pPixmap, int fd)
+{
+ struct etnaviv *etnaviv = etnaviv_get_screen_priv(pScreen);
+ struct etnaviv_pixmap *vpix;
+ struct etnaviv_format fmt;
+
+ etnaviv_free_pixmap(pPixmap);
+
+ if (!etnaviv_format(&fmt, pPixmap->drawable.depth,
+ pPixmap->drawable.bitsPerPixel))
+ return TRUE;
+
+ vpix = etnaviv_pixmap_attach_dmabuf(etnaviv, pPixmap, fmt, fd);
+ if (!vpix)
+ return FALSE;
+
/*
* Pixmaps imported via dmabuf are write-combining, so don't
* need CPU cache state tracking. We still need to track
@@ -1027,16 +1104,15 @@ static Bool etnaviv_import_dmabuf(ScreenPtr pScreen, PixmapPtr pPixmap, int fd)
*/
vpix->state |= ST_DMABUF;
- etnaviv_set_pixmap_priv(pPixmap, vpix);
-
#ifdef DEBUG_PIXMAP
dbg("Pixmap %p: vPix=%p etna_bo=%p format=%u/%u/%u\n",
- pixmap, vPix, bo, fmt.format, fmt.swizzle, fmt.tile);
+ pixmap, vPix, vPix->etna_bo, fmt.format, fmt.swizzle, fmt.tile);
#endif
return TRUE;
}
+
static void etnaviv_attach_name(ScreenPtr pScreen, PixmapPtr pPixmap,
uint32_t name)
{
diff --git a/etnaviv/etnaviv_accel.h b/etnaviv/etnaviv_accel.h
index 26e939c..d2cf1a6 100644
--- a/etnaviv/etnaviv_accel.h
+++ b/etnaviv/etnaviv_accel.h
@@ -88,6 +88,10 @@ struct etnaviv {
Bool dri2_armada;
struct etnaviv_dri2_info *dri2;
#endif
+#ifdef HAVE_DRI3
+ Bool dri3_enabled;
+ const char *render_node;
+#endif
uint32_t batch[MAX_BATCH_SIZE];
unsigned int batch_setup_size;
@@ -257,6 +261,9 @@ static inline void etnaviv_set_screen_priv(ScreenPtr pScreen, struct etnaviv *g)
dixSetPrivate(&pScreen->devPrivates, &etnaviv_screen_index, g);
}
+PixmapPtr etnaviv_pixmap_from_dmabuf(ScreenPtr pScreen, int fd,
+ CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp);
+
Bool etnaviv_pixmap_flink(PixmapPtr pixmap, uint32_t *name);
extern const struct armada_accel_ops etnaviv_ops;
diff --git a/etnaviv/etnaviv_dri3.c b/etnaviv/etnaviv_dri3.c
new file mode 100644
index 0000000..85a2baa
--- /dev/null
+++ b/etnaviv/etnaviv_dri3.c
@@ -0,0 +1,128 @@
+/*
+ * Vivante GPU Acceleration Xorg driver
+ *
+ * Written by Russell King, 2015
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* drm includes */
+#include <xf86drm.h>
+
+#include "fb.h"
+#include "gcstruct.h"
+#include "xf86.h"
+#include "dri3.h"
+#include "misyncshm.h"
+#include "compat-api.h"
+
+#include <etnaviv/etna.h>
+
+#include "etnaviv_accel.h"
+#include "etnaviv_dri3.h"
+
+static Bool etnaviv_dri3_authorise(struct etnaviv *etnaviv, int fd)
+{
+ struct stat st;
+ drm_magic_t magic;
+
+ if (fstat(fd, &st) || !S_ISCHR(st.st_mode))
+ return FALSE;
+
+ /*
+ * If the device is a render node, we don't need to auth it.
+ * Render devices start at minor number 128 and up, though it
+ * would be nice to have some other test for this.
+ */
+ if (st.st_rdev & 0x80)
+ return TRUE;
+
+ return drmGetMagic(fd, &magic) == 0 &&
+ drmAuthMagic(etnaviv->conn->fd, magic) == 0;
+}
+
+static int etnaviv_dri3_open(ScreenPtr pScreen, RRProviderPtr provider, int *o)
+{
+ struct etnaviv *etnaviv = etnaviv_get_screen_priv(pScreen);
+ int fd;
+
+ fd = open(etnaviv->render_node, O_RDWR | O_CLOEXEC);
+ if (fd < 0)
+ return BadAlloc;
+
+ if (!etnaviv_dri3_authorise(etnaviv, fd)) {
+ close(fd);
+ return BadMatch;
+ }
+
+ *o = fd;
+
+ return Success;
+}
+
+static PixmapPtr etnaviv_dri3_pixmap_from_fd(ScreenPtr pScreen, int fd,
+ CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp)
+{
+ return etnaviv_pixmap_from_dmabuf(pScreen, fd, width, height,
+ stride, depth, bpp);
+}
+
+static int etnaviv_dri3_fd_from_pixmap(ScreenPtr pScreen, PixmapPtr pixmap,
+ CARD16 *stride, CARD32 *size)
+{
+ struct etnaviv *etnaviv = etnaviv_get_screen_priv(pScreen);
+ struct etnaviv_pixmap *vPix = etnaviv_get_pixmap_priv(pixmap);
+
+ /* Only support pixmaps backed by an etnadrm bo */
+ if (!vPix || !vPix->etna_bo)
+ return BadMatch;
+
+ *stride = pixmap->devKind;
+ *size = etna_bo_size(vPix->etna_bo);
+
+ return etna_bo_to_dmabuf(etnaviv->conn, vPix->etna_bo);
+}
+
+static dri3_screen_info_rec etnaviv_dri3_info = {
+ .version = 0,
+ .open = etnaviv_dri3_open,
+ .pixmap_from_fd = etnaviv_dri3_pixmap_from_fd,
+ .fd_from_pixmap = etnaviv_dri3_fd_from_pixmap,
+};
+
+Bool etnaviv_dri3_ScreenInit(ScreenPtr pScreen)
+{
+ struct etnaviv *etnaviv = etnaviv_get_screen_priv(pScreen);
+ struct stat st;
+ char buf[64];
+
+ free((void *)etnaviv->render_node);
+
+ if (fstat(etnaviv->conn->fd, &st) || !S_ISCHR(st.st_mode))
+ return FALSE;
+
+ snprintf(buf, sizeof(buf), "%s/card%d", DRM_DIR_NAME,
+ (unsigned int)st.st_rdev & 0x7f);
+
+ if (access(buf, F_OK))
+ return FALSE;
+
+ etnaviv->render_node = strdup(buf);
+ if (!etnaviv->render_node)
+ return FALSE;
+
+ if (!miSyncShmScreenInit(pScreen))
+ return FALSE;
+
+ return dri3_screen_init(pScreen, &etnaviv_dri3_info);
+}
diff --git a/etnaviv/etnaviv_dri3.h b/etnaviv/etnaviv_dri3.h
new file mode 100644
index 0000000..f7cdd76
--- /dev/null
+++ b/etnaviv/etnaviv_dri3.h
@@ -0,0 +1,12 @@
+/*
+ * Vivante GPU Acceleration Xorg driver
+ *
+ * Written by Russell King, 2012, derived in part from the
+ * Intel xorg X server driver.
+ */
+#ifndef ETNAVIV_DRI3_H
+#define ETNAVIV_DRI3_H
+
+Bool etnaviv_dri3_ScreenInit(ScreenPtr pScreen);
+
+#endif
diff --git a/man/armada.man b/man/armada.man
index 2622fff..94acc3f 100644
--- a/man/armada.man
+++ b/man/armada.man
@@ -20,8 +20,8 @@ This is kernel mode setting front end driver, with modular acceleration
backends. The following framebuffer depths are supported: 8, 15, 16, 24.
All visual types are supported for depth 8, and TrueColor visual is
supported for the other depths. The driver has preliminary support for
-the Direct Rendering Infrastructure (DRI). Multi-head configurations
-are supported.
+the Direct Rendering Infrastructure (DRI) version 2 and version 3.
+Multi-head configurations are supported.
.PP
Acceleration support is dependent on a separate acceleration module. See
the "GPU ACCELERATION MODULES" section below for additional information.