summaryrefslogtreecommitdiff
authorChris Wilson <chris@chris-wilson.co.uk>2013-07-24 00:44:30 (GMT)
committer Chris Wilson <chris@chris-wilson.co.uk>2013-09-04 14:18:29 (GMT)
commit42d94356f65972eb7fb8991234a4e9388c4c2031 (patch) (side-by-side diff)
tree94ee6a9dc6f87762e581d99899c82826579b9f26
parentf906a4de62856df5b2536ce9704750c3530636fa (diff)
downloadxf86-video-intel-42d94356f65972eb7fb8991234a4e9388c4c2031.zip
xf86-video-intel-42d94356f65972eb7fb8991234a4e9388c4c2031.tar.gz
sna: Add XMir support
With lots of updates by Christopher James Halse Rogers as he updated the XMir API - but now supposedly frozen! "<RAOF> ickle: I think the xmir api should be pretty much stable now, barring people coming up with more awesome ways of doing things." Signed-off-by: Christopher James Halse Rogers <raof@ubuntu.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/Makefile.am1
-rw-r--r--src/intel_device.c24
-rw-r--r--src/intel_driver.h4
-rw-r--r--src/intel_xmir.h15
-rw-r--r--src/sna/Makefile.am1
-rw-r--r--src/sna/sna.h35
-rw-r--r--src/sna/sna_dri.c14
-rw-r--r--src/sna/sna_driver.c19
-rw-r--r--src/sna/sna_xmir.c179
9 files changed, 284 insertions, 8 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b0781ca..126bde2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,7 @@ intel_drv_la_SOURCES = \
intel_driver.h \
intel_options.c \
intel_module.c \
+ intel_xmir.h \
compat-api.h \
$(NULL)
diff --git a/src/intel_device.c b/src/intel_device.c
index b3926df..710348e 100644
--- a/src/intel_device.c
+++ b/src/intel_device.c
@@ -144,10 +144,34 @@ static int fd_set_nonblock(int fd)
return fd;
}
+static int __intel_open_xmir(const struct pci_device *pci,
+ char **path)
+{
+ char id[20];
+ int fd;
+
+ snprintf(id, sizeof(id),
+ "pci:%04x:%02x:%02x.%d",
+ pci->domain, pci->bus, pci->dev, pci->func);
+ fd = xmir_get_drm_fd(id);
+ if (fd == -1)
+ return -1;
+
+ if (*path == NULL) /* XXX Fix Xmir - it knows both the fd and path */
+ *path = drmGetDeviceNameFromFd(fd);
+ if (*path == NULL)
+ fd = -1;
+
+ return fd;
+}
+
static int __intel_open_device(const struct pci_device *pci, char **path)
{
int fd;
+ if (xorgMir)
+ return __intel_open_xmir(pci, path);
+
if (*path == NULL) {
char id[20];
int ret;
diff --git a/src/intel_driver.h b/src/intel_driver.h
index e54054f..0c5e4ae 100644
--- a/src/intel_driver.h
+++ b/src/intel_driver.h
@@ -1,6 +1,8 @@
#ifndef INTEL_DRIVER_H
#define INTEL_DRIVER_H
+#include "intel_xmir.h"
+
#define INTEL_VERSION 4000
#define INTEL_NAME "intel"
#define INTEL_DRIVER_NAME "intel"
@@ -129,6 +131,6 @@ void intel_put_device(ScrnInfoPtr scrn);
void __intel_uxa_release_device(ScrnInfoPtr scrn);
-#define hosted() (0)
+#define hosted() (xorgMir)
#endif /* INTEL_DRIVER_H */
diff --git a/src/intel_xmir.h b/src/intel_xmir.h
new file mode 100644
index 0000000..2e3c85a
--- a/dev/null
+++ b/src/intel_xmir.h
@@ -0,0 +1,15 @@
+#ifndef INTEL_XMIR_H
+#define INTEL_XMIR_H
+
+#include <xorg-server.h>
+
+#if XMIR
+#include <xf86Priv.h>
+#include <xmir.h>
+#else
+typedef struct xmir_screen xmir_screen;
+#define xorgMir 0
+#define xmir_get_drm_fd(id) -1
+#endif
+
+#endif /* INTEL_XMIR_H */
diff --git a/src/sna/Makefile.am b/src/sna/Makefile.am
index 5d5417e..1c5dda0 100644
--- a/src/sna/Makefile.am
+++ b/src/sna/Makefile.am
@@ -75,6 +75,7 @@ libsna_la_SOURCES = \
sna_video_overlay.c \
sna_video_sprite.c \
sna_video_textured.c \
+ sna_xmir.c \
gen2_render.c \
gen2_render.h \
gen3_render.c \
diff --git a/src/sna/sna.h b/src/sna/sna.h
index e2d1ef8..5889c5f 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -288,6 +288,7 @@ struct sna {
EntityInfoPtr pEnt;
struct pci_device *PciInfo;
const struct intel_device_info *info;
+ xmir_screen *xmir;
ScreenBlockHandlerProcPtr BlockHandler;
ScreenWakeupHandlerProcPtr WakeupHandler;
@@ -426,14 +427,24 @@ CARD32 sna_render_format_for_depth(int depth);
void sna_debug_flush(struct sna *sna);
static inline bool
+get_window_deltas(PixmapPtr pixmap, int16_t *x, int16_t *y)
+{
+#ifdef COMPOSITE
+ *x = -pixmap->screen_x;
+ *y = -pixmap->screen_y;
+ return pixmap->screen_x | pixmap->screen_y;
+#else
+ *x = *y = 0;
+ return false;
+#endif
+}
+
+static inline bool
get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int16_t *x, int16_t *y)
{
#ifdef COMPOSITE
- if (drawable->type == DRAWABLE_WINDOW) {
- *x = -pixmap->screen_x;
- *y = -pixmap->screen_y;
- return pixmap->screen_x | pixmap->screen_y;
- }
+ if (drawable->type == DRAWABLE_WINDOW)
+ return get_window_deltas(pixmap, x, y);
#endif
*x = *y = 0;
return false;
@@ -946,4 +957,18 @@ void sna_image_composite(pixman_op_t op,
uint16_t width,
uint16_t height);
+/* sna_xmir.c */
+
+#if XMIR
+bool sna_xmir_create(struct sna *sna);
+bool sna_xmir_pre_init(struct sna *sna);
+void sna_xmir_init(struct sna *sna, ScreenPtr screen);
+void sna_xmir_post_damage(struct sna *sna);
+#else
+inline static bool sna_xmir_create(struct sna *sna) { return true; }
+inline static bool sna_xmir_pre_init(struct sna *sna) { return true; }
+inline static void sna_xmir_init(struct sna *sna, ScreenPtr screen) { }
+inline static void sna_xmir_post_damage(struct sna *sna) { }
+#endif
+
#endif /* _SNA_H */
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 2527884..e0a1fc0 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -2249,6 +2249,13 @@ out_complete:
}
#endif
+#if DRI2INFOREC_VERSION >= 8 && XMIR
+static int sna_dri_auth_magic2(ScreenPtr screen, uint32_t magic)
+{
+ return xmir_auth_drm_magic(to_sna_from_screen(screen)->xmir, magic);
+}
+#endif
+
static bool has_i830_dri(void)
{
return access(DRI_DRIVER_PATH "/i830_dri.so", R_OK) == 0;
@@ -2324,6 +2331,13 @@ bool sna_dri_open(struct sna *sna, ScreenPtr screen)
info.ReuseBufferNotify = NULL;
#endif
+#if DRI2INFOREC_VERSION >= 8 && XMIR
+ if (sna->xmir) {
+ info.version = 8;
+ info.AuthMagic2 = sna_dri_auth_magic2;
+ }
+#endif
+
#if USE_ASYNC_SWAP
info.version = 10;
info.scheduleSwap0 = 1;
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 2a4a830..44eea33 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -442,6 +442,9 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
goto cleanup;
}
+ if (!sna_xmir_create(sna))
+ goto cleanup;
+
/* Sanity check */
if (hosted() && (sna->flags & SNA_IS_HOSTED) == 0) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -449,9 +452,14 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
goto cleanup;
}
- preferred_depth = sna->info->gen < 030 ? 15 : 24;
- if (!fb_supports_depth(fd, preferred_depth))
+ if (sna->xmir) {
+ /* XXX query depth from xmir */
preferred_depth = 24;
+ } else {
+ preferred_depth = sna->info->gen < 030 ? 15 : 24;
+ if (!fb_supports_depth(fd, preferred_depth))
+ preferred_depth = 24;
+ }
if (!xf86SetDepthBpp(scrn, preferred_depth, 0, 0,
Support32bppFb |
@@ -488,6 +496,9 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
intel_detect_chipset(scrn, sna->pEnt, sna->PciInfo);
+ if (!sna_xmir_pre_init(sna))
+ goto cleanup;
+
kgem_init(&sna->kgem, fd, sna->PciInfo, sna->info->gen);
if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE) ||
!sna_option_cast_to_bool(sna, OPTION_ACCEL_METHOD, TRUE)) {
@@ -571,6 +582,8 @@ sna_block_handler(BLOCKHANDLER_ARGS_DECL)
if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec))
sna_accel_block_handler(sna, tv);
+
+ sna_xmir_post_damage(sna);
}
static void
@@ -918,6 +931,8 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
if (!miDCInitialize(screen, xf86GetPointerScreenFuncs()))
return FALSE;
+ sna_xmir_init(sna, screen); /* after DirectCursor is initialised */
+
if ((sna->flags & SNA_IS_HOSTED) == 0 &&
xf86_cursors_init(screen, SNA_CURSOR_X, SNA_CURSOR_Y,
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
diff --git a/src/sna/sna_xmir.c b/src/sna/sna_xmir.c
new file mode 100644
index 0000000..ddce984
--- a/dev/null
+++ b/src/sna/sna_xmir.c
@@ -0,0 +1,179 @@
+/***************************************************************************
+
+ Copyright 2013 Intel Corporation. All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sub license, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial portions
+ of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **************************************************************************/
+
+#include <assert.h>
+
+#include "sna.h"
+
+#if XMIR
+
+/* Theory of Operation
+ * -------------------
+ *
+ * 1. Clients render to their pixmaps and Windows aggregating damage.
+ * 2. Before blocking, we walk the list of dirty Windows and submit
+ * any damage to Mir. This consumes the xfer buffer.
+ * 3. Clients continue to render and we accumulate damage. However,
+ * as there is now no xfer buffer free, damage accumulates.
+ * 4. Mir reports that its exchange has complete and gives us a new
+ * transport buffer.
+ * 5. Before going to sleep, we iterate over dirty Windows and copy
+ * their damage into the xfer buffer and send back to Mir.
+ *
+ * Clients render uninterrupted, but we only send damage to Mir once
+ * every frame.
+ */
+
+#define FORCE_FULL_REDRAW 0
+
+static void
+sna_xmir_copy_to_mir(xmir_window *xmir_win, RegionPtr region)
+{
+ PixmapPtr src = get_window_pixmap(xmir_window_to_windowptr(xmir_win));
+ struct sna *sna = to_sna_from_pixmap(src);
+ const BoxRec *dst_box = xmir_window_get_drawable_region(xmir_win);
+ struct sna_pixmap *priv;
+ struct kgem_bo *bo;
+ BoxRec *box;
+ const int pitch = xmir_window_get_stride(xmir_win);
+ int16_t sx, sy, dx, dy;
+ int n;
+
+#if FORCE_FULL_REDRAW
+ RegionRec whole = { { 0, 0, src->drawable.width, src->drawable.height } };
+ region = &whole;
+#endif
+
+ assert(region);
+
+ DBG(("%s: copying region (%d, %d), (%d, %d) x %d, dst box=(%d, %d), (%d, %d), pitch=%d, fd=%d\n",
+ __FUNCTION__,
+ region->extents.x1, region->extents.y1,
+ region->extents.x2, region->extents.y2,
+ REGION_NUM_RECTS(region),
+ dst_box->x1, dst_box->y1,
+ dst_box->x2, dst_box->y2,
+ pitch, xmir_window_get_fd(xmir_win)));
+
+ box = REGION_RECTS(region);
+ n = REGION_NUM_RECTS(region);
+ if (n == 0)
+ return;
+
+ /* XXX size is bogus, but only used for sanity checks */
+ bo = kgem_create_for_prime(&sna->kgem,
+ xmir_window_get_fd(xmir_win),
+ pitch * (dst_box->y2 - dst_box->y1));
+ if (bo == NULL)
+ return;
+
+ bo->pitch = pitch;
+ bo->scanout = true; /* presume the worst (almost always true) */
+
+ if (get_window_deltas(src, &sx, &sy))
+ RegionTranslate(region, sx, sy);
+
+ dx = sx + dst_box->x1;
+ dy = sy + dst_box->y1;
+
+ priv = sna_pixmap_move_area_to_gpu(src, &region->extents, MOVE_READ);
+ if (priv && sna->render.copy_boxes(sna, GXcopy,
+ src, priv->gpu_bo, 0, 0,
+ src, bo, -dx, -dy,
+ box, n, COPY_LAST)) {
+ kgem_submit(&sna->kgem);
+ n = 0;
+ } else {
+ void *dst = kgem_bo_map__gtt(&sna->kgem, bo);
+ if (dst && sna_drawable_move_region_to_cpu(&src->drawable,
+ region, MOVE_READ)) {
+ kgem_bo_sync__gtt(&sna->kgem, bo);
+ do {
+ memcpy_blt(src->devPrivate.ptr, dst,
+ src->drawable.bitsPerPixel,
+ src->devKind, bo->pitch,
+ box->x1, box->y1,
+ box->x1 - dx, box->y1 - dy,
+ box->x2 - box->x1,
+ box->y2 - box->y1);
+ } while (--n);
+ }
+ }
+
+ if (sx | sy)
+ RegionTranslate(region, -sx, -sy);
+
+ if (n == 0)
+ xmir_submit_rendering_for_window(xmir_win, region);
+
+ bo->scanout = false; /* but don't confuse our caching! */
+ kgem_bo_destroy(&sna->kgem, bo);
+}
+
+static xmir_driver sna_xmir_driver = {
+ XMIR_DRIVER_VERSION,
+ sna_xmir_copy_to_mir
+};
+
+bool sna_xmir_create(struct sna *sna)
+{
+ if (!xorgMir)
+ return true;
+
+ sna->xmir = xmir_screen_create(sna->scrn);
+ if (sna->xmir == NULL)
+ return false;
+
+ sna->flags |= SNA_IS_HOSTED;
+ return true;
+}
+
+bool sna_xmir_pre_init(struct sna *sna)
+{
+ if (sna->xmir == NULL)
+ return true;
+
+ return xmir_screen_pre_init(sna->scrn, sna->xmir, &sna_xmir_driver);
+}
+
+void sna_xmir_init(struct sna *sna, ScreenPtr screen)
+{
+ if (sna->xmir == NULL)
+ return;
+
+ xmir_screen_init(screen, sna->xmir);
+}
+
+void sna_xmir_post_damage(struct sna *sna)
+{
+ if (sna->xmir == NULL)
+ return;
+
+ xmir_screen_for_each_damaged_window(sna->xmir,
+ sna_xmir_copy_to_mir);
+}
+
+#endif