diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-09-03 20:43:48 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-09-04 08:49:59 +0100 |
commit | df68723baae71498de95924c72d4f23fa7fc7fdf (patch) | |
tree | ff2c26b526c490f3bb611e28f7a447079a7a0fa8 /src | |
parent | e3ad18036b4dca29744ecfa4694006f01dd3fd18 (diff) |
sna: Port prime interfacing
Preliminary prime support.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r-- | src/sna/fb/fb.h | 14 | ||||
-rw-r--r-- | src/sna/kgem.c | 59 | ||||
-rw-r--r-- | src/sna/kgem.h | 2 | ||||
-rw-r--r-- | src/sna/sna.h | 12 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 158 | ||||
-rw-r--r-- | src/sna/sna_display.c | 32 | ||||
-rw-r--r-- | src/sna/sna_dri.c | 8 | ||||
-rw-r--r-- | src/sna/sna_driver.c | 29 | ||||
-rw-r--r-- | src/sna/sna_glyphs.c | 4 |
9 files changed, 290 insertions, 28 deletions
diff --git a/src/sna/fb/fb.h b/src/sna/fb/fb.h index 3339236e..215aec99 100644 --- a/src/sna/fb/fb.h +++ b/src/sna/fb/fb.h @@ -28,15 +28,15 @@ #include "config.h" #endif -#include <stdbool.h> -#include <pixman.h> - #include <xorg-server.h> #include <servermd.h> #include <gcstruct.h> #include <colormap.h> #include <windowstr.h> +#include <stdbool.h> +#include <pixman.h> + #if HAS_DEBUG_FULL #define DBG(x) ErrorF x #else @@ -288,13 +288,17 @@ typedef struct { unsigned char bpp; /* current drawable bpp */ } FbGCPrivate, *FbGCPrivPtr; +extern DevPrivateKeyRec sna_gc_key; +extern DevPrivateKeyRec sna_window_key; + static inline FbGCPrivate *fb_gc(GCPtr gc) { - return (FbGCPrivate *)gc->devPrivates; + return dixGetPrivateAddr(&gc->devPrivates, &sna_gc_key); } + static inline PixmapPtr fbGetWindowPixmap(WindowPtr window) { - return *(void **)window->devPrivates; + return *(PixmapPtr *)dixGetPrivateAddr(&window->devPrivates, &sna_window_key); } #ifdef ROOTLESS diff --git a/src/sna/kgem.c b/src/sna/kgem.c index cb0c82a7..d68ad9f2 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -2771,6 +2771,65 @@ struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name) return bo; } +struct kgem_bo *kgem_create_for_prime(struct kgem *kgem, int name, uint32_t size) +{ +#ifdef DRM_IOCTL_PRIME_FD_TO_HANDLE + struct drm_prime_handle args; + struct drm_i915_gem_get_tiling tiling; + struct kgem_bo *bo; + + DBG(("%s(name=%d)\n", __FUNCTION__, name)); + + VG_CLEAR(args); + args.fd = name; + args.flags = 0; + if (drmIoctl(kgem->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args)) + return NULL; + + VG_CLEAR(tiling); + tiling.handle = args.handle; + if (drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &tiling)) { + gem_close(kgem->fd, args.handle); + return NULL; + } + + DBG(("%s: new handle=%d, tiling=%d\n", __FUNCTION__, + args.handle, tiling.tiling_mode)); + bo = __kgem_bo_alloc(args.handle, NUM_PAGES(size)); + if (bo == NULL) { + gem_close(kgem->fd, args.handle); + return NULL; + } + + bo->tiling = tiling.tiling_mode; + bo->reusable = false; + + debug_alloc__bo(kgem, bo); + return bo; +#else + return NULL; +#endif +} + +int kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo) +{ +#ifdef DRM_IOCTL_PRIME_HANDLE_TO_PRIME + struct drm_prime_handle args; + + VG_CLEAR(args); + args.handle = bo->handle; + args.flags = DRM_CLOEXEC; + + if (drmIoctl(kgem->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args)) + return -1; + + bo->reusable = false; + return args.fd; +#else + return -1; +#endif +} + struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags) { struct kgem_bo *bo; diff --git a/src/sna/kgem.h b/src/sna/kgem.h index d72db559..33cd3ff3 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -207,6 +207,8 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem, bool read_only); struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name); +struct kgem_bo *kgem_create_for_prime(struct kgem *kgem, int name, uint32_t size); +int kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo); struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags); struct kgem_bo *kgem_create_proxy(struct kgem *kgem, diff --git a/src/sna/sna.h b/src/sna/sna.h index d655da0b..b8760616 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -47,6 +47,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <xorg-server.h> #include <xf86Crtc.h> +#if XF86_CRTC_VERSION >= 5 +#define HAS_PIXMAP_SHARING 1 +#endif + #include <xf86str.h> #include <windowstr.h> #include <glyphstr.h> @@ -149,9 +153,11 @@ static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable) return get_window_pixmap((WindowPtr)drawable); } +extern DevPrivateKeyRec sna_pixmap_key; + constant static inline struct sna_pixmap *sna_pixmap(PixmapPtr pixmap) { - return ((void **)pixmap->devPrivates)[1]; + return ((void **)dixGetPrivateAddr(&pixmap->devPrivates, &sna_pixmap_key))[1]; } static inline struct sna_pixmap *sna_pixmap_from_drawable(DrawablePtr drawable) @@ -167,7 +173,7 @@ struct sna_gc { static inline struct sna_gc *sna_gc(GCPtr gc) { - return (struct sna_gc *)gc->devPrivates; + return dixGetPrivateAddr(&gc->devPrivates, &sna_gc_key); } enum { @@ -309,7 +315,7 @@ to_sna_from_screen(ScreenPtr screen) constant static inline struct sna * to_sna_from_pixmap(PixmapPtr pixmap) { - return *(void **)pixmap->devPrivates; + return ((void **)dixGetPrivateAddr(&pixmap->devPrivates, &sna_pixmap_key))[0]; } constant static inline struct sna * diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 0cb10bc2..b9bf93b6 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -601,11 +601,7 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling) static inline void sna_set_pixmap(PixmapPtr pixmap, struct sna_pixmap *sna) { -#if 0 - dixSetPrivate(&pixmap->devPrivates, &sna_private_index, sna); -#else - ((void **)pixmap->devPrivates)[1] = sna; -#endif + ((void **)dixGetPrivateAddr(&pixmap->devPrivates, &sna_pixmap_key))[1] = sna; assert(sna_pixmap(pixmap) == sna); } @@ -709,7 +705,8 @@ create_pixmap(struct sna *sna, ScreenPtr screen, if (!pixmap) return NullPixmap; - ((void **)pixmap->devPrivates)[0] = sna; + ((void **)dixGetPrivateAddr(&pixmap->devPrivates, &sna_pixmap_key))[0] = sna; + assert(to_sna_from_pixmap(pixmap) == sna); pixmap->drawable.type = DRAWABLE_PIXMAP; pixmap->drawable.class = 0; @@ -924,6 +921,111 @@ sna_pixmap_create_scratch(ScreenPtr screen, return pixmap; } +#ifdef CREATE_PIXMAP_USAGE_SHARED +static Bool +sna_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle) +{ + struct sna *sna = to_sna_from_pixmap(pixmap); + struct sna_pixmap *priv; + int fd; + + priv = sna_pixmap_move_to_gpu(pixmap, + MOVE_READ | MOVE_WRITE | __MOVE_DRI | __MOVE_FORCE); + if (priv == NULL) + return FALSE; + + assert(priv->gpu_bo); + + /* XXX */ + if (priv->gpu_bo->tiling && + !sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) + return FALSE; + assert(priv->gpu_bo->tiling == I915_TILING_NONE); + + /* And export the bo->pitch via pixmap->devKind */ + pixmap->devPrivate.ptr = + kgem_bo_map(&sna->kgem, priv->gpu_bo); + if (pixmap->devPrivate.ptr == NULL) + return FALSE; + + pixmap->devKind = priv->gpu_bo->pitch; + priv->mapped = true; + + fd = kgem_bo_export_to_prime(&sna->kgem, priv->gpu_bo); + if (fd == -1) + return FALSE; + + priv->pinned = true; + + *fd_handle = (void *)(intptr_t)fd; + return TRUE; +} + +static Bool +sna_set_shared_pixmap_backing(PixmapPtr pixmap, void *fd_handle) +{ + struct sna *sna = to_sna_from_pixmap(pixmap); + struct sna_pixmap *priv; + struct kgem_bo *bo; + + priv = sna_pixmap(pixmap); + if (priv == NULL) + return FALSE; + + assert(!priv->pinned); + assert(priv->gpu_bo == NULL); + assert(priv->cpu_bo == NULL); + assert(priv->cpu_damage == NULL); + assert(priv->gpu_damage == NULL); + + bo = kgem_bo_create_for_prime(&sna->kgem, + (intptr_t)fd_handle, + pixmap->devKind * pixmap->drawable.height); + if (bo == NULL) + return FALSE; + + sna_damage_all(&priv->gpu_damage, + pixmap->drawable.width, + pixmap->drawable.height); + + bo->pitch = pixmap->devKind; + priv->stride = pixmap->devKind; + + priv->gpu_bo = bo; + priv->pinned = true; + + close((intptr_t)fd_handle); + return TRUE; +} + +static PixmapPtr +sna_create_pixmap_shared(struct sna *sna, ScreenPtr screen, int depth) +{ + PixmapPtr pixmap; + struct sna_pixmap *priv; + + /* Create a stub to be attached later */ + pixmap = create_pixmap(sna, screen, 0, 0, depth, 0); + if (pixmap == NullPixmap) + return NullPixmap; + + pixmap->drawable.width = 0; + pixmap->drawable.height = 0; + pixmap->devKind = 0; + pixmap->devPrivate.ptr = NULL; + + priv = sna_pixmap_attach(pixmap); + if (priv == NULL) { + free(pixmap); + return NullPixmap; + } + + priv->stride = 0; + priv->create = 0; + return pixmap; +} +#endif + static PixmapPtr sna_create_pixmap(ScreenPtr screen, int width, int height, int depth, unsigned int usage) @@ -936,6 +1038,13 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen, DBG(("%s(%d, %d, %d, usage=%x)\n", __FUNCTION__, width, height, depth, usage)); +#ifdef CREATE_PIXMAP_USAGE_SHARED + if (usage == CREATE_PIXMAP_USAGE_SHARED) { + assert((width|height) == 0); + return sna_create_pixmap_shared(sna, screen, depth); + } +#endif + if ((width|height) == 0) { usage = -1; goto fallback; @@ -13675,6 +13784,31 @@ static int32_t sna_timeout(struct sna *sna) return next; } +static void sna_accel_post_damage(struct sna *sna) +{ +#if HAS_PIXMAP_SHARING + ScreenPtr screen = sna->scrn->pScreen; + PixmapDirtyUpdatePtr dirty; + + xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { + RegionRec pixregion; + + if (!RegionNotEmpty(DamageRegion(dirty->damage))) + continue; + + PixmapRegionInit(&pixregion, + dirty->slave_dst->master_pixmap); + PixmapSyncDirtyHelper(dirty, &pixregion); + + DamageRegionAppend(&dirty->slave_dst->drawable, + &pixregion); + RegionUninit(&pixregion); + + DamageEmpty(dirty->damage); + } +#endif +} + static void sna_accel_flush(struct sna *sna) { struct sna_pixmap *priv = sna_accel_scanout(sna); @@ -13699,6 +13833,7 @@ static void sna_accel_flush(struct sna *sna) } sna_mode_redisplay(sna); + sna_accel_post_damage(sna); } static void sna_accel_throttle(struct sna *sna) @@ -13859,7 +13994,7 @@ sna_get_window_pixmap(WindowPtr window) static void sna_set_window_pixmap(WindowPtr window, PixmapPtr pixmap) { - *(PixmapPtr *)window->devPrivates = pixmap; + *(PixmapPtr *)dixGetPrivateAddr(&window->devPrivates, &sna_window_key) = pixmap; } static Bool @@ -13988,6 +14123,10 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna) screen->CreatePixmap = sna_create_pixmap; assert(screen->DestroyPixmap == NULL); screen->DestroyPixmap = sna_destroy_pixmap; +#ifdef CREATE_PIXMAP_USAGE_SHARED + screen->SharePixmapBacking = sna_share_pixmap_backing; + screen->SetSharedPixmapBacking = sna_set_shared_pixmap_backing; +#endif screen->RealizeFont = sna_realize_font; screen->UnrealizeFont = sna_unrealize_font; assert(screen->CreateGC == NULL); @@ -14002,6 +14141,11 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna) screen->StoreColors = sna_store_colors; screen->BitmapToRegion = fbBitmapToRegion; +#if HAS_PIXMAP_SHARING + screen->StartPixmapTracking = PixmapStartDirtyTracking; + screen->StopPixmapTracking = PixmapStopDirtyTracking; +#endif + assert(screen->GetWindowPixmap == NULL); screen->GetWindowPixmap = sna_get_window_pixmap; assert(screen->SetWindowPixmap == NULL); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 3ec6dc10..7e872041 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -60,6 +60,7 @@ struct sna_crtc { struct drm_mode_modeinfo kmode; int dpms_mode; + PixmapPtr scanout_pixmap; struct kgem_bo *bo; uint32_t cursor; bool shadow; @@ -960,6 +961,22 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc) sna_crtc->transform = true; return bo; + } else if (sna_crtc->scanout_pixmap) { + DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__)); + if (!sna_crtc_enable_shadow(sna, sna_crtc)) + return NULL; + + bo = sna_pixmap_pin(sna_crtc->scanout_pixmap); + if (bo == NULL) + return NULL; + + if (!get_fb(sna, bo, + sna_crtc->scanout_pixmap->drawable.width, + sna_crtc->scanout_pixmap->drawable.height)) + return NULL; + + sna_crtc->transform = true; + return kgem_bo_reference(bo); } else if (sna->flags & SNA_TEAR_FREE) { DBG(("%s: tear-free updates requested\n", __FUNCTION__)); @@ -1299,6 +1316,15 @@ sna_crtc_destroy(xf86CrtcPtr crtc) crtc->driver_private = NULL; } +#if HAS_PIXMAP_SHARING +static Bool +sna_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr pixmap) +{ + to_sna_crtc(crtc)->scanout_pixmap = pixmap; + return TRUE; +} +#endif + static const xf86CrtcFuncsRec sna_crtc_funcs = { .dpms = sna_crtc_dpms, .set_mode_major = sna_crtc_set_mode_major, @@ -1309,6 +1335,9 @@ static const xf86CrtcFuncsRec sna_crtc_funcs = { .load_cursor_argb = sna_crtc_load_cursor_argb, .gamma_set = sna_crtc_gamma_set, .destroy = sna_crtc_destroy, +#if HAS_PIXMAP_SHARING + .set_scanout_pixmap = sna_set_scanout_pixmap, +#endif }; static uint32_t @@ -2412,6 +2441,9 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna) for (i = 0; i < mode->kmode->count_connectors; i++) sna_output_init(scrn, mode, i); +#if HAS_PIXMAP_SHARING + xf86ProviderSetup(scrn, NULL, "Intel"); +#endif xf86InitialConfiguration(scrn, TRUE); return true; diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c index 77e4e26c..ff18fe3f 100644 --- a/src/sna/sna_dri.c +++ b/src/sna/sna_dri.c @@ -195,12 +195,12 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna, constant static inline void *sna_pixmap_get_buffer(PixmapPtr pixmap) { - return ((void **)pixmap->devPrivates)[2]; + return ((void **)dixGetPrivateAddr(&pixmap->devPrivates, &sna_pixmap_key))[2]; } static inline void sna_pixmap_set_buffer(PixmapPtr pixmap, void *ptr) { - ((void **)pixmap->devPrivates)[2] = ptr; + ((void **)dixGetPrivateAddr(&pixmap->devPrivates, &sna_pixmap_key))[2] = ptr; } static DRI2Buffer2Ptr @@ -841,7 +841,7 @@ sna_dri_get_pipe(DrawablePtr pDraw) static struct sna_dri_frame_event * sna_dri_window_get_chain(WindowPtr win) { - return ((void **)win->devPrivates)[1]; + return ((void **)dixGetPrivateAddr(&win->devPrivates, &sna_window_key))[1]; } static void @@ -850,7 +850,7 @@ sna_dri_window_set_chain(WindowPtr win, { DBG(("%s: head now %p\n", __FUNCTION__, chain)); assert(win->drawable.type == DRAWABLE_WINDOW); - ((void **)win->devPrivates)[1] = chain; + ((void **)dixGetPrivateAddr(&win->devPrivates, &sna_window_key))[1] = chain; } static void diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c index 2eab460b..a1936079 100644 --- a/src/sna/sna_driver.c +++ b/src/sna/sna_driver.c @@ -75,10 +75,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "git_version.h" #endif -static DevPrivateKeyRec sna_pixmap_key; -static DevPrivateKeyRec sna_gc_key; -static DevPrivateKeyRec sna_glyph_key; -static DevPrivateKeyRec sna_window_key; +DevPrivateKeyRec sna_pixmap_key; +DevPrivateKeyRec sna_gc_key; +DevPrivateKeyRec sna_window_key; +DevPrivateKeyRec sna_glyph_key; static Bool sna_enter_vt(VT_FUNC_ARGS_DECL); @@ -343,6 +343,21 @@ static bool has_pageflipping(struct sna *sna) return v > 0; } +static void sna_setup_capabilities(ScrnInfoPtr scrn, int fd) +{ +#if HAS_PIXMAP_SHARING && defined(DRM_CAP_PRIME) + uint64_t value; + + scrn->capabilities = 0; + if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0) { + if (value & DRM_PRIME_CAP_EXPORT) + scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload; + if (value & DRM_PRIME_CAP_IMPORT) + scrn->capabilities |= RR_Capability_SinkOutput; + } +#endif +} + /** * This is called before ScreenInit to do any require probing of screen * configuration. @@ -442,6 +457,8 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags) if (sna->Options == NULL) return FALSE; + sna_setup_capabilities(scrn, fd); + intel_detect_chipset(scrn, sna->pEnt, sna->PciInfo); kgem_init(&sna->kgem, fd, sna->PciInfo, sna->info->gen); @@ -777,22 +794,18 @@ sna_register_all_privates(void) if (!dixRegisterPrivateKey(&sna_pixmap_key, PRIVATE_PIXMAP, 3*sizeof(void *))) return FALSE; - assert(sna_pixmap_key.offset == 0); if (!dixRegisterPrivateKey(&sna_gc_key, PRIVATE_GC, sizeof(FbGCPrivate))) return FALSE; - assert(sna_gc_key.offset == 0); if (!dixRegisterPrivateKey(&sna_glyph_key, PRIVATE_GLYPH, sizeof(struct sna_glyph))) return FALSE; - assert(sna_glyph_key.offset == 0); if (!dixRegisterPrivateKey(&sna_window_key, PRIVATE_WINDOW, 2*sizeof(void *))) return FALSE; - assert(sna_window_key.offset == 0); return TRUE; } diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c index 8cbe39cd..f7331a57 100644 --- a/src/sna/sna_glyphs.c +++ b/src/sna/sna_glyphs.c @@ -104,9 +104,11 @@ static void _assert_pixmap_contains_box(PixmapPtr pixmap, BoxPtr box, const char #define assert_pixmap_contains_box(p, b) #endif +extern DevPrivateKeyRec sna_glyph_key; + static inline struct sna_glyph *sna_glyph(GlyphPtr glyph) { - return (struct sna_glyph *)glyph->devPrivates; + return dixGetPrivateAddr(&glyph->devPrivates, &sna_glyph_key); } #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) |