Signed-off-by: Keith Packard <keithp@xxxxxxxxxx> --- configure.ac | 14 ++++ src/uxa/Makefile.am | 7 ++ src/uxa/intel.h | 17 +++++ src/uxa/intel_dri3.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++ src/uxa/intel_driver.c | 13 ++++ src/uxa/intel_sync.c | 109 +++++++++++++++++++++++++++++ src/uxa/intel_uxa.c | 1 + 7 files changed, 345 insertions(+) create mode 100644 src/uxa/intel_dri3.c create mode 100644 src/uxa/intel_sync.c diff --git a/configure.ac b/configure.ac index 0783d61..13b9970 100644 --- a/configure.ac +++ b/configure.ac @@ -276,6 +276,7 @@ XORG_DRIVER_CHECK_EXT(RANDR, randrproto) XORG_DRIVER_CHECK_EXT(RENDER, renderproto) XORG_DRIVER_CHECK_EXT(XF86DRI, xextproto x11) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) +XORG_DRIVER_CHECK_EXT(DRI3, dri3proto) # Obtain compiler/linker options for the driver dependencies PKG_CHECK_MODULES(DRM, [libdrm >= 2.4.20]) # libdrm_intel is checked separately @@ -463,6 +464,19 @@ else UXA=no 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 + dri_msg="$dri_msg DRI3" +fi +AC_MSG_CHECKING([whether to include DRI3 support]) +AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes) +AC_MSG_RESULT([$DRI3]) + AC_CHECK_HEADERS([X11/extensions/dpmsconst.h]) AC_MSG_CHECKING([whether to include UXA support]) diff --git a/src/uxa/Makefile.am b/src/uxa/Makefile.am index 971ac21..3c9e693 100644 --- a/src/uxa/Makefile.am +++ b/src/uxa/Makefile.am @@ -80,6 +80,13 @@ libuxa_la_LIBADD += \ $(NULL) endif +if DRI3 +libuxa_la_SOURCES += \ + intel_dri3.c \ + intel_sync.c \ + $(NULL) +endif + if XVMC AM_CFLAGS += -I$(top_srcdir)/xvmc libuxa_la_SOURCES += \ diff --git a/src/uxa/intel.h b/src/uxa/intel.h index 922b208..c3d00f4 100644 --- a/src/uxa/intel.h +++ b/src/uxa/intel.h @@ -59,6 +59,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86xv.h" #include "xf86Crtc.h" #include "xf86RandR12.h" +#include "misync.h" #include "xorg-server.h" #include <pciaccess.h> @@ -352,6 +353,11 @@ typedef struct intel_screen_private { InputHandlerProc uevent_handler; #endif Bool has_prime_vmap_flush; + + SyncScreenFuncsRec save_sync_screen_funcs; + + void (*flush_rendering)(struct intel_screen_private *intel); + } intel_screen_private; #define INTEL_INFO(intel) ((intel)->info) @@ -519,6 +525,9 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec, void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, DRI2FrameEventPtr flip_info); +/* intel_dri3.c */ +Bool intel_dri3_screen_init(ScreenPtr screen); + extern Bool intel_crtc_on(xf86CrtcPtr crtc); int intel_crtc_to_pipe(xf86CrtcPtr crtc); @@ -725,4 +734,12 @@ static inline Bool intel_pixmap_is_offscreen(PixmapPtr pixmap) return priv && priv->offscreen; } +#if DRI3 +Bool +intel_sync_init(ScreenPtr screen); +#endif + +void +intel_sync_close(ScreenPtr screen); + #endif /* _I830_H_ */ diff --git a/src/uxa/intel_dri3.c b/src/uxa/intel_dri3.c new file mode 100644 index 0000000..99ac9d5 --- /dev/null +++ b/src/uxa/intel_dri3.c @@ -0,0 +1,184 @@ +/* + * 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 "intel.h" +#include "i830_reg.h" + +#include "i915_drm.h" + +#include "dri3.h" + +#include "intel_glamor.h" +#include "uxa.h" + +static int +intel_dri3_open(ScreenPtr screen, + RRProviderPtr provider, + int *fdp) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + intel_screen_private *intel = intel_get_screen_private(scrn); + drm_magic_t magic; + int fd; + + /* Open the device for the client */ + fd = open(intel->deviceName, O_RDWR | O_CLOEXEC); + if (fd == -1 && errno == EINVAL) { + fd = open(intel->deviceName, O_RDWR); + if (fd != -1) + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + + if (fd < 0) + return BadAlloc; + + /* Go through the auth dance locally */ + if (drmGetMagic(fd, &magic) < 0) { + close(fd); + return BadMatch; + } + + if (drmAuthMagic(intel->drmSubFD, magic) < 0) { + close (fd); + return BadMatch; + } + + /* And we're done */ + *fdp = fd; + return Success; +} + +static PixmapPtr intel_dri3_pixmap_from_fd (ScreenPtr screen, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, + CARD8 depth, + CARD8 bpp) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + intel_screen_private *intel = intel_get_screen_private(scrn); + struct intel_pixmap *priv; + PixmapPtr pixmap; + uint32_t bit_6_swizzle, tiling; + int ret; + + if (depth == 1) + return NULL; + + pixmap = fbCreatePixmap(screen, 0, 0, depth, 0); + if (!pixmap) + goto no_pixmap; + priv = calloc(1, sizeof (struct intel_pixmap)); + if (priv == NULL) + goto no_priv; + + priv->bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, + fd, (uint32_t) height * stride); + if (priv->bo == NULL) + goto no_bo; + + ret = drm_intel_bo_get_tiling(priv->bo, &tiling, &bit_6_swizzle); + if (ret != 0) + goto no_tiling; + + priv->stride = stride; + priv->tiling = tiling; + priv->offscreen = 1; + list_init(&priv->batch); + intel_set_pixmap_private(pixmap, priv); + + screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL); + + return pixmap; +no_tiling: + drm_intel_bo_unreference(priv->bo); +no_bo: + free (priv); +no_priv: + fbDestroyPixmap(pixmap); +no_pixmap: + return NULL; +} + +static int intel_dri3_fd_from_pixmap (ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, + CARD32 *size) +{ + struct intel_pixmap *priv; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + intel_screen_private *intel = intel_get_screen_private(scrn); + int fd; + int ret; + + priv = intel_get_pixmap_private(pixmap); + if (!priv) + return -1; + (*intel->flush_rendering)(intel); + ret = drm_intel_bo_gem_export_to_prime(priv->bo, &fd); + if (ret < 0) + return -1; + *stride = priv->stride; + *size = priv->bo->size; + return fd; +} + +static dri3_screen_info_rec intel_dri3_screen_info = { + .version = DRI3_SCREEN_INFO_VERSION, + + .open = intel_dri3_open, + .pixmap_from_fd = intel_dri3_pixmap_from_fd, + .fd_from_pixmap = intel_dri3_fd_from_pixmap +}; + +Bool +intel_dri3_screen_init(ScreenPtr screen) +{ + return dri3_screen_init(screen, &intel_dri3_screen_info); +} diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c index 431c34b..12c7b34 100644 --- a/src/uxa/intel_driver.c +++ b/src/uxa/intel_driver.c @@ -1050,6 +1050,10 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) if (intel->XvEnabled) I830InitVideo(screen); +#if DRI3 + intel_dri3_screen_init(screen); +#endif + #if defined(DRI2) switch (intel->directRenderingType) { case DRI_DRI2: @@ -1076,6 +1080,11 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) intel_mode_init(intel); + +#if DRI3 + (void) intel_sync_init(screen); +#endif + intel->suspended = FALSE; #if HAVE_UDEV @@ -1163,6 +1172,10 @@ static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL) I830UeventFini(scrn); #endif +#if DRI3 + intel_sync_close(screen); +#endif + intel_mode_close(intel); DeleteCallback(&FlushCallback, intel_flush_callback, scrn); diff --git a/src/uxa/intel_sync.c b/src/uxa/intel_sync.c new file mode 100644 index 0000000..94426d3 --- /dev/null +++ b/src/uxa/intel_sync.c @@ -0,0 +1,109 @@ +/* + * 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 "intel.h" +#include "misyncshm.h" +#include "misyncstr.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 intel_sync_fence_private_key; + +typedef struct _intel_sync_fence_private { + SyncFenceSetTriggeredFunc set_triggered; +} intel_sync_fence_private; + +#define SYNC_FENCE_PRIV(pFence) \ + (intel_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &intel_sync_fence_private_key) + +static void +intel_sync_fence_set_triggered (SyncFence *fence) +{ + ScreenPtr screen = fence->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + intel_screen_private *intel = intel_get_screen_private(scrn); + intel_sync_fence_private *private = SYNC_FENCE_PRIV(fence); + + + /* Flush pending rendering operations */ + if (intel->flush_rendering) + intel->flush_rendering(intel); + + fence->funcs.SetTriggered = private->set_triggered; + (*fence->funcs.SetTriggered)(fence); + private->set_triggered = fence->funcs.SetTriggered; + fence->funcs.SetTriggered = intel_sync_fence_set_triggered; +} + +static void +intel_sync_create_fence(ScreenPtr screen, + SyncFence *fence, + Bool initially_triggered) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + intel_screen_private *intel = intel_get_screen_private(scrn); + SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen); + intel_sync_fence_private *private = SYNC_FENCE_PRIV(fence); + + screen_funcs->CreateFence = intel->save_sync_screen_funcs.CreateFence; + (*screen_funcs->CreateFence)(screen, fence, initially_triggered); + + private->set_triggered = fence->funcs.SetTriggered; + fence->funcs.SetTriggered = intel_sync_fence_set_triggered; +} + +Bool +intel_sync_init(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + intel_screen_private *intel = intel_get_screen_private(scrn); + SyncScreenFuncsPtr screen_funcs; + if (!miSyncShmScreenInit(screen)) + return FALSE; + + if (!dixPrivateKeyRegistered(&intel_sync_fence_private_key)) { + if (!dixRegisterPrivateKey(&intel_sync_fence_private_key, + PRIVATE_SYNC_FENCE, + sizeof (intel_sync_fence_private))) + return FALSE; + } + + screen_funcs = miSyncGetScreenFuncs(screen); + intel->save_sync_screen_funcs.CreateFence = screen_funcs->CreateFence; + screen_funcs->CreateFence = intel_sync_create_fence; + return TRUE; +} + +void +intel_sync_close(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + intel_screen_private *intel = intel_get_screen_private(scrn); + SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen); + + if (screen_funcs) + screen_funcs->CreateFence = intel->save_sync_screen_funcs.CreateFence; +} diff --git a/src/uxa/intel_uxa.c b/src/uxa/intel_uxa.c index 6fb1333..a31d196 100644 --- a/src/uxa/intel_uxa.c +++ b/src/uxa/intel_uxa.c @@ -1420,5 +1420,6 @@ Bool intel_uxa_init(ScreenPtr screen) uxa_set_fallback_debug(screen, intel->fallback_debug); uxa_set_force_fallback(screen, intel->force_fallback); + intel->flush_rendering = intel_flush_rendering; return TRUE; } -- 1.8.4.2 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx