diff options
-rw-r--r-- | configure.ac | 13 | ||||
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/drmmode_display.c | 10 | ||||
-rw-r--r-- | src/drmmode_display.h | 6 | ||||
-rw-r--r-- | src/radeon.h | 13 | ||||
-rw-r--r-- | src/radeon_dri3.c | 172 | ||||
-rw-r--r-- | src/radeon_sync.c | 106 |
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; +} |