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