present_vblank.c revision a035e2b2
11b5d61b8Smrg/*
21b5d61b8Smrg * Copyright © 2013 Keith Packard
31b5d61b8Smrg *
41b5d61b8Smrg * Permission to use, copy, modify, distribute, and sell this software and its
51b5d61b8Smrg * documentation for any purpose is hereby granted without fee, provided that
61b5d61b8Smrg * the above copyright notice appear in all copies and that both that copyright
71b5d61b8Smrg * notice and this permission notice appear in supporting documentation, and
81b5d61b8Smrg * that the name of the copyright holders not be used in advertising or
91b5d61b8Smrg * publicity pertaining to distribution of the software without specific,
101b5d61b8Smrg * written prior permission.  The copyright holders make no representations
111b5d61b8Smrg * about the suitability of this software for any purpose.  It is provided "as
121b5d61b8Smrg * is" without express or implied warranty.
131b5d61b8Smrg *
141b5d61b8Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
151b5d61b8Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
161b5d61b8Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
171b5d61b8Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
181b5d61b8Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
191b5d61b8Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
201b5d61b8Smrg * OF THIS SOFTWARE.
211b5d61b8Smrg */
221b5d61b8Smrg
231b5d61b8Smrg#ifdef HAVE_XORG_CONFIG_H
241b5d61b8Smrg#include <xorg-config.h>
251b5d61b8Smrg#endif
261b5d61b8Smrg
271b5d61b8Smrg#include "present_priv.h"
281b5d61b8Smrg
291b5d61b8Smrgvoid
301b5d61b8Smrgpresent_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc)
311b5d61b8Smrg{
321b5d61b8Smrg    int n;
331b5d61b8Smrg
341b5d61b8Smrg    if (vblank->window)
351b5d61b8Smrg        present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset);
361b5d61b8Smrg    for (n = 0; n < vblank->num_notifies; n++) {
371b5d61b8Smrg        WindowPtr   window = vblank->notifies[n].window;
381b5d61b8Smrg        CARD32      serial = vblank->notifies[n].serial;
391b5d61b8Smrg
401b5d61b8Smrg        if (window)
411b5d61b8Smrg            present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset);
421b5d61b8Smrg    }
431b5d61b8Smrg}
441b5d61b8Smrg
451b5d61b8Smrgpresent_vblank_ptr
461b5d61b8Smrgpresent_vblank_create(WindowPtr window,
471b5d61b8Smrg                      PixmapPtr pixmap,
481b5d61b8Smrg                      CARD32 serial,
491b5d61b8Smrg                      RegionPtr valid,
501b5d61b8Smrg                      RegionPtr update,
511b5d61b8Smrg                      int16_t x_off,
521b5d61b8Smrg                      int16_t y_off,
531b5d61b8Smrg                      RRCrtcPtr target_crtc,
541b5d61b8Smrg                      SyncFence *wait_fence,
551b5d61b8Smrg                      SyncFence *idle_fence,
561b5d61b8Smrg                      uint32_t options,
571b5d61b8Smrg                      const uint32_t *capabilities,
581b5d61b8Smrg                      present_notify_ptr notifies,
591b5d61b8Smrg                      int num_notifies,
605a7dfde8Smrg                      uint64_t target_msc,
611b5d61b8Smrg                      uint64_t crtc_msc)
621b5d61b8Smrg{
631b5d61b8Smrg    ScreenPtr                   screen = window->drawable.pScreen;
641b5d61b8Smrg    present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
651b5d61b8Smrg    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
661b5d61b8Smrg    present_vblank_ptr          vblank;
671b5d61b8Smrg    PresentFlipReason           reason = PRESENT_FLIP_REASON_UNKNOWN;
681b5d61b8Smrg
69a035e2b2Smrg    if (target_crtc) {
70a035e2b2Smrg        screen_priv = present_screen_priv(target_crtc->pScreen);
71a035e2b2Smrg    }
72a035e2b2Smrg
731b5d61b8Smrg    vblank = calloc (1, sizeof (present_vblank_rec));
741b5d61b8Smrg    if (!vblank)
751b5d61b8Smrg        return NULL;
761b5d61b8Smrg
771b5d61b8Smrg    xorg_list_append(&vblank->window_list, &window_priv->vblank);
781b5d61b8Smrg    xorg_list_init(&vblank->event_queue);
791b5d61b8Smrg
801b5d61b8Smrg    vblank->screen = screen;
811b5d61b8Smrg    vblank->window = window;
821b5d61b8Smrg    vblank->pixmap = pixmap;
831b5d61b8Smrg
841b5d61b8Smrg    screen_priv->create_event_id(window_priv, vblank);
851b5d61b8Smrg
861b5d61b8Smrg    if (pixmap) {
871b5d61b8Smrg        vblank->kind = PresentCompleteKindPixmap;
881b5d61b8Smrg        pixmap->refcnt++;
891b5d61b8Smrg    } else
901b5d61b8Smrg        vblank->kind = PresentCompleteKindNotifyMSC;
911b5d61b8Smrg
921b5d61b8Smrg    vblank->serial = serial;
931b5d61b8Smrg
941b5d61b8Smrg    if (valid) {
951b5d61b8Smrg        vblank->valid = RegionDuplicate(valid);
961b5d61b8Smrg        if (!vblank->valid)
971b5d61b8Smrg            goto no_mem;
981b5d61b8Smrg    }
991b5d61b8Smrg    if (update) {
1001b5d61b8Smrg        vblank->update = RegionDuplicate(update);
1011b5d61b8Smrg        if (!vblank->update)
1021b5d61b8Smrg            goto no_mem;
1031b5d61b8Smrg    }
1041b5d61b8Smrg
1051b5d61b8Smrg    vblank->x_off = x_off;
1061b5d61b8Smrg    vblank->y_off = y_off;
1075a7dfde8Smrg    vblank->target_msc = target_msc;
1085a7dfde8Smrg    vblank->exec_msc = target_msc;
1091b5d61b8Smrg    vblank->crtc = target_crtc;
1101b5d61b8Smrg    vblank->msc_offset = window_priv->msc_offset;
1111b5d61b8Smrg    vblank->notifies = notifies;
1121b5d61b8Smrg    vblank->num_notifies = num_notifies;
1131b5d61b8Smrg    vblank->has_suboptimal = (options & PresentOptionSuboptimal);
1141b5d61b8Smrg    vblank->flip_idler = FALSE;
1151b5d61b8Smrg
1161b5d61b8Smrg    if (pixmap != NULL &&
1171b5d61b8Smrg        !(options & PresentOptionCopy) &&
1181b5d61b8Smrg        capabilities) {
1195a7dfde8Smrg        if (msc_is_after(target_msc, crtc_msc) &&
1201b5d61b8Smrg            screen_priv->check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason))
1211b5d61b8Smrg        {
1221b5d61b8Smrg            vblank->flip = TRUE;
1231b5d61b8Smrg            vblank->sync_flip = TRUE;
1241b5d61b8Smrg        } else if ((*capabilities & PresentCapabilityAsync) &&
1251b5d61b8Smrg            screen_priv->check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason))
1261b5d61b8Smrg        {
1271b5d61b8Smrg            vblank->flip = TRUE;
1281b5d61b8Smrg        }
1291b5d61b8Smrg    }
1301b5d61b8Smrg    vblank->reason = reason;
1311b5d61b8Smrg
1321b5d61b8Smrg    if (wait_fence) {
1331b5d61b8Smrg        vblank->wait_fence = present_fence_create(wait_fence);
1341b5d61b8Smrg        if (!vblank->wait_fence)
1351b5d61b8Smrg            goto no_mem;
1361b5d61b8Smrg    }
1371b5d61b8Smrg
1381b5d61b8Smrg    if (idle_fence) {
1391b5d61b8Smrg        vblank->idle_fence = present_fence_create(idle_fence);
1401b5d61b8Smrg        if (!vblank->idle_fence)
1411b5d61b8Smrg            goto no_mem;
1421b5d61b8Smrg    }
1431b5d61b8Smrg
1441b5d61b8Smrg    if (pixmap)
145e23ec014Smrg        DebugPresent(("q %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p) flip %d vsync %d serial %d\n",
1465a7dfde8Smrg                      vblank->event_id, vblank, target_msc,
1471b5d61b8Smrg                      vblank->pixmap->drawable.id, vblank->window->drawable.id,
1481b5d61b8Smrg                      target_crtc, vblank->flip, vblank->sync_flip, vblank->serial));
1491b5d61b8Smrg    return vblank;
1501b5d61b8Smrg
1511b5d61b8Smrgno_mem:
1521b5d61b8Smrg    vblank->notifies = NULL;
1531b5d61b8Smrg    present_vblank_destroy(vblank);
1541b5d61b8Smrg    return NULL;
1551b5d61b8Smrg}
1561b5d61b8Smrg
1571b5d61b8Smrgvoid
1581b5d61b8Smrgpresent_vblank_scrap(present_vblank_ptr vblank)
1591b5d61b8Smrg{
1605a7dfde8Smrg    DebugPresent(("\tx %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p)\n",
1615a7dfde8Smrg                  vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
1621b5d61b8Smrg                  vblank->pixmap->drawable.id, vblank->window->drawable.id,
1631b5d61b8Smrg                  vblank->crtc));
1641b5d61b8Smrg
1651b5d61b8Smrg    present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
1661b5d61b8Smrg    present_fence_destroy(vblank->idle_fence);
1671b5d61b8Smrg    dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
1681b5d61b8Smrg
1691b5d61b8Smrg    vblank->pixmap = NULL;
1701b5d61b8Smrg    vblank->idle_fence = NULL;
1711b5d61b8Smrg    vblank->flip = FALSE;
1721b5d61b8Smrg}
1731b5d61b8Smrg
1741b5d61b8Smrgvoid
1751b5d61b8Smrgpresent_vblank_destroy(present_vblank_ptr vblank)
1761b5d61b8Smrg{
1771b5d61b8Smrg    /* Remove vblank from window and screen lists */
1781b5d61b8Smrg    xorg_list_del(&vblank->window_list);
1791b5d61b8Smrg    /* Also make sure vblank is removed from event queue (wnmd) */
1801b5d61b8Smrg    xorg_list_del(&vblank->event_queue);
1811b5d61b8Smrg
1825a7dfde8Smrg    DebugPresent(("\td %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
1835a7dfde8Smrg                  vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
1841b5d61b8Smrg                  vblank->pixmap ? vblank->pixmap->drawable.id : 0,
1851b5d61b8Smrg                  vblank->window ? vblank->window->drawable.id : 0));
1861b5d61b8Smrg
1871b5d61b8Smrg    /* Drop pixmap reference */
1881b5d61b8Smrg    if (vblank->pixmap)
1891b5d61b8Smrg        dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
1901b5d61b8Smrg
1911b5d61b8Smrg    /* Free regions */
1921b5d61b8Smrg    if (vblank->valid)
1931b5d61b8Smrg        RegionDestroy(vblank->valid);
1941b5d61b8Smrg    if (vblank->update)
1951b5d61b8Smrg        RegionDestroy(vblank->update);
1961b5d61b8Smrg
1971b5d61b8Smrg    if (vblank->wait_fence)
1981b5d61b8Smrg        present_fence_destroy(vblank->wait_fence);
1991b5d61b8Smrg
2001b5d61b8Smrg    if (vblank->idle_fence)
2011b5d61b8Smrg        present_fence_destroy(vblank->idle_fence);
2021b5d61b8Smrg
2031b5d61b8Smrg    if (vblank->notifies)
2041b5d61b8Smrg        present_destroy_notifies(vblank->notifies, vblank->num_notifies);
2051b5d61b8Smrg
2061b5d61b8Smrg    free(vblank);
2071b5d61b8Smrg}
208