Rebased ref, commits from common ancestor: commit 7817949314a21293c8bc34dec214b42932b19aaf Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Wed Jan 27 10:54:46 2016 +0000
sna/dri2: Avoiding marking a pending-signal on a dead Drawable If the Drawable is gone, we cannot send it a frame-complete signal, and in particular we cannot continue the pending flip-chain. References: https://bugs.freedesktop.org/show_bug.cgi?id=93844 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index f2f4908..045b12d 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -2787,6 +2787,9 @@ sna_dri2_flip_continue(struct sna_dri2_event *info) info->type = info->flip_continue; info->flip_continue = 0; + if (info->draw == NULL) + return false; + if (info->sna->mode.front_active == 0) return false; @@ -2801,6 +2804,7 @@ sna_dri2_flip_continue(struct sna_dri2_event *info) info->sna->dri2.flip_pending == info); info->sna->dri2.flip_pending = info; info->queued = true; + assert(info->draw); info->signal = info->type == FLIP_THROTTLE; return true; @@ -3097,6 +3101,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc, assert(info->crtc == crtc); info->event_complete = func; info->event_data = data; + assert(info->draw); info->signal = true; info->front = sna_dri2_reference_buffer(front); @@ -3133,6 +3138,7 @@ new_back: sna_dri2_get_back(sna, draw, back); DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE); + assert(info->draw); info->signal = signal; if (info->type == FLIP_ASYNC) sna_dri2_event_free(info); @@ -3156,6 +3162,7 @@ queue: assert(info->crtc == crtc); info->event_complete = func; info->event_data = data; + assert(info->draw); info->signal = true; info->type = FLIP; @@ -3312,6 +3319,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, assert(info->crtc == crtc); info->event_complete = func; info->event_data = data; + assert(info->draw); info->signal = true; info->front = sna_dri2_reference_buffer(front); @@ -3391,6 +3399,7 @@ fake: /* XXX Use a Timer to throttle the client? */ fake_swap_complete(sna, client, draw, crtc, type, func, data); if (info) { + assert(info->draw); info->signal = false; sna_dri2_event_free(info); } commit bb8dc3ef37580a221a40ba3dcbde755edc59bb62 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Tue Jan 26 12:50:13 2016 +0000 sna/video: ValidateGC before use We required the GC->pCompositeClip in order to apply the current Drawable's clip to video region, this requires us to call ValidateGC first. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93874 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h index dfb8c0c..b278991 100644 --- a/src/sna/sna_video.h +++ b/src/sna/sna_video.h @@ -213,4 +213,26 @@ sna_window_set_port(WindowPtr window, XvPortPtr port) ((void **)__get_private(window, sna_window_key))[2] = port; } +static inline int offset_and_clip(int x, int dx) +{ + x += dx; + if (x <= 0) + return 0; + if (x >= MAXSHORT) + return MAXSHORT; + return x; +} + +static inline void init_video_region(RegionRec *region, + DrawablePtr draw, + int drw_x, int drw_y, + int drw_w, int drw_h) +{ + region->extents.x1 = offset_and_clip(draw->x, drw_x); + region->extents.y1 = offset_and_clip(draw->y, drw_y); + region->extents.x2 = offset_and_clip(draw->x, drw_x + drw_w); + region->extents.y2 = offset_and_clip(draw->y, drw_y + drw_h); + region->data = NULL; +} + #endif /* SNA_VIDEO_H */ diff --git a/src/sna/sna_video_overlay.c b/src/sna/sna_video_overlay.c index d782113..9bc5ce4 100644 --- a/src/sna/sna_video_overlay.c +++ b/src/sna/sna_video_overlay.c @@ -474,15 +474,13 @@ sna_video_overlay_put_image(ddPutImage_ARGS) if (src_h >= (drw_h * 8)) drw_h = src_h / 7; - clip.extents.x1 = draw->x + drw_x; - clip.extents.y1 = draw->y + drw_y; - clip.extents.x2 = clip.extents.x1 + drw_w; - clip.extents.y2 = clip.extents.y1 + drw_h; - clip.data = NULL; + init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h); DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop)); - if (!video->AlwaysOnTop) + if (!video->AlwaysOnTop) { + ValidateGC(draw, gc); RegionIntersect(&clip, &clip, gc->pCompositeClip); + } if (box_empty(&clip.extents)) goto invisible; diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c index 7c8a73f..9e85049 100644 --- a/src/sna/sna_video_sprite.c +++ b/src/sna/sna_video_sprite.c @@ -373,15 +373,13 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS) RegionRec clip; int ret, i; - clip.extents.x1 = draw->x + drw_x; - clip.extents.y1 = draw->y + drw_y; - clip.extents.x2 = clip.extents.x1 + drw_w; - clip.extents.y2 = clip.extents.y1 + drw_h; - clip.data = NULL; + init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h); DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop)); - if (!video->AlwaysOnTop) + if (!video->AlwaysOnTop) { + ValidateGC(draw, gc); RegionIntersect(&clip, &clip, gc->pCompositeClip); + } DBG(("%s: src=(%d, %d),(%d, %d), dst=(%d, %d),(%d, %d), id=%d, sizep=%dx%d, sync?=%d\n", __FUNCTION__, diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c index 3f14a59..f5b7e98 100644 --- a/src/sna/sna_video_textured.c +++ b/src/sna/sna_video_textured.c @@ -156,12 +156,9 @@ sna_video_textured_put_image(ddPutImage_ARGS) if (wedged(sna)) return BadAlloc; - clip.extents.x1 = draw->x + drw_x; - clip.extents.y1 = draw->y + drw_y; - clip.extents.x2 = clip.extents.x1 + drw_w; - clip.extents.y2 = clip.extents.y1 + drw_h; - clip.data = NULL; + init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h); + ValidateGC(draw, gc); RegionIntersect(&clip, &clip, gc->pCompositeClip); if (!RegionNotEmpty(&clip)) return Success; commit 8ab71cd3293ad420b0cdf487e8d5c66170ddc13c Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Mon Jan 25 21:41:57 2016 +0000 sna/dri2: Guard signalling swap completion after a FLIP Before sending the frame swap complete signal after a FLIP, make sure the client didn't die in the meantime. Reported-by: Diego Viola <diego.vi...@gmail.com> References: https://bugs.freedesktop.org/show_bug.cgi?id=93844 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 5450434..f2f4908 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -2873,8 +2873,10 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip) /* We assume our flips arrive in order, so we don't check the frame */ switch (flip->type) { case FLIP: - DBG(("%s: swap complete, unblocking client\n", __FUNCTION__)); - frame_swap_complete(flip, DRI2_FLIP_COMPLETE); + if (flip->signal) { + DBG(("%s: swap complete, unblocking client\n", __FUNCTION__)); + frame_swap_complete(flip, DRI2_FLIP_COMPLETE); + } sna_dri2_event_free(flip); if (sna->dri2.flip_pending) commit 7bebe12afe549af3eceab35b29415f804949f994 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Mon Jan 25 16:03:27 2016 +0000 sna/damage: Clear all-damaged NULL pointer on destroy Remember to reset the all-damaged pointer, even if it is NULL. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h index 3665255..d5c727e 100644 --- a/src/sna/sna_damage.h +++ b/src/sna/sna_damage.h @@ -319,10 +319,11 @@ static inline void sna_damage_reduce_all(struct sna_damage **_damage, void __sna_damage_destroy(struct sna_damage *damage); static inline void sna_damage_destroy(struct sna_damage **damage) { - if (DAMAGE_PTR(*damage) == NULL) + if (*damage == NULL) return; - __sna_damage_destroy(DAMAGE_PTR(*damage)); + if (DAMAGE_PTR(*damage)) + __sna_damage_destroy(DAMAGE_PTR(*damage)); *damage = NULL; } commit 21fa92a9ba254527a8661ddde837c7a4c5ff5493 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Mon Jan 25 15:37:01 2016 +0000 sna/damage: Prevent freeing a NULL damage marked as all-damage After an allocation failure, we may mark a NULL damage pointer as being all-damaged. This works on the whole as most places we only ask whether it is all or not damaged, and if we do a partial fallback we should just then migrate the whole pixmap. However, we tried to destroy the NULL damage pointer, and crashed. Reported-by: Franck Delache <franck.dela...@grassvalley.com> References: https://bugs.freedesktop.org/show_bug.cgi?id=93720 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h index 272e83b..3665255 100644 --- a/src/sna/sna_damage.h +++ b/src/sna/sna_damage.h @@ -267,7 +267,7 @@ int _sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes); static inline int sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes) { - assert(damage); + assert(DAMAGE_PTR(damage)); if (DAMAGE_IS_ALL(damage)) { *boxes = &DAMAGE_PTR(damage)->extents; @@ -319,7 +319,7 @@ static inline void sna_damage_reduce_all(struct sna_damage **_damage, void __sna_damage_destroy(struct sna_damage *damage); static inline void sna_damage_destroy(struct sna_damage **damage) { - if (*damage == NULL) + if (DAMAGE_PTR(*damage) == NULL) return; __sna_damage_destroy(DAMAGE_PTR(*damage)); commit b48d4a7917ab793526be47559becc64aacd347ae Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Fri Jan 22 20:11:31 2016 +0000 sna/dri2: Tweak enginement placement on inherited render targets The main motivation is try and isolate from an upcoming API change in busy-ioctl, but is also based on the observation that we now only care about write-synchronisation. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 0e18456..5450434 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1110,13 +1110,12 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg * The ultimate question is whether preserving the ring outweighs * the cost of the query. */ - if (popcount(busy.busy >> 16) > 1) - mode = busy.busy & 0xffff ? KGEM_BLT : KGEM_RENDER; - else if (busy.busy & (0xfffe << 16)) + mode = KGEM_RENDER; + if ((busy.busy & 0xffff) == KGEM_BLT) mode = KGEM_BLT; - else - mode = KGEM_RENDER; - kgem_bo_mark_busy(&sna->kgem, busy.handle == src->handle ? src : dst, mode); + kgem_bo_mark_busy(&sna->kgem, + busy.handle == src->handle ? src : dst, + mode); _kgem_set_mode(&sna->kgem, mode); } commit 26cc364d2eb078085ff4a6dd2968b426bf333b4f Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Wed Jan 20 11:06:56 2016 +0000 sna: Allow for a Y-tiled shadow If the CRTC can use Y-tiling, why not try it for the shadow allocation and perhaps save a composited rotation (still requiring the copy onto the shadow)? Suggestd-by: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 1a1bebb..511aa84 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -2394,6 +2394,10 @@ force_shadow: } tiling = I915_TILING_X; + if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270) && + sna->kgem.can_scanout_y) + tiling = I915_TILING_Y; + if (sna->kgem.gen == 071) tiled_limit = 16 * 1024 * 8; else if ((sna->kgem.gen >> 3) > 4) commit 3a057beca9f290854dd22cd4d2c0fed01c82dd78 Author: Damien Lespiau <damien.lesp...@intel.com> Date: Tue Jan 12 15:01:04 2016 +0000 Sync PCI ids with latest kernel, adding SKL GT4 Syncs with: commit 15620206ae87ba9643ffa6f5ddb5471be7192006 Author: Mika Kuoppala <mika.kuopp...@linux.intel.com> Date: Fri Nov 6 14:11:16 2015 +0200 drm/i915/skl: Add SKL GT4 PCI IDs Signed-off-by: Damien Lespiau <damien.lesp...@intel.com> diff --git a/src/i915_pciids.h b/src/i915_pciids.h index f1a113e..f970209 100644 --- a/src/i915_pciids.h +++ b/src/i915_pciids.h @@ -279,12 +279,19 @@ #define INTEL_SKL_GT3_IDS(info) \ INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \ INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \ - INTEL_VGA_DEVICE(0x192A, info) /* SRV GT3 */ \ + INTEL_VGA_DEVICE(0x192A, info) /* SRV GT3 */ -#define INTEL_SKL_IDS(info) \ +#define INTEL_SKL_GT4_IDS(info) \ + INTEL_VGA_DEVICE(0x1932, info), /* DT GT4 */ \ + INTEL_VGA_DEVICE(0x193B, info), /* Halo GT4 */ \ + INTEL_VGA_DEVICE(0x193D, info), /* WKS GT4 */ \ + INTEL_VGA_DEVICE(0x193A, info) /* SRV GT4 */ + +#define INTEL_SKL_IDS(info) \ INTEL_SKL_GT1_IDS(info), \ INTEL_SKL_GT2_IDS(info), \ - INTEL_SKL_GT3_IDS(info) + INTEL_SKL_GT3_IDS(info), \ + INTEL_SKL_GT4_IDS(info) #define INTEL_BXT_IDS(info) \ INTEL_VGA_DEVICE(0x0A84, info), \ commit c3dccf76b614d8bcf7fc8b0906754e187a7b7ac4 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Wed Jan 20 10:52:19 2016 +0000 sna: Reset CRTC if setting rotation fails If the kernel doesn't like chaning the native rotation mode with the output currently enabled, try disabling it before cryinc foul. Suggestd-by: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 8082e9f..1a1bebb 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1351,6 +1351,12 @@ sna_crtc_apply(xf86CrtcPtr crtc) sna_crtc_disable_cursor(sna, sna_crtc); if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) { + memset(&arg, 0, sizeof(arg)); + arg.crtc_id = __sna_crtc_id(sna_crtc); + (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg); + } + + if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) { ERR(("%s: set-primary-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n", __FUNCTION__, sna_crtc->primary.rotation.prop, sna_crtc->rotation, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), errno)); sna_crtc->primary.rotation.supported &= ~sna_crtc->rotation; commit 928050d4e4b0ee958be897d148b60328e9207228 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Tue Jan 19 08:49:18 2016 +0000 sna/dri2: Catch setting signal=true when we have no drawable Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 63c4932..0e18456 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1507,6 +1507,7 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc) { struct dri2_window *priv; + assert(draw); if (draw->type != DRAWABLE_WINDOW) return msc; @@ -1595,6 +1596,8 @@ static void fake_swap_complete(struct sna *sna, ClientPtr client, { const struct ust_msc *swap; + assert(draw); + swap = sna_crtc_last_swap(crtc); DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc %lld], tv=%d.%06d\n", __FUNCTION__, type, (long)draw->id, crtc ? sna_crtc_pipe(crtc) : -1, @@ -1716,6 +1719,8 @@ sna_dri2_client_gone(CallbackListPtr *list, void *closure, void *data) event->client = NULL; event->draw = NULL; + event->keepalive = 1; + assert(!event->signal); if (!event->queued) sna_dri2_event_free(event); @@ -1751,6 +1756,7 @@ sna_dri2_add_event(struct sna *sna, struct dri2_window *priv; struct sna_dri2_event *info, *chain; + assert(draw != NULL); assert(draw->type == DRAWABLE_WINDOW); DBG(("%s: adding event to window %ld)\n", __FUNCTION__, (long)draw->id)); @@ -1852,6 +1858,8 @@ void sna_dri2_destroy_window(WindowPtr win) info->signal = false; info->draw = NULL; + info->keepalive = 1; + assert(!info->signal); list_del(&info->link); chain = info->chain; @@ -2636,8 +2644,10 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event) else __sna_dri2_copy_event(info, info->sync | DRI2_BO); - info->keepalive++; - info->signal = true; + if (info->draw) { + info->keepalive++; + info->signal = true; + } } if (--info->keepalive) { @@ -2729,6 +2739,7 @@ sna_dri2_immediate_blit(struct sna *sna, bool signal = chain->signal; DBG(("%s: swap elision, unblocking client\n", __FUNCTION__)); + assert(chain->draw); chain->signal = true; frame_swap_complete(chain, DRI2_EXCHANGE_COMPLETE); chain->signal = signal; @@ -3072,6 +3083,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc, } else { info->flip_continue = FLIP_COMPLETE; signal = info->signal; + assert(info->draw); info->signal = true; goto new_back; } @@ -3363,6 +3375,7 @@ skip: info->type = SWAP_COMPLETE; info->event_complete = func; info->event_data = data; + assert(info->draw); info->signal = true; info->front = sna_dri2_reference_buffer(front); commit d04e3f63f98eab02614119d59f5df6767bbbf11a Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Tue Jan 12 09:28:34 2016 +0000 sna: Setup the GTT domain on the new cursors We should not rely on first-fault setting the domain for us. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 60bc42b..8082e9f 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -657,6 +657,7 @@ static uint32_t gem_create(int fd, int size) static void *gem_mmap(int fd, int handle, int size) { struct drm_i915_gem_mmap_gtt mmap_arg; + struct drm_i915_gem_set_domain set_domain; void *ptr; VG_CLEAR(mmap_arg); @@ -668,6 +669,15 @@ static void *gem_mmap(int fd, int handle, int size) if (ptr == MAP_FAILED) return NULL; + VG_CLEAR(set_domain); + set_domain.handle = handle; + set_domain.read_domains = I915_GEM_DOMAIN_GTT; + set_domain.write_domain = I915_GEM_DOMAIN_GTT; + if (drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) { + munmap(ptr, size); + return NULL; + } + return ptr; } commit 371219c34a54707a0d568c51defae478079fbf71 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Fri Jan 8 09:17:19 2016 +0000 intel-virtual-output: Virtual heads are numbered from index 1 When checking for VIRTUAL support on the xserver, it helps to check for the right name. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/tools/virtual.c b/tools/virtual.c index 6b6d977..77e6a58 100644 --- a/tools/virtual.c +++ b/tools/virtual.c @@ -994,14 +994,14 @@ static int check_virtual(struct display *display) if (output == NULL) continue; - if (strcmp(output->name, "VIRTUAL0") == 0) + if (strcmp(output->name, "VIRTUAL1") == 0) found = 0; XRRFreeOutputInfo(output); } XRRFreeScreenResources(res); - DBG(XRR, ("%s(%s): has VIRTUAL0? %d\n", + DBG(XRR, ("%s(%s): has VIRTUAL1? %d\n", __func__, DisplayString(display->dpy), found)); return found; } commit 9083d2ed5876f1891727b512da57766d8d11af56 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Wed Jan 6 14:09:40 2016 +0000 intel-virtual-output: Print more helpful error when run on the wrong server Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/tools/virtual.c b/tools/virtual.c index bcbcb42..6b6d977 100644 --- a/tools/virtual.c +++ b/tools/virtual.c @@ -977,6 +977,35 @@ out: return rr_output; } +static int check_virtual(struct display *display) +{ + XRRScreenResources *res; + int found = -ENOENT; + int i; + + res = _XRRGetScreenResourcesCurrent(display->dpy, display->root); + if (res == NULL) + return -ENOMEM; + + for (i = 0; found == -ENOENT && i < res->noutput; i++) { + XRROutputInfo *output; + + output = XRRGetOutputInfo(display->dpy, res, res->outputs[i]); + if (output == NULL) + continue; + + if (strcmp(output->name, "VIRTUAL0") == 0) + found = 0; + + XRRFreeOutputInfo(output); + } + XRRFreeScreenResources(res); + + DBG(XRR, ("%s(%s): has VIRTUAL0? %d\n", + __func__, DisplayString(display->dpy), found)); + return found; +} + static int stride_for_depth(int width, int depth) { if (depth == 24) @@ -3419,6 +3448,13 @@ int main(int argc, char **argv) goto out; } + ret = check_virtual(ctx.display); + if (ret) { + fprintf(stderr, "No VIRTUAL outputs on \"%s\".\n", + DisplayString(ctx.display->dpy)); + goto out; + } + if (singleton) { XSelectInput(ctx.display->dpy, ctx.display->root, PropertyChangeMask); if (first_display_has_singleton(&ctx)) { commit 5c735befdcc40f94bd740be9fc0df54ad53aa174 Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Wed Jan 6 10:00:19 2016 +0000 sna/dri2: Ignore pending SwapComplete events when the window is destroyed Since we need the drawable to call DRI2SwapComplete/DRI2WakeClient, if the window is destroyed that becomes inoperable (as we are called late in the chain). Let's hope the client isn't blocked. Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 33cf3d9..63c4932 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1837,20 +1837,20 @@ void sna_dri2_destroy_window(WindowPtr win) chain = priv->chain; while ((info = chain)) { + DBG(("%s: freeing event, pending signal? %d, pending swap? handle=%d\n", + __FUNCTION__, info->signal, + info->pending.bo ? info->pending.bo->handle : 0)); assert(info->draw == &win->drawable); - if (info->signal) - frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE); + if (info->pending.bo) { assert(info->pending.bo->active_scanout > 0); info->pending.bo->active_scanout--; - info->signal = true; - frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE); - kgem_bo_destroy(&sna->kgem, info->pending.bo); info->pending.bo = NULL; } + info->signal = false; info->draw = NULL; list_del(&info->link); commit 8e987511f0f190115e2587a94922b766d4f8719a Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Sat Jan 2 21:29:58 2016 +0000 tools/intel-virtual-output: Propagate screen blanking When attaching to a target display, disable the builtin screen blanking (equivalent to xset -d :8 s off, or setting Option "BlankTime" "0" Option "StandbyTime" "0" Option "SuspendTime" "0" Option "OffTime" "0" in the target xorg.conf). Then listen to the ScreenSaver notify events on the host and forward the activations/resets to the targets. This should then keep all the screen blanking in sync. Reported-by: Raffael Herzog <her...@raffael.ch> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93562 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/configure.ac b/configure.ac index 9aa7d97..c18ad96 100644 --- a/configure.ac +++ b/configure.ac @@ -291,7 +291,7 @@ if test "x$shm" != "xyes"; then tools="no" fi if test "x$tools" != "xno"; then - ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xext x11 pixman-1" + ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xscrnsaver xext x11 pixman-1" extra_cflags="" ignore="xinerama" diff --git a/tools/virtual.c b/tools/virtual.c index 7bf6ee8..bcbcb42 100644 --- a/tools/virtual.c +++ b/tools/virtual.c @@ -31,6 +31,7 @@ #include <X11/Xlibint.h> #include <X11/extensions/record.h> +#include <X11/extensions/scrnsaver.h> #include <X11/extensions/XShm.h> #if HAVE_X11_EXTENSIONS_SHMPROTO_H #include <X11/extensions/shmproto.h> @@ -79,13 +80,15 @@ static int verbose; #define DRAW 0x8 #define DAMAGE 0x10 #define CURSOR 0x20 -#define POLL 0x40 +#define SCREEN 0x40 +#define POLL 0x80 struct display { Display *dpy; struct clone *clone; struct context *ctx; + int saver_event, saver_error, saver_active; int damage_event, damage_error; int xfixes_event, xfixes_error; int rr_event, rr_error, rr_active; @@ -98,6 +101,7 @@ struct display { int width; int height; int depth; + int active; XRenderPictFormat *root_format; XRenderPictFormat *rgb16_format; @@ -123,6 +127,13 @@ struct display { int send; int skip_clone; int skip_frame; + + struct { + int timeout; + int interval; + int prefer_blank; + int allow_exp; + } saver; }; struct output { @@ -1249,6 +1260,56 @@ static void clone_update(struct clone *clone) clone->rr_update = 0; } +static void screensaver_save(struct display *display) +{ + display->saver_active = + XScreenSaverQueryExtension(display->dpy, + &display->saver_event, + &display->saver_error); + DBG(SCREEN, + ("%s screen saver active? %d [event=%d, error=%d]\n", + DisplayString(display->dpy), + display->saver_active, + display->saver_event, + display->saver_error)); + + XGetScreenSaver(display->dpy, + &display->saver.timeout, + &display->saver.interval, + &display->saver.prefer_blank, + &display->saver.allow_exp); + + DBG(SCREEN, + ("%s saving screen saver defaults: timeout=%d interval=%d prefer_blank=%d allow_exp=%d\n", + DisplayString(display->dpy), + display->saver.timeout, + display->saver.interval, + display->saver.prefer_blank, + display->saver.allow_exp)); +} + +static void screensaver_disable(struct display *display) +{ + DBG(SCREEN, + ("%s disabling screen saver\n", DisplayString(display->dpy))); + + XSetScreenSaver(display->dpy, 0, 0, DefaultBlanking, DefaultExposures); + display_mark_flush(display); +} + +static void screensaver_restore(struct display *display) +{ + DBG(SCREEN, + ("%s restoring screen saver\n", DisplayString(display->dpy))); + + XSetScreenSaver(display->dpy, + display->saver.timeout, + display->saver.interval, + display->saver.prefer_blank, + display->saver.allow_exp); + display_mark_flush(display); +} + static int context_update(struct context *ctx) { Display *dpy = ctx->display->dpy; @@ -1605,6 +1666,13 @@ ungrab: XUngrabServer(display->dpy); } + for (n = 1; n < ctx->ndisplay; n++) { + struct display *display = &ctx->display[n]; + + display->active = 0; + screensaver_restore(display); + } + ctx->active = NULL; for (n = 0; n < ctx->nclone; n++) { struct clone *clone = &ctx->clones[n]; @@ -1615,7 +1683,10 @@ ungrab: continue; DBG(XRR, ("%s-%s: added to active list\n", - DisplayString(clone->dst.display->dpy), clone->dst.name)); + DisplayString(clone->dst.display->dpy), clone->dst.name)); + + if (clone->dst.display->active++ == 0) + screensaver_disable(clone->dst.display); clone->active = ctx->active; ctx->active = clone; @@ -2396,6 +2467,8 @@ static int add_display(struct context *ctx, Display *dpy) display->shm_opcode, display->has_shm_pixmap)); + screensaver_save(display); + display->rr_active = XRRQueryExtension(dpy, &display->rr_event, &display->rr_error); DBG(X11, ("%s: randr_active?=%d, event=%d, error=%d\n", DisplayString(dpy), @@ -3400,6 +3473,11 @@ int main(int argc, char **argv) if (ret) goto out; + if (ctx.display->saver_active) + XScreenSaverSelectInput(ctx.display->dpy, + ctx.display->root, + ScreenSaverNotifyMask); + if ((ctx.display->rr_event | ctx.display->rr_error) == 0) { fprintf(stderr, "RandR extension not supported by %s\n", DisplayString(ctx.display->dpy)); ret = EINVAL; @@ -3476,7 +3554,32 @@ int main(int argc, char **argv) do { XNextEvent(ctx.display->dpy, &e); - if (e.type == ctx.display->damage_event + XDamageNotify ) { + DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[0].dpy), e.type)); + + if (e.type == ctx.display->saver_event + ScreenSaverNotify) { + const XScreenSaverNotifyEvent *se = (const XScreenSaverNotifyEvent *)&e; + DBG(SCREEN, + ("%s screen saver: state=%d, kind=%d, forced=%d\n", + DisplayString(ctx.display->dpy), + se->state, se->kind, se->forced)); + for (i = 1; i < ctx.ndisplay; i++) { + struct display *display = &ctx.display[i]; + + if (!display->active) + continue; + + DBG(SCREEN, + ("%s %s screen saver\n", + DisplayString(display->dpy), + se->state == ScreenSaverOn ? "activating" : "resetting\n")); + + if (se->state == ScreenSaverOn) + XActivateScreenSaver(display->dpy); + else + XResetScreenSaver(display->dpy); + XFlush(display->dpy); + } + } else if (e.type == ctx.display->damage_event + XDamageNotify) { const XDamageNotifyEvent *de = (const XDamageNotifyEvent *)&e; struct clone *clone; @@ -3530,7 +3633,7 @@ int main(int argc, char **argv) DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[i].dpy), e.type)); if (e.type == Expose) { - XExposeEvent *xe = (XExposeEvent *)&e; + const XExposeEvent *xe = (XExposeEvent *)&e; struct clone *clone; int damaged = 0; @@ -3555,7 +3658,7 @@ int main(int argc, char **argv) if (damaged) context_enable_timer(&ctx); } else if (ctx.display[i].rr_active && e.type == ctx.display[i].rr_event + RRNotify) { - XRRNotifyEvent *re = (XRRNotifyEvent *)&e; + const XRRNotifyEvent *re = (XRRNotifyEvent *)&e; DBG(XRR, ("%s received RRNotify, type %d\n", DisplayString(ctx.display[i].dpy), re->subtype)); if (re->subtype == RRNotify_OutputChange) { commit 082a57e6eb3b364aad681f137364a34988c4af5d Author: Chris Wilson <ch...@chris-wilson.co.uk> Date: Sat Jan 2 21:29:58 2016 +0000 tools/intel-virtual-output: Respond to expose events on target displays If the destination screen is exposed (for example screensavers), we need to redraw. So enable the ExposeEvent on the target and synthesize damage to any clones on that display in order to trigger a redraw. Reported-by: Raffael Herzog <her...@raffael.ch> References: https://bugs.freedesktop.org/show_bug.cgi?id=93562 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> diff --git a/tools/virtual.c b/tools/virtual.c index ffda54a..7bf6ee8 100644 --- a/tools/virtual.c +++ b/tools/virtual.c @@ -2037,8 +2037,9 @@ static void clone_damage(struct clone *c, const XRectangle *rec) if ((v = (int)rec->y + rec->height) > c->damaged.y2) c->damaged.y2 = v; - DBG(DAMAGE, ("%s-%s damaged: (%d, %d), (%d, %d)\n", + DBG(DAMAGE, ("%s-%s damaged: +(%d,%d)x(%d, %d) -> (%d, %d), (%d, %d)\n", DisplayString(c->dst.display->dpy), c->dst.name, + rec->x, rec->y, rec->width, rec->height, c->damaged.x1, c->damaged.y1, c->damaged.x2, c->damaged.y2)); } @@ -2382,6 +2383,8 @@ static int add_display(struct context *ctx, Display *dpy) display->depth = DefaultDepth(dpy, DefaultScreen(dpy)); display->visual = DefaultVisual(dpy, DefaultScreen(dpy)); + XSelectInput(dpy, display->root, ExposureMask); + display->has_shm = can_use_shm(dpy, display->root, &display->shm_event, &display->shm_opcode, @@ -3526,7 +3529,32 @@ int main(int argc, char **argv) XNextEvent(ctx.display[i].dpy, &e); DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[i].dpy), e.type)); - if (ctx.display[i].rr_active && e.type == ctx.display[i].rr_event + RRNotify) { + if (e.type == Expose) { + XExposeEvent *xe = (XExposeEvent *)&e; + struct clone *clone; + int damaged = 0; + + DBG(DAMAGE, ("%s exposed: (%d, %d)x(%d, %d)\n", + DisplayString(ctx.display[i].dpy), + xe->x, xe->y, xe->width, xe->height)); + + for (clone = ctx.active; clone; clone = clone->active) { + XRectangle r; + + if (clone->dst.display != &ctx.display[i]) + continue; + + r.x = clone->src.x + xe->x; + r.y = clone->src.y + xe->y; + r.width = xe->width; + r.height = xe->height; + clone_damage(clone, &r);