summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-09-03 20:43:48 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-09-04 08:49:59 +0100
commitdf68723baae71498de95924c72d4f23fa7fc7fdf (patch)
treeff2c26b526c490f3bb611e28f7a447079a7a0fa8 /src
parente3ad18036b4dca29744ecfa4694006f01dd3fd18 (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.h14
-rw-r--r--src/sna/kgem.c59
-rw-r--r--src/sna/kgem.h2
-rw-r--r--src/sna/sna.h12
-rw-r--r--src/sna/sna_accel.c158
-rw-r--r--src/sna/sna_display.c32
-rw-r--r--src/sna/sna_dri.c8
-rw-r--r--src/sna/sna_driver.c29
-rw-r--r--src/sna/sna_glyphs.c4
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)