From 60c987018d6a738cb98637384922fde2104819a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Jul 2013 16:11:57 -0700 Subject: [PATCH 01/76] present: Add Present extension Provides both a software implementation using timers and driver hooks to base everything on vblank intervals. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/Makefile.am | 17 + nx-X11/programs/Xserver/present/present.c | 775 ++++++++++++++++++ nx-X11/programs/Xserver/present/present.h | 118 +++ .../programs/Xserver/present/present_event.c | 239 ++++++ .../programs/Xserver/present/present_fake.c | 140 ++++ .../programs/Xserver/present/present_fence.c | 112 +++ .../programs/Xserver/present/present_notify.c | 114 +++ .../programs/Xserver/present/present_priv.h | 288 +++++++ .../Xserver/present/present_request.c | 330 ++++++++ .../programs/Xserver/present/present_screen.c | 231 ++++++ nx-X11/programs/Xserver/present/presentext.h | 29 + 11 files changed, 2393 insertions(+) create mode 100644 nx-X11/programs/Xserver/present/Makefile.am create mode 100644 nx-X11/programs/Xserver/present/present.c create mode 100644 nx-X11/programs/Xserver/present/present.h create mode 100644 nx-X11/programs/Xserver/present/present_event.c create mode 100644 nx-X11/programs/Xserver/present/present_fake.c create mode 100644 nx-X11/programs/Xserver/present/present_fence.c create mode 100644 nx-X11/programs/Xserver/present/present_notify.c create mode 100644 nx-X11/programs/Xserver/present/present_priv.h create mode 100644 nx-X11/programs/Xserver/present/present_request.c create mode 100644 nx-X11/programs/Xserver/present/present_screen.c create mode 100644 nx-X11/programs/Xserver/present/presentext.h diff --git a/nx-X11/programs/Xserver/present/Makefile.am b/nx-X11/programs/Xserver/present/Makefile.am new file mode 100644 index 0000000000..7fea6699fb --- /dev/null +++ b/nx-X11/programs/Xserver/present/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libpresent.la +AM_CFLAGS = \ + -DHAVE_XORG_CONFIG_H \ + @DIX_CFLAGS@ @XORG_CFLAGS@ + +libpresent_la_SOURCES = \ + present.h \ + present.c \ + present_event.c \ + present_fake.c \ + present_fence.c \ + present_notify.c \ + present_priv.h \ + present_request.c \ + present_screen.c + +sdk_HEADERS = present.h presentext.h diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c new file mode 100644 index 0000000000..4c97ce40c7 --- /dev/null +++ b/nx-X11/programs/Xserver/present/present.c @@ -0,0 +1,775 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "present_priv.h" +#include +#include +#include +#ifdef MONOTONIC_CLOCK +#include +#endif + +static uint64_t present_event_id; +static struct xorg_list present_exec_queue; +static struct xorg_list present_flip_queue; + +#if 0 +#define DebugPresent(x) ErrorF x +#else +#define DebugPresent(x) +#endif + +/* + * Copies the update region from a pixmap to the target drawable + */ +static void +present_copy_region(DrawablePtr drawable, + PixmapPtr pixmap, + RegionPtr update, + int16_t x_off, + int16_t y_off) +{ + ScreenPtr screen = drawable->pScreen; + GCPtr gc; + + gc = GetScratchGC(drawable->depth, screen); + if (update) { + ChangeGCVal changes[2]; + + changes[0].val = x_off; + changes[1].val = y_off; + ChangeGC(serverClient, gc, + GCClipXOrigin|GCClipYOrigin, + changes); + (*gc->funcs->ChangeClip)(gc, CT_REGION, update, 0); + } + ValidateGC(drawable, gc); + (*gc->ops->CopyArea)(&pixmap->drawable, + drawable, + gc, + 0, 0, + pixmap->drawable.width, pixmap->drawable.height, + x_off, y_off); + if (update) + (*gc->funcs->ChangeClip)(gc, CT_NONE, NULL, 0); + FreeScratchGC(gc); +} + +static Bool +present_check_flip(RRCrtcPtr crtc, + WindowPtr window, + PixmapPtr pixmap, + Bool sync_flip, + RegionPtr valid, + int16_t x_off, + int16_t y_off) +{ + ScreenPtr screen = window->drawable.pScreen; + WindowPtr root = screen->root; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return FALSE; + + if (!screen_priv->info) + return FALSE; + + if (!crtc) + return FALSE; + + /* Check to see if the driver supports flips at all */ + if (!screen_priv->info->flip) + return FALSE; + + /* Can't pend a flip while unflipping */ + if (screen_priv->unflip_event_id) { + return FALSE; + } + + /* Can't have two pending flips at the same time */ + if (screen_priv->flip_pending) { + return FALSE; + } + + /* Make sure the window hasn't been redirected with Composite */ + if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen)) + return FALSE; + + /* Check for full-screen window */ + if (!RegionEqual(&window->clipList, &root->winSize)) { + return FALSE; + } + + /* Source pixmap must align with window exactly */ + if (x_off || y_off) { + return FALSE; + } + + /* Make sure the area marked as valid fills the screen */ + if (valid && !RegionEqual(valid, &root->winSize)) { + return FALSE; + } + + /* Does the window match the pixmap exactly? */ + if (window->drawable.x != 0 || window->drawable.y != 0 || +#ifdef COMPOSITE + window->drawable.x != pixmap->screen_x || window->drawable.y != pixmap->screen_y || +#endif + window->drawable.width != pixmap->drawable.width || + window->drawable.height != pixmap->drawable.height) { + return FALSE; + } + + /* Ask the driver for permission */ + if (screen_priv->info->check_flip) { + if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) { + return FALSE; + } + } + + return TRUE; +} + +static Bool +present_flip(RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip) +{ + ScreenPtr screen = crtc->pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + return (*screen_priv->info->flip) (crtc, event_id, target_msc, pixmap, sync_flip); +} + +static void +present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc) +{ + int n; + + present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); + for (n = 0; n < vblank->num_notifies; n++) { + WindowPtr window = vblank->notifies[n].window; + CARD32 serial = vblank->notifies[n].serial; + + if (window) + present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset); + } +} + +static void +present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence) +{ + present_fence_set_triggered(present_fence); + present_send_idle_notify(window, serial, pixmap, present_fence); +} + +RRCrtcPtr +present_get_crtc(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return NULL; + + if (!screen_priv->info) + return NULL; + + return (*screen_priv->info->get_crtc)(window); +} + +uint32_t +present_query_capabilities(RRCrtcPtr crtc) +{ + present_screen_priv_ptr screen_priv; + + if (!crtc) + return 0; + + screen_priv = present_screen_priv(crtc->pScreen); + + if (!screen_priv) + return 0; + + if (!screen_priv->info) + return 0; + + return screen_priv->info->capabilities; +} + +static int +present_get_ust_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (crtc == NULL) + return present_fake_get_ust_msc(screen, ust, msc); + else + return (*screen_priv->info->get_ust_msc)(crtc, ust, msc); +} + +static void +present_flush(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return; + + if (!screen_priv->info) + return; + + (*screen_priv->info->flush) (window); +} + +static int +present_queue_vblank(ScreenPtr screen, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc) +{ + Bool ret; + + if (crtc == NULL) + ret = present_fake_queue_vblank(screen, event_id, msc); + else + { + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + ret = (*screen_priv->info->queue_vblank) (crtc, event_id, msc); + } + return ret; +} + +static uint64_t +present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc) +{ + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + + if (crtc != window_priv->crtc) { + uint64_t old_ust, old_msc; + + /* The old CRTC may have been turned off, in which case + * we'll just use whatever previous MSC we'd seen from this CRTC + */ + + if (present_get_ust_msc(window, window_priv->crtc, &old_ust, &old_msc) != Success) + old_msc = window_priv->msc; + + window_priv->msc_offset += new_msc - old_msc; + window_priv->crtc = crtc; + } + + return window_msc + window_priv->msc_offset; +} + +static void +present_flip_idle(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (screen_priv->flip_pixmap) { + present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window, + screen_priv->flip_serial, screen_priv->flip_idle_fence); + present_fence_destroy(screen_priv->flip_idle_fence); + dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id); + screen_priv->flip_crtc = NULL; + screen_priv->flip_window = NULL; + screen_priv->flip_serial = 0; + screen_priv->flip_pixmap = NULL; + screen_priv->flip_idle_fence = NULL; + } +} + +static void +present_unflip(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + assert (!screen_priv->unflip_event_id); + assert (!screen_priv->flip_pending); + + /* Update the screen pixmap with the current flip pixmap contents + */ + if (screen_priv->flip_pixmap) { + present_copy_region(&screen->GetScreenPixmap(screen)->drawable, + screen_priv->flip_pixmap, + NULL, 0, 0); + } + screen_priv->unflip_event_id = ++present_event_id; + DebugPresent(("u %lld\n", screen_priv->unflip_event_id)); + (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id); +} + +static void +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); + +static void +present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, + vblank->window->drawable.id)); + + assert (vblank == screen_priv->flip_pending); + + present_flip_idle(screen); + + /* Transfer reference for pixmap and fence from vblank to screen_priv */ + screen_priv->flip_crtc = vblank->crtc; + screen_priv->flip_window = vblank->window; + screen_priv->flip_serial = vblank->serial; + screen_priv->flip_pixmap = vblank->pixmap; + screen_priv->flip_idle_fence = vblank->idle_fence; + + vblank->pixmap = NULL; + vblank->idle_fence = NULL; + + screen_priv->flip_pending = NULL; + + if (vblank->abort_flip) + present_unflip(screen); + + if (!vblank->window_destroyed) + present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc); + present_vblank_destroy(vblank); +} + +void +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) +{ + present_vblank_ptr vblank, tmp; + int s; + + xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + present_execute(vblank, ust, msc); + return; + } + } + xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + present_flip_notify(vblank, ust, msc); + return; + } + } + + for (s = 0; s < screenInfo.numScreens; s++) { + ScreenPtr screen = screenInfo.screens[s]; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (event_id == screen_priv->unflip_event_id) { + DebugPresent(("\tun %lld\n", event_id)); + screen_priv->unflip_event_id = 0; + present_flip_idle(screen); + } + } +} + +/* + * 'window' is being reconfigured. Check to see if it is involved + * in flipping and clean up as necessary + */ +void +present_check_flip_window (WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr flip_pending = screen_priv->flip_pending; + present_vblank_ptr vblank; + + /* If this window hasn't ever been used with Present, it can't be + * flipping + */ + if (!window_priv) + return; + + if (screen_priv->unflip_event_id) + return; + + if (flip_pending) { + /* + * Check pending flip + */ + if (flip_pending->window == window) { + if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap, + flip_pending->sync_flip, NULL, 0, 0)) + flip_pending->abort_flip = TRUE; + } + } else { + /* + * Check current flip + */ + if (window == screen_priv->flip_window) { + if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0)) + present_unflip(screen); + } + } + + /* Now check any queued vblanks */ + xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + if (vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0)) + vblank->flip = FALSE; + } +} + +/* + * Once the required MSC has been reached, execute the pending request. + * + * For requests to actually present something, either blt contents to + * the screen or queue a frame buffer swap. + * + * For requests to just get the current MSC/UST combo, skip that part and + * go straight to event delivery + */ + +static void +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen); + + if (vblank->wait_fence) { + /* XXX check fence, queue if not ready */ + } + + xorg_list_del(&vblank->event_queue); + if (vblank->pixmap) { + + if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) { + + DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); + /* Prepare to flip by removing from the window/screen lists + * and sticking it into the flip_pending field + */ + screen_priv->flip_pending = vblank; + xorg_list_del(&vblank->window_list); + + xorg_list_add(&vblank->event_queue, &present_flip_queue); + /* Try to flip + */ + if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) + return; + + xorg_list_del(&vblank->event_queue); + /* Oops, flip failed. Clear the flip_pending field + */ + screen_priv->flip_pending = NULL; + vblank->flip = FALSE; + } + DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); + if (screen_priv->flip_pending) { + + /* Check pending flip + */ + if (window == screen_priv->flip_pending->window) + screen_priv->flip_pending->abort_flip = TRUE; + } else if (!screen_priv->unflip_event_id) { + + /* Check current flip + */ + if (window == screen_priv->flip_window) + present_unflip(window->drawable.pScreen); + } + present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off); + + /* present_copy_region sticks the region into a scratch GC, + * which is then freed, freeing the region + */ + vblank->update = NULL; + present_flush(window); + + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + } + present_vblank_notify(vblank, vblank->kind, PresentCompleteModeCopy, ust, crtc_msc); + present_vblank_destroy(vblank); +} + +int +present_pixmap(WindowPtr window, + PixmapPtr pixmap, + CARD32 serial, + RegionPtr valid, + RegionPtr update, + int16_t x_off, + int16_t y_off, + RRCrtcPtr target_crtc, + SyncFence *wait_fence, + SyncFence *idle_fence, + uint32_t options, + uint64_t window_msc, + uint64_t divisor, + uint64_t remainder, + present_notify_ptr notifies, + int num_notifies) +{ + uint64_t ust; + uint64_t target_msc; + uint64_t crtc_msc; + int ret; + present_vblank_ptr vblank; + ScreenPtr screen = window->drawable.pScreen; + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!window_priv) + return BadAlloc; + + if (!target_crtc) { + /* Update the CRTC if we have a pixmap or we don't have a CRTC + */ + if (!pixmap) + target_crtc = window_priv->crtc; + + if (!target_crtc) + target_crtc = present_get_crtc(window); + } + + present_get_ust_msc(window, target_crtc, &ust, &crtc_msc); + + target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc); + + /* Stash the current MSC away in case we need it later + */ + window_priv->msc = crtc_msc; + + /* Adjust target_msc to match modulus + */ + if (crtc_msc >= target_msc) { + if (divisor != 0) { + target_msc = crtc_msc - (crtc_msc % divisor) + remainder; + if (target_msc <= crtc_msc) + target_msc += divisor; + } else + target_msc = crtc_msc; + } + + /* + * Look for a matching presentation already on the list and + * don't bother doing the previous one if this one will overwrite it + * in the same frame + */ + + if (!update) { + xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + + if (!vblank->pixmap) + continue; + + if (vblank->crtc != target_crtc || vblank->target_msc != target_msc) + continue; + + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + present_fence_destroy(vblank->idle_fence); + dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); + + vblank->pixmap = NULL; + vblank->idle_fence = NULL; + } + } + + vblank = calloc (1, sizeof (present_vblank_rec)); + if (!vblank) + return BadAlloc; + + xorg_list_append(&vblank->window_list, &window_priv->vblank); + xorg_list_init(&vblank->event_queue); + + vblank->screen = screen; + vblank->window = window; + vblank->pixmap = pixmap; + vblank->event_id = ++present_event_id; + if (pixmap) { + vblank->kind = PresentCompleteKindPixmap; + pixmap->refcnt++; + } else + vblank->kind = PresentCompleteKindNotifyMSC; + + vblank->serial = serial; + + if (valid) { + vblank->valid = RegionDuplicate(valid); + if (!vblank->valid) + goto no_mem; + } + if (update) { + vblank->update = RegionDuplicate(update); + if (!vblank->update) + goto no_mem; + } + + vblank->x_off = x_off; + vblank->y_off = y_off; + vblank->target_msc = target_msc; + vblank->crtc = target_crtc; + vblank->msc_offset = window_priv->msc_offset; + vblank->notifies = notifies; + vblank->num_notifies = num_notifies; + + if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync)) + vblank->sync_flip = TRUE; + + if (pixmap && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) { + vblank->flip = TRUE; + if (vblank->sync_flip) + target_msc--; + } + + if (idle_fence) { + vblank->idle_fence = present_fence_create(idle_fence); + if (!vblank->idle_fence) + goto no_mem; + } + + if (pixmap) + DebugPresent(("q %p %8lld: %08lx -> %08lx (crtc %d)\n", + vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc ? 1 : 0)); + + xorg_list_add(&vblank->event_queue, &present_exec_queue); + if (target_msc >= crtc_msc) { + ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); + if (ret != Success) { + xorg_list_del(&vblank->event_queue); + goto failure; + } + } else + present_execute(vblank, ust, crtc_msc); + + return Success; + +no_mem: + ret = BadAlloc; +failure: + vblank->notifies = NULL; + present_vblank_destroy(vblank); + return ret; +} + +void +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) +{ + present_vblank_ptr vblank, tmp; + + if (crtc == NULL) + present_fake_abort_vblank(screen, event_id, msc); + else + { + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + (*screen_priv->info->abort_vblank) (crtc, event_id, msc); + } + + xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + return; + } + } + xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + return; + } + } +} + +int +present_notify_msc(WindowPtr window, + CARD32 serial, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder) +{ + return present_pixmap(window, + NULL, + serial, + NULL, NULL, + 0, 0, + NULL, + NULL, NULL, + 0, + target_msc, divisor, remainder, NULL, 0); +} + +void +present_flip_destroy(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + /* XXX this needs to be synchronous for server reset */ + + /* Do the actual cleanup once the flip has been performed by the hardware */ + if (screen_priv->flip_pending) + screen_priv->flip_pending->abort_flip = TRUE; +} + +void +present_vblank_destroy(present_vblank_ptr vblank) +{ + /* Remove vblank from window and screen lists */ + xorg_list_del(&vblank->window_list); + + DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, + vblank->window->drawable.id)); + + /* Drop pixmap reference */ + if (vblank->pixmap) + dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); + + /* Free regions */ + if (vblank->valid) + RegionDestroy(vblank->valid); + if (vblank->update) + RegionDestroy(vblank->update); + + if (vblank->idle_fence) + present_fence_destroy(vblank->idle_fence); + + if (vblank->notifies) + present_destroy_notifies(vblank->notifies, vblank->num_notifies); + + free(vblank); +} + +Bool +present_init(void) +{ + xorg_list_init(&present_exec_queue); + xorg_list_init(&present_flip_queue); + present_fake_queue_init(); + return TRUE; +} diff --git a/nx-X11/programs/Xserver/present/present.h b/nx-X11/programs/Xserver/present/present.h new file mode 100644 index 0000000000..6a451fb234 --- /dev/null +++ b/nx-X11/programs/Xserver/present/present.h @@ -0,0 +1,118 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENT_H_ +#define _PRESENT_H_ + +#include +#include "randrstr.h" +#include "presentext.h" + +typedef struct present_vblank present_vblank_rec, *present_vblank_ptr; + +/* Return the current CRTC for 'window'. + */ +typedef RRCrtcPtr (*present_get_crtc_ptr) (WindowPtr window); + +/* Return the current ust/msc for 'crtc' + */ +typedef int (*present_get_ust_msc_ptr) (RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc); + +/* Queue callback on 'crtc' for time 'msc'. Call present_event_notify with 'event_id' + * at or after 'msc'. Return false if it didn't happen (which might occur if 'crtc' + * is not currently generating vblanks). + */ +typedef Bool (*present_queue_vblank_ptr) (RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc); + +/* Abort pending vblank. The extension is no longer interested in + * 'event_id' which was to be notified at 'msc'. If possible, the + * driver is free to de-queue the notification. + */ +typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uint64_t msc); + +/* Flush pending drawing on 'window' to the hardware. + */ +typedef void (*present_flush_ptr) (WindowPtr window); + +/* Check if 'pixmap' is suitable for flipping to 'window'. + */ +typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip); + +/* Flip pixmap, return false if it didn't happen. + * + * 'crtc' is to be used for any necessary synchronization. + * + * 'sync_flip' requests that the flip be performed at the next + * vertical blank interval to avoid tearing artifacts. If false, the + * flip should be performed as soon as possible. + * + * present_event_notify should be called with 'event_id' when the flip + * occurs + */ +typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip); + +/* "unflip" back to the regular screen scanout buffer + * + * present_event_notify should be called with 'event_id' when the unflip occurs. + */ +typedef void (*present_unflip_ptr) (ScreenPtr screen, + uint64_t event_id); + +#define PRESENT_SCREEN_INFO_VERSION 0 + +typedef struct present_screen_info { + uint32_t version; + + present_get_crtc_ptr get_crtc; + present_get_ust_msc_ptr get_ust_msc; + present_queue_vblank_ptr queue_vblank; + present_abort_vblank_ptr abort_vblank; + present_flush_ptr flush; + uint32_t capabilities; + present_check_flip_ptr check_flip; + present_flip_ptr flip; + present_unflip_ptr unflip; + +} present_screen_info_rec, *present_screen_info_ptr; + +/* + * Called when 'event_id' occurs. 'ust' and 'msc' indicate when the + * event actually happened + */ +extern _X_EXPORT void +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc); + +/* 'crtc' has been turned off, so any pending events will never occur. + */ +extern _X_EXPORT void +present_event_abandon(RRCrtcPtr crtc); + +extern _X_EXPORT Bool +present_screen_init(ScreenPtr screen, present_screen_info_ptr info); + +#endif /* _PRESENT_H_ */ diff --git a/nx-X11/programs/Xserver/present/present_event.c b/nx-X11/programs/Xserver/present/present_event.c new file mode 100644 index 0000000000..a30bc82860 --- /dev/null +++ b/nx-X11/programs/Xserver/present/present_event.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "present_priv.h" + +#include "present_priv.h" + +RESTYPE present_event_type; + +static int +present_free_event(pointer data, XID id) +{ + present_event_ptr present_event = (present_event_ptr) data; + present_window_priv_ptr window_priv = present_window_priv(present_event->window); + present_event_ptr *previous, current; + + for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { + if (current == present_event) { + *previous = present_event->next; + break; + } + } + free((pointer) present_event); + return 1; + +} + +void +present_free_events(WindowPtr window) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + present_event_ptr event; + + if (!window_priv) + return; + + while ((event = window_priv->events)) + FreeResource(event->id, RT_NONE); +} + +static void +present_event_swap(xGenericEvent *from, xGenericEvent *to) +{ + *to = *from; + swaps(&to->sequenceNumber); + swapl(&to->length); + swaps(&to->evtype); + switch (from->evtype) { + case PresentConfigureNotify: { + xPresentConfigureNotify *c = (xPresentConfigureNotify *) to; + + swapl(&c->eid); + swapl(&c->window); + swaps(&c->x); + swaps(&c->y); + swaps(&c->width); + swaps(&c->height); + swaps(&c->off_x); + swaps(&c->off_y); + swaps(&c->pixmap_width); + swaps(&c->pixmap_height); + swapl(&c->pixmap_flags); + break; + } + case PresentCompleteNotify: + { + xPresentCompleteNotify *c = (xPresentCompleteNotify *) to; + swapl(&c->eid); + swapl(&c->window); + swapl(&c->serial); + swapll(&c->ust); + swapll(&c->msc); + } + case PresentIdleNotify: + { + xPresentIdleNotify *c = (xPresentIdleNotify *) to; + swapl(&c->eid); + swapl(&c->window); + swapl(&c->serial); + swapl(&c->idle_fence); + } + } +} + +void +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentConfigureNotify cn = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentConfigureNotify) - 32) >> 2, + .evtype = PresentConfigureNotify, + .eid = 0, + .window = window->drawable.id, + .x = x, + .y = y, + .width = w, + .height = h, + .off_x = 0, + .off_y = 0, + .pixmap_width = w, + .pixmap_height = h, + .pixmap_flags = 0 + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & (1 << PresentConfigureNotify)) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +void +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentCompleteNotify cn = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentCompleteNotify) - 32) >> 2, + .evtype = PresentCompleteNotify, + .kind = kind, + .mode = mode, + .eid = 0, + .window = window->drawable.id, + .serial = serial, + .ust = ust, + .msc = msc, + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & PresentCompleteNotifyMask) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +void +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentIdleNotify in = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentIdleNotify) - 32) >> 2, + .evtype = PresentIdleNotify, + .eid = 0, + .window = window->drawable.id, + .serial = serial, + .pixmap = pixmap->drawable.id, + .idle_fence = present_fence_id(idle_fence) + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & PresentIdleNotifyMask) { + in.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &in); + } + } + } +} + +int +present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) +{ + present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0); + present_event_ptr event; + + if (!window_priv) { + if (mask) + return BadAlloc; + return Success; + } + + event = calloc (1, sizeof (present_event_rec)); + if (!event) + return BadAlloc; + + event->client = client; + event->window = window; + event->id = eid; + event->mask = mask; + + event->next = window_priv->events; + window_priv->events = event; + + if (!AddResource(event->id, present_event_type, (pointer) event)) + return BadAlloc; + + return Success; +} + +Bool +present_event_init(void) +{ + present_event_type = CreateNewResourceType(present_free_event, "PresentEvent"); + if (!present_event_type) + return FALSE; + + GERegisterExtension(present_request, present_event_swap); + return TRUE; +} diff --git a/nx-X11/programs/Xserver/present/present_fake.c b/nx-X11/programs/Xserver/present/present_fake.c new file mode 100644 index 0000000000..a677592543 --- /dev/null +++ b/nx-X11/programs/Xserver/present/present_fake.c @@ -0,0 +1,140 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "present_priv.h" +#include "list.h" + +static struct xorg_list fake_vblank_queue; + +typedef struct present_fake_vblank { + struct xorg_list list; + uint64_t event_id; + OsTimerPtr timer; + ScreenPtr screen; +} present_fake_vblank_rec, *present_fake_vblank_ptr; + +int +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + *ust = GetTimeInMicros(); + *msc = *ust / screen_priv->fake_interval; + return Success; +} + +static void +present_fake_notify(ScreenPtr screen, uint64_t event_id) +{ + uint64_t ust, msc; + + present_fake_get_ust_msc(screen, &ust, &msc); + present_event_notify(event_id, ust, msc); +} + +static CARD32 +present_fake_do_timer(OsTimerPtr timer, + CARD32 time, + pointer arg) +{ + present_fake_vblank_ptr fake_vblank = arg; + + present_fake_notify(fake_vblank->screen, fake_vblank->event_id); + xorg_list_del(&fake_vblank->list); + free(fake_vblank); + return 0; +} + +void +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc) +{ + present_fake_vblank_ptr fake_vblank, tmp; + + xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) { + if (fake_vblank->event_id == event_id) { + TimerCancel(fake_vblank->timer); + xorg_list_del(&fake_vblank->list); + free (fake_vblank); + break; + } + } +} + +int +present_fake_queue_vblank(ScreenPtr screen, + uint64_t event_id, + uint64_t msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + uint64_t ust = msc * screen_priv->fake_interval; + uint64_t now = GetTimeInMicros(); + INT32 delay = ((int64_t) (ust - now)) / 1000; + present_fake_vblank_ptr fake_vblank; + + if (delay <= 0) { + present_fake_notify(screen, event_id); + return Success; + } + + fake_vblank = calloc (1, sizeof (present_fake_vblank_rec)); + if (!fake_vblank) + return BadAlloc; + + fake_vblank->screen = screen; + fake_vblank->event_id = event_id; + fake_vblank->timer = TimerSet(NULL, 0, delay, present_fake_do_timer, fake_vblank); + if (!fake_vblank->timer) { + free(fake_vblank); + return BadAlloc; + } + + xorg_list_add(&fake_vblank->list, &fake_vblank_queue); + + return Success; +} + +void +present_fake_screen_init(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + /* For screens with hardware vblank support, the fake code + * will be used for off-screen windows and while screens are blanked, + * in which case we want a slow interval here + * + * Otherwise, pretend that the screen runs at 60Hz + */ + if (screen_priv->info && screen_priv->info->get_crtc) + screen_priv->fake_interval = 1000000; + else + screen_priv->fake_interval = 16667; +} + +void +present_fake_queue_init(void) +{ + xorg_list_init(&fake_vblank_queue); +} diff --git a/nx-X11/programs/Xserver/present/present_fence.c b/nx-X11/programs/Xserver/present/present_fence.c new file mode 100644 index 0000000000..db5efcaad4 --- /dev/null +++ b/nx-X11/programs/Xserver/present/present_fence.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "present_priv.h" +#include +#include +#include + +/* + * Wraps SyncFence objects so we can add a SyncTrigger to find out + * when the SyncFence gets destroyed and clean up appropriately + */ + +struct present_fence { + SyncTrigger trigger; + SyncFence *fence; +}; + +/* + * SyncTrigger callbacks + */ +static Bool +present_fence_sync_check_trigger(SyncTrigger *trigger, XSyncValue oldval) +{ + return FALSE; +} + +static void +present_fence_sync_trigger_fired(SyncTrigger *trigger) +{ +} + +static void +present_fence_sync_counter_destroyed(SyncTrigger *trigger) +{ + struct present_fence *present_fence = container_of(trigger, struct present_fence, trigger); + + present_fence->fence = NULL; +} + +struct present_fence * +present_fence_create(SyncFence *fence) +{ + struct present_fence *present_fence; + + present_fence = calloc (1, sizeof (struct present_fence)); + if (!present_fence) + return NULL; + + present_fence->fence = fence; + present_fence->trigger.pSync = (SyncObject *) fence; + present_fence->trigger.CheckTrigger = present_fence_sync_check_trigger; + present_fence->trigger.TriggerFired = present_fence_sync_trigger_fired; + present_fence->trigger.CounterDestroyed = present_fence_sync_counter_destroyed; + + if (SyncAddTriggerToSyncObject(&present_fence->trigger) != Success) { + free (present_fence); + return NULL; + } + return present_fence; +} + +void +present_fence_destroy(struct present_fence *present_fence) +{ + if (present_fence) { + if (present_fence->fence) + SyncDeleteTriggerFromSyncObject(&present_fence->trigger); + free(present_fence); + } +} + +void +present_fence_set_triggered(struct present_fence *present_fence) +{ + if (present_fence) + if (present_fence->fence) + (*present_fence->fence->funcs.SetTriggered) (present_fence->fence); +} + +XID +present_fence_id(struct present_fence *present_fence) +{ + if (!present_fence) + return None; + if (!present_fence->fence) + return None; + return present_fence->fence->sync.id; +} diff --git a/nx-X11/programs/Xserver/present/present_notify.c b/nx-X11/programs/Xserver/present/present_notify.c new file mode 100644 index 0000000000..e272e08dce --- /dev/null +++ b/nx-X11/programs/Xserver/present/present_notify.c @@ -0,0 +1,114 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "present_priv.h" + +/* + * Mark all pending notifies for 'window' as invalid when + * the window is destroyed + */ + +void +present_clear_window_notifies(WindowPtr window) +{ + present_notify_ptr notify; + present_window_priv_ptr window_priv = present_window_priv(window); + + if (!window_priv) + return; + + xorg_list_for_each_entry(notify, &window_priv->notifies, window_list) { + notify->window = NULL; + } +} + +/* + * 'notify' is being freed; remove it from the window's notify list + */ + +void +present_free_window_notify(present_notify_ptr notify) +{ + xorg_list_del(¬ify->window_list); +} + +/* + * 'notify' is new; add it to the specified window + */ + +int +present_add_window_notify(present_notify_ptr notify) +{ + WindowPtr window = notify->window; + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + + if (!window_priv) + return BadAlloc; + + xorg_list_add(¬ify->window_list, &window_priv->notifies); + return Success; +} + +int +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies) +{ + present_notify_ptr notifies; + int i; + int added = 0; + int status; + + notifies = calloc (num_notifies, sizeof (present_notify_rec)); + if (!notifies) + return BadAlloc; + + for (i = 0; i < num_notifies; i++) { + status = dixLookupWindow(¬ifies[i].window, x_notifies[i].window, client, DixGetAttrAccess); + if (status != Success) + goto bail; + + notifies[i].serial = x_notifies[i].serial; + status = present_add_window_notify(¬ifies[i]); + if (status != Success) + goto bail; + + added = i; + } + return Success; + +bail: + present_destroy_notifies(notifies, added); + return status; +} + +void +present_destroy_notifies(present_notify_ptr notifies, int num_notifies) +{ + int i; + for (i = 0; i < num_notifies; i++) + present_free_window_notify(¬ifies[i]); + + free(notifies); +} diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h new file mode 100644 index 0000000000..a92b62a2d6 --- /dev/null +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -0,0 +1,288 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENT_PRIV_H_ +#define _PRESENT_PRIV_H_ + +#include +#include "scrnintstr.h" +#include "misc.h" +#include "list.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "present.h" +#include +#include +#include +#include + +extern int present_request; + +extern DevPrivateKeyRec present_screen_private_key; + +typedef struct present_fence *present_fence_ptr; + +typedef struct present_notify present_notify_rec, *present_notify_ptr; + +struct present_notify { + struct xorg_list window_list; + WindowPtr window; + CARD32 serial; +}; + +struct present_vblank { + struct xorg_list window_list; + struct xorg_list event_queue; + ScreenPtr screen; + WindowPtr window; + PixmapPtr pixmap; + RegionPtr valid; + RegionPtr update; + RRCrtcPtr crtc; + uint32_t serial; + int16_t x_off; + int16_t y_off; + CARD16 kind; + uint64_t event_id; + uint64_t target_msc; + uint64_t msc_offset; + present_fence_ptr idle_fence; + present_fence_ptr wait_fence; + present_notify_ptr notifies; + int num_notifies; + Bool flip; + Bool sync_flip; + Bool abort_flip; + + Bool window_destroyed; +}; + +typedef struct present_screen_priv { + CloseScreenProcPtr CloseScreen; + ConfigNotifyProcPtr ConfigNotify; + DestroyWindowProcPtr DestroyWindow; + ClipNotifyProcPtr ClipNotify; + + present_vblank_ptr flip_pending; + uint64_t unflip_event_id; + + uint32_t fake_interval; + + /* Currently active flipped pixmap and fence */ + RRCrtcPtr flip_crtc; + WindowPtr flip_window; + uint32_t flip_serial; + PixmapPtr flip_pixmap; + present_fence_ptr flip_idle_fence; + + present_screen_info_ptr info; +} present_screen_priv_rec, *present_screen_priv_ptr; + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static inline present_screen_priv_ptr +present_screen_priv(ScreenPtr screen) +{ + return (present_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &present_screen_private_key); +} + +/* + * Each window has a list of clients and event masks + */ +typedef struct present_event *present_event_ptr; + +typedef struct present_event { + present_event_ptr next; + ClientPtr client; + WindowPtr window; + XID id; + int mask; +} present_event_rec; + +typedef struct present_window_priv { + present_event_ptr events; + RRCrtcPtr crtc; /* Last reported CRTC from get_ust_msc */ + uint64_t msc_offset; + uint64_t msc; /* Last reported MSC from the current crtc */ + struct xorg_list vblank; + struct xorg_list notifies; +} present_window_priv_rec, *present_window_priv_ptr; + +extern DevPrivateKeyRec present_window_private_key; + +static inline present_window_priv_ptr +present_window_priv(WindowPtr window) +{ + return (present_window_priv_ptr)dixGetPrivate(&(window)->devPrivates, &present_window_private_key); +} + +present_window_priv_ptr +present_get_window_priv(WindowPtr window, Bool create); + +extern RESTYPE present_event_type; + +/* + * present.c + */ +int +present_pixmap(WindowPtr window, + PixmapPtr pixmap, + CARD32 serial, + RegionPtr valid, + RegionPtr update, + int16_t x_off, + int16_t y_off, + RRCrtcPtr target_crtc, + SyncFence *wait_fence, + SyncFence *idle_fence, + uint32_t options, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder, + present_notify_ptr notifies, + int num_notifies); + +int +present_notify_msc(WindowPtr window, + CARD32 serial, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder); + +void +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc); + +void +present_vblank_destroy(present_vblank_ptr vblank); + +void +present_flip_destroy(ScreenPtr screen); + +void +present_check_flip_window(WindowPtr window); + +RRCrtcPtr +present_get_crtc(WindowPtr window); + +uint32_t +present_query_capabilities(RRCrtcPtr crtc); + +Bool +present_init(void); + +/* + * present_event.c + */ + +void +present_free_events(WindowPtr window); + +void +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling); + +void +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc); + +void +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, present_fence_ptr idle_fence); + +int +present_select_input(ClientPtr client, + CARD32 eid, + WindowPtr window, + CARD32 event_mask); + +Bool +present_event_init(void); + +/* + * present_fake.c + */ +int +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc); + +int +present_fake_queue_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc); + +void +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc); + +void +present_fake_screen_init(ScreenPtr screen); + +void +present_fake_queue_init(void); + +/* + * present_fence.c + */ +struct present_fence * +present_fence_create(SyncFence *sync_fence); + +void +present_fence_destroy(struct present_fence *present_fence); + +void +present_fence_set_triggered(struct present_fence *present_fence); + +XID +present_fence_id(struct present_fence *present_fence); + +/* + * present_notify.c + */ +void +present_clear_window_notifies(WindowPtr window); + +void +present_free_window_notify(present_notify_ptr notify); + +int +present_add_window_notify(present_notify_ptr notify); + +int +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies); + +void +present_destroy_notifies(present_notify_ptr notifies, int num_notifies); + +/* + * present_request.c + */ +int +proc_present_dispatch(ClientPtr client); + +int +sproc_present_dispatch(ClientPtr client); + +/* + * present_screen.c + */ + +#endif /* _PRESENT_PRIV_H_ */ diff --git a/nx-X11/programs/Xserver/present/present_request.c b/nx-X11/programs/Xserver/present/present_request.c new file mode 100644 index 0000000000..095fa2daf0 --- /dev/null +++ b/nx-X11/programs/Xserver/present/present_request.c @@ -0,0 +1,330 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "present_priv.h" +#include "randrstr.h" + +static int +proc_present_query_version(ClientPtr client) +{ + REQUEST(xPresentQueryVersionReq); + xPresentQueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .majorVersion = PRESENT_MAJOR, + .minorVersion = PRESENT_MINOR + }; + + REQUEST_SIZE_MATCH(xPresentQueryVersionReq); + (void) stuff; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.majorVersion); + swapl(&rep.minorVersion); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +#define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do { \ + if ((fence_id) == None) \ + (fence_ptr) = NULL; \ + else { \ + int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \ + if (__rc__ != Success) \ + return __rc__; \ + } \ + } while (0) + +#define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do { \ + if ((crtc_id) == None) \ + (crtc_ptr) = NULL; \ + else { \ + VERIFY_RR_CRTC(crtc_id, crtc_ptr, access); \ + } \ + } while (0) + +static int +proc_present_pixmap(ClientPtr client) +{ + REQUEST(xPresentPixmapReq); + WindowPtr window; + PixmapPtr pixmap; + RegionPtr valid = NULL; + RegionPtr update = NULL; + SyncFence *wait_fence; + SyncFence *idle_fence; + RRCrtcPtr target_crtc; + int ret; + int nnotifies; + present_notify_ptr notifies = NULL; + + REQUEST_AT_LEAST_SIZE(xPresentPixmapReq); + ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess); + if (ret != Success) + return ret; + ret = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess); + if (ret != Success) + return ret; + + if (window->drawable.depth != pixmap->drawable.depth) + return BadMatch; + + VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess); + VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess); + + VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess); + + VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess); + VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess); + + if (stuff->options & ~(PresentAllOptions)) { + client->errorValue = stuff->options; + return BadValue; + } + + /* + * Check to see if remainder is sane + */ + if (stuff->divisor == 0) { + if (stuff->remainder != 0) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } else { + if (stuff->remainder >= stuff->divisor) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } + + nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq); + if (nnotifies % sizeof (xPresentNotify)) + return BadLength; + + nnotifies /= sizeof (xPresentNotify); + if (nnotifies) { + ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), ¬ifies); + if (ret != Success) + return ret; + } + + ret = present_pixmap(window, pixmap, stuff->serial, valid, update, + stuff->x_off, stuff->y_off, target_crtc, + wait_fence, idle_fence, stuff->options, + stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies); + if (ret != Success) + present_destroy_notifies(notifies, nnotifies); + return ret; +} + +static int +proc_present_notify_msc(ClientPtr client) +{ + REQUEST(xPresentNotifyMSCReq); + WindowPtr window; + int rc; + + REQUEST_SIZE_MATCH(xPresentNotifyMSCReq); + rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess); + if (rc != Success) + return rc; + + /* + * Check to see if remainder is sane + */ + if (stuff->divisor == 0) { + if (stuff->remainder != 0) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } else { + if (stuff->remainder >= stuff->divisor) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } + + return present_notify_msc(window, stuff->serial, + stuff->target_msc, stuff->divisor, stuff->remainder); +} + +static int +proc_present_select_input (ClientPtr client) +{ + REQUEST(xPresentSelectInputReq); + WindowPtr window; + int rc; + + REQUEST_SIZE_MATCH(xPresentSelectInputReq); + + LEGAL_NEW_RESOURCE(stuff->eid, client); + + rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (stuff->eventMask & ~PresentAllEvents) { + client->errorValue = stuff->eventMask; + return BadValue; + } + return present_select_input(client, stuff->eid, window, stuff->eventMask); +} + +static int +proc_present_query_capabilities (ClientPtr client) +{ + REQUEST(xPresentQueryCapabilitiesReq); + xPresentQueryCapabilitiesReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + }; + WindowPtr window; + RRCrtcPtr crtc = NULL; + int r; + + r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess); + switch (r) { + case Success: + crtc = present_get_crtc(window); + break; + case BadWindow: + VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess); + break; + default: + return r; + } + + rep.capabilities = present_query_capabilities(crtc); + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.capabilities); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = { + proc_present_query_version, /* 0 */ + proc_present_pixmap, /* 1 */ + proc_present_notify_msc, /* 2 */ + proc_present_select_input, /* 3 */ + proc_present_query_capabilities, /* 4 */ +}; + +int +proc_present_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data]) + return BadRequest; + return (*proc_present_vector[stuff->data]) (client); +} + +static int +sproc_present_query_version(ClientPtr client) +{ + REQUEST(xPresentQueryVersionReq); + + swaps(&stuff->length); + swapl(&stuff->majorVersion); + swapl(&stuff->minorVersion); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_pixmap(ClientPtr client) +{ + REQUEST(xPresentPixmapReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapl(&stuff->pixmap); + swapl(&stuff->valid); + swapl(&stuff->update); + swaps(&stuff->x_off); + swaps(&stuff->y_off); + swapll(&stuff->target_msc); + swapll(&stuff->divisor); + swapll(&stuff->remainder); + swapl(&stuff->idle_fence); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_notify_msc(ClientPtr client) +{ + REQUEST(xPresentNotifyMSCReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapll(&stuff->target_msc); + swapll(&stuff->divisor); + swapll(&stuff->remainder); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_select_input (ClientPtr client) +{ + REQUEST(xPresentSelectInputReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapl(&stuff->eventMask); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_query_capabilities (ClientPtr client) +{ + REQUEST(xPresentQueryCapabilitiesReq); + swaps(&stuff->length); + swapl(&stuff->target); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = { + sproc_present_query_version, /* 0 */ + sproc_present_pixmap, /* 1 */ + sproc_present_notify_msc, /* 2 */ + sproc_present_select_input, /* 3 */ + sproc_present_query_capabilities, /* 4 */ +}; + +int +sproc_present_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data]) + return BadRequest; + return (*sproc_present_vector[stuff->data]) (client); +} diff --git a/nx-X11/programs/Xserver/present/present_screen.c b/nx-X11/programs/Xserver/present/present_screen.c new file mode 100644 index 0000000000..50b2b2d23e --- /dev/null +++ b/nx-X11/programs/Xserver/present/present_screen.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "present_priv.h" + +int present_request; +DevPrivateKeyRec present_screen_private_key; +DevPrivateKeyRec present_window_private_key; + +/* + * Get a pointer to a present window private, creating if necessary + */ +present_window_priv_ptr +present_get_window_priv(WindowPtr window, Bool create) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (!create || window_priv != NULL) + return window_priv; + window_priv = calloc (1, sizeof (present_window_priv_rec)); + if (!window_priv) + return NULL; + xorg_list_init(&window_priv->vblank); + xorg_list_init(&window_priv->notifies); + dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); + return window_priv; +} + +/* + * Hook the close screen function to clean up our screen private + */ +static Bool +present_close_screen(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_flip_destroy(screen); + + unwrap(screen_priv, screen, CloseScreen); + (*screen->CloseScreen) (screen); + free(screen_priv); + return TRUE; +} + +/* + * Free any queued presentations for this window + */ +static void +present_free_window_vblank(WindowPtr window) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr vblank, tmp; + + xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { + present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc); + present_vblank_destroy(vblank); + } +} + +/* + * Clean up any pending or current flips for this window + */ +static void +present_clear_window_flip(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_vblank_ptr flip_pending = screen_priv->flip_pending; + + if (flip_pending && flip_pending->window == window) { + assert (flip_pending->abort_flip); + flip_pending->window_destroyed = TRUE; + } + if (screen_priv->flip_window == window) + screen_priv->flip_window = NULL; +} + +/* + * Hook the close window function to clean up our window private + */ +static Bool +present_destroy_window(WindowPtr window) +{ + Bool ret; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + present_clear_window_notifies(window); + present_free_events(window); + present_free_window_vblank(window); + present_clear_window_flip(window); + free(window_priv); + } + unwrap(screen_priv, screen, DestroyWindow); + if (screen->DestroyWindow) + ret = screen->DestroyWindow (window); + else + ret = TRUE; + wrap(screen_priv, screen, DestroyWindow, present_destroy_window); + return ret; +} + +/* + * Hook the config notify screen function to deliver present config notify events + */ +static int +present_config_notify(WindowPtr window, + int x, int y, int w, int h, int bw, + WindowPtr sibling) +{ + int ret; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_send_config_notify(window, x, y, w, h, bw, sibling); + + unwrap(screen_priv, screen, ConfigNotify); + if (screen->ConfigNotify) + ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); + else + ret = 0; + wrap(screen_priv, screen, ConfigNotify, present_config_notify); + return ret; +} + +/* + * Hook the clip notify screen function to un-flip as necessary + */ + +static void +present_clip_notify(WindowPtr window, int dx, int dy) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_check_flip_window(window); + unwrap(screen_priv, screen, ClipNotify) + if (screen->ClipNotify) + screen->ClipNotify (window, dx, dy); + wrap(screen_priv, screen, ClipNotify, present_clip_notify); +} + +/* + * Initialize a screen for use with present + */ +int +present_screen_init(ScreenPtr screen, present_screen_info_ptr info) +{ + if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) + return FALSE; + + if (!present_screen_priv(screen)) { + present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec)); + if (!screen_priv) + return FALSE; + + wrap(screen_priv, screen, CloseScreen, present_close_screen); + wrap(screen_priv, screen, DestroyWindow, present_destroy_window); + wrap(screen_priv, screen, ConfigNotify, present_config_notify); + wrap(screen_priv, screen, ClipNotify, present_clip_notify); + + screen_priv->info = info; + + dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); + + present_fake_screen_init(screen); + } + + return TRUE; +} + +/* + * Initialize the present extension + */ +void +present_extension_init(void) +{ + ExtensionEntry *extension; + int i; + + extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, + proc_present_dispatch, sproc_present_dispatch, + NULL, StandardMinorOpcode); + if (!extension) + goto bail; + + present_request = extension->base; + + if (!present_init()) + goto bail; + + if (!present_event_init()) + goto bail; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (!present_screen_init(screenInfo.screens[i], NULL)) + goto bail; + } + return; + +bail: + FatalError("Cannot initialize Present extension"); +} diff --git a/nx-X11/programs/Xserver/present/presentext.h b/nx-X11/programs/Xserver/present/presentext.h new file mode 100644 index 0000000000..f177f55dce --- /dev/null +++ b/nx-X11/programs/Xserver/present/presentext.h @@ -0,0 +1,29 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENTEXT_H_ +#define _PRESENTEXT_H_ + +extern _X_EXPORT void +present_extension_init(void); + +#endif /* _PRESENTEXT_H_ */ From 97d956c60b9917d83e89c1e05cceef6dccb10d8d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Nov 2013 23:56:26 -0800 Subject: [PATCH 02/76] Present: Check for window/fence destroyed when idling pixmaps A client destroying objects in the middle of an unflip can end up having the screen flip window or fence set to NULL in the unflip notify path. Check for these and don't try to use those objects. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 4c97ce40c7..fab105d0d2 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -184,8 +184,10 @@ present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_ static void present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence) { - present_fence_set_triggered(present_fence); - present_send_idle_notify(window, serial, pixmap, present_fence); + if (present_fence) + present_fence_set_triggered(present_fence); + if (window) + present_send_idle_notify(window, serial, pixmap, present_fence); } RRCrtcPtr @@ -297,7 +299,8 @@ present_flip_idle(ScreenPtr screen) if (screen_priv->flip_pixmap) { present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window, screen_priv->flip_serial, screen_priv->flip_idle_fence); - present_fence_destroy(screen_priv->flip_idle_fence); + if (screen_priv->flip_idle_fence) + present_fence_destroy(screen_priv->flip_idle_fence); dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id); screen_priv->flip_crtc = NULL; screen_priv->flip_window = NULL; From 6a12b3b444abdd9dae8837dcd69a45eb9d46a445 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 7 Nov 2013 03:19:42 -0800 Subject: [PATCH 03/76] present: Change debug output a bit to help diagnose missing vblank signals Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index fab105d0d2..228d43a204 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -374,6 +374,7 @@ present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) present_vblank_ptr vblank, tmp; int s; + DebugPresent(("\te %lld ust %lld msc %lld\n", event_id, ust, msc)); xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { if (vblank->event_id == event_id) { xorg_list_del(&vblank->event_queue); @@ -658,8 +659,10 @@ present_pixmap(WindowPtr window, } if (pixmap) - DebugPresent(("q %p %8lld: %08lx -> %08lx (crtc %d)\n", - vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc ? 1 : 0)); + DebugPresent(("q %lld %p %8lld: %08lx -> %08lx (crtc %p)\n", + vblank->event_id, vblank, target_msc, + vblank->pixmap->drawable.id, vblank->window->drawable.id, + target_crtc)); xorg_list_add(&vblank->event_queue, &present_exec_queue); if (target_msc >= crtc_msc) { From 727ee98deedaa31276f9b634444e163615de4e10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 7 Nov 2013 14:17:12 -0800 Subject: [PATCH 04/76] present: Round fake MSC computations intead of truncating If the timer fired too early, we'd sometimes mis-compute the MSC for fake vblanks. Rounding the computation to the nearest MSC fixes this nicely. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present_fake.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present_fake.c b/nx-X11/programs/Xserver/present/present_fake.c index a677592543..e550e98f8e 100644 --- a/nx-X11/programs/Xserver/present/present_fake.c +++ b/nx-X11/programs/Xserver/present/present_fake.c @@ -42,7 +42,7 @@ present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc) present_screen_priv_ptr screen_priv = present_screen_priv(screen); *ust = GetTimeInMicros(); - *msc = *ust / screen_priv->fake_interval; + *msc = (*ust + screen_priv->fake_interval / 2) / screen_priv->fake_interval; return Success; } From 17e57d234c2a4c04b69896e78e5abd98a23568f2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Nov 2013 12:33:02 -0800 Subject: [PATCH 05/76] present: Ignore event_id 0 from driver vblank notify We use event_id 0 to mean 'no such event'; if a driver sends us that event_id, make sure we don't accidentally match it. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 228d43a204..bfafa928e2 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -374,6 +374,8 @@ present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) present_vblank_ptr vblank, tmp; int s; + if (!event_id) + return; DebugPresent(("\te %lld ust %lld msc %lld\n", event_id, ust, msc)); xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { if (vblank->event_id == event_id) { @@ -398,6 +400,7 @@ present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) DebugPresent(("\tun %lld\n", event_id)); screen_priv->unflip_event_id = 0; present_flip_idle(screen); + return; } } } From 2b5dc6f2915894ec84b689c2d7f4ade214d2f849 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Nov 2013 12:36:47 -0800 Subject: [PATCH 06/76] present: Signal destroyed flip window with vblank->window == NULL This eliminates dereferencing freed window pointers when there is a flip for that window in progress. The flip will complete, and then immediately get undone (as we can't stop an in-progress flip). Remove the vblank->window_destroyed field as we can signal this with vblank->window == NULL instead. Change check to vblank->window == NULL in: present_flip_notify Add check for vblank->window == NULL in: present_vblank_notify present_execute present_flip_notify was also using vblank->window->drawable.pScreen, so stop doing that and use vblank->screen instead. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 11 +++++------ nx-X11/programs/Xserver/present/present_priv.h | 2 -- nx-X11/programs/Xserver/present/present_screen.c | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index bfafa928e2..67d7f6eee5 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -171,7 +171,8 @@ present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_ { int n; - present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); + if (vblank->window) + present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); for (n = 0; n < vblank->num_notifies; n++) { WindowPtr window = vblank->notifies[n].window; CARD32 serial = vblank->notifies[n].serial; @@ -336,8 +337,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); static void present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) { - WindowPtr window = vblank->window; - ScreenPtr screen = window->drawable.pScreen; + ScreenPtr screen = vblank->screen; present_screen_priv_ptr screen_priv = present_screen_priv(screen); DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, @@ -363,8 +363,7 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) if (vblank->abort_flip) present_unflip(screen); - if (!vblank->window_destroyed) - present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc); + present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc); present_vblank_destroy(vblank); } @@ -474,7 +473,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) } xorg_list_del(&vblank->event_queue); - if (vblank->pixmap) { + if (vblank->pixmap && vblank->window) { if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) { diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index a92b62a2d6..40c88dd0b7 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -72,8 +72,6 @@ struct present_vblank { Bool flip; Bool sync_flip; Bool abort_flip; - - Bool window_destroyed; }; typedef struct present_screen_priv { diff --git a/nx-X11/programs/Xserver/present/present_screen.c b/nx-X11/programs/Xserver/present/present_screen.c index 50b2b2d23e..2702cd6cac 100644 --- a/nx-X11/programs/Xserver/present/present_screen.c +++ b/nx-X11/programs/Xserver/present/present_screen.c @@ -92,7 +92,7 @@ present_clear_window_flip(WindowPtr window) if (flip_pending && flip_pending->window == window) { assert (flip_pending->abort_flip); - flip_pending->window_destroyed = TRUE; + flip_pending->window = NULL; } if (screen_priv->flip_window == window) screen_priv->flip_window = NULL; From 3807711c7cfe86948b43fed2c541fe34a346be3c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 11 Nov 2013 18:03:42 -0800 Subject: [PATCH 07/76] present: Block for wait_fence in present_execute Pend presentation until wait_fence is also triggered by having the SyncFence trigger invoke present_execute once triggered. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 34 ++++++++++++++++++- .../programs/Xserver/present/present_event.c | 2 -- .../programs/Xserver/present/present_fence.c | 29 +++++++++++++++- .../programs/Xserver/present/present_priv.h | 15 ++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 67d7f6eee5..16dc3811e1 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -452,6 +452,26 @@ present_check_flip_window (WindowPtr window) } } +/* + * Called when the wait fence is triggered; just gets the current msc/ust and + * calls present_execute again. That will re-check the fence and pend the + * request again if it's still not actually ready + */ +static void +present_wait_fence_triggered(void *param) +{ + present_vblank_ptr vblank = param; + WindowPtr window = vblank->window; + uint64_t ust = 0, crtc_msc = 0; + + if (window) { + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + if (window_priv) + (void) present_get_ust_msc(window, window_priv->crtc, &ust, &crtc_msc); + } + present_execute(vblank, ust, crtc_msc); +} + /* * Once the required MSC has been reached, execute the pending request. * @@ -469,7 +489,10 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen); if (vblank->wait_fence) { - /* XXX check fence, queue if not ready */ + if (!present_fence_check_triggered(vblank->wait_fence)) { + present_fence_set_callback(vblank->wait_fence, present_wait_fence_triggered, vblank); + return; + } } xorg_list_del(&vblank->event_queue); @@ -654,6 +677,12 @@ present_pixmap(WindowPtr window, target_msc--; } + if (wait_fence) { + vblank->wait_fence = present_fence_create(wait_fence); + if (!vblank->wait_fence) + goto no_mem; + } + if (idle_fence) { vblank->idle_fence = present_fence_create(idle_fence); if (!vblank->idle_fence) @@ -764,6 +793,9 @@ present_vblank_destroy(present_vblank_ptr vblank) if (vblank->update) RegionDestroy(vblank->update); + if (vblank->wait_fence) + present_fence_destroy(vblank->wait_fence); + if (vblank->idle_fence) present_fence_destroy(vblank->idle_fence); diff --git a/nx-X11/programs/Xserver/present/present_event.c b/nx-X11/programs/Xserver/present/present_event.c index a30bc82860..a8f7176ebb 100644 --- a/nx-X11/programs/Xserver/present/present_event.c +++ b/nx-X11/programs/Xserver/present/present_event.c @@ -26,8 +26,6 @@ #include "present_priv.h" -#include "present_priv.h" - RESTYPE present_event_type; static int diff --git a/nx-X11/programs/Xserver/present/present_fence.c b/nx-X11/programs/Xserver/present/present_fence.c index db5efcaad4..e09657d31f 100644 --- a/nx-X11/programs/Xserver/present/present_fence.c +++ b/nx-X11/programs/Xserver/present/present_fence.c @@ -37,6 +37,8 @@ struct present_fence { SyncTrigger trigger; SyncFence *fence; + void (*callback)(void *param); + void *param; }; /* @@ -45,12 +47,18 @@ struct present_fence { static Bool present_fence_sync_check_trigger(SyncTrigger *trigger, XSyncValue oldval) { - return FALSE; + struct present_fence *present_fence = container_of(trigger, struct present_fence, trigger); + + return present_fence->callback != NULL; } static void present_fence_sync_trigger_fired(SyncTrigger *trigger) { + struct present_fence *present_fence = container_of(trigger, struct present_fence, trigger); + + if (present_fence->callback) + (*present_fence->callback)(present_fence->param); } static void @@ -101,6 +109,25 @@ present_fence_set_triggered(struct present_fence *present_fence) (*present_fence->fence->funcs.SetTriggered) (present_fence->fence); } +Bool +present_fence_check_triggered(struct present_fence *present_fence) +{ + if (!present_fence) + return TRUE; + if (!present_fence->fence) + return TRUE; + return (*present_fence->fence->funcs.CheckTriggered)(present_fence->fence); +} + +void +present_fence_set_callback(struct present_fence *present_fence, + void (*callback) (void *param), + void *param) +{ + present_fence->callback = callback; + present_fence->param = param; +} + XID present_fence_id(struct present_fence *present_fence) { diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index 40c88dd0b7..500c7c2652 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -249,6 +249,14 @@ present_fence_destroy(struct present_fence *present_fence); void present_fence_set_triggered(struct present_fence *present_fence); +Bool +present_fence_check_triggered(struct present_fence *present_fence); + +void +present_fence_set_callback(struct present_fence *present_fence, + void (*callback)(void *param), + void *param); + XID present_fence_id(struct present_fence *present_fence); @@ -270,6 +278,13 @@ present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_no void present_destroy_notifies(present_notify_ptr notifies, int num_notifies); +/* + * present_redirect.c + */ + +WindowPtr +present_redirect(ClientPtr client, WindowPtr target); + /* * present_request.c */ From 6dfb1ede96e1f25283164b679f19c0e00d2fc146 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Nov 2013 22:13:54 -0800 Subject: [PATCH 08/76] present: When unflipping, copy to flip window rather than screen unflip happens after the clip lists have been updated, so instead of smashing the whole screen and drawing over other windows, just draw to the original flip window; it'll have the right clip list and so the copy will work just fine. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 16dc3811e1..f9eef6b26a 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -321,8 +321,8 @@ present_unflip(ScreenPtr screen) /* Update the screen pixmap with the current flip pixmap contents */ - if (screen_priv->flip_pixmap) { - present_copy_region(&screen->GetScreenPixmap(screen)->drawable, + if (screen_priv->flip_pixmap && screen_priv->flip_window) { + present_copy_region(&screen_priv->flip_window->drawable, screen_priv->flip_pixmap, NULL, 0, 0); } From 9508f53622677c964c661dc458d3796b46440a3c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Nov 2013 03:07:55 -0800 Subject: [PATCH 09/76] present: Add a debug output line when skipping a pending present When an application provides two pixmaps for the same MSC, the previous one is skipped. This just dumps out some information at that point Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index f9eef6b26a..f446febda8 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -621,6 +621,11 @@ present_pixmap(WindowPtr window, if (vblank->crtc != target_crtc || vblank->target_msc != target_msc) continue; + DebugPresent(("\tx %lld %p %8lld: %08lx -> %08lx (crtc %p)\n", + vblank->event_id, vblank, target_msc, + vblank->pixmap->drawable.id, vblank->window->drawable.id, + vblank->crtc)); + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); present_fence_destroy(vblank->idle_fence); dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); From a654d324b220db3ffa83832e123aa1418eb52e8a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Nov 2013 23:10:17 -0800 Subject: [PATCH 10/76] present: Leave vblank on window list until flip complete If the window is destroyed, then we've got cleanup work to do, even if the vblank has already been executed -- we need to clear the window pointer so that we don't try to deliver events to it. Leaving it on the window list meant that when walking that list, we need to know whether the vblank is waiting to be executed or waiting for the flip to complete, so a new 'queued' flag was added to the vblank to distinguish between the two states. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 14 +++++++++----- nx-X11/programs/Xserver/present/present_priv.h | 7 ++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index f446febda8..af5bf64125 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -348,6 +348,8 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_flip_idle(screen); + xorg_list_del(&vblank->event_queue); + /* Transfer reference for pixmap and fence from vblank to screen_priv */ screen_priv->flip_crtc = vblank->crtc; screen_priv->flip_window = vblank->window; @@ -378,14 +380,12 @@ present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) DebugPresent(("\te %lld ust %lld msc %lld\n", event_id, ust, msc)); xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { if (vblank->event_id == event_id) { - xorg_list_del(&vblank->event_queue); present_execute(vblank, ust, msc); return; } } xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { if (vblank->event_id == event_id) { - xorg_list_del(&vblank->event_queue); present_flip_notify(vblank, ust, msc); return; } @@ -447,7 +447,7 @@ present_check_flip_window (WindowPtr window) /* Now check any queued vblanks */ xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { - if (vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0)) + if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0)) vblank->flip = FALSE; } } @@ -496,16 +496,17 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) } xorg_list_del(&vblank->event_queue); + vblank->queued = FALSE; + if (vblank->pixmap && vblank->window) { if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) { DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); - /* Prepare to flip by removing from the window/screen lists + /* Prepare to flip by placing it in the flip queue and * and sticking it into the flip_pending field */ screen_priv->flip_pending = vblank; - xorg_list_del(&vblank->window_list); xorg_list_add(&vblank->event_queue, &present_flip_queue); /* Try to flip @@ -701,10 +702,12 @@ present_pixmap(WindowPtr window, target_crtc)); xorg_list_add(&vblank->event_queue, &present_exec_queue); + vblank->queued = TRUE; if (target_msc >= crtc_msc) { ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); if (ret != Success) { xorg_list_del(&vblank->event_queue); + vblank->queued = FALSE; goto failure; } } else @@ -737,6 +740,7 @@ present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64 xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { if (vblank->event_id == event_id) { xorg_list_del(&vblank->event_queue); + vblank->queued = FALSE; return; } } diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index 500c7c2652..8d3e0079ca 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -69,9 +69,10 @@ struct present_vblank { present_fence_ptr wait_fence; present_notify_ptr notifies; int num_notifies; - Bool flip; - Bool sync_flip; - Bool abort_flip; + Bool queued; /* on present_exec_queue */ + Bool flip; /* planning on using flip */ + Bool sync_flip; /* do flip synchronous to vblank */ + Bool abort_flip; /* aborting this flip */ }; typedef struct present_screen_priv { From 2f1bab0d30b62d3b428c9b3e1d80aa66105e926e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Nov 2013 23:06:08 -0800 Subject: [PATCH 11/76] present: Set window pixmap to flipped pixmap This makes other drawing to the window appear on the screen. Note that no child windows can be affected because only full-screen windows are eligible for flipping, and so we only need to set pixmap for the window itself. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 24 +++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index af5bf64125..76e12ed5d0 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -115,7 +115,8 @@ present_check_flip(RRCrtcPtr crtc, } /* Make sure the window hasn't been redirected with Composite */ - if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen)) + if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen) && + screen->GetWindowPixmap(window) != screen_priv->flip_pixmap) return FALSE; /* Check for full-screen window */ @@ -319,6 +320,10 @@ present_unflip(ScreenPtr screen) assert (!screen_priv->unflip_event_id); assert (!screen_priv->flip_pending); + if (screen_priv->flip_window) + (*screen->SetWindowPixmap)(screen_priv->flip_window, + (*screen->GetScreenPixmap)(screen)); + /* Update the screen pixmap with the current flip pixmap contents */ if (screen_priv->flip_pixmap && screen_priv->flip_window) { @@ -486,7 +491,8 @@ static void present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) { WindowPtr window = vblank->window; - present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen); + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); if (vblank->wait_fence) { if (!present_fence_check_triggered(vblank->wait_fence)) { @@ -511,8 +517,18 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) xorg_list_add(&vblank->event_queue, &present_flip_queue); /* Try to flip */ - if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) + if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) { + + /* Fix window pixmaps: + * 1) Restore previous flip window pixmap + * 2) Set current flip window pixmap to the new pixmap + */ + if (screen_priv->flip_window && screen_priv->flip_window != window) + (*screen->SetWindowPixmap)(screen_priv->flip_window, + (*screen->GetScreenPixmap)(screen)); + (*screen->SetWindowPixmap)(vblank->window, vblank->pixmap); return; + } xorg_list_del(&vblank->event_queue); /* Oops, flip failed. Clear the flip_pending field @@ -532,7 +548,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) /* Check current flip */ if (window == screen_priv->flip_window) - present_unflip(window->drawable.pScreen); + present_unflip(screen); } present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off); From e49716936b8962916ab3c5844f96dbe19605e5b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Nov 2013 22:48:31 -0800 Subject: [PATCH 12/76] present: Send GLX_BufferSwapComplete events from present extension This allows GL to support the GLX_INTEL_swap_event extension. v2: Return GLX_BLIT_COMPLETE_INTEL for unknown swap types Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.h | 9 +++++++++ nx-X11/programs/Xserver/present/present_event.c | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.h b/nx-X11/programs/Xserver/present/present.h index 6a451fb234..0e3bdc08eb 100644 --- a/nx-X11/programs/Xserver/present/present.h +++ b/nx-X11/programs/Xserver/present/present.h @@ -115,4 +115,13 @@ present_event_abandon(RRCrtcPtr crtc); extern _X_EXPORT Bool present_screen_init(ScreenPtr screen, present_screen_info_ptr info); +typedef void (*present_complete_notify_proc)(WindowPtr window, + CARD8 mode, + CARD32 serial, + uint64_t ust, + uint64_t msc); + +extern _X_EXPORT void +present_register_complete_notify(present_complete_notify_proc proc); + #endif /* _PRESENT_H_ */ diff --git a/nx-X11/programs/Xserver/present/present_event.c b/nx-X11/programs/Xserver/present/present_event.c index a8f7176ebb..f0d509ed4f 100644 --- a/nx-X11/programs/Xserver/present/present_event.c +++ b/nx-X11/programs/Xserver/present/present_event.c @@ -137,6 +137,14 @@ present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, } } +static present_complete_notify_proc complete_notify; + +void +present_register_complete_notify(present_complete_notify_proc proc) +{ + complete_notify = proc; +} + void present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) { @@ -165,6 +173,8 @@ present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 se } } } + if (complete_notify) + (*complete_notify)(window, mode, serial, ust, msc); } void From e1d43f581ca4115bb08d175fd5efb3c64fef247d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Nov 2013 12:06:57 -0800 Subject: [PATCH 13/76] present: Clear target_crtc if driver lacks Present support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the driver doesn't have the necessary hooks for Present, then the target_crtc needs to be set to NULL to make sure the extension uses the present_fake code. Signed-off-by: Keith Packard Tested-by: Fredrik Höglund Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 76e12ed5d0..3fd5e8bb1e 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -594,7 +594,9 @@ present_pixmap(WindowPtr window, if (!window_priv) return BadAlloc; - if (!target_crtc) { + if (!screen_priv || !screen_priv->info) + target_crtc = NULL; + else if (!target_crtc) { /* Update the CRTC if we have a pixmap or we don't have a CRTC */ if (!pixmap) From 8d250d523e1aeeab880292dab65c1fc40745bb9c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Nov 2013 12:10:48 -0800 Subject: [PATCH 14/76] present: Also set the root window pixmap when flipping This makes sure that things like software cursors continue to work while the screen is flipped. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 3fd5e8bb1e..251931a06d 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -324,6 +324,8 @@ present_unflip(ScreenPtr screen) (*screen->SetWindowPixmap)(screen_priv->flip_window, (*screen->GetScreenPixmap)(screen)); + (*screen->SetWindowPixmap)(screen->root, (*screen->GetScreenPixmap)(screen)); + /* Update the screen pixmap with the current flip pixmap contents */ if (screen_priv->flip_pixmap && screen_priv->flip_window) { @@ -527,6 +529,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) (*screen->SetWindowPixmap)(screen_priv->flip_window, (*screen->GetScreenPixmap)(screen)); (*screen->SetWindowPixmap)(vblank->window, vblank->pixmap); + (*screen->SetWindowPixmap)(screen->root, vblank->pixmap); return; } From 539f0b6fecb1a705d1861199408c037c643d3300 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Nov 2013 12:18:12 -0800 Subject: [PATCH 15/76] present: Report damage when flipping Limit damage to the 'update' region. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 251931a06d..ffbb0b3701 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -520,6 +520,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) /* Try to flip */ if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) { + RegionPtr damage; /* Fix window pixmaps: * 1) Restore previous flip window pixmap @@ -530,6 +531,16 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) (*screen->GetScreenPixmap)(screen)); (*screen->SetWindowPixmap)(vblank->window, vblank->pixmap); (*screen->SetWindowPixmap)(screen->root, vblank->pixmap); + + /* Report update region as damaged + */ + if (vblank->update) { + damage = vblank->update; + RegionIntersect(damage, damage, &window->clipList); + } else + damage = &window->clipList; + + DamageDamageRegion(&vblank->window->drawable, damage); return; } From 9242988155fb27496794bacd78bfd84101f7a267 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 8 Nov 2013 09:06:59 -0500 Subject: [PATCH 16/76] present: Disable when Xinerama is active Among much else Present depends on RANDR types, and RANDR isn't properly Xinerama-aware yet anyway. Reviewed-by: Julien Cristau Signed-off-by: Adam Jackson --- nx-X11/programs/Xserver/present/present_screen.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present_screen.c b/nx-X11/programs/Xserver/present/present_screen.c index 2702cd6cac..25ef6818d8 100644 --- a/nx-X11/programs/Xserver/present/present_screen.c +++ b/nx-X11/programs/Xserver/present/present_screen.c @@ -206,6 +206,11 @@ present_extension_init(void) ExtensionEntry *extension; int i; +#ifdef PANORAMIX + if (!noPanoramiXExtension) + return; +#endif + extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, proc_present_dispatch, sproc_present_dispatch, NULL, StandardMinorOpcode); From 855e3e318fafafeb6b23d3f13dd120fa0dc34437 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Dec 2013 11:27:47 -0800 Subject: [PATCH 17/76] present: recursively set window pixmaps on flip Newly created windows inherit the pixmap of their parent, similarly, reparenting a tree inherits the pixmap of the destination tree. Making present preserve the invariant that unredirected windows always have the same pixmap as their parent ensures that the above cases work correctly. v2: name the recursive function to 'set_tree_pixmap' instead of 'set_window_pixmap' Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 44 +++++++++++++++++++---- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index ffbb0b3701..50bd055398 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -312,6 +312,36 @@ present_flip_idle(ScreenPtr screen) } } +struct pixmap_visit { + PixmapPtr old; + PixmapPtr new; +}; + +static int +present_set_tree_pixmap_visit(WindowPtr window, pointer data) +{ + struct pixmap_visit *visit = data; + ScreenPtr screen = window->drawable.pScreen; + + if ((*screen->GetWindowPixmap)(window) != visit->old) + return WT_DONTWALKCHILDREN; + (*screen->SetWindowPixmap)(window, visit->new); + return WT_WALKCHILDREN; +} + +static void +present_set_tree_pixmap(WindowPtr window, PixmapPtr pixmap) +{ + struct pixmap_visit visit; + ScreenPtr screen = window->drawable.pScreen; + + visit.old = (*screen->GetWindowPixmap)(window); + visit.new = pixmap; + if (visit.old == visit.new) + return; + TraverseTree(window, present_set_tree_pixmap_visit, &visit); +} + static void present_unflip(ScreenPtr screen) { @@ -321,10 +351,10 @@ present_unflip(ScreenPtr screen) assert (!screen_priv->flip_pending); if (screen_priv->flip_window) - (*screen->SetWindowPixmap)(screen_priv->flip_window, - (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(screen_priv->flip_window, + (*screen->GetScreenPixmap)(screen)); - (*screen->SetWindowPixmap)(screen->root, (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen)); /* Update the screen pixmap with the current flip pixmap contents */ @@ -527,10 +557,10 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) * 2) Set current flip window pixmap to the new pixmap */ if (screen_priv->flip_window && screen_priv->flip_window != window) - (*screen->SetWindowPixmap)(screen_priv->flip_window, - (*screen->GetScreenPixmap)(screen)); - (*screen->SetWindowPixmap)(vblank->window, vblank->pixmap); - (*screen->SetWindowPixmap)(screen->root, vblank->pixmap); + present_set_tree_pixmap(screen_priv->flip_window, + (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(vblank->window, vblank->pixmap); + present_set_tree_pixmap(screen->root, vblank->pixmap); /* Report update region as damaged */ From 08c63859fa758a17f99914fe3d6abde18aa9469a Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 13 Dec 2013 11:39:16 -0500 Subject: [PATCH 18/76] present: Don't use the major/minor version from the protocol headers We want to advertise the version we implement, not the version the protocol headers happen to describe. Reviewed-by: Jasper St. Pierre < Signed-off-by: Adam Jackson --- nx-X11/programs/Xserver/present/present_request.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present_request.c b/nx-X11/programs/Xserver/present/present_request.c index 095fa2daf0..1064dcb3b0 100644 --- a/nx-X11/programs/Xserver/present/present_request.c +++ b/nx-X11/programs/Xserver/present/present_request.c @@ -26,6 +26,7 @@ #include "present_priv.h" #include "randrstr.h" +#include static int proc_present_query_version(ClientPtr client) @@ -35,8 +36,8 @@ proc_present_query_version(ClientPtr client) .type = X_Reply, .sequenceNumber = client->sequence, .length = 0, - .majorVersion = PRESENT_MAJOR, - .minorVersion = PRESENT_MINOR + .majorVersion = SERVER_PRESENT_MAJOR_VERSION, + .minorVersion = SERVER_PRESENT_MINOR_VERSION }; REQUEST_SIZE_MATCH(xPresentQueryVersionReq); From 1ff4b360fcc8c7e616c7593a556d918750061585 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Dec 2013 14:17:40 -0800 Subject: [PATCH 19/76] present: Handle PresentOptionAsync for copy mode Check for Async flag and execute immediately if set, otherwise wait for the next appropriate vblank before copying. Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 50bd055398..4c0d63baf6 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -663,10 +663,18 @@ present_pixmap(WindowPtr window, if (crtc_msc >= target_msc) { if (divisor != 0) { target_msc = crtc_msc - (crtc_msc % divisor) + remainder; - if (target_msc <= crtc_msc) - target_msc += divisor; - } else + if (options & PresentOptionAsync) { + if (target_msc < crtc_msc) + target_msc += divisor; + } else { + if (target_msc <= crtc_msc) + target_msc += divisor; + } + } else { target_msc = crtc_msc; + if (!(options & PresentOptionAsync)) + target_msc++; + } } /* From 9d5ff2382a3364e37bb3d27c335019e8ba59fc1c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Dec 2013 14:52:35 -0800 Subject: [PATCH 20/76] present: Don't abandon presents which are already queued for flip Presents which are not marked 'queued' and are in the window present list are waiting for the flip event; discarding those won't work very well (it'll end up trashing displayed content for the next frame), so skip over those when looking for duplicate frame presents Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 4c0d63baf6..3caa8b771b 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -689,6 +689,9 @@ present_pixmap(WindowPtr window, if (!vblank->pixmap) continue; + if (!vblank->queued) + continue; + if (vblank->crtc != target_crtc || vblank->target_msc != target_msc) continue; From 2033c298f79ee18aea689f7b0f0bb693ef858b40 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Dec 2013 15:48:08 -0800 Subject: [PATCH 21/76] present: Set complete notify mode to Skip as needed Skipped present pixmap calls were not setting the mode to PresentCompleteModeSkip for skipped operations. Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 3caa8b771b..30cd3b936c 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -525,6 +525,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) WindowPtr window = vblank->window; ScreenPtr screen = window->drawable.pScreen; present_screen_priv_ptr screen_priv = present_screen_priv(screen); + uint8_t mode; if (vblank->wait_fence) { if (!present_fence_check_triggered(vblank->wait_fence)) { @@ -604,7 +605,20 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); } - present_vblank_notify(vblank, vblank->kind, PresentCompleteModeCopy, ust, crtc_msc); + + /* Compute correct CompleteMode + */ + if (vblank->kind == PresentCompleteKindPixmap) { + if (vblank->pixmap && vblank->window) + mode = PresentCompleteModeCopy; + else + mode = PresentCompleteModeSkip; + } + else + mode = PresentCompleteModeCopy; + + + present_vblank_notify(vblank, vblank->kind, mode, ust, crtc_msc); present_vblank_destroy(vblank); } From 6fbe97d37a38c24cfc268c5781593d8c9ec5de73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Dec 2013 01:05:51 -0800 Subject: [PATCH 22/76] Replace 'pointer' type with 'void *' This lets us stop using the 'pointer' typedef in Xdefs.h as 'pointer' is used throughout the X server for other things, and having duplicate names generates compiler warnings. Signed-off-by: Keith Packard Reviewed-by: Eric Anholt --- nx-X11/programs/Xserver/present/present.c | 2 +- nx-X11/programs/Xserver/present/present_event.c | 6 +++--- nx-X11/programs/Xserver/present/present_fake.c | 2 +- nx-X11/programs/Xserver/present/present_request.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 30cd3b936c..73d5f69835 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -318,7 +318,7 @@ struct pixmap_visit { }; static int -present_set_tree_pixmap_visit(WindowPtr window, pointer data) +present_set_tree_pixmap_visit(WindowPtr window, void *data) { struct pixmap_visit *visit = data; ScreenPtr screen = window->drawable.pScreen; diff --git a/nx-X11/programs/Xserver/present/present_event.c b/nx-X11/programs/Xserver/present/present_event.c index f0d509ed4f..ff57eba419 100644 --- a/nx-X11/programs/Xserver/present/present_event.c +++ b/nx-X11/programs/Xserver/present/present_event.c @@ -29,7 +29,7 @@ RESTYPE present_event_type; static int -present_free_event(pointer data, XID id) +present_free_event(void *data, XID id) { present_event_ptr present_event = (present_event_ptr) data; present_window_priv_ptr window_priv = present_window_priv(present_event->window); @@ -41,7 +41,7 @@ present_free_event(pointer data, XID id) break; } } - free((pointer) present_event); + free((void *) present_event); return 1; } @@ -229,7 +229,7 @@ present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) event->next = window_priv->events; window_priv->events = event; - if (!AddResource(event->id, present_event_type, (pointer) event)) + if (!AddResource(event->id, present_event_type, (void *) event)) return BadAlloc; return Success; diff --git a/nx-X11/programs/Xserver/present/present_fake.c b/nx-X11/programs/Xserver/present/present_fake.c index e550e98f8e..4985c81e33 100644 --- a/nx-X11/programs/Xserver/present/present_fake.c +++ b/nx-X11/programs/Xserver/present/present_fake.c @@ -58,7 +58,7 @@ present_fake_notify(ScreenPtr screen, uint64_t event_id) static CARD32 present_fake_do_timer(OsTimerPtr timer, CARD32 time, - pointer arg) + void *arg) { present_fake_vblank_ptr fake_vblank = arg; diff --git a/nx-X11/programs/Xserver/present/present_request.c b/nx-X11/programs/Xserver/present/present_request.c index 1064dcb3b0..835890d28a 100644 --- a/nx-X11/programs/Xserver/present/present_request.c +++ b/nx-X11/programs/Xserver/present/present_request.c @@ -89,7 +89,7 @@ proc_present_pixmap(ClientPtr client) ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess); if (ret != Success) return ret; - ret = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess); + ret = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess); if (ret != Success) return ret; From c01d5074f0215d05206e5018fb6fd7237260af21 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Jan 2014 11:23:58 -0800 Subject: [PATCH 23/76] present: Queue flips for later execution When a flip (or unflip) is pending and a flip request comes in, leave it queued until the pending flip completes and then execute it. This fixes a bug where an application submitting back-to-back present_pixmap requests for sequential frames would alternate between flipping and copying as the pending flip would cause the new present_pixmap request to not use a flip. Signed-off-by: Keith Packard Reviewed-by: Chris Wilson Tested-by: Frank Binns --- nx-X11/programs/Xserver/present/present.c | 126 ++++++++++++------ .../programs/Xserver/present/present_priv.h | 1 + 2 files changed, 89 insertions(+), 38 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 73d5f69835..1bf3a5865a 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -42,6 +42,9 @@ static struct xorg_list present_flip_queue; #define DebugPresent(x) #endif +static void +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); + /* * Copies the update region from a pixmap to the target drawable */ @@ -78,6 +81,20 @@ present_copy_region(DrawablePtr drawable, FreeScratchGC(gc); } +static inline PixmapPtr +present_flip_pending_pixmap(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return NULL; + + if (!screen_priv->flip_pending) + return NULL; + + return screen_priv->flip_pending->pixmap; +} + static Bool present_check_flip(RRCrtcPtr crtc, WindowPtr window, @@ -88,6 +105,7 @@ present_check_flip(RRCrtcPtr crtc, int16_t y_off) { ScreenPtr screen = window->drawable.pScreen; + PixmapPtr window_pixmap; WindowPtr root = screen->root; present_screen_priv_ptr screen_priv = present_screen_priv(screen); @@ -104,19 +122,11 @@ present_check_flip(RRCrtcPtr crtc, if (!screen_priv->info->flip) return FALSE; - /* Can't pend a flip while unflipping */ - if (screen_priv->unflip_event_id) { - return FALSE; - } - - /* Can't have two pending flips at the same time */ - if (screen_priv->flip_pending) { - return FALSE; - } - /* Make sure the window hasn't been redirected with Composite */ - if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen) && - screen->GetWindowPixmap(window) != screen_priv->flip_pixmap) + window_pixmap = screen->GetWindowPixmap(window); + if (window_pixmap != screen->GetScreenPixmap(screen) && + window_pixmap != screen_priv->flip_pixmap && + window_pixmap != present_flip_pending_pixmap(screen)) return FALSE; /* Check for full-screen window */ @@ -147,6 +157,7 @@ present_check_flip(RRCrtcPtr crtc, /* Ask the driver for permission */ if (screen_priv->info->check_flip) { if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) { + DebugPresent(("\td %08lx -> %08lx\n", window->drawable.id, pixmap ? pixmap->drawable.id : 0)); return FALSE; } } @@ -188,8 +199,10 @@ present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct pr { if (present_fence) present_fence_set_triggered(present_fence); - if (window) + if (window) { + DebugPresent(("\ti %08lx\n", pixmap ? pixmap->drawable.id : 0)); present_send_idle_notify(window, serial, pixmap, present_fence); + } } RRCrtcPtr @@ -227,9 +240,8 @@ present_query_capabilities(RRCrtcPtr crtc) } static int -present_get_ust_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc) +present_get_ust_msc(ScreenPtr screen, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc) { - ScreenPtr screen = window->drawable.pScreen; present_screen_priv_ptr screen_priv = present_screen_priv(screen); if (crtc == NULL) @@ -283,7 +295,7 @@ present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc * we'll just use whatever previous MSC we'd seen from this CRTC */ - if (present_get_ust_msc(window, window_priv->crtc, &old_ust, &old_msc) != Success) + if (present_get_ust_msc(window->drawable.pScreen, window_priv->crtc, &old_ust, &old_msc) != Success) old_msc = window_priv->msc; window_priv->msc_offset += new_msc - old_msc; @@ -293,6 +305,34 @@ present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc return window_msc + window_priv->msc_offset; } +/* + * When the wait fence or previous flip is completed, it's time + * to re-try the request + */ +static void +present_re_execute(present_vblank_ptr vblank) +{ + uint64_t ust = 0, crtc_msc = 0; + + if (vblank->crtc) + (void) present_get_ust_msc(vblank->screen, vblank->crtc, &ust, &crtc_msc); + + present_execute(vblank, ust, crtc_msc); +} + +static void +present_flip_try_ready(ScreenPtr screen) +{ + present_vblank_ptr vblank, tmp; + + xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { + if (vblank->flip_ready) { + present_re_execute(vblank); + return; + } + } +} + static void present_flip_idle(ScreenPtr screen) { @@ -368,17 +408,15 @@ present_unflip(ScreenPtr screen) (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id); } -static void -present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); - static void present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) { ScreenPtr screen = vblank->screen; present_screen_priv_ptr screen_priv = present_screen_priv(screen); - DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, - vblank->pixmap ? vblank->pixmap->drawable.id : 0, + DebugPresent(("\tn %lld %p %8lld: %08lx -> %08lx\n", + vblank->event_id, vblank, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, vblank->window->drawable.id)); assert (vblank == screen_priv->flip_pending); @@ -404,6 +442,8 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc); present_vblank_destroy(vblank); + + present_flip_try_ready(screen); } void @@ -436,6 +476,7 @@ present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) DebugPresent(("\tun %lld\n", event_id)); screen_priv->unflip_event_id = 0; present_flip_idle(screen); + present_flip_try_ready(screen); return; } } @@ -498,15 +539,7 @@ static void present_wait_fence_triggered(void *param) { present_vblank_ptr vblank = param; - WindowPtr window = vblank->window; - uint64_t ust = 0, crtc_msc = 0; - - if (window) { - present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); - if (window_priv) - (void) present_get_ust_msc(window, window_priv->crtc, &ust, &crtc_msc); - } - present_execute(vblank, ust, crtc_msc); + present_re_execute(vblank); } /* @@ -534,14 +567,27 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) } } + if (vblank->flip && vblank->pixmap && vblank->window) { + if (screen_priv->flip_pending || screen_priv->unflip_event_id) { + DebugPresent(("\tr %lld %p (pending %p unflip %lld)\n", + vblank->event_id, vblank, + screen_priv->flip_pending, screen_priv->unflip_event_id)); + vblank->flip_ready = TRUE; + return; + } + } + xorg_list_del(&vblank->event_queue); vblank->queued = FALSE; if (vblank->pixmap && vblank->window) { - if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) { + if (vblank->flip) { + + DebugPresent(("\tf %lld %p %8lld: %08lx -> %08lx\n", + vblank->event_id, vblank, crtc_msc, + vblank->pixmap->drawable.id, vblank->window->drawable.id)); - DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); /* Prepare to flip by placing it in the flip queue and * and sticking it into the flip_pending field */ @@ -644,7 +690,7 @@ present_pixmap(WindowPtr window, uint64_t target_msc; uint64_t crtc_msc; int ret; - present_vblank_ptr vblank; + present_vblank_ptr vblank, tmp; ScreenPtr screen = window->drawable.pScreen; present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); present_screen_priv_ptr screen_priv = present_screen_priv(screen); @@ -664,7 +710,7 @@ present_pixmap(WindowPtr window, target_crtc = present_get_crtc(window); } - present_get_ust_msc(window, target_crtc, &ust, &crtc_msc); + present_get_ust_msc(screen, target_crtc, &ust, &crtc_msc); target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc); @@ -698,7 +744,7 @@ present_pixmap(WindowPtr window, */ if (!update) { - xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { if (!vblank->pixmap) continue; @@ -706,11 +752,11 @@ present_pixmap(WindowPtr window, if (!vblank->queued) continue; - if (vblank->crtc != target_crtc || vblank->target_msc != target_msc) + if (vblank->crtc != target_crtc || vblank->target_msc > target_msc) continue; DebugPresent(("\tx %lld %p %8lld: %08lx -> %08lx (crtc %p)\n", - vblank->event_id, vblank, target_msc, + vblank->event_id, vblank, vblank->target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, vblank->crtc)); @@ -720,6 +766,9 @@ present_pixmap(WindowPtr window, vblank->pixmap = NULL; vblank->idle_fence = NULL; + vblank->flip = FALSE; + if (vblank->flip_ready) + present_re_execute(vblank); } } @@ -875,7 +924,8 @@ present_vblank_destroy(present_vblank_ptr vblank) /* Remove vblank from window and screen lists */ xorg_list_del(&vblank->window_list); - DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, + DebugPresent(("\td %lld %p %8lld: %08lx -> %08lx\n", + vblank->event_id, vblank, vblank->target_msc, vblank->pixmap ? vblank->pixmap->drawable.id : 0, vblank->window->drawable.id)); diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index 8d3e0079ca..d8569a2b6e 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -71,6 +71,7 @@ struct present_vblank { int num_notifies; Bool queued; /* on present_exec_queue */ Bool flip; /* planning on using flip */ + Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */ Bool sync_flip; /* do flip synchronous to vblank */ Bool abort_flip; /* aborting this flip */ }; From c82a467a8757b33bf04dd0fc573385d9a4bc12fd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jun 2014 15:50:48 -0700 Subject: [PATCH 24/76] present: Remove executing vblank from window list. Bug# 79709. Once the vblank is actually getting executed, it's lifetime is no longer tied to the window, and so it shouldn't be controlled by window destruction. In particular, if the vblank is queued for flip, it will get stored in the flip_pending field, and will be correctly destroyed when the flip completes. Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 1bf3a5865a..165860af8b 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -578,6 +578,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) } xorg_list_del(&vblank->event_queue); + xorg_list_del(&vblank->window_list); vblank->queued = FALSE; if (vblank->pixmap && vblank->window) { From 837bc50a8c44e2b7f490f6167318334745e66c17 Mon Sep 17 00:00:00 2001 From: Frank Binns Date: Tue, 10 Jun 2014 13:43:31 +0100 Subject: [PATCH 25/76] present: restore screen pixmap when aborting a flip If a 2D application is started on top of a fullscreen 3D application, which is flipping, then we need to stop flipping and restore the root window, and possibly the flip window, to using the screen pixmap. Normally this would be done as part of an unflip. However, in the case that there is a pending flip there is no mechanism to abort so the unflip is deferred until the pending flip completes. This provides a window of opportunity for the 2D application to draw to the wrong pixmap. Restore the screen pixmap at the point a pending flip is marked as aborted, thus avoiding this issue. Reviewed-by: Keith Packard Signed-off-by: Frank Binns Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 24 ++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 165860af8b..271c251a9d 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -382,6 +382,24 @@ present_set_tree_pixmap(WindowPtr window, PixmapPtr pixmap) TraverseTree(window, present_set_tree_pixmap_visit, &visit); } +static void +present_set_abort_flip(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + /* Switch back to using the screen pixmap now to avoid + * 2D applications drawing to the wrong pixmap. + */ + + if (screen_priv->flip_window) + present_set_tree_pixmap(screen_priv->flip_window, + (*screen->GetScreenPixmap)(screen)); + + present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen)); + + screen_priv->flip_pending->abort_flip = TRUE; +} + static void present_unflip(ScreenPtr screen) { @@ -511,7 +529,7 @@ present_check_flip_window (WindowPtr window) if (flip_pending->window == window) { if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap, flip_pending->sync_flip, NULL, 0, 0)) - flip_pending->abort_flip = TRUE; + present_set_abort_flip(screen); } } else { /* @@ -634,7 +652,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) /* Check pending flip */ if (window == screen_priv->flip_pending->window) - screen_priv->flip_pending->abort_flip = TRUE; + present_set_abort_flip(screen); } else if (!screen_priv->unflip_event_id) { /* Check current flip @@ -916,7 +934,7 @@ present_flip_destroy(ScreenPtr screen) /* Do the actual cleanup once the flip has been performed by the hardware */ if (screen_priv->flip_pending) - screen_priv->flip_pending->abort_flip = TRUE; + present_set_abort_flip(screen); } void From f40f1d5d9189c29f0c067112657d87f4913ee73a Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Wed, 18 Jun 2014 22:22:09 -0400 Subject: [PATCH 26/76] present: fix bad logic in cancelling scheduled operations. If we present several pixmaps in advance for different msc, the later one shouldn't cancel the previous ones. This reverts a change made by commit e6f5d9d7b7efdacea0f22f1808efca849bcede4c Without this fix, vblank_mode=0 glxgears doesn't update with the present fallback. Signed-off-by: Axel Davy Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 271c251a9d..3aea0d7c6c 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -771,7 +771,7 @@ present_pixmap(WindowPtr window, if (!vblank->queued) continue; - if (vblank->crtc != target_crtc || vblank->target_msc > target_msc) + if (vblank->crtc != target_crtc || vblank->target_msc != target_msc) continue; DebugPresent(("\tx %lld %p %8lld: %08lx -> %08lx (crtc %p)\n", From dc059fe13840320b440ff7d078b4fbbd8ac75c7a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 20 Jul 2014 18:53:52 -0700 Subject: [PATCH 27/76] present: Make window MSC offset 0 initially The MSC offset used by a window is adjusted as the window moves between screens, and between shown/unshown. The value shouldn't matter, but it's helpful for debugging to have window MSC values be the same as the CRTC MSC at first. This patch introduces a unique CRTC value so that Present can detect the first time a window is a PresentPixmap destination and set the MSC offset to zero, rather than using the fake MSC value as the previous window MSC. Signed-off-by: Keith Packard Reviewed-by: Eric Anholt --- nx-X11/programs/Xserver/present/present.c | 18 +++++++++++------- nx-X11/programs/Xserver/present/present_priv.h | 2 ++ .../programs/Xserver/present/present_screen.c | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 3aea0d7c6c..f624e5b7bf 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -291,14 +291,18 @@ present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc if (crtc != window_priv->crtc) { uint64_t old_ust, old_msc; - /* The old CRTC may have been turned off, in which case - * we'll just use whatever previous MSC we'd seen from this CRTC - */ + if (window_priv->crtc == PresentCrtcNeverSet) { + window_priv->msc_offset = 0; + } else { + /* The old CRTC may have been turned off, in which case + * we'll just use whatever previous MSC we'd seen from this CRTC + */ - if (present_get_ust_msc(window->drawable.pScreen, window_priv->crtc, &old_ust, &old_msc) != Success) - old_msc = window_priv->msc; + if (present_get_ust_msc(window->drawable.pScreen, window_priv->crtc, &old_ust, &old_msc) != Success) + old_msc = window_priv->msc; - window_priv->msc_offset += new_msc - old_msc; + window_priv->msc_offset += new_msc - old_msc; + } window_priv->crtc = crtc; } @@ -725,7 +729,7 @@ present_pixmap(WindowPtr window, if (!pixmap) target_crtc = window_priv->crtc; - if (!target_crtc) + if (!target_crtc || target_crtc == PresentCrtcNeverSet) target_crtc = present_get_crtc(window); } diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index d8569a2b6e..f5c1652d1c 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -134,6 +134,8 @@ typedef struct present_window_priv { struct xorg_list notifies; } present_window_priv_rec, *present_window_priv_ptr; +#define PresentCrtcNeverSet ((RRCrtcPtr) 1) + extern DevPrivateKeyRec present_window_private_key; static inline present_window_priv_ptr diff --git a/nx-X11/programs/Xserver/present/present_screen.c b/nx-X11/programs/Xserver/present/present_screen.c index 25ef6818d8..2f91ac7dc8 100644 --- a/nx-X11/programs/Xserver/present/present_screen.c +++ b/nx-X11/programs/Xserver/present/present_screen.c @@ -45,6 +45,7 @@ present_get_window_priv(WindowPtr window, Bool create) return NULL; xorg_list_init(&window_priv->vblank); xorg_list_init(&window_priv->notifies); + window_priv->crtc = PresentCrtcNeverSet; dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); return window_priv; } From 0032a712e5b93dabcd914ed56ad39fd5e185d2a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 20 Jul 2014 18:57:42 -0700 Subject: [PATCH 28/76] present: Avoid crash at server shutdown When a present flip operation is still in process during server reset, the call to present_set_abort_flip may not happen until the screen is being closed, at which point there is no root window to set pixmaps for. Check to make sure there's a window before resetting window pixmaps. Signed-off-by: Keith Packard Reviewed-by: Eric Anholt --- nx-X11/programs/Xserver/present/present.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index f624e5b7bf..f488e21ccd 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -399,7 +399,8 @@ present_set_abort_flip(ScreenPtr screen) present_set_tree_pixmap(screen_priv->flip_window, (*screen->GetScreenPixmap)(screen)); - present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen)); + if (screen->root) + present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen)); screen_priv->flip_pending->abort_flip = TRUE; } From 29f4c13ff79e5b12c0b4229dae2dd73e0a0f4eb3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 4 Sep 2014 08:36:07 -0700 Subject: [PATCH 29/76] glx/present: Only send GLX_BufferSwapComplete for PresentCompleteKindPixmap Present didn't provide the 'kind' argument to the present_complete_notify hook that GLX uses to construct GLX_BufferSwapComplete events, so GLX was reporting events for PresentCompleteKindMSC notifications, which resulted in duplicate GLX_BufferSwapComplete events and crashes in clutter. See the gnome bug: https://bugzilla.gnome.org/show_bug.cgi?id=733282 Signed-off-by: Keith Packard Reviewed-by: Eric Anholt --- nx-X11/programs/Xserver/present/present.h | 1 + nx-X11/programs/Xserver/present/present_event.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.h b/nx-X11/programs/Xserver/present/present.h index 0e3bdc08eb..aab2e168ac 100644 --- a/nx-X11/programs/Xserver/present/present.h +++ b/nx-X11/programs/Xserver/present/present.h @@ -116,6 +116,7 @@ extern _X_EXPORT Bool present_screen_init(ScreenPtr screen, present_screen_info_ptr info); typedef void (*present_complete_notify_proc)(WindowPtr window, + CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, diff --git a/nx-X11/programs/Xserver/present/present_event.c b/nx-X11/programs/Xserver/present/present_event.c index ff57eba419..d3a59ea25b 100644 --- a/nx-X11/programs/Xserver/present/present_event.c +++ b/nx-X11/programs/Xserver/present/present_event.c @@ -174,7 +174,7 @@ present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 se } } if (complete_notify) - (*complete_notify)(window, mode, serial, ust, msc); + (*complete_notify)(window, kind, mode, serial, ust, msc); } void From 0ba3ebb3c8c35bc144e45a265f3f382a59a6bb4e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Sep 2014 14:02:13 -0700 Subject: [PATCH 30/76] present: Support PresentOptionCopy We added this option to the present protocol before 1.0 but somehow never implemented it in the server. It's pretty simple; just don't ever do flips if the application specifies Copy. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index f488e21ccd..9be690ce62 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -837,7 +837,10 @@ present_pixmap(WindowPtr window, if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync)) vblank->sync_flip = TRUE; - if (pixmap && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) { + if (!(options & PresentOptionCopy) && + pixmap != NULL && + present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) + { vblank->flip = TRUE; if (vblank->sync_flip) target_msc--; From 3cb43a952c3508d05cd5f2c3d7c13448a622fdbe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Sep 2014 14:01:59 -0700 Subject: [PATCH 31/76] present: Clear pending flip pixmaps at CloseScreen If a flip is active at server reset time, the associated window will get destroyed which will queue an unflip operation. If that isn't synchronous, then it won't have finished by the time CloseScreen is called. Calling present_flip_idle will signal the fence and remove the reference to the fence and pixmap, freeing these in the X server and allowing a DRM client to clean up as well. This also rewords other comments in present_flip_destroy, removing scary words about needing synchronous operation (everything in this function is synchronous now) and describing what effect we actually need from present_set_abort_flip. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson --- nx-X11/programs/Xserver/present/present.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 9be690ce62..e838da7922 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -938,11 +938,12 @@ present_flip_destroy(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); - /* XXX this needs to be synchronous for server reset */ - - /* Do the actual cleanup once the flip has been performed by the hardware */ + /* Reset window pixmaps back to the screen pixmap */ if (screen_priv->flip_pending) present_set_abort_flip(screen); + + /* Drop reference to any pending flip or unflip pixmaps. */ + present_flip_idle(screen); } void From 129668439ff0ae13fece05d675c5abeec49f0768 Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Sat, 27 Sep 2014 23:17:13 +0200 Subject: [PATCH 32/76] Fix present_pixmap when using present_notify_msc Calling present_notify_msc could cancel a pending pixmap presentation. Signed-off-by: Axel Davy Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index e838da7922..47566c74e1 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -767,7 +767,7 @@ present_pixmap(WindowPtr window, * in the same frame */ - if (!update) { + if (!update && pixmap) { xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { if (!vblank->pixmap) From ff4526cba9f430daa31ecf0098e2ce7f0fbae3d2 Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Wed, 29 Oct 2014 13:31:42 +0100 Subject: [PATCH 33/76] Fix present_notify to return right away when querying current or past msc. When the target msc is past or is the current one, we want to get immediate feedback. This patch fixes this behaviour. Signed-off-by: Axel Davy Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 47566c74e1..a9f221418d 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -866,7 +866,7 @@ present_pixmap(WindowPtr window, xorg_list_add(&vblank->event_queue, &present_exec_queue); vblank->queued = TRUE; - if (target_msc >= crtc_msc) { + if ((pixmap && target_msc >= crtc_msc) || (!pixmap && target_msc > crtc_msc)) { ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); if (ret != Success) { xorg_list_del(&vblank->event_queue); @@ -929,7 +929,7 @@ present_notify_msc(WindowPtr window, 0, 0, NULL, NULL, NULL, - 0, + PresentOptionAsync, target_msc, divisor, remainder, NULL, 0); } From 1e727b469ccdf4d1926c3ee408da7d2ad74ee8a4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 31 Oct 2014 09:45:12 +1000 Subject: [PATCH 34/76] Drop trailing whitespaces sed -i "s/[ ]\+$//g" **/*.(c|h) happy reviewing... git diff -w is an empty diff. Signed-off-by: Peter Hutterer --- nx-X11/programs/Xserver/present/present.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index a9f221418d..ac9047edbd 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -91,7 +91,7 @@ present_flip_pending_pixmap(ScreenPtr screen) if (!screen_priv->flip_pending) return NULL; - + return screen_priv->flip_pending->pixmap; } @@ -372,7 +372,7 @@ present_set_tree_pixmap_visit(WindowPtr window, void *data) (*screen->SetWindowPixmap)(window, visit->new); return WT_WALKCHILDREN; } - + static void present_set_tree_pixmap(WindowPtr window, PixmapPtr pixmap) { From 59774fe701c05558c7207ecbd17649ef522682de Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Sat, 6 Dec 2014 05:40:07 +0100 Subject: [PATCH 35/76] present: Avoid crashes in DebugPresent(), a bit more info. DebugPresent() crashed the server when a dri3 drawable was closed while a pageflipped present was still pending, due to vblank->window-> Null-Ptr deref, so debug builds caused new problems to debug. E.g., glXSwapBuffers(...); glXDestroyWindow(...); -> Pageflip for non-existent window completes -> boom. Also often happens when switching desktop compositor on/off due to Present unflips, or when logging out of session. Also add info if a Present is queued for copyswap or pageflip, if the present is vsynced, and the serial no of the Present request, to aid debugging of pageflip and vsync issues. The serial number is useful as Mesa's dri3/present backend encodes its sendSBC in the serial number, so one can easily correlate server debug output with Mesa and with the SBC values returned to actual OpenGL client applications via OML_sync_control and INTEL_swap_events extension, makes debugging quite a bit more easy. Please also cherry-pick this for a 1.16.x stable update. Signed-off-by: Mario Kleiner Reviewed-by: Eric Anholt Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index ac9047edbd..e5d3fd5511 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -440,7 +440,7 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) DebugPresent(("\tn %lld %p %8lld: %08lx -> %08lx\n", vblank->event_id, vblank, vblank->target_msc, vblank->pixmap ? vblank->pixmap->drawable.id : 0, - vblank->window->drawable.id)); + vblank->window ? vblank->window->drawable.id : 0)); assert (vblank == screen_priv->flip_pending); @@ -859,10 +859,10 @@ present_pixmap(WindowPtr window, } if (pixmap) - DebugPresent(("q %lld %p %8lld: %08lx -> %08lx (crtc %p)\n", + DebugPresent(("q %lld %p %8lld: %08lx -> %08lx (crtc %p) flip %d vsync %d serial %d\n", vblank->event_id, vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, - target_crtc)); + target_crtc, vblank->flip, vblank->sync_flip, vblank->serial)); xorg_list_add(&vblank->event_queue, &present_exec_queue); vblank->queued = TRUE; @@ -955,7 +955,7 @@ present_vblank_destroy(present_vblank_ptr vblank) DebugPresent(("\td %lld %p %8lld: %08lx -> %08lx\n", vblank->event_id, vblank, vblank->target_msc, vblank->pixmap ? vblank->pixmap->drawable.id : 0, - vblank->window->drawable.id)); + vblank->window ? vblank->window->drawable.id : 0)); /* Drop pixmap reference */ if (vblank->pixmap) From bcc7de756b80ca426f40dfedf8f1c905fa5860bd Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Sat, 6 Dec 2014 05:40:08 +0100 Subject: [PATCH 36/76] present: Fix use of vsynced pageflips and honor PresentOptionAsync. (v4) Pageflips for Pixmap presents were not synchronized to vblank on drivers with support for PresentCapabilityAsync, due to some missing init for vblank->sync_flips. The PresentOptionAsync flag was completely ignored for pageflipped presents. Vsynced flips only worked by accident on the intel-ddx, as that driver doesn't have PresentCapabilityAsync support. On nouveau-ddx, which supports PresentCapabilityAsync, this always caused non-vsynced pageflips with pretty ugly tearing. This patch fixes the problem, as tested on top of XOrg 1.16.2 on nouveau and intel. v4: Add additional PresentCapabilityAsync caps check, as suggested by Eric Anholt. Please also apply to XOrg 1.17 and XOrg 1.16.2 stable. Applying on top of XOrg 1.16.2 requires cherry-picking commit 2051514652481a83bd7cf22e57cb0fcd40333f33 which trivially fixes lack of support for protocol option PresentOptionCopy - get two bug fixes for the price of one! Signed-off-by: Mario Kleiner Reviewed-by: Eric Anholt Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index e5d3fd5511..e27fe30ad4 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -834,10 +834,13 @@ present_pixmap(WindowPtr window, vblank->notifies = notifies; vblank->num_notifies = num_notifies; - if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync)) + if (!(options & PresentOptionAsync)) vblank->sync_flip = TRUE; if (!(options & PresentOptionCopy) && + !((options & PresentOptionAsync) && + (!screen_priv->info || + !(screen_priv->info->capabilities & PresentCapabilityAsync))) && pixmap != NULL && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) { From 23b6ac52acfca6a77efe350ab4099978b852d6bf Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 19:33:34 -0800 Subject: [PATCH 37/76] present: unvalidated lengths in Present extension procs [CVE-2014-8103 2/2] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer Reviewed-by: Julien Cristau --- nx-X11/programs/Xserver/present/present_request.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present_request.c b/nx-X11/programs/Xserver/present/present_request.c index 835890d28a..7c53e72623 100644 --- a/nx-X11/programs/Xserver/present/present_request.c +++ b/nx-X11/programs/Xserver/present/present_request.c @@ -210,6 +210,7 @@ proc_present_query_capabilities (ClientPtr client) RRCrtcPtr crtc = NULL; int r; + REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq); r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess); switch (r) { case Success: @@ -254,6 +255,7 @@ static int sproc_present_query_version(ClientPtr client) { REQUEST(xPresentQueryVersionReq); + REQUEST_SIZE_MATCH(xPresentQueryVersionReq); swaps(&stuff->length); swapl(&stuff->majorVersion); @@ -265,6 +267,7 @@ static int sproc_present_pixmap(ClientPtr client) { REQUEST(xPresentPixmapReq); + REQUEST_AT_LEAST_SIZE(xPresentPixmapReq); swaps(&stuff->length); swapl(&stuff->window); @@ -284,6 +287,7 @@ static int sproc_present_notify_msc(ClientPtr client) { REQUEST(xPresentNotifyMSCReq); + REQUEST_SIZE_MATCH(xPresentNotifyMSCReq); swaps(&stuff->length); swapl(&stuff->window); @@ -297,6 +301,7 @@ static int sproc_present_select_input (ClientPtr client) { REQUEST(xPresentSelectInputReq); + REQUEST_SIZE_MATCH(xPresentSelectInputReq); swaps(&stuff->length); swapl(&stuff->window); @@ -308,6 +313,7 @@ static int sproc_present_query_capabilities (ClientPtr client) { REQUEST(xPresentQueryCapabilitiesReq); + REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq); swaps(&stuff->length); swapl(&stuff->target); return (*proc_present_vector[stuff->presentReqType]) (client); From 5c33ce0e19eceebeb21ea0a38e682babbedb2a0e Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 18 Dec 2014 17:22:00 -0800 Subject: [PATCH 38/76] present: If present_queue_vblank() fails, do present_execute(). Previously, if present_queue_vblank() failed, we simply dropped the present request on the floor, and returned an error. This was rather mean to clients - after presenting, they wait for a PresentComplete event to come back. But since the present never happens, they end up waiting forever, and lock up in poll(). This patch falls back to present_execute if present_queue_vblank fails. We still print a debugging message to warn when queueing fails, which allows us to continue debugging problems, but makes Present robust enough to not lock up people's compositing manager when vblank bugs happen. v2: Don't do present_queue_vblank() /and/ present_execute() (a bug that snuck in during last minute tidying). Signed-off-by: Kenneth Graunke Reviewed-by: Keith Packard Tested-by: Jason Ekstrand Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index e27fe30ad4..2a705a9687 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -871,19 +871,18 @@ present_pixmap(WindowPtr window, vblank->queued = TRUE; if ((pixmap && target_msc >= crtc_msc) || (!pixmap && target_msc > crtc_msc)) { ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); - if (ret != Success) { - xorg_list_del(&vblank->event_queue); - vblank->queued = FALSE; - goto failure; - } - } else - present_execute(vblank, ust, crtc_msc); + if (ret == Success) + return Success; + + DebugPresent(("present_queue_vblank failed\n")); + } + + present_execute(vblank, ust, crtc_msc); return Success; no_mem: ret = BadAlloc; -failure: vblank->notifies = NULL; present_vblank_destroy(vblank); return ret; From 314115e1d0339e72ee40db6a8b00f3f770703665 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Feb 2015 08:25:42 +0000 Subject: [PATCH 39/76] present: Copy unflip contents back to the Screen Pixmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we unflip after the flip Window no longer passes the pixel ownership test for the full Screen Pixmap, we can no longer utilize that Window to copy the contents back to the backing pixmap. To first flip means that the Window was originally backed by the Screen Pixmap and wholly covered the Pixmap, thus we need to copy the last frame contents to the Screen Pixmap when the flip chain is complete. Signed-off-by: Chris Wilson Reviewed-and-Tested-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 2a705a9687..a6346015ef 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -409,20 +409,20 @@ static void present_unflip(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); + PixmapPtr pixmap = (*screen->GetScreenPixmap)(screen); assert (!screen_priv->unflip_event_id); assert (!screen_priv->flip_pending); if (screen_priv->flip_window) - present_set_tree_pixmap(screen_priv->flip_window, - (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(screen_priv->flip_window, pixmap); - present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(screen->root, pixmap); /* Update the screen pixmap with the current flip pixmap contents */ if (screen_priv->flip_pixmap && screen_priv->flip_window) { - present_copy_region(&screen_priv->flip_window->drawable, + present_copy_region(&pixmap->drawable, screen_priv->flip_pixmap, NULL, 0, 0); } From f02f29eb5c679865f0511ed047c90ee11257d178 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 22 Oct 2014 10:31:29 -0400 Subject: [PATCH 40/76] present: static cleanup Reviewed-by: Alex Deucher Signed-off-by: Adam Jackson --- nx-X11/programs/Xserver/present/present_event.c | 2 +- nx-X11/programs/Xserver/present/present_priv.h | 2 -- nx-X11/programs/Xserver/present/present_request.c | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present_event.c b/nx-X11/programs/Xserver/present/present_event.c index d3a59ea25b..c586c9a60f 100644 --- a/nx-X11/programs/Xserver/present/present_event.c +++ b/nx-X11/programs/Xserver/present/present_event.c @@ -26,7 +26,7 @@ #include "present_priv.h" -RESTYPE present_event_type; +static RESTYPE present_event_type; static int present_free_event(void *data, XID id) diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index f5c1652d1c..996292e948 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -147,8 +147,6 @@ present_window_priv(WindowPtr window) present_window_priv_ptr present_get_window_priv(WindowPtr window, Bool create); -extern RESTYPE present_event_type; - /* * present.c */ diff --git a/nx-X11/programs/Xserver/present/present_request.c b/nx-X11/programs/Xserver/present/present_request.c index 7c53e72623..35320b64ef 100644 --- a/nx-X11/programs/Xserver/present/present_request.c +++ b/nx-X11/programs/Xserver/present/present_request.c @@ -234,7 +234,7 @@ proc_present_query_capabilities (ClientPtr client) return Success; } -int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = { +static int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = { proc_present_query_version, /* 0 */ proc_present_pixmap, /* 1 */ proc_present_notify_msc, /* 2 */ @@ -319,7 +319,7 @@ sproc_present_query_capabilities (ClientPtr client) return (*proc_present_vector[stuff->presentReqType]) (client); } -int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = { +static int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = { sproc_present_query_version, /* 0 */ sproc_present_pixmap, /* 1 */ sproc_present_notify_msc, /* 2 */ From 33c1d62b18b9d0fe88d85999b132a56fae60cd33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Thu, 10 Sep 2015 23:33:20 +0200 Subject: [PATCH 41/76] present: Don't stash the MSC value when present_get_ust_msc fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we stash an uninitalized value, and later use it to compute the msc_offset for the window. Also initialize ust and crtc_msc so we never use uninitalized values when present_get_ust_msc fails. This fixes clients getting stuck waiting indefinitely for an idle event when a CRTC is turned off. Signed-off-by: Fredrik Höglund Reviewed-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index a6346015ef..7ddffbd282 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -710,9 +710,9 @@ present_pixmap(WindowPtr window, present_notify_ptr notifies, int num_notifies) { - uint64_t ust; + uint64_t ust = 0; uint64_t target_msc; - uint64_t crtc_msc; + uint64_t crtc_msc = 0; int ret; present_vblank_ptr vblank, tmp; ScreenPtr screen = window->drawable.pScreen; @@ -734,13 +734,15 @@ present_pixmap(WindowPtr window, target_crtc = present_get_crtc(window); } - present_get_ust_msc(screen, target_crtc, &ust, &crtc_msc); + ret = present_get_ust_msc(screen, target_crtc, &ust, &crtc_msc); target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc); - /* Stash the current MSC away in case we need it later - */ - window_priv->msc = crtc_msc; + if (ret == Success) { + /* Stash the current MSC away in case we need it later + */ + window_priv->msc = crtc_msc; + } /* Adjust target_msc to match modulus */ From 0f2b6ab27e4c35e6cceca5d26fe28e0490377e43 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Feb 2015 09:49:18 +0000 Subject: [PATCH 42/76] present: Fix missed notify MSC computation Only treat divisor==0 as async to immediately report the actual vblank. If the user species a non-zero divisor, we should compute the missed vblank properly or else we report too early. Signed-off-by: Chris Wilson Reviewed-by: Mario Kleiner --- nx-X11/programs/Xserver/present/present.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 7ddffbd282..beb4ff03ab 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -933,7 +933,7 @@ present_notify_msc(WindowPtr window, 0, 0, NULL, NULL, NULL, - PresentOptionAsync, + divisor == 0 ? PresentOptionAsync : 0, target_msc, divisor, remainder, NULL, 0); } From 26f9a9c9fa38dd1fead19f30aaf0dad84d9ae59e Mon Sep 17 00:00:00 2001 From: Jammy Zhou Date: Wed, 28 Oct 2015 18:39:10 +0800 Subject: [PATCH 43/76] present: Execute right away if target_msc equals current_msc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is according to the protocol: "If 'options' contains PresentOptionAsync, and the 'target-msc' is less than or equal to the current msc for 'window', then the operation will be performed as soon as possible, not necessarily waiting for the next vertical blank interval." Signed-off-by: Jammy Zhou Reviewed-by: Michel Dänzer Reviewed-by: Axel Davy --- nx-X11/programs/Xserver/present/present.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index beb4ff03ab..5900c22890 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -871,7 +871,7 @@ present_pixmap(WindowPtr window, xorg_list_add(&vblank->event_queue, &present_exec_queue); vblank->queued = TRUE; - if ((pixmap && target_msc >= crtc_msc) || (!pixmap && target_msc > crtc_msc)) { + if (target_msc > crtc_msc) { ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); if (ret == Success) return Success; From e937aa8bb929411d2ea6dd41333661fbcf2deb3b Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Wed, 4 Nov 2015 18:42:42 +0100 Subject: [PATCH 44/76] present: Fix Async swap logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the spec, PresentOptionAsync should only trigger a different behaviour when the target msc has been reached. In this case if the driver is able to do async swaps, we use them to avoid a screen copy. When the target msc hasn't been reached yet, we want to use sync swaps. v2: Fix indentation and simplify checks for Async flips Signed-off-by: Axel Davy Reviewed-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 25 ++++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 5900c22890..beb01dcbd2 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -836,19 +836,20 @@ present_pixmap(WindowPtr window, vblank->notifies = notifies; vblank->num_notifies = num_notifies; - if (!(options & PresentOptionAsync)) - vblank->sync_flip = TRUE; - - if (!(options & PresentOptionCopy) && - !((options & PresentOptionAsync) && - (!screen_priv->info || - !(screen_priv->info->capabilities & PresentCapabilityAsync))) && - pixmap != NULL && - present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) - { - vblank->flip = TRUE; - if (vblank->sync_flip) + if (pixmap != NULL && + !(options & PresentOptionCopy) && + screen_priv->info) { + if (target_msc > crtc_msc && + present_check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off)) + { + vblank->flip = TRUE; + vblank->sync_flip = TRUE; target_msc--; + } else if ((screen_priv->info->capabilities & PresentCapabilityAsync) && + present_check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off)) + { + vblank->flip = TRUE; + } } if (wait_fence) { From 2a3b076c482e0408904c3f21b22417ae6124e05c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Feb 2015 09:47:40 +0000 Subject: [PATCH 45/76] present: Requery pending flips with the right sync_flip mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When verifying whether a pending flip is still valid, we need to pass down the orignal sync_flip mode (e.g. if the driver only supports sync flips, verifying a async flip will falsely fail). Signed-off-by: Chris Wilson Reviewed-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 5 +++-- nx-X11/programs/Xserver/present/present_priv.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index beb01dcbd2..7af6bb7b86 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -453,6 +453,7 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) screen_priv->flip_window = vblank->window; screen_priv->flip_serial = vblank->serial; screen_priv->flip_pixmap = vblank->pixmap; + screen_priv->flip_sync = vblank->sync_flip; screen_priv->flip_idle_fence = vblank->idle_fence; vblank->pixmap = NULL; @@ -541,14 +542,14 @@ present_check_flip_window (WindowPtr window) * Check current flip */ if (window == screen_priv->flip_window) { - if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0)) + if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, screen_priv->flip_sync, NULL, 0, 0)) present_unflip(screen); } } /* Now check any queued vblanks */ xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { - if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0)) + if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, vblank->sync_flip, NULL, 0, 0)) vblank->flip = FALSE; } } diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index 996292e948..d007fdb240 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -93,6 +93,7 @@ typedef struct present_screen_priv { uint32_t flip_serial; PixmapPtr flip_pixmap; present_fence_ptr flip_idle_fence; + Bool flip_sync; present_screen_info_ptr info; } present_screen_priv_rec, *present_screen_priv_ptr; From 66933d077998faa1767fdbf9bd28c29ed2c01150 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Feb 2015 09:47:41 +0000 Subject: [PATCH 46/76] present: When cancelling a pending synchronous flip, requeue it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vblank event request for a synchronous flip is scheduled for the vblank before the target flip msc (so that the flip itself appears at the right frame). If we cancel that flip and so wish to schedule a copy instead, that copy needs to be postponed by a frame in order for it be performed at the requested time. Signed-off-by: Chris Wilson Reviewed-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 16 +++++++++++++++- nx-X11/programs/Xserver/present/present_priv.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 7af6bb7b86..c55a56e7cf 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -549,8 +549,13 @@ present_check_flip_window (WindowPtr window) /* Now check any queued vblanks */ xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { - if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, vblank->sync_flip, NULL, 0, 0)) + if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, vblank->sync_flip, NULL, 0, 0)) { vblank->flip = FALSE; + if (vblank->sync_flip) { + vblank->requeue = TRUE; + vblank->target_msc++; + } + } } } @@ -584,6 +589,15 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_screen_priv_ptr screen_priv = present_screen_priv(screen); uint8_t mode; + if (vblank->requeue) { + vblank->requeue = FALSE; + if (Success == present_queue_vblank(screen, + vblank->crtc, + vblank->event_id, + vblank->target_msc)) + return; + } + if (vblank->wait_fence) { if (!present_fence_check_triggered(vblank->wait_fence)) { present_fence_set_callback(vblank->wait_fence, present_wait_fence_triggered, vblank); diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index d007fdb240..0d16cfabad 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -70,6 +70,7 @@ struct present_vblank { present_notify_ptr notifies; int num_notifies; Bool queued; /* on present_exec_queue */ + Bool requeue; /* on queue, but target_msc has changed */ Bool flip; /* planning on using flip */ Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */ Bool sync_flip; /* do flip synchronous to vblank */ From 9727a19f023597234d26aa56e5402a14d4f3e199 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Feb 2015 09:47:42 +0000 Subject: [PATCH 47/76] present: Do not replace Pixmaps on redirected Window on unflip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When unflipping, we may find that our flip window has been redirected. If we replace the redirected Window with the Screen Pixmap we then have mutliple fullscreen Windows believing that their own the Screen Pixmap - multiple fullscreen Windows that are being flipped by Clients, and so continue to flip causing popping between e.g. the compositor and the game. [ajax: Fix up present_execute() hunk to account for changes introduced in fe07ec19e212a68076560d243a2a935c54589068] Signed-off-by: Chris Wilson Reviewed-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 28 +++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index c55a56e7cf..66e0f21b31 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -374,12 +374,17 @@ present_set_tree_pixmap_visit(WindowPtr window, void *data) } static void -present_set_tree_pixmap(WindowPtr window, PixmapPtr pixmap) +present_set_tree_pixmap(WindowPtr window, + PixmapPtr expected, + PixmapPtr pixmap) { struct pixmap_visit visit; ScreenPtr screen = window->drawable.pScreen; visit.old = (*screen->GetWindowPixmap)(window); + if (expected && visit.old != expected) + return; + visit.new = pixmap; if (visit.old == visit.new) return; @@ -390,6 +395,7 @@ static void present_set_abort_flip(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); + PixmapPtr pixmap = (*screen->GetScreenPixmap)(screen); /* Switch back to using the screen pixmap now to avoid * 2D applications drawing to the wrong pixmap. @@ -397,10 +403,11 @@ present_set_abort_flip(ScreenPtr screen) if (screen_priv->flip_window) present_set_tree_pixmap(screen_priv->flip_window, - (*screen->GetScreenPixmap)(screen)); + screen_priv->flip_pixmap, + pixmap); if (screen->root) - present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(screen->root, NULL, pixmap); screen_priv->flip_pending->abort_flip = TRUE; } @@ -414,10 +421,12 @@ present_unflip(ScreenPtr screen) assert (!screen_priv->unflip_event_id); assert (!screen_priv->flip_pending); - if (screen_priv->flip_window) - present_set_tree_pixmap(screen_priv->flip_window, pixmap); + if (screen_priv->flip_pixmap && screen_priv->flip_window) + present_set_tree_pixmap(screen_priv->flip_window, + screen_priv->flip_pixmap, + pixmap); - present_set_tree_pixmap(screen->root, pixmap); + present_set_tree_pixmap(screen->root, NULL, pixmap); /* Update the screen pixmap with the current flip pixmap contents */ @@ -644,9 +653,10 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) */ if (screen_priv->flip_window && screen_priv->flip_window != window) present_set_tree_pixmap(screen_priv->flip_window, - (*screen->GetScreenPixmap)(screen)); - present_set_tree_pixmap(vblank->window, vblank->pixmap); - present_set_tree_pixmap(screen->root, vblank->pixmap); + screen_priv->flip_pixmap, + (*screen->GetScreenPixmap)(screen)); + present_set_tree_pixmap(vblank->window, NULL, vblank->pixmap); + present_set_tree_pixmap(screen->root, NULL, vblank->pixmap); /* Report update region as damaged */ From e9dd837656b9f116627c836324b8207a78c827f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 15 Jan 2016 18:22:21 +0900 Subject: [PATCH 48/76] present: Handle wraparound when comparing MSC values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a window moves from one CRTC to another, present_window_to_crtc_msc updates window_priv->msc_offset according to the delta between the current MSC values of the old and new CRTC: window_priv->msc_offset += new_msc - old_msc; window_priv->msc_offset is initially 0, so if new_msc < old_msc, window_priv->msc_offset wraps around and becomes a large number. If the window_msc parameter passed in is small (in particular if it's 0, such as is the case when the client just wants to know the current window MSC value), the returned CRTC MSC value may still be a large number. In that case, the existing MSC comparisons in pixmap_present weren't working as intended, resulting in scheduling a wait far into the future when the target MSC had actually already passed. This would result in the client (e.g. the Chromium browser) hanging when moving its window between CRTCs. In order to fix this, introduce msc_is_(equal_or_)after helper functions which take the wraparound into account for comparing two MSC values. Signed-off-by: Michel Dänzer Reviewed-by: Keith Packard Reviewed-by: Martin Peres Signed-off-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 32 +++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 66e0f21b31..8cf3b6f773 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -717,6 +717,28 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_vblank_destroy(vblank); } +/* + * Returns: + * TRUE if the first MSC value is after the second one + * FALSE if the first MSC value is equal to or before the second one + */ +static Bool +msc_is_after(uint64_t test, uint64_t reference) +{ + return (int64_t)(test - reference) > 0; +} + +/* + * Returns: + * TRUE if the first MSC value is equal to or after the second one + * FALSE if the first MSC value is before the second one + */ +static Bool +msc_is_equal_or_after(uint64_t test, uint64_t reference) +{ + return (int64_t)(test - reference) >= 0; +} + int present_pixmap(WindowPtr window, PixmapPtr pixmap, @@ -771,14 +793,14 @@ present_pixmap(WindowPtr window, /* Adjust target_msc to match modulus */ - if (crtc_msc >= target_msc) { + if (msc_is_equal_or_after(crtc_msc, target_msc)) { if (divisor != 0) { target_msc = crtc_msc - (crtc_msc % divisor) + remainder; if (options & PresentOptionAsync) { - if (target_msc < crtc_msc) + if (msc_is_after(crtc_msc, target_msc)) target_msc += divisor; } else { - if (target_msc <= crtc_msc) + if (msc_is_equal_or_after(crtc_msc, target_msc)) target_msc += divisor; } } else { @@ -864,7 +886,7 @@ present_pixmap(WindowPtr window, if (pixmap != NULL && !(options & PresentOptionCopy) && screen_priv->info) { - if (target_msc > crtc_msc && + if (msc_is_after(target_msc, crtc_msc) && present_check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off)) { vblank->flip = TRUE; @@ -897,7 +919,7 @@ present_pixmap(WindowPtr window, xorg_list_add(&vblank->event_queue, &present_exec_queue); vblank->queued = TRUE; - if (target_msc > crtc_msc) { + if (msc_is_after(target_msc, crtc_msc)) { ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); if (ret == Success) return Success; From 15924176b620183b58a18ba1e1d0ef33f0f5dd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 24 Feb 2016 16:52:57 +0900 Subject: [PATCH 49/76] present: Move msc_is_(equal_or_)after to the top of present.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make them usable from any other function in the file. No functional change. Reviewed-by: Chris Wilson Signed-off-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 44 +++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 8cf3b6f773..17ec52632f 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -45,6 +45,28 @@ static struct xorg_list present_flip_queue; static void present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); +/* + * Returns: + * TRUE if the first MSC value is after the second one + * FALSE if the first MSC value is equal to or before the second one + */ +static Bool +msc_is_after(uint64_t test, uint64_t reference) +{ + return (int64_t)(test - reference) > 0; +} + +/* + * Returns: + * TRUE if the first MSC value is equal to or after the second one + * FALSE if the first MSC value is before the second one + */ +static Bool +msc_is_equal_or_after(uint64_t test, uint64_t reference) +{ + return (int64_t)(test - reference) >= 0; +} + /* * Copies the update region from a pixmap to the target drawable */ @@ -717,28 +739,6 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) present_vblank_destroy(vblank); } -/* - * Returns: - * TRUE if the first MSC value is after the second one - * FALSE if the first MSC value is equal to or before the second one - */ -static Bool -msc_is_after(uint64_t test, uint64_t reference) -{ - return (int64_t)(test - reference) > 0; -} - -/* - * Returns: - * TRUE if the first MSC value is equal to or after the second one - * FALSE if the first MSC value is before the second one - */ -static Bool -msc_is_equal_or_after(uint64_t test, uint64_t reference) -{ - return (int64_t)(test - reference) >= 0; -} - int present_pixmap(WindowPtr window, PixmapPtr pixmap, From d2e42592aa8e2a27cfba2ed076466b92811d8c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 24 Feb 2016 16:52:58 +0900 Subject: [PATCH 50/76] present: Requeue if flip driver hook fails and target MSC not reached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For flipping, we wait for the MSC before the target MSC and then call the driver flip hook. If the latter fails, we have to wait for the target MSC before falling back to a copy, or else it's executed too early. Fixes glxgears running at unbounded framerate (not synchronized to the refresh rate) in fullscreen if the driver flip hook fails. Reviewed-by: Chris Wilson Signed-off-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 17ec52632f..7f9fc17c36 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -712,6 +712,20 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) if (window == screen_priv->flip_window) present_unflip(screen); } + + /* If present_flip failed, we may have to requeue for the target MSC */ + if (msc_is_after(vblank->target_msc, crtc_msc) && + Success == present_queue_vblank(screen, + vblank->crtc, + vblank->event_id, + vblank->target_msc)) { + xorg_list_add(&vblank->event_queue, &present_exec_queue); + xorg_list_append(&vblank->window_list, + &present_get_window_priv(window, TRUE)->vblank); + vblank->queued = TRUE; + return; + } + present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off); /* present_copy_region sticks the region into a scratch GC, From ad5b38987136b24d9801693425bf62c544eceab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 24 Feb 2016 16:52:59 +0900 Subject: [PATCH 51/76] present: Only requeue if target MSC is not reached after an unflip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While present_pixmap decrements target_msc by 1 for present_queue_vblank, it leaves the original vblank->target_msc intact. So incrementing the latter for requeueing resulted in the requeued presentation being executed too late. Also, no need to requeue if the target MSC is already reached. This further reduces stutter when a popup menu appears on top of a flipping fullscreen window. Reviewed-by: Chris Wilson Signed-off-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 7f9fc17c36..62865be69c 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -582,10 +582,8 @@ present_check_flip_window (WindowPtr window) xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { if (vblank->queued && vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, vblank->sync_flip, NULL, 0, 0)) { vblank->flip = FALSE; - if (vblank->sync_flip) { + if (vblank->sync_flip) vblank->requeue = TRUE; - vblank->target_msc++; - } } } } @@ -622,7 +620,8 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) if (vblank->requeue) { vblank->requeue = FALSE; - if (Success == present_queue_vblank(screen, + if (msc_is_after(vblank->target_msc, crtc_msc) && + Success == present_queue_vblank(screen, vblank->crtc, vblank->event_id, vblank->target_msc)) From 33b593f1031ebe3de7446546004402905eb7661f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 18 Feb 2016 18:23:47 +0900 Subject: [PATCH 52/76] present: Only update screen pixmap from flip pixmap once per unflip present_unflip may be called several times from present_check_flip_window during the same unflip. We can only copy to the screen pixmap the first time, otherwise we may scribble over other windows. The flip pixmap contents don't get updated after the first time anyway. Fixes at least the following problems, which were introduced by commit 806470b9 ("present: Copy unflip contents back to the Screen Pixmap"): On xfwm4 without compositing, run glxgears and put its window into fullscreen mode to start flipping. While in fullscreen, open the xfwm4 window menu by pressing Alt-Space. The window menu was invisible most of the time because it was getting scribbled over by a repeated unflip copy. When switching a flipping window out of fullscreen, a repeated unflip copy could leave artifacts of the flip pixmap on the desktop. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94325 Reviewed-by: Keith Packard Reviewed-by: Chris Wilson --- nx-X11/programs/Xserver/present/present.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 62865be69c..a9241d2780 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -443,6 +443,15 @@ present_unflip(ScreenPtr screen) assert (!screen_priv->unflip_event_id); assert (!screen_priv->flip_pending); + /* Update the screen pixmap with the current flip pixmap contents + * Only do this the first time for a particular unflip operation, or + * we'll probably scribble over other windows + */ + if (screen->GetWindowPixmap(screen->root) == screen_priv->flip_pixmap) { + present_copy_region(&pixmap->drawable, screen_priv->flip_pixmap, + NULL, 0, 0); + } + if (screen_priv->flip_pixmap && screen_priv->flip_window) present_set_tree_pixmap(screen_priv->flip_window, screen_priv->flip_pixmap, @@ -450,13 +459,6 @@ present_unflip(ScreenPtr screen) present_set_tree_pixmap(screen->root, NULL, pixmap); - /* Update the screen pixmap with the current flip pixmap contents - */ - if (screen_priv->flip_pixmap && screen_priv->flip_window) { - present_copy_region(&pixmap->drawable, - screen_priv->flip_pixmap, - NULL, 0, 0); - } screen_priv->unflip_event_id = ++present_event_id; DebugPresent(("u %lld\n", screen_priv->unflip_event_id)); (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id); From 8f67145f7c0a36f7cf66e4b5341a852657e55b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 18 Feb 2016 17:20:45 +0900 Subject: [PATCH 53/76] present: Factor code for restoring screen pixmap out of present_unflip (v2) The following fix will use the refactored function. The logic in the refactored function is slightly simplified, exploiting the fact that this function is only ever called with a valid flip pixmap. v2: Assert that flip_pixmap is non-NULL instead of testing and bailing on NULL, preserve test for flip_window being non-NULL before calling present_set_tree_pixmap for it (Keith Packard) Reviewed-by: Chris Wilson (v1) Reviewed-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 39 +++++++++++++---------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index a9241d2780..ffb7a4a67f 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -413,6 +413,28 @@ present_set_tree_pixmap(WindowPtr window, TraverseTree(window, present_set_tree_pixmap_visit, &visit); } +static void +present_restore_screen_pixmap(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + PixmapPtr screen_pixmap = (*screen->GetScreenPixmap)(screen); + PixmapPtr flip_pixmap = screen_priv->flip_pixmap; + WindowPtr flip_window = screen_priv->flip_window; + + assert (flip_pixmap); + + /* Update the screen pixmap with the current flip pixmap contents + * Only do this the first time for a particular unflip operation, or + * we'll probably scribble over other windows + */ + if (screen->GetWindowPixmap(screen->root) == flip_pixmap) + present_copy_region(&screen_pixmap->drawable, flip_pixmap, NULL, 0, 0); + + if (flip_window) + present_set_tree_pixmap(flip_window, flip_pixmap, screen_pixmap); + present_set_tree_pixmap(screen->root, NULL, screen_pixmap); +} + static void present_set_abort_flip(ScreenPtr screen) { @@ -438,26 +460,11 @@ static void present_unflip(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); - PixmapPtr pixmap = (*screen->GetScreenPixmap)(screen); assert (!screen_priv->unflip_event_id); assert (!screen_priv->flip_pending); - /* Update the screen pixmap with the current flip pixmap contents - * Only do this the first time for a particular unflip operation, or - * we'll probably scribble over other windows - */ - if (screen->GetWindowPixmap(screen->root) == screen_priv->flip_pixmap) { - present_copy_region(&pixmap->drawable, screen_priv->flip_pixmap, - NULL, 0, 0); - } - - if (screen_priv->flip_pixmap && screen_priv->flip_window) - present_set_tree_pixmap(screen_priv->flip_window, - screen_priv->flip_pixmap, - pixmap); - - present_set_tree_pixmap(screen->root, NULL, pixmap); + present_restore_screen_pixmap(screen); screen_priv->unflip_event_id = ++present_event_id; DebugPresent(("u %lld\n", screen_priv->unflip_event_id)); From 718a01d5d4ec3b301a4a7c8bcfd6f1667850dc28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 18 Feb 2016 17:33:19 +0900 Subject: [PATCH 54/76] present: Call present_restore_screen_pixmap from present_set_abort_flip After present_set_abort_flip, the screen pixmap will be used for all screen drawing, so we need to restore the current flip pixmap contents to the screen pixmap here as well. Improves flashing / stutter e.g. when something like a popup menu appears on top of a flipping fullscreen window or when switching out of fullscreen. Note that this means present_set_abort_flip now relies on screen->root being non-NULL, but that's already the case in other present code. Reviewed-by: Keith Packard Reviewed-by: Chris Wilson --- nx-X11/programs/Xserver/present/present.c | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index ffb7a4a67f..1ce16afab3 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -418,8 +418,16 @@ present_restore_screen_pixmap(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); PixmapPtr screen_pixmap = (*screen->GetScreenPixmap)(screen); - PixmapPtr flip_pixmap = screen_priv->flip_pixmap; - WindowPtr flip_window = screen_priv->flip_window; + PixmapPtr flip_pixmap; + WindowPtr flip_window; + + if (screen_priv->flip_pending) { + flip_window = screen_priv->flip_pending->window; + flip_pixmap = screen_priv->flip_pending->pixmap; + } else { + flip_window = screen_priv->flip_window; + flip_pixmap = screen_priv->flip_pixmap; + } assert (flip_pixmap); @@ -430,6 +438,9 @@ present_restore_screen_pixmap(ScreenPtr screen) if (screen->GetWindowPixmap(screen->root) == flip_pixmap) present_copy_region(&screen_pixmap->drawable, flip_pixmap, NULL, 0, 0); + /* Switch back to using the screen pixmap now to avoid + * 2D applications drawing to the wrong pixmap. + */ if (flip_window) present_set_tree_pixmap(flip_window, flip_pixmap, screen_pixmap); present_set_tree_pixmap(screen->root, NULL, screen_pixmap); @@ -439,19 +450,8 @@ static void present_set_abort_flip(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); - PixmapPtr pixmap = (*screen->GetScreenPixmap)(screen); - /* Switch back to using the screen pixmap now to avoid - * 2D applications drawing to the wrong pixmap. - */ - - if (screen_priv->flip_window) - present_set_tree_pixmap(screen_priv->flip_window, - screen_priv->flip_pixmap, - pixmap); - - if (screen->root) - present_set_tree_pixmap(screen->root, NULL, pixmap); + present_restore_screen_pixmap(screen); screen_priv->flip_pending->abort_flip = TRUE; } From ca26ebb8412be7a2087047b71b0996ab5df7c235 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 9 Feb 2016 16:54:22 +1000 Subject: [PATCH 55/76] present: fail flipping if we have any slave outputs Due to the way present currently works, we don't ever check with the secondary adapters if we can flip at all. We shouldn't flip if the secondary adapters are attached to the pixmap currently, however using the current check_flip callback isn't possible as it passes the Window to the driver (something we shouldn't be doing), so the slave driver can never get it's own screen ptr back. For now to fix the problem just block flips if we have any slaves configured. We can fix the ABI up later, but this fix can be backported to stable. Signed-off-by: Dave Airlie Reviewed-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 1ce16afab3..55f6aa7b1d 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -144,6 +144,10 @@ present_check_flip(RRCrtcPtr crtc, if (!screen_priv->info->flip) return FALSE; + /* Fail to flip if we have slave outputs */ + if (!xorg_list_is_empty(&screen->output_slave_list)) + return FALSE; + /* Make sure the window hasn't been redirected with Composite */ window_pixmap = screen->GetWindowPixmap(window); if (window_pixmap != screen->GetScreenPixmap(screen) && From 07b952df4e9fd4859e2ea86150f645c470180451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 24 Mar 2016 17:42:47 +0900 Subject: [PATCH 56/76] present: Only requeue for next MSC after flip failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code was added to deal with the driver present hook failing, in which case we need to wait for the next MSC before executing the presentation. However, it could also take effect in cases where the driver incorrectly thinks the current MSC matches the target one (e.g. due to the kernel interface only supporting 32-bit MSC values), in which case it could result in the presentation getting requeued over and over. To prevent such issues, check specifically for the target MSC immediately following the current MSC. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94596 Signed-off-by: Michel Dänzer Reviewed-by: Keith Packard --- nx-X11/programs/Xserver/present/present.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 55f6aa7b1d..105e2bf47d 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -726,7 +726,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) } /* If present_flip failed, we may have to requeue for the target MSC */ - if (msc_is_after(vblank->target_msc, crtc_msc) && + if (vblank->target_msc == crtc_msc + 1 && Success == present_queue_vblank(screen, vblank->crtc, vblank->event_id, From 61832d8730ec5de37470df474b760385f1453709 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 14 Feb 2015 09:58:43 +0000 Subject: [PATCH 57/76] present: Improve scaling of vblank handler With large numbers of queued vblank, the list iteration on every interupt dominates processing time. If we reorder the list to be in ascending event order, then not only is also likely to be in order for notification queries (i.e. the notification will be near the start of the list), we can also stop iterating when past the target event_id. Signed-off-by: Chris Wilson Reviewed-and-tested-by: Mario Kleiner Signed-off-by: Hans de Goede --- nx-X11/programs/Xserver/present/present.c | 24 ++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 105e2bf47d..2ae7d3a80d 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -517,19 +517,22 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) void present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) { - present_vblank_ptr vblank, tmp; + present_vblank_ptr vblank; int s; if (!event_id) return; DebugPresent(("\te %lld ust %lld msc %lld\n", event_id, ust, msc)); - xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { - if (vblank->event_id == event_id) { + xorg_list_for_each_entry(vblank, &present_exec_queue, event_queue) { + int64_t match = event_id - vblank->event_id; + if (match == 0) { present_execute(vblank, ust, msc); return; } + if (match < 0) + break; } - xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) { if (vblank->event_id == event_id) { present_flip_notify(vblank, ust, msc); return; @@ -943,7 +946,7 @@ present_pixmap(WindowPtr window, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc, vblank->flip, vblank->sync_flip, vblank->serial)); - xorg_list_add(&vblank->event_queue, &present_exec_queue); + xorg_list_append(&vblank->event_queue, &present_exec_queue); vblank->queued = TRUE; if (msc_is_after(target_msc, crtc_msc)) { ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); @@ -967,7 +970,7 @@ present_pixmap(WindowPtr window, void present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) { - present_vblank_ptr vblank, tmp; + present_vblank_ptr vblank; if (crtc == NULL) present_fake_abort_vblank(screen, event_id, msc); @@ -978,14 +981,17 @@ present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64 (*screen_priv->info->abort_vblank) (crtc, event_id, msc); } - xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { - if (vblank->event_id == event_id) { + xorg_list_for_each_entry(vblank, &present_exec_queue, event_queue) { + int64_t match = event_id - vblank->event_id; + if (match == 0) { xorg_list_del(&vblank->event_queue); vblank->queued = FALSE; return; } + if (match < 0) + break; } - xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) { if (vblank->event_id == event_id) { xorg_list_del(&vblank->event_queue); return; From 0b39411e8ae98d3333b6b1a47ccf28a527507702 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 14 Feb 2015 09:58:44 +0000 Subject: [PATCH 58/76] present: Fix presentation of flips out of order The flip queue currently only holds events submitted to the driver for flipping, awaiting the completion notifier. It is short. We therefore can speed up interrupt processing by keeping the small number of events ready to be flipped on the end of the flip queue. By appending the events to the flip_queue in the order that they become ready, we also resolve one issue causing Present to display frames out of order. Signed-off-by: Chris Wilson Reviewed-and-tested-by: Mario Kleiner Signed-off-by: Hans de Goede --- nx-X11/programs/Xserver/present/present.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 2ae7d3a80d..cebd2f786e 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -353,10 +353,10 @@ present_re_execute(present_vblank_ptr vblank) static void present_flip_try_ready(ScreenPtr screen) { - present_vblank_ptr vblank, tmp; + present_vblank_ptr vblank; - xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { - if (vblank->flip_ready) { + xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) { + if (vblank->queued) { present_re_execute(vblank); return; } @@ -656,6 +656,8 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) DebugPresent(("\tr %lld %p (pending %p unflip %lld)\n", vblank->event_id, vblank, screen_priv->flip_pending, screen_priv->unflip_event_id)); + xorg_list_del(&vblank->event_queue); + xorg_list_append(&vblank->event_queue, &present_flip_queue); vblank->flip_ready = TRUE; return; } @@ -994,6 +996,7 @@ present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64 xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) { if (vblank->event_id == event_id) { xorg_list_del(&vblank->event_queue); + vblank->queued = FALSE; return; } } From ec7ace97ac1271a8e7c7ea013940865b92f08f8f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 13 May 2016 15:58:10 +0200 Subject: [PATCH 59/76] xrandrprovider: Do not use separate lists for unbound / source / offload slaves A single provider can be both a offload and source slave at the same time, the use of seperate lists breaks in this case e.g. : xrandr --listproviders Providers: number : 2 Provider 0: id: 0x7b cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 2 associated providers: 0 name:modesetting Provider 1: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 0 name:modesetting xrandr --setprovideroutputsource 1 0x7b xrandr --listproviders Providers: number : 2 Provider 0: id: 0x7b cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 2 associated providers: 1 name:modesetting Provider 1: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 1 name:modesetting xrandr --setprovideroffloadsink 1 0x7b xrandr --listproviders Providers: number : 3 Provider 0: id: 0x7b cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 2 associated providers: 2 name:modesetting Provider 1: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 2 name:modesetting Provider 2: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 2 name:modesetting Not good. The problem is that the provider with id 0x46 now is on both the output_slave_list and the offload_slave_list of the master screen. This commit fixes this by unifying all 3 lists into a single slaves list. Note that this does change the struct _Screen definition, so this is an ABI break. I do not expect any of the drivers to actually use the removed / changed fields so a recompile should suffice. Signed-off-by: Hans de Goede Reviewed-by: Dave Airlie --- nx-X11/programs/Xserver/present/present.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index cebd2f786e..5210832876 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -145,7 +145,7 @@ present_check_flip(RRCrtcPtr crtc, return FALSE; /* Fail to flip if we have slave outputs */ - if (!xorg_list_is_empty(&screen->output_slave_list)) + if (screen->output_slaves) return FALSE; /* Make sure the window hasn't been redirected with Composite */ From a71a16c7a595161eaf790224e8b4e47130961797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 26 Jul 2016 17:28:33 +0900 Subject: [PATCH 60/76] present: Only call restore_screen_pixmap once from set_abort_flip present_restore_screen_pixmap's work doesn't need to be done several times for the same pending flip. Fixes a crash if the X server quits while a flip is pending, in which case present_set_abort_flip may be called several times, including when screen->root is already cleared to NULL. Reviewed-by: Hans de Goede --- nx-X11/programs/Xserver/present/present.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 5210832876..5fde846262 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -455,9 +455,10 @@ present_set_abort_flip(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); - present_restore_screen_pixmap(screen); - - screen_priv->flip_pending->abort_flip = TRUE; + if (!screen_priv->flip_pending->abort_flip) { + present_restore_screen_pixmap(screen); + screen_priv->flip_pending->abort_flip = TRUE; + } } static void From c5241764018d3b184297e4a858ccddeaabfe06e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 29 Jul 2016 18:41:06 +0900 Subject: [PATCH 61/76] present: Handle event mask updates as specified v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the Present extension specification: An event context is associated with a specific window; using an existing event context with a different window generates a Match error. If eventContext specifies an existing event context, then if eventMask is empty, PresentSelectInput deletes the specified context, otherwise the specified event context is changed to select a different set of events. If eventContext is an unused XID, then if eventMask is empty no operation is performed. Otherwise, a new event context is created selecting the specified events. Without this change, there's no way for a client to explicitly change or destroy an existing event mask entry. Trying to do so as specified above would just result in a protocol error. v2: (Keith Packard) * Use dixLookupResourceByType instead of walking window_priv->events * Return BadMatch if the existing event context is associated with a different window or client * Call LEGAL_NEW_RESOURCE again when creating a new event context * Drop invalid "leak fix" Signed-off-by: Michel Dänzer Signed-off-by: Keith Packard Reviewed-by: Keith Packard Reviewed-by: Kenneth Graunke --- .../programs/Xserver/present/present_event.c | 29 +++++++++++++++++-- .../Xserver/present/present_request.c | 2 -- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present_event.c b/nx-X11/programs/Xserver/present/present_event.c index c586c9a60f..c222dd5ffe 100644 --- a/nx-X11/programs/Xserver/present/present_event.c +++ b/nx-X11/programs/Xserver/present/present_event.c @@ -208,14 +208,37 @@ present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, stru int present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) { - present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0); + present_window_priv_ptr window_priv; present_event_ptr event; + int ret; + + /* Check to see if we're modifying an existing event selection */ + ret = dixLookupResourceByType((void **) &event, eid, present_event_type, + client, DixWriteAccess); + if (ret == Success) { + /* Match error for the wrong window; also don't modify some other + * client's event selection + */ + if (event->window != window || event->client != client) + return BadMatch; - if (!window_priv) { if (mask) - return BadAlloc; + event->mask = mask; + else + FreeResource(eid, RT_NONE); return Success; } + if (ret != BadValue) + return ret; + + if (mask == 0) + return Success; + + LEGAL_NEW_RESOURCE(eid, client); + + window_priv = present_get_window_priv(window, TRUE); + if (!window_priv) + return BadAlloc; event = calloc (1, sizeof (present_event_rec)); if (!event) diff --git a/nx-X11/programs/Xserver/present/present_request.c b/nx-X11/programs/Xserver/present/present_request.c index 35320b64ef..c7663fcc89 100644 --- a/nx-X11/programs/Xserver/present/present_request.c +++ b/nx-X11/programs/Xserver/present/present_request.c @@ -184,8 +184,6 @@ proc_present_select_input (ClientPtr client) REQUEST_SIZE_MATCH(xPresentSelectInputReq); - LEGAL_NEW_RESOURCE(stuff->eid, client); - rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); if (rc != Success) return rc; From c3f27bbce7e141731694cd561ca092bbfc540c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 3 Aug 2016 10:19:19 +0900 Subject: [PATCH 62/76] present: Make present_restore_screen_pixmap handle screen->root == NULL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Easier than dealing with it in all paths that can end up here during server shutdown. Signed-off-by: Michel Dänzer Reviewed-by: Hans de Goede --- nx-X11/programs/Xserver/present/present.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 5fde846262..8d37395fca 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -439,7 +439,7 @@ present_restore_screen_pixmap(ScreenPtr screen) * Only do this the first time for a particular unflip operation, or * we'll probably scribble over other windows */ - if (screen->GetWindowPixmap(screen->root) == flip_pixmap) + if (screen->root && screen->GetWindowPixmap(screen->root) == flip_pixmap) present_copy_region(&screen_pixmap->drawable, flip_pixmap, NULL, 0, 0); /* Switch back to using the screen pixmap now to avoid @@ -447,7 +447,8 @@ present_restore_screen_pixmap(ScreenPtr screen) */ if (flip_window) present_set_tree_pixmap(flip_window, flip_pixmap, screen_pixmap); - present_set_tree_pixmap(screen->root, NULL, screen_pixmap); + if (screen->root) + present_set_tree_pixmap(screen->root, NULL, screen_pixmap); } static void From 8ac0b53608b2bbaa43f12e7547c4414dca434ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 3 Aug 2016 10:19:20 +0900 Subject: [PATCH 63/76] present: Call set_abort_flip / restore_screen_pixmap in clear_window_flip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were asserting that these were called before from other places, but that isn't always the case, e.g. during server shutdown. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96951 Reported-and-Tested-by: Tod Jackson Reviewed-by: Hans de Goede Signed-off-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 4 ++-- nx-X11/programs/Xserver/present/present_priv.h | 6 ++++++ nx-X11/programs/Xserver/present/present_screen.c | 6 ++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index 8d37395fca..a7ca06e360 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -417,7 +417,7 @@ present_set_tree_pixmap(WindowPtr window, TraverseTree(window, present_set_tree_pixmap_visit, &visit); } -static void +void present_restore_screen_pixmap(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); @@ -451,7 +451,7 @@ present_restore_screen_pixmap(ScreenPtr screen) present_set_tree_pixmap(screen->root, NULL, screen_pixmap); } -static void +void present_set_abort_flip(ScreenPtr screen) { present_screen_priv_ptr screen_priv = present_screen_priv(screen); diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index 0d16cfabad..dfb4bdea9b 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -186,6 +186,12 @@ present_vblank_destroy(present_vblank_ptr vblank); void present_flip_destroy(ScreenPtr screen); +void +present_restore_screen_pixmap(ScreenPtr screen); + +void +present_set_abort_flip(ScreenPtr screen); + void present_check_flip_window(WindowPtr window); diff --git a/nx-X11/programs/Xserver/present/present_screen.c b/nx-X11/programs/Xserver/present/present_screen.c index 2f91ac7dc8..9d03c8aa4b 100644 --- a/nx-X11/programs/Xserver/present/present_screen.c +++ b/nx-X11/programs/Xserver/present/present_screen.c @@ -92,11 +92,13 @@ present_clear_window_flip(WindowPtr window) present_vblank_ptr flip_pending = screen_priv->flip_pending; if (flip_pending && flip_pending->window == window) { - assert (flip_pending->abort_flip); + present_set_abort_flip(screen); flip_pending->window = NULL; } - if (screen_priv->flip_window == window) + if (screen_priv->flip_window == window) { + present_restore_screen_pixmap(screen); screen_priv->flip_window = NULL; + } } /* From 73bca415a0229a221a74cbe5dfb05f8ec47b47eb Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Mon, 8 Aug 2016 17:25:35 +0200 Subject: [PATCH 64/76] present: Free the fake_present OsTimerPtr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plug a leak in present_fake_queue_vblank() where the OsTimer would not be freed. 492,608 (482,816 direct, 9,792 indirect) bytes in 15,088 blocks are definitely lost in loss record 3,954 of 3,954 at 0x4C2ABDE: malloc (in vgpreload_memcheck-amd64-linux.so) by 0x586B19: TimerSet (WaitFor.c:433) by 0x4F1AA9: present_fake_queue_vblank (present_fake.c:108) by 0x4F15E0: present_pixmap (present.c:954) by 0x4F23B4: proc_present_pixmap (present_request.c:138) by 0x552BCE: Dispatch (dispatch.c:430) by 0x556C22: dix_main (main.c:300) by 0x6F0D290: (below main) (in /usr/lib/libc-2.24.so) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97065 Signed-off-by: Olivier Fourdan Reviewed-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present_fake.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present_fake.c b/nx-X11/programs/Xserver/present/present_fake.c index 4985c81e33..2350638ead 100644 --- a/nx-X11/programs/Xserver/present/present_fake.c +++ b/nx-X11/programs/Xserver/present/present_fake.c @@ -64,6 +64,7 @@ present_fake_do_timer(OsTimerPtr timer, present_fake_notify(fake_vblank->screen, fake_vblank->event_id); xorg_list_del(&fake_vblank->list); + TimerFree(fake_vblank->timer); free(fake_vblank); return 0; } @@ -75,7 +76,7 @@ present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc) xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) { if (fake_vblank->event_id == event_id) { - TimerCancel(fake_vblank->timer); + TimerFree(fake_vblank->timer); /* TimerFree will call TimerCancel() */ xorg_list_del(&fake_vblank->list); free (fake_vblank); break; From 2440993a7aed99798e42fade2212c9c954840c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 25 Nov 2016 17:34:05 +0900 Subject: [PATCH 65/76] present: Only call present_flip_notify if vblank->queued == FALSE We are no longer using the present_flip_queue list only for presents which have already been submitted to the driver for page flipping, but also for those which we are queueing up to be flipped later, marked with vblank->queued == TRUE. We were incorrectly calling present_flip_notify for such entries, failing the assertion in present_flip_notify (or presumably resulting in other undesirable behaviour with assertions disabled). Reproduction recipe: Run the JavaFX test case referenced by https://bugs.freedesktop.org/show_bug.cgi?id=98831#c6 and alt-tab out of it while it's fullscreen. May take a few attempts to hit the assertion failure. Fixes: bab0f450a719 ("present: Fix presentation of flips out of order") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98854 Reviewed-by: Alex Deucher --- nx-X11/programs/Xserver/present/present.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index a7ca06e360..ef89045371 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -536,7 +536,10 @@ present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) } xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) { if (vblank->event_id == event_id) { - present_flip_notify(vblank, ust, msc); + if (vblank->queued) + present_execute(vblank, ust, msc); + else + present_flip_notify(vblank, ust, msc); return; } } From e47e29ecc64f09fc3f2b2ef84536f71e0f57fd9c Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 26 Jan 2017 18:13:53 +0800 Subject: [PATCH 66/76] present: disable page flip only when a slave crtc is active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prevents the tearing of moving window in a composite WM desktop when output slave is attached but none of its crtc is really active. Signed-off-by: Qiang Yu Reviewed-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index ef89045371..c9c68dcba2 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -117,6 +117,18 @@ present_flip_pending_pixmap(ScreenPtr screen) return screen_priv->flip_pending->pixmap; } +static Bool +present_check_output_slaves_active(ScreenPtr pScreen) +{ + ScreenPtr pSlave; + + xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) { + if (RRHasScanoutPixmap(pSlave)) + return TRUE; + } + return FALSE; +} + static Bool present_check_flip(RRCrtcPtr crtc, WindowPtr window, @@ -145,7 +157,7 @@ present_check_flip(RRCrtcPtr crtc, return FALSE; /* Fail to flip if we have slave outputs */ - if (screen->output_slaves) + if (screen->output_slaves && present_check_output_slaves_active(screen)) return FALSE; /* Make sure the window hasn't been redirected with Composite */ From dd60cdf4d8acf4eb61aa0c95dd4b09fbf9bbc096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 1 Feb 2017 18:35:57 +0900 Subject: [PATCH 67/76] present: Allow flipping with PRIME slave outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Works fine now. Reviewed-by: Alex Deucher Signed-off-by: Michel Dänzer --- nx-X11/programs/Xserver/present/present.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/nx-X11/programs/Xserver/present/present.c b/nx-X11/programs/Xserver/present/present.c index c9c68dcba2..aa9c041df0 100644 --- a/nx-X11/programs/Xserver/present/present.c +++ b/nx-X11/programs/Xserver/present/present.c @@ -117,18 +117,6 @@ present_flip_pending_pixmap(ScreenPtr screen) return screen_priv->flip_pending->pixmap; } -static Bool -present_check_output_slaves_active(ScreenPtr pScreen) -{ - ScreenPtr pSlave; - - xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) { - if (RRHasScanoutPixmap(pSlave)) - return TRUE; - } - return FALSE; -} - static Bool present_check_flip(RRCrtcPtr crtc, WindowPtr window, @@ -156,10 +144,6 @@ present_check_flip(RRCrtcPtr crtc, if (!screen_priv->info->flip) return FALSE; - /* Fail to flip if we have slave outputs */ - if (screen->output_slaves && present_check_output_slaves_active(screen)) - return FALSE; - /* Make sure the window hasn't been redirected with Composite */ window_pixmap = screen->GetWindowPixmap(window); if (window_pixmap != screen->GetScreenPixmap(screen) && From 0688d8b811718463bfd18716f733f1c640ca78a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Jul 2013 15:52:50 -0700 Subject: [PATCH 68/76] Initial Present protocol specification Signed-off-by: Keith Packard --- nx-X11/include/extensions/presentproto.h | 158 ++++++++++++++++++++++ nx-X11/include/extensions/presenttokens.h | 47 +++++++ 2 files changed, 205 insertions(+) create mode 100644 nx-X11/include/extensions/presentproto.h create mode 100644 nx-X11/include/extensions/presenttokens.h diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h new file mode 100644 index 0000000000..01fcb67523 --- /dev/null +++ b/nx-X11/include/extensions/presentproto.h @@ -0,0 +1,158 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENT_PROTO_H_ +#define _PRESENT_PROTO_H_ + +#include + +#define Region CARD32 +#define XSyncFence CARD32 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + CARD32 majorVersion B32; + CARD32 minorVersion B32; +} xPresentQueryVersionReq; +#define sz_xPresentQueryVersionReq 12 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 majorVersion B32; + CARD32 minorVersion B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xPresentQueryVersionReply; +#define sz_xPresentQueryVersionReply 32 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + Window window B32; + Pixmap pixmap B32; + Region valid B32; + Region update B32; + INT16 x_off B16; + INT16 y_off B16; + CARD64 target_msc; + CARD64 divisor; + CARD64 remainder; + XSyncFence idle_fence B32; +} xPresentRegionReq; +#define sz_xPresentRegionReq 52 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + CARD32 eid B32; + CARD32 window B32; + CARD32 eventMask B32; +} xPresentSelectInputReq; +#define sz_xPresentSelectInputReq 12 + +/* + * Events + * + * All Present events are X Generic Events + */ + +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD16 pad2; + CARD32 eid B32; + CARD32 window B32; + INT16 x B16; + INT16 y B16; + CARD16 width B16; + CARD16 height B16; + INT16 off_x B16; + INT16 off_y B16; + + CARD16 pixmap_width B16; + CARD16 pixmap_height B16; + CARD32 pixmap_flags B32; +} xPresentConfigureNotify; +#define sz_xPresentConfigureNotify 40 + +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD16 pad2 B16; + CARD32 eid B32; + Window window B32; + CARD32 pad3 B32; + CARD64 ust; + CARD64 msc; + CARD64 sbc; +} xPresentCompleteNotify; +#define sz_xPresentCompleteNotify 48 + +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD16 pad2; + CARD32 eid B32; + + Window event_window B32; + Window window B32; + Pixmap pixmap B32; + Region valid_region B32; + + xRectangle valid_rect; + xRectangle update_rect; + + Region update_region B32; + INT16 x_off B16; + INT16 y_off B16; + CARD64 target_msc; + + CARD64 divisor; + CARD64 remainder; + + XSyncFence idle_fence; +} xPresentRedirectNotify; + +#define sz_xPresentRedirectNotify 84 + +#undef Region +#undef XSyncFence + +#endif diff --git a/nx-X11/include/extensions/presenttokens.h b/nx-X11/include/extensions/presenttokens.h new file mode 100644 index 0000000000..ba13390f3e --- /dev/null +++ b/nx-X11/include/extensions/presenttokens.h @@ -0,0 +1,47 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENT_TOKENS_H_ +#define _PRESENT_TOKENS_H_ + +#define PRESENT_NAME "Present" +#define PRESENT_MAJOR 1 +#define PRESENT_MINOR 0 + +#define PresentNumberErrors 0 +#define PresentNumberEvents 0 + +#define X_PresentQueryVersion 0 +#define X_PresentRegion 1 +#define X_PresentSelectInput 2 + +#define PresentNumberRequests 3 + +#define PresentConfigureNotify 0 +#define PresentCompleteNotify 1 +#define PresentRedirectNotify 2 + +#define PresentAllEvents ((1 << PresentConfigureNotify) | \ + (1 << PresentCompleteNotify) | \ + (1 << PresentRedirectNotify)) + +#endif From c80928417601740d69ba0779edc80a212f42f5f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Jul 2013 02:40:11 -0700 Subject: [PATCH 69/76] Add NotifyMSC. Add serial numbers to Complete and MSC events Signed-off-by: Keith Packard --- nx-X11/include/extensions/presentproto.h | 29 +++++++++++++++++++---- nx-X11/include/extensions/presenttokens.h | 22 +++++++++++------ 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index 01fcb67523..44dc96cbbc 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -56,17 +56,37 @@ typedef struct { CARD8 presentReqType; CARD16 length B16; Window window B32; + Pixmap pixmap B32; + CARD32 serial B32; + Region valid B32; Region update B32; + INT16 x_off B16; INT16 y_off B16; + XSyncFence idle_fence B32; + CARD64 target_msc; CARD64 divisor; CARD64 remainder; - XSyncFence idle_fence B32; } xPresentRegionReq; -#define sz_xPresentRegionReq 52 +#define sz_xPresentRegionReq 56 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + Window window B32; + + CARD32 serial B32; + CARD32 pad0 B32; + + CARD64 target_msc; + CARD64 divisor; + CARD64 remainder; +} xPresentNotifyMSCReq; +#define sz_xPresentNotifyMSCReq 40 typedef struct { CARD8 reqType; @@ -115,12 +135,13 @@ typedef struct { CARD16 pad2 B16; CARD32 eid B32; Window window B32; - CARD32 pad3 B32; + CARD32 serial B32; CARD64 ust; CARD64 msc; CARD64 sbc; -} xPresentCompleteNotify; +} xPresentCompleteNotify, xPresentMSCNotify; #define sz_xPresentCompleteNotify 48 +#define sz_xPresentMSCNotify 48 typedef struct { CARD8 type; diff --git a/nx-X11/include/extensions/presenttokens.h b/nx-X11/include/extensions/presenttokens.h index ba13390f3e..d829f11bc0 100644 --- a/nx-X11/include/extensions/presenttokens.h +++ b/nx-X11/include/extensions/presenttokens.h @@ -32,16 +32,24 @@ #define X_PresentQueryVersion 0 #define X_PresentRegion 1 -#define X_PresentSelectInput 2 +#define X_PresentNotifyMSC 2 +#define X_PresentSelectInput 3 -#define PresentNumberRequests 3 +#define PresentNumberRequests 4 #define PresentConfigureNotify 0 #define PresentCompleteNotify 1 -#define PresentRedirectNotify 2 - -#define PresentAllEvents ((1 << PresentConfigureNotify) | \ - (1 << PresentCompleteNotify) | \ - (1 << PresentRedirectNotify)) +#define PresentMSCNotify 2 +#define PresentRedirectNotify 3 + +#define PresentConfigureNotifyMask 1 +#define PresentCompleteNotifyMask 2 +#define PresentMSCNotifyMask 4 +#define PresentRedirectNotifyMask 8 + +#define PresentAllEvents (PresentConfigureNotifyMask | \ + PresentCompleteNotifyMask | \ + PresentMSCNotifyMask | \ + PresentRedirectNotifyMask) #endif From 21fe0f555196f9541df8cc0a1ce155be98d9a388 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Jul 2013 10:55:48 -0700 Subject: [PATCH 70/76] Remove SBC, use CompleteNotify for both Region and NotifyMSC SBC is entire a client-side notion, so remove it from the protocol. No need to have two events with the same content, but we do need to tell which request generated the event so stick a new field in some spare bytes Signed-off-by: Keith Packard --- nx-X11/include/extensions/presentproto.h | 9 ++++----- nx-X11/include/extensions/presenttokens.h | 15 ++++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index 44dc96cbbc..3e2c0bbc56 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -132,16 +132,15 @@ typedef struct { CARD16 sequenceNumber B16; CARD32 length; CARD16 evtype B16; - CARD16 pad2 B16; + CARD16 kind B16; CARD32 eid B32; Window window B32; CARD32 serial B32; CARD64 ust; + CARD64 msc; - CARD64 sbc; -} xPresentCompleteNotify, xPresentMSCNotify; -#define sz_xPresentCompleteNotify 48 -#define sz_xPresentMSCNotify 48 +} xPresentCompleteNotify; +#define sz_xPresentCompleteNotify 40 typedef struct { CARD8 type; diff --git a/nx-X11/include/extensions/presenttokens.h b/nx-X11/include/extensions/presenttokens.h index d829f11bc0..dbfdb3619c 100644 --- a/nx-X11/include/extensions/presenttokens.h +++ b/nx-X11/include/extensions/presenttokens.h @@ -30,6 +30,7 @@ #define PresentNumberErrors 0 #define PresentNumberEvents 0 +/* Requests */ #define X_PresentQueryVersion 0 #define X_PresentRegion 1 #define X_PresentNotifyMSC 2 @@ -37,19 +38,23 @@ #define PresentNumberRequests 4 +/* Events */ #define PresentConfigureNotify 0 #define PresentCompleteNotify 1 -#define PresentMSCNotify 2 -#define PresentRedirectNotify 3 +#define PresentRedirectNotify 2 +/* Event Masks */ #define PresentConfigureNotifyMask 1 #define PresentCompleteNotifyMask 2 -#define PresentMSCNotifyMask 4 -#define PresentRedirectNotifyMask 8 +#define PresentRedirectNotifyMask 4 #define PresentAllEvents (PresentConfigureNotifyMask | \ PresentCompleteNotifyMask | \ - PresentMSCNotifyMask | \ PresentRedirectNotifyMask) +/* Complete Kinds */ + +#define PresentCompleteKindRegion 0 +#define PresentCompleteKindNotifyMSC 1 + #endif From aa63d2c1d1d8e4e3dfc0f203d8f1c042b9bbeca6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Jul 2013 21:07:20 -0700 Subject: [PATCH 71/76] Start reworking for present redirection. In PresentRegion, add the PresentNotify list, add explicit CRTC. In PresentRedirectNotify, add CRTC and update_window values Signed-off-by: Keith Packard --- nx-X11/include/extensions/presentproto.h | 32 ++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index 3e2c0bbc56..1df7d589d6 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -28,6 +28,12 @@ #define Region CARD32 #define XSyncFence CARD32 +typedef struct { + Window window B32; + CARD32 serial B32; +} xPresentNotify; +#define sz_xPresentNotify 8 + typedef struct { CARD8 reqType; CARD8 presentReqType; @@ -67,11 +73,15 @@ typedef struct { INT16 y_off B16; XSyncFence idle_fence B32; + CARD32 target_crtc B32; + CARD32 pad1 B32; + CARD64 target_msc; CARD64 divisor; CARD64 remainder; + /* followed by a LISTofPRESENTNOTIFY */ } xPresentRegionReq; -#define sz_xPresentRegionReq 56 +#define sz_xPresentRegionReq 64 typedef struct { CARD8 reqType; @@ -148,29 +158,37 @@ typedef struct { CARD16 sequenceNumber B16; CARD32 length; CARD16 evtype B16; - CARD16 pad2; + CARD8 update_window; + CARD8 pad1; CARD32 eid B32; - Window event_window B32; Window window B32; Pixmap pixmap B32; + CARD32 serial B32; + + /* 32-byte boundary */ + Region valid_region B32; + Region update_region B32; xRectangle valid_rect; + xRectangle update_rect; - Region update_region B32; INT16 x_off B16; INT16 y_off B16; - CARD64 target_msc; + CARD32 target_crtc B32; + CARD64 target_msc; CARD64 divisor; CARD64 remainder; - XSyncFence idle_fence; + XSyncFence idle_fence B32; + CARD32 pad2 B32; + } xPresentRedirectNotify; -#define sz_xPresentRedirectNotify 84 +#define sz_xPresentRedirectNotify 96 #undef Region #undef XSyncFence From 38ce813a1bd900ba8e9739b7d9728c270e632a1b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Oct 2013 16:42:20 -0700 Subject: [PATCH 72/76] PresentRegion->PresentPixmap, define options, add UST mode Changes the name of the PresentPixmap request from PresentRegion in anticipation of future additions of non-pixmap sourced updates (YUV images in particular). Adds definitions for all of the new PresentPixmap options. Adds PresentQueryCapabilities to provide applications the ability to learn what the underlying hardware can support. One requirement for any capability is that the X server must do something sensible even if the client behaves as if a capability is supported when it is not. Adds IdleNotify events. As pixmaps can go idle in any order, it's important for applications to know which pixmap to use next. We cannot use fences as the fence itself may not be signaled for some time after the X server has figured out which pixmap to idle. Note that the encoding and header files are not entirely up to date now. Signed-off-by: Keith Packard --- nx-X11/include/extensions/presentproto.h | 24 +++++++++++++++-------- nx-X11/include/extensions/presenttokens.h | 18 +++++++++++++++-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index 1df7d589d6..a8391f51da 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -71,17 +71,20 @@ typedef struct { INT16 x_off B16; INT16 y_off B16; + CARD32 target_crtc B32; + + XSyncFence wait_fence B32; XSyncFence idle_fence B32; - CARD32 target_crtc B32; + CARD32 options B32; CARD32 pad1 B32; CARD64 target_msc; CARD64 divisor; CARD64 remainder; /* followed by a LISTofPRESENTNOTIFY */ -} xPresentRegionReq; -#define sz_xPresentRegionReq 64 +} xPresentPixmapReq; +#define sz_xPresentPixmapReq 72 typedef struct { CARD8 reqType; @@ -142,7 +145,8 @@ typedef struct { CARD16 sequenceNumber B16; CARD32 length; CARD16 evtype B16; - CARD16 kind B16; + CARD8 kind; + CARD8 mode; CARD32 eid B32; Window window B32; CARD32 serial B32; @@ -162,6 +166,7 @@ typedef struct { CARD8 pad1; CARD32 eid B32; Window event_window B32; + Window window B32; Pixmap pixmap B32; CARD32 serial B32; @@ -179,16 +184,19 @@ typedef struct { INT16 y_off B16; CARD32 target_crtc B32; + XSyncFence wait_fence B32; + XSyncFence idle_fence B32; + + CARD32 options B32; + CARD32 pad2 B32; + CARD64 target_msc; CARD64 divisor; CARD64 remainder; - XSyncFence idle_fence B32; - CARD32 pad2 B32; - } xPresentRedirectNotify; -#define sz_xPresentRedirectNotify 96 +#define sz_xPresentRedirectNotify 104 #undef Region #undef XSyncFence diff --git a/nx-X11/include/extensions/presenttokens.h b/nx-X11/include/extensions/presenttokens.h index dbfdb3619c..4eb4a9b9e4 100644 --- a/nx-X11/include/extensions/presenttokens.h +++ b/nx-X11/include/extensions/presenttokens.h @@ -32,12 +32,20 @@ /* Requests */ #define X_PresentQueryVersion 0 -#define X_PresentRegion 1 +#define X_PresentPixmap 1 #define X_PresentNotifyMSC 2 #define X_PresentSelectInput 3 #define PresentNumberRequests 4 +/* Present operation options */ +#define PresentOptionNone 0 +#define PresentOptionAsync (1 << 0) +#define PresentOptionCopy (1 << 1) + +#define PresentAllOptions (PresentOptionAsync | \ + PresentOptionCopy) + /* Events */ #define PresentConfigureNotify 0 #define PresentCompleteNotify 1 @@ -54,7 +62,13 @@ /* Complete Kinds */ -#define PresentCompleteKindRegion 0 +#define PresentCompleteKindPixmap 0 #define PresentCompleteKindNotifyMSC 1 +/* Complete Modes */ + +#define PresentCompleteModeCopy 0 +#define PresentCompleteModeFlip 1 +#define PresentCompleteModeSkip 2 + #endif From 9d94b05eca9d76f58204b1e75a5b44166ac5b4c1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Oct 2013 17:38:27 -0700 Subject: [PATCH 73/76] Update to version 1.0 Add presentproto.h updates for current protocol. Finish encoding specification. Signed-off-by: Keith Packard --- nx-X11/include/extensions/presentproto.h | 42 +++++++++++++++++++++-- nx-X11/include/extensions/presenttokens.h | 25 +++++++++++--- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index a8391f51da..8303a942f1 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -27,6 +27,7 @@ #define Region CARD32 #define XSyncFence CARD32 +#define EventID CARD32 typedef struct { Window window B32; @@ -109,7 +110,29 @@ typedef struct { CARD32 window B32; CARD32 eventMask B32; } xPresentSelectInputReq; -#define sz_xPresentSelectInputReq 12 +#define sz_xPresentSelectInputReq 16 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + CARD32 target B32; +} xPresentQueryCapabilitiesReq; +#define sz_xPresentQueryCapabilitiesReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 capabilities B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xPresentQueryCapabilitiesReply; +#define sz_xPresentQueryCapabilitiesReply 32 /* * Events @@ -156,6 +179,21 @@ typedef struct { } xPresentCompleteNotify; #define sz_xPresentCompleteNotify 40 +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD16 pad2 B16; + CARD32 eid B32; + Window window B32; + CARD32 serial B32; + Pixmap pixmap B32; + CARD32 idle_fence B32; +} xPresentIdleNotify; +#define sz_xPresentIdleNotify 32 + typedef struct { CARD8 type; CARD8 extension; @@ -166,7 +204,6 @@ typedef struct { CARD8 pad1; CARD32 eid B32; Window event_window B32; - Window window B32; Pixmap pixmap B32; CARD32 serial B32; @@ -200,5 +237,6 @@ typedef struct { #undef Region #undef XSyncFence +#undef EventID #endif diff --git a/nx-X11/include/extensions/presenttokens.h b/nx-X11/include/extensions/presenttokens.h index 4eb4a9b9e4..807dbcfa5f 100644 --- a/nx-X11/include/extensions/presenttokens.h +++ b/nx-X11/include/extensions/presenttokens.h @@ -35,29 +35,46 @@ #define X_PresentPixmap 1 #define X_PresentNotifyMSC 2 #define X_PresentSelectInput 3 +#define X_PresentQueryCapabilities 4 -#define PresentNumberRequests 4 +#define PresentNumberRequests 5 /* Present operation options */ #define PresentOptionNone 0 #define PresentOptionAsync (1 << 0) #define PresentOptionCopy (1 << 1) +#define PresentOptionUST (1 << 2) #define PresentAllOptions (PresentOptionAsync | \ - PresentOptionCopy) + PresentOptionCopy | \ + PresentOptionUST) + +/* Present capabilities */ + +#define PresentCapabilityNone 0 +#define PresentCapabilityAsync 1 +#define PresentCapabilityFence 2 +#define PresentCapabilityUST 4 + +#define PresentAllCapabilities (PresentCapabilityAsync | \ + PresentCapabilityFence | \ + PresentCapabilityUST) /* Events */ #define PresentConfigureNotify 0 #define PresentCompleteNotify 1 -#define PresentRedirectNotify 2 +#define PresentIdleNotify 2 +#define PresentRedirectNotify 3 /* Event Masks */ #define PresentConfigureNotifyMask 1 #define PresentCompleteNotifyMask 2 -#define PresentRedirectNotifyMask 4 +#define PresentIdleNotifyMask 4 +#define PresentRedirectNotifyMask 8 #define PresentAllEvents (PresentConfigureNotifyMask | \ PresentCompleteNotifyMask | \ + PresentIdleNotifyMask | \ PresentRedirectNotifyMask) /* Complete Kinds */ From 83465e01df6a0175bd563f847da758e28b257198 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 11 Dec 2013 13:25:06 -0500 Subject: [PATCH 74/76] Force Window and Pixmap to be CARD32 on the wire If you don't do this then the client libs on 64-bit machines see them as XIDs, which are 64-bit wide (sigh), which ruins the wire encoding and nothing works. Reviewed-by: Jasper St. Pierre Signed-off-by: Adam Jackson --- nx-X11/include/extensions/presentproto.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index 8303a942f1..ee65fa47e8 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -25,6 +25,8 @@ #include +#define Window CARD32 +#define Pixmap CARD32 #define Region CARD32 #define XSyncFence CARD32 #define EventID CARD32 @@ -235,6 +237,8 @@ typedef struct { #define sz_xPresentRedirectNotify 104 +#undef Window +#undef Pixmap #undef Region #undef XSyncFence #undef EventID From 11be6fc18e62bd6b11a5f3152e785bdf11d38b44 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Dec 2013 12:21:02 -0800 Subject: [PATCH 75/76] Don't define 'redirect' stuff in header files Leave it all under #if PRESENT_FUTURE_VERSION for documentation Signed-off-by: Keith Packard --- nx-X11/include/extensions/presentproto.h | 2 ++ nx-X11/include/extensions/presenttokens.h | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index ee65fa47e8..08ddc05ebd 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -196,6 +196,7 @@ typedef struct { } xPresentIdleNotify; #define sz_xPresentIdleNotify 32 +#if PRESENT_FUTURE_VERSION typedef struct { CARD8 type; CARD8 extension; @@ -236,6 +237,7 @@ typedef struct { } xPresentRedirectNotify; #define sz_xPresentRedirectNotify 104 +#endif #undef Window #undef Pixmap diff --git a/nx-X11/include/extensions/presenttokens.h b/nx-X11/include/extensions/presenttokens.h index 807dbcfa5f..acb757621f 100644 --- a/nx-X11/include/extensions/presenttokens.h +++ b/nx-X11/include/extensions/presenttokens.h @@ -64,18 +64,28 @@ #define PresentConfigureNotify 0 #define PresentCompleteNotify 1 #define PresentIdleNotify 2 +#if PRESENT_FUTURE_VERSION #define PresentRedirectNotify 3 +#endif /* Event Masks */ #define PresentConfigureNotifyMask 1 #define PresentCompleteNotifyMask 2 #define PresentIdleNotifyMask 4 +#if PRESENT_FUTURE_VERSION #define PresentRedirectNotifyMask 8 +#endif + +#if PRESENT_FUTURE_VERSION +#define PRESENT_REDIRECT_NOTIFY_MASK PresentRedirectNotifyMask +#else +#define PRESENT_REDIRECT_NOTIFY_MASK 0 +#endif #define PresentAllEvents (PresentConfigureNotifyMask | \ PresentCompleteNotifyMask | \ PresentIdleNotifyMask | \ - PresentRedirectNotifyMask) + PRESENT_REDIRECT_NOTIFY_MASK) /* Complete Kinds */ From 9d604f9ba32d369b6708f6d82db854d27b258b2f Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Fri, 24 Feb 2017 11:53:17 +0100 Subject: [PATCH 76/76] Present Xserver extension: Enable build via imake in nx-libs. --- nx-X11/config/cf/X11.tmpl | 3 ++ nx-X11/config/cf/xorg.cf | 5 ++ nx-X11/include/extensions/Imakefile | 4 ++ nx-X11/include/extensions/presentproto.h | 2 +- nx-X11/programs/Xserver/Imakefile | 12 ++++- .../Xserver/include/protocol-versions.h | 2 - nx-X11/programs/Xserver/mi/miinitext.c | 6 +++ nx-X11/programs/Xserver/present/Imakefile | 49 +++++++++++++++++++ nx-X11/programs/Xserver/present/present.h | 2 +- .../programs/Xserver/present/present_priv.h | 2 +- 10 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 nx-X11/programs/Xserver/present/Imakefile diff --git a/nx-X11/config/cf/X11.tmpl b/nx-X11/config/cf/X11.tmpl index ddd6e0bada..e5d4bb9afc 100644 --- a/nx-X11/config/cf/X11.tmpl +++ b/nx-X11/config/cf/X11.tmpl @@ -223,6 +223,9 @@ XORGRELSTRING = XorgManVersionString #ifndef BuildRender #define BuildRender YES #endif +#ifndef BuildPresent +#define BuildPresent YES +#endif #ifndef BuildRandR #define BuildRandR YES diff --git a/nx-X11/config/cf/xorg.cf b/nx-X11/config/cf/xorg.cf index 1aa7daf06f..8f73b8ceff 100644 --- a/nx-X11/config/cf/xorg.cf +++ b/nx-X11/config/cf/xorg.cf @@ -449,6 +449,11 @@ IPLAN2P8_DEFS = -DUSE_IPLAN2P8 # define BuildRender YES #endif +/* Build Present extension */ +#ifndef BuildPresent +# define BuildPresent YES +#endif + #if 0 #ifndef JoystickSupport # define JoystickSupport NO diff --git a/nx-X11/include/extensions/Imakefile b/nx-X11/include/extensions/Imakefile index f1760d274a..e76c9b7b18 100644 --- a/nx-X11/include/extensions/Imakefile +++ b/nx-X11/include/extensions/Imakefile @@ -20,6 +20,9 @@ RANDRHEADERS = randr.h randrproto.h #if BuildRender RENDERHEADERS = render.h renderproto.h #endif +#if BuildPresent +PRESENTHEADERS = presentproto.h presenttokens.h +#endif #if BuildXfixes XFIXESHEADERS = xfixeswire.h xfixesproto.h #endif @@ -43,6 +46,7 @@ EXTRAHEADERS = \ $(XVMCHEADERS) \ $(RANDRHEADERS) \ $(RENDERHEADERS) \ + $(PRESENTHEADERS) \ $(XFIXESHEADERS) \ $(COMPOSITEHEADERS) \ $(DAMAGEHEADERS) \ diff --git a/nx-X11/include/extensions/presentproto.h b/nx-X11/include/extensions/presentproto.h index 08ddc05ebd..b4069411d0 100644 --- a/nx-X11/include/extensions/presentproto.h +++ b/nx-X11/include/extensions/presentproto.h @@ -23,7 +23,7 @@ #ifndef _PRESENT_PROTO_H_ #define _PRESENT_PROTO_H_ -#include +#include #define Window CARD32 #define Pixmap CARD32 diff --git a/nx-X11/programs/Xserver/Imakefile b/nx-X11/programs/Xserver/Imakefile index e5dfa93209..432e9fa32f 100644 --- a/nx-X11/programs/Xserver/Imakefile +++ b/nx-X11/programs/Xserver/Imakefile @@ -86,6 +86,10 @@ INSTPGMFLAGS = #if BuildDBE DBEDIR = dbe #endif +#if BuildPresent + PRESENTEXT = present/LibraryTargetName(present) + PRESENTDIR = present +#endif #if BuildRECORD RECORDEXT = record/LibraryTargetName(record) #endif @@ -105,6 +109,10 @@ INSTPGMFLAGS = RENDERDIR = render RENDERLIB = $(RENDERDIR)/librender.a #endif +#if BuildPresent + PRESENTDIR = present + PRESENTEXT = present/LibraryTargetName(present) +#endif #if BuildRandR RANDRDIR = randr RANDRLIB = $(RANDRDIR)/librandr.a @@ -124,11 +132,11 @@ INSTPGMFLAGS = CW = miext/cw/LibraryTargetName(cw) #endif EXTENSIONS = $(COMPOSITELIB) $(DAMAGELIB) $(DAMAGE) $(FIXESLIB) $(CW) \ - $(OTHEREXTS) $(GLXEXT) $(RANDRLIB) $(RENDERLIB) + $(OTHEREXTS) $(GLXEXT) $(PRESENTEXT) $(RANDRLIB) $(RENDERLIB) OTHEREXTS = Xext/LibraryTargetName(ext) $(XKBEXT) $(XINPUTEXT) \ $(DBEEXT) $(RECORDEXT) $(SITEEXTS) EXTDIRS = Xext $(XKBDIR) $(XIDIR) $(GLXDIR) \ - $(DBEDIR) $(RECORDDIR) $(SITEEXTDIRS) \ + $(DBEDIR) $(PRESENTDIR) $(RECORDDIR) $(SITEEXTDIRS) \ $(RANDRDIR) $(RENDERDIR) $(XPCONFIGDIR) \ $(FIXESDIR) $(DAMAGEDIR) $(CWDIR) $(COMPOSITEDIR) OS = os/LibraryTargetName(os) diff --git a/nx-X11/programs/Xserver/include/protocol-versions.h b/nx-X11/programs/Xserver/include/protocol-versions.h index 9b9319fd2d..403c5e0e55 100644 --- a/nx-X11/programs/Xserver/include/protocol-versions.h +++ b/nx-X11/programs/Xserver/include/protocol-versions.h @@ -75,11 +75,9 @@ #define SERVER_PANORAMIX_MAJOR_VERSION 1 #define SERVER_PANORAMIX_MINOR_VERSION 1 -#ifndef NXAGENT_SERVER /* Present */ #define SERVER_PRESENT_MAJOR_VERSION 1 #define SERVER_PRESENT_MINOR_VERSION 0 -#endif /* !defined(NXAGENT_SERVER) */ /* RandR */ #define SERVER_RANDR_MAJOR_VERSION 1 diff --git a/nx-X11/programs/Xserver/mi/miinitext.c b/nx-X11/programs/Xserver/mi/miinitext.c index 6f6d678411..ffb19bd4a1 100644 --- a/nx-X11/programs/Xserver/mi/miinitext.c +++ b/nx-X11/programs/Xserver/mi/miinitext.c @@ -238,6 +238,9 @@ extern void XFree86DRIExtensionInit(void); #ifdef DPMSExtension extern void DPMSExtensionInit(void); #endif +#ifdef PRESENT +extern void present_extension_init(void); +#endif #ifdef DPSEXT extern void DPSExtensionInit(void); #endif @@ -292,6 +295,9 @@ static ExtensionToggle ExtensionToggleList[] = #ifdef DPMSExtension { "DPMS", &noDPMSExtension }, #endif +#ifdef PRESENT + { "Present", &noPresentExtension }, +#endif #ifdef GLXEXT { "GLX", &noGlxExtension }, #endif diff --git a/nx-X11/programs/Xserver/present/Imakefile b/nx-X11/programs/Xserver/present/Imakefile new file mode 100644 index 0000000000..5abbba41e0 --- /dev/null +++ b/nx-X11/programs/Xserver/present/Imakefile @@ -0,0 +1,49 @@ +NULL = + +#include + + SRCS = \ + present.c \ + present_event.c \ + present_fake.c \ + present_fence.c \ + present_notify.c \ + present_request.c \ + present_screen.c \ + $(NULL) + OBJS = \ + present.o \ + present_event.o \ + present_fake.o \ + present_fence.o \ + present_notify.o \ + present_request.o \ + present_screen.o \ + $(NULL) + INCLUDES = \ + -I$(SERVERSRC)/include \ + -I$(SERVERSRC)/randr \ + -I$(SERVERSRC)/render \ + -I$(XINCLUDESRC) \ + -I$(EXTINCSRC) \ + `pkg-config --cflags-only-I pixman-1` \ + $(NULL) + + LINTLIBS = \ + ../dix/llib-ldix.ln \ + ../os/llib-los.ln \ + $(NULL) + +RESENT_DEFINES = \ + -DPRESENT_FUTURE_VERSION=0 \ + $(NULL) + +NormalLibraryObjectRule() + +NormalLibraryTarget(present,$(OBJS)) + +LintLibraryTarget(present,$(SRCS)) +NormalLintTarget($(SRCS)) + + +DependTarget() diff --git a/nx-X11/programs/Xserver/present/present.h b/nx-X11/programs/Xserver/present/present.h index aab2e168ac..fb7c33724a 100644 --- a/nx-X11/programs/Xserver/present/present.h +++ b/nx-X11/programs/Xserver/present/present.h @@ -23,7 +23,7 @@ #ifndef _PRESENT_H_ #define _PRESENT_H_ -#include +#include #include "randrstr.h" #include "presentext.h" diff --git a/nx-X11/programs/Xserver/present/present_priv.h b/nx-X11/programs/Xserver/present/present_priv.h index dfb4bdea9b..0ef539c44b 100644 --- a/nx-X11/programs/Xserver/present/present_priv.h +++ b/nx-X11/programs/Xserver/present/present_priv.h @@ -23,7 +23,7 @@ #ifndef _PRESENT_PRIV_H_ #define _PRESENT_PRIV_H_ -#include +#include #include "scrnintstr.h" #include "misc.h" #include "list.h"