diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/intel_device.c | 24 | ||||
-rw-r--r-- | src/intel_driver.h | 4 | ||||
-rw-r--r-- | src/intel_xmir.h | 15 | ||||
-rw-r--r-- | src/sna/Makefile.am | 1 | ||||
-rw-r--r-- | src/sna/sna.h | 35 | ||||
-rw-r--r-- | src/sna/sna_dri.c | 14 | ||||
-rw-r--r-- | src/sna/sna_driver.c | 19 | ||||
-rw-r--r-- | src/sna/sna_xmir.c | 179 |
9 files changed, 284 insertions, 8 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b0781ca4..126bde2d 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 b3926df9..710348e9 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 e54054fe..0c5e4aec 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 00000000..2e3c85ab --- /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 5d5417ec..1c5dda0b 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 e2d1ef84..5889c5f0 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 2527884f..e0a1fc07 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 2a4a830d..44eea338 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 00000000..ddce984c --- /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, ®ion->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 |