diff options
-rw-r--r-- | configure.ac | 19 | ||||
-rw-r--r-- | etnaviv/Makefile.am | 6 | ||||
-rw-r--r-- | etnaviv/etnaviv.c | 134 | ||||
-rw-r--r-- | etnaviv/etnaviv_accel.h | 7 | ||||
-rw-r--r-- | etnaviv/etnaviv_dri3.c | 128 | ||||
-rw-r--r-- | etnaviv/etnaviv_dri3.h | 12 | ||||
-rw-r--r-- | man/armada.man | 4 |
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. |