summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-11-17 16:02:21 -0800
committerKeith Packard <keithp@keithp.com>2013-11-17 16:02:21 -0800
commit18a319b6d15d5c59d4b85565ab54260ef3810ec3 (patch)
tree93bb4a60b97b723a8575886570c905da01b6102f
parentd571d6af70ef27efd1ed6420eb892bdde963ed7a (diff)
Add DRI3 and miSyncShm supportdri3
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--configure.ac13
-rw-r--r--src/Makefile.am7
-rw-r--r--src/drmmode_display.c10
-rw-r--r--src/drmmode_display.h6
-rw-r--r--src/radeon.h13
-rw-r--r--src/radeon_dri3.c172
-rw-r--r--src/radeon_sync.c106
7 files changed, 321 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac
index 835b7b9f..9b19f324 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
XORG_DRIVER_CHECK_EXT(XV, videoproto)
XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
+XORG_DRIVER_CHECK_EXT(DRI3, dri3proto)
# Checks for libraries.
PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.46])
@@ -112,6 +113,18 @@ if test "x$GLAMOR" != "xno"; then
AC_DEFINE(USE_GLAMOR, 1, [Enable glamor acceleration])
fi
+if test "x$DRI3" != "xno"; then
+ save_CFLAGS=$CFLAGS
+ CFLAGS="$XORG_CFLAGS $DRM_CFLAGS $DRI_CFLAGS $DRI3_CFLAGS"
+ AC_CHECK_DECL(DRI3,
+ [DRI3=yes], [DRI3=no],
+ [#include <xorg-server.h>])
+ CFLAGS=$save_CFLAGS
+fi
+AC_MSG_CHECKING([whether to include DRI3 support])
+AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes)
+AC_MSG_RESULT([$DRI3])
+
AC_CHECK_HEADERS([list.h],
[have_list_h="yes"], [have_list_h="no"],
[#include <X11/Xdefs.h>
diff --git a/src/Makefile.am b/src/Makefile.am
index e23dc1df..97eeab82 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -44,6 +44,10 @@ if LIBUDEV
radeon_drv_la_LIBADD += $(LIBUDEV_LIBS)
endif
+if DRI3
+RADEON_DRI3_SOURCES = radeon_dri3.c radeon_sync.c
+endif
+
ati_drv_la_LTLIBRARIES = ati_drv.la
ati_drv_la_LDFLAGS = -module -avoid-version
ati_drv_ladir = @moduledir@/drivers
@@ -58,7 +62,8 @@ radeon_drv_la_SOURCES = \
radeon_misc.c radeon_probe.c \
radeon_textured_video.c radeon_xvmc.c \
$(RADEON_EXA_SOURCES) \
- $(RADEON_KMS_SRCS)
+ $(RADEON_KMS_SRCS) \
+ $(RADEON_DRI3_SOURCES)
if GLAMOR
AM_CFLAGS += @LIBGLAMOR_CFLAGS@
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 76b79d8c..e9c2825b 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -87,11 +87,11 @@ RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
return FALSE;
}
-static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
- int width, int height,
- int depth, int bpp,
- int pitch, int tiling,
- struct radeon_bo *bo, struct radeon_surface *psurf)
+PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
+ int width, int height,
+ int depth, int bpp,
+ int pitch, int tiling,
+ struct radeon_bo *bo, struct radeon_surface *psurf)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 41e29f62..0da5927f 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -126,5 +126,11 @@ extern int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id);
int drmmode_get_current_ust(int drm_fd, CARD64 *ust);
+PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
+ int width, int height,
+ int depth, int bpp,
+ int pitch, int tiling,
+ struct radeon_bo *bo, struct radeon_surface *psurf);
+
#endif
diff --git a/src/radeon.h b/src/radeon.h
index f1817e74..e1262bd3 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -87,6 +87,13 @@
#include "picturestr.h"
#endif
+#ifdef DRI3
+#include "syncsdk.h"
+#include "misyncshm.h"
+#include "misyncstr.h"
+#undef CARD64
+#endif
+
#include "compat-api.h"
#include "simple_list.h"
@@ -483,6 +490,12 @@ typedef struct {
/* cursor size */
int cursor_w;
int cursor_h;
+
+#ifdef DRI3
+ SyncScreenFuncsRec save_sync_screen_funcs;
+
+ void (*flush_rendering)(ScrnInfoPtr scrn);
+#endif
} RADEONInfoRec, *RADEONInfoPtr;
/* radeon_accel.c */
diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c
new file mode 100644
index 00000000..5f2db3fa
--- /dev/null
+++ b/src/radeon_dri3.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "xf86Pci.h"
+#include "xf86drm.h"
+
+#include "windowstr.h"
+#include "shadow.h"
+#include "fb.h"
+
+#include "radeon.h"
+#include <radeon_bo_gem.h>
+
+#include "dri3.h"
+
+static int
+radeon_dri3_open(ScreenPtr screen,
+ RRProviderPtr provider,
+ int *fdp)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
+ struct pci_device *dev = info->PciInfo;
+ drm_magic_t magic;
+ int fd;
+ char *busid;
+
+ /* Open the device for the client */
+
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,9,99,901,0)
+ XNFasprintf(&busid, "pci:%04x:%02x:%02x.%d",
+ dev->domain, dev->bus, dev->dev, dev->func);
+#else
+ busid = XNFprintf("pci:%04x:%02x:%02x.%d",
+ dev->domain, dev->bus, dev->dev, dev->func);
+#endif
+
+ fd = drmOpen("radeon", busid);
+
+ if (fd < 0)
+ return BadAlloc;
+
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+
+ /* Go through the auth dance locally */
+ if (drmGetMagic(fd, &magic) < 0) {
+ close(fd);
+ return BadMatch;
+ }
+
+ if (drmAuthMagic(pRADEONEnt->fd, magic) < 0) {
+ close (fd);
+ return BadMatch;
+ }
+
+ /* And we're done */
+ *fdp = fd;
+ return Success;
+}
+
+static PixmapPtr radeon_dri3_pixmap_from_fd (ScreenPtr screen,
+ int fd,
+ CARD16 width,
+ CARD16 height,
+ CARD16 stride,
+ CARD8 depth,
+ CARD8 bpp)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ PixmapPtr pixmap;
+ uint32_t tiling_flags, tiling;
+ int ret;
+ struct radeon_bo *bo;
+
+ if (depth == 1)
+ return NULL;
+
+ bo = radeon_gem_bo_open_prime(info->bufmgr,
+ fd, (uint32_t) height * stride);
+ if (bo == NULL)
+ return NULL;
+
+ ret = radeon_bo_get_tiling(bo, &tiling, &tiling_flags);
+ if (ret != 0)
+ goto no_tiling;
+
+ pixmap = drmmode_create_bo_pixmap(scrn, width, height, depth, bpp, stride, tiling,
+ bo, NULL);
+ if (!pixmap)
+ goto no_tiling;
+
+ return pixmap;
+no_tiling:
+ radeon_bo_unref(bo);
+ return NULL;
+}
+
+static int radeon_dri3_fd_from_pixmap (ScreenPtr screen,
+ PixmapPtr pixmap,
+ CARD16 *stride,
+ CARD32 *size)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+ int fd;
+ int ret;
+
+ if (info->flush_rendering)
+ (*info->flush_rendering)(scrn);
+
+ ret = radeon_gem_prime_share_bo(priv->bo, &fd);
+ if (ret < 0)
+ return -1;
+ *stride = priv->stride;
+ *size = priv->bo->size;
+ return fd;
+}
+
+static dri3_screen_info_rec radeon_dri3_screen_info = {
+ .version = DRI3_SCREEN_INFO_VERSION,
+
+ .open = radeon_dri3_open,
+ .pixmap_from_fd = radeon_dri3_pixmap_from_fd,
+ .fd_from_pixmap = radeon_dri3_fd_from_pixmap
+};
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+ return dri3_screen_init(screen, &radeon_dri3_screen_info);
+}
diff --git a/src/radeon_sync.c b/src/radeon_sync.c
new file mode 100644
index 00000000..3baa12f3
--- /dev/null
+++ b/src/radeon_sync.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "radeon.h"
+
+/*
+ * This whole file exists to wrap a sync fence trigger operation
+ * so that we can flush the batch buffer to provide serialization
+ * between the server and the shm fence client
+ */
+
+static DevPrivateKeyRec radeon_sync_fence_private_key;
+
+typedef struct _radeon_sync_fence_private {
+ SyncFenceSetTriggeredFunc set_triggered;
+} radeon_sync_fence_private;
+
+#define SYNC_FENCE_PRIV(pFence) \
+ (radeon_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &radeon_sync_fence_private_key)
+
+static void
+radeon_sync_fence_set_triggered (SyncFence *fence)
+{
+ ScreenPtr screen = fence->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+ /* Flush pending rendering operations */
+ if (info->flush_rendering)
+ info->flush_rendering(scrn);
+
+ fence->funcs.SetTriggered = private->set_triggered;
+ (*fence->funcs.SetTriggered)(fence);
+ private->set_triggered = fence->funcs.SetTriggered;
+ fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+static void
+radeon_sync_create_fence(ScreenPtr screen,
+ SyncFence *fence,
+ Bool initially_triggered)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+ radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+ screen_funcs->CreateFence = info->save_sync_screen_funcs.CreateFence;
+ (*screen_funcs->CreateFence)(screen, fence, initially_triggered);
+
+ private->set_triggered = fence->funcs.SetTriggered;
+ fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+Bool
+radeon_sync_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs;
+ if (!miSyncShmScreenInit(screen))
+ return FALSE;
+
+ if (!dixPrivateKeyRegistered(&radeon_sync_fence_private_key)) {
+ if (!dixRegisterPrivateKey(&radeon_sync_fence_private_key,
+ PRIVATE_SYNC_FENCE,
+ sizeof (radeon_sync_fence_private)))
+ return FALSE;
+ }
+
+ screen_funcs = miSyncGetScreenFuncs(screen);
+ info->save_sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
+ screen_funcs->CreateFence = radeon_sync_create_fence;
+ return TRUE;
+}
+
+void
+radeon_sync_close(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+
+ if (screen_funcs)
+ screen_funcs->CreateFence = info->save_sync_screen_funcs.CreateFence;
+}