diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-05-09 20:26:19 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-06-02 08:32:11 +0100 |
commit | dd6db82680b05cde4a47116b7096c054f3837e20 (patch) | |
tree | aa977913aed14f1aff7f3843edc17f5e59d16a9a /src/uxa | |
parent | 975b9798be77b30cbed485583d0ccb48318708f7 (diff) |
uxa: Add DRI3 and miSyncShm support
Based on a patch by Keith Packard.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/uxa')
-rw-r--r-- | src/uxa/Makefile.am | 7 | ||||
-rw-r--r-- | src/uxa/intel.h | 27 | ||||
-rw-r--r-- | src/uxa/intel_dri.c | 1 | ||||
-rw-r--r-- | src/uxa/intel_dri3.c | 140 | ||||
-rw-r--r-- | src/uxa/intel_driver.c | 87 | ||||
-rw-r--r-- | src/uxa/intel_sync.c | 111 | ||||
-rw-r--r-- | src/uxa/intel_uxa.c | 67 |
7 files changed, 402 insertions, 38 deletions
diff --git a/src/uxa/Makefile.am b/src/uxa/Makefile.am index 4fa1b8cc..29a83296 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 a4cae139..287ffe4f 100644 --- a/src/uxa/intel.h +++ b/src/uxa/intel.h @@ -78,6 +78,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <libudev.h> #endif +#if HAVE_DRI3 +#include "misync.h" +#endif + /* remain compatible to xorg-server 1.6 */ #ifndef MONITOR_EDID_COMPLETE_RAWDATA #define MONITOR_EDID_COMPLETE_RAWDATA EDID_COMPLETE_RAWDATA @@ -162,7 +166,7 @@ enum last_3d { enum dri_type { DRI_DISABLED, DRI_NONE, - DRI_DRI2 + DRI_ACTIVE }; typedef struct intel_screen_private { @@ -324,9 +328,8 @@ typedef struct intel_screen_private { /* 965 render acceleration state */ struct gen4_render_state *gen4_render_state; - enum dri_type directRenderingType; /* DRI enabled this generation. */ - - Bool directRenderingOpen; + /* DRI enabled this generation. */ + enum dri_type dri2, dri3; int drmSubFD; char *deviceName; @@ -356,6 +359,11 @@ typedef struct intel_screen_private { pointer uevent_handler; #endif Bool has_prime_vmap_flush; + +#if HAVE_DRI3 + SyncScreenFuncsRec save_sync_screen_funcs; +#endif + void (*flush_rendering)(struct intel_screen_private *intel); } intel_screen_private; #define INTEL_INFO(intel) ((intel)->info) @@ -485,6 +493,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); @@ -691,4 +702,12 @@ static inline Bool intel_pixmap_is_offscreen(PixmapPtr pixmap) return priv && priv->offscreen; } +#if HAVE_DRI3 +Bool intel_sync_init(ScreenPtr screen); +void intel_sync_close(ScreenPtr screen); +#else +static inline Bool intel_sync_init(ScreenPtr screen) { return 0; } +void intel_sync_close(ScreenPtr screen); +#endif + #endif /* _I830_H_ */ diff --git a/src/uxa/intel_dri.c b/src/uxa/intel_dri.c index 01209b9d..d10673e6 100644 --- a/src/uxa/intel_dri.c +++ b/src/uxa/intel_dri.c @@ -1650,6 +1650,5 @@ void I830DRI2CloseScreen(ScreenPtr screen) intel_screen_private *intel = intel_get_screen_private(scrn); DRI2CloseScreen(screen); - intel->directRenderingType = DRI_NONE; drmFree(intel->deviceName); } diff --git a/src/uxa/intel_dri3.c b/src/uxa/intel_dri3.c new file mode 100644 index 00000000..dc8d7621 --- /dev/null +++ b/src/uxa/intel_dri3.c @@ -0,0 +1,140 @@ +/* + * Copyright © 2013-2014 Intel Corporation + * + * 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 "xorg-server.h" +#include "xf86.h" +#include "fb.h" + +#include "intel.h" +#include "dri3.h" + +static int +intel_dri3_open(ScreenPtr screen, + RRProviderPtr provider, + int *out) +{ + int fd; + + fd = intel_get_client_fd(xf86ScreenToScrn(screen)); + if (fd < 0) + return -fd; + + *out = 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; + dri_bo *bo; + + if (depth < 8) + return NULL; + + switch (bpp) { + case 8: + case 16: + case 32: + break; + default: + return NULL; + } + + pixmap = fbCreatePixmap(screen, 0, 0, depth, 0); + if (!pixmap) + return NULL; + + if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL)) + goto free_pixmap; + + bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, + fd, (uint32_t)height * stride); + if (bo == NULL) + goto free_pixmap; + + intel_set_pixmap_bo(pixmap, bo); + dri_bo_unreference(bo); + + priv = intel_get_pixmap_private(pixmap); + if (priv == NULL) + goto free_pixmap; + + priv->pinned |= PIN_DRI3; + + return pixmap; + +free_pixmap: + fbDestroyPixmap(pixmap); + return NULL; +} + +static int intel_dri3_fd_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, + CARD32 *size) +{ + struct intel_pixmap *priv; + int fd; + + priv = intel_get_pixmap_private(pixmap); + if (!priv) + return -1; + + if (priv->stride > UINT16_MAX) + return -1; + + if (drm_intel_bo_gem_export_to_prime(priv->bo, &fd) < 0) + return -1; + + priv->pinned |= PIN_DRI3; + + *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 654038c8..9e21742b 100644 --- a/src/uxa/intel_driver.c +++ b/src/uxa/intel_driver.c @@ -232,15 +232,15 @@ static void intel_check_dri_option(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - intel->directRenderingType = DRI_NONE; + intel->dri2 = intel->dri3 = DRI_NONE; if (!intel_option_cast_string_to_bool(intel, OPTION_DRI, TRUE)) - intel->directRenderingType = DRI_DISABLED; + intel->dri2 = intel->dri3 = DRI_DISABLED; if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) { xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "DRI is disabled because it " "runs only at depths 16, 24, and 30.\n"); - intel->directRenderingType = DRI_DISABLED; + intel->dri2 = intel->dri3 = DRI_DISABLED; } } @@ -599,9 +599,15 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags) return FALSE; } - /* Load the dri2 module if requested. */ - if (intel->directRenderingType != DRI_DISABLED) - xf86LoadSubModule(scrn, "dri2"); + /* Load the dri modules if requested. */ +#if HAVE_DRI2 + if (intel->dri2 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri2")) + intel->dri2 = DRI_DISABLED; +#endif +#if HAVE_DRI3 + if (intel->dri3 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri3")) + intel->dri3 = DRI_DISABLED; +#endif return TRUE; } @@ -871,13 +877,6 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) */ intel->XvEnabled = TRUE; -#ifdef DRI2 - if (intel->directRenderingType == DRI_NONE - && I830DRI2ScreenInit(screen)) - intel->directRenderingType = DRI_DRI2; -#endif - - if (!intel_init_initial_framebuffer(scrn)) return FALSE; intel_batch_init(scrn); @@ -893,6 +892,7 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) if (!miSetPixmapDepths()) return FALSE; + /* Must be first, before anything else installs screen callbacks. */ if (!fbScreenInit(screen, NULL, scrn->virtualX, scrn->virtualY, scrn->xDpi, scrn->yDpi, @@ -924,6 +924,18 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) return FALSE; } +#if HAVE_DRI2 + if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen)) + intel->dri2 = DRI_ACTIVE; +#endif + +#if HAVE_DRI3 + if (!intel_sync_init(screen)) + intel->dri3 = DRI_DISABLED; + if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen)) + intel->dri3 = DRI_ACTIVE; +#endif + xf86SetBackingStore(screen); xf86SetSilkenMouse(screen); miDCInitialize(screen, xf86GetPointerScreenFuncs()); @@ -977,7 +989,7 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) #ifdef INTEL_XVMC if (INTEL_INFO(intel)->gen >= 040) intel->XvMCEnabled = TRUE; - from = ((intel->directRenderingType == DRI_DRI2) && + from = (intel->dri2 == DRI_ACTIVE && xf86GetOptValBool(intel->Options, OPTION_XVMC, &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT); xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n", @@ -987,25 +999,44 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) if (intel->XvEnabled) I830InitVideo(screen); -#if defined(DRI2) - switch (intel->directRenderingType) { - case DRI_DRI2: - intel->directRenderingOpen = TRUE; +#if HAVE_DRI2 + switch (intel->dri2) { + case DRI_ACTIVE: + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "DRI2: Enabled\n"); + break; + case DRI_DISABLED: + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "DRI2: Disabled\n"); + break; + case DRI_NONE: + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "DRI2: Failed\n"); + break; + } +#else + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "DRI2: Not available\n"); +#endif + +#if HAVE_DRI3 + switch (intel->dri3) { + case DRI_ACTIVE: xf86DrvMsg(scrn->scrnIndex, X_INFO, - "direct rendering: DRI2 Enabled\n"); + "DRI3: Enabled\n"); break; case DRI_DISABLED: xf86DrvMsg(scrn->scrnIndex, X_INFO, - "direct rendering: Disabled\n"); + "DRI3: Disabled\n"); break; case DRI_NONE: xf86DrvMsg(scrn->scrnIndex, X_INFO, - "direct rendering: Failed\n"); + "DRI3: Failed\n"); break; } #else xf86DrvMsg(scrn->scrnIndex, X_INFO, - "direct rendering: Not available\n"); + "DRI3: Not available\n"); #endif if (serverGeneration == 1) @@ -1142,12 +1173,18 @@ static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL) screen->CloseScreen = intel->CloseScreen; (*screen->CloseScreen) (CLOSE_SCREEN_ARGS); - if (intel->directRenderingOpen - && intel->directRenderingType == DRI_DRI2) { - intel->directRenderingOpen = FALSE; + if (intel->dri2 == DRI_ACTIVE) { I830DRI2CloseScreen(screen); + intel->dri2 = DRI_NONE; } + if (intel->dri3 == DRI_ACTIVE) { + /* nothing to do here? */ + intel->dri3 = DRI_NONE; + } + + intel_sync_close(screen); + xf86GARTCloseScreen(scrn->scrnIndex); scrn->vtSema = FALSE; diff --git a/src/uxa/intel_sync.c b/src/uxa/intel_sync.c new file mode 100644 index 00000000..cd73a1b5 --- /dev/null +++ b/src/uxa/intel_sync.c @@ -0,0 +1,111 @@ +/* + * Copyright © 2013-2014 Intel Corporation + * + * 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); + intel->save_sync_screen_funcs.CreateFence = screen_funcs->CreateFence; + screen_funcs->CreateFence = intel_sync_create_fence; + + 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 e90b1489..3bc1d23b 100644 --- a/src/uxa/intel_uxa.c +++ b/src/uxa/intel_uxa.c @@ -633,18 +633,38 @@ dri_bo *intel_get_pixmap_bo(PixmapPtr pixmap) return intel->bo; } +static unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch) +{ + unsigned long tile_width; + + if (tiling == I915_TILING_NONE) + return 4; + + tile_width = (tiling == I915_TILING_Y) ? 128 : 512; + if (INTEL_INFO(intel)->gen >= 040) + return tile_width; + + while (tile_width < pitch) + tile_width <<= 1; + + return tile_width; +} + void intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) { + ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); + intel_screen_private *intel = intel_get_screen_private(scrn); struct intel_pixmap *priv; priv = intel_get_pixmap_private(pixmap); if (priv == NULL && bo == NULL) - return; + return; if (priv != NULL) { if (priv->bo == bo) return; +free_priv: dri_bo_unreference(priv->bo); list_del(&priv->batch); @@ -653,9 +673,9 @@ void intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) } if (bo != NULL) { - uint32_t tiling; - uint32_t swizzle_mode; - int ret; + uint32_t tiling, swizzle_mode; + unsigned tile_width; + int size, stride; priv = calloc(1, sizeof (struct intel_pixmap)); if (priv == NULL) @@ -667,15 +687,45 @@ void intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) priv->bo = bo; priv->stride = intel_pixmap_pitch(pixmap); - ret = drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode); - if (ret != 0) { - FatalError("Couldn't get tiling on bo %p: %s\n", - bo, strerror(-ret)); + if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) { + bo = NULL; + goto free_priv; } priv->tiling = tiling; priv->busy = -1; priv->offscreen = 1; + + stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8; + tile_width = intel_get_tile_width(intel, tiling, stride); + stride = ALIGN(stride, tile_width); + + if (priv->stride < stride || + priv->stride & (tile_width - 1) || + priv->stride >= KB(32)) { + bo = NULL; + goto free_priv; + } + + if (tiling != I915_TILING_NONE) { + int height; + + if (IS_GEN2(intel)) + height = 16; + else if (tiling == I915_TILING_X) + height = 8; + else + height = 32; + + height = ALIGN(pixmap->drawable.height, 2*height); + size = intel_get_fence_size(intel, priv->stride * height); + } else + size = priv->stride * pixmap->drawable.height; + + if (bo->size < size || bo->size > intel->max_bo_size) { + bo = NULL; + goto free_priv; + } } BAIL: @@ -1422,5 +1472,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; } |