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#include "present_priv.h" 241b5d61b8Smrg 251b5d61b8Smrgvoid 261b5d61b8Smrgpresent_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc) 271b5d61b8Smrg{ 281b5d61b8Smrg int n; 291b5d61b8Smrg 301b5d61b8Smrg if (vblank->window) 311b5d61b8Smrg present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); 321b5d61b8Smrg for (n = 0; n < vblank->num_notifies; n++) { 331b5d61b8Smrg WindowPtr window = vblank->notifies[n].window; 341b5d61b8Smrg CARD32 serial = vblank->notifies[n].serial; 351b5d61b8Smrg 361b5d61b8Smrg if (window) 371b5d61b8Smrg present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset); 381b5d61b8Smrg } 391b5d61b8Smrg} 401b5d61b8Smrg 41ed6184dfSmrg/* The memory vblank points to must be 0-initialized before calling this function. 42ed6184dfSmrg * 43ed6184dfSmrg * If this function returns FALSE, present_vblank_destroy must be called to clean 44ed6184dfSmrg * up. 45ed6184dfSmrg */ 46ed6184dfSmrgBool 47ed6184dfSmrgpresent_vblank_init(present_vblank_ptr vblank, 48ed6184dfSmrg WindowPtr window, 49ed6184dfSmrg PixmapPtr pixmap, 50ed6184dfSmrg CARD32 serial, 51ed6184dfSmrg RegionPtr valid, 52ed6184dfSmrg RegionPtr update, 53ed6184dfSmrg int16_t x_off, 54ed6184dfSmrg int16_t y_off, 55ed6184dfSmrg RRCrtcPtr target_crtc, 56ed6184dfSmrg SyncFence *wait_fence, 57ed6184dfSmrg SyncFence *idle_fence, 58ed6184dfSmrg uint32_t options, 59ed6184dfSmrg const uint32_t capabilities, 60ed6184dfSmrg present_notify_ptr notifies, 61ed6184dfSmrg int num_notifies, 62ed6184dfSmrg uint64_t target_msc, 63ed6184dfSmrg uint64_t crtc_msc) 641b5d61b8Smrg{ 651b5d61b8Smrg ScreenPtr screen = window->drawable.pScreen; 661b5d61b8Smrg present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); 671b5d61b8Smrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 681b5d61b8Smrg PresentFlipReason reason = PRESENT_FLIP_REASON_UNKNOWN; 691b5d61b8Smrg 70a035e2b2Smrg if (target_crtc) { 71a035e2b2Smrg screen_priv = present_screen_priv(target_crtc->pScreen); 72a035e2b2Smrg } 73a035e2b2Smrg 741b5d61b8Smrg xorg_list_append(&vblank->window_list, &window_priv->vblank); 751b5d61b8Smrg xorg_list_init(&vblank->event_queue); 761b5d61b8Smrg 771b5d61b8Smrg vblank->screen = screen; 781b5d61b8Smrg vblank->window = window; 791b5d61b8Smrg vblank->pixmap = pixmap; 801b5d61b8Smrg 811b5d61b8Smrg if (pixmap) { 821b5d61b8Smrg vblank->kind = PresentCompleteKindPixmap; 831b5d61b8Smrg pixmap->refcnt++; 841b5d61b8Smrg } else 851b5d61b8Smrg vblank->kind = PresentCompleteKindNotifyMSC; 861b5d61b8Smrg 871b5d61b8Smrg vblank->serial = serial; 881b5d61b8Smrg 891b5d61b8Smrg if (valid) { 901b5d61b8Smrg vblank->valid = RegionDuplicate(valid); 911b5d61b8Smrg if (!vblank->valid) 921b5d61b8Smrg goto no_mem; 931b5d61b8Smrg } 941b5d61b8Smrg if (update) { 951b5d61b8Smrg vblank->update = RegionDuplicate(update); 961b5d61b8Smrg if (!vblank->update) 971b5d61b8Smrg goto no_mem; 981b5d61b8Smrg } 991b5d61b8Smrg 1001b5d61b8Smrg vblank->x_off = x_off; 1011b5d61b8Smrg vblank->y_off = y_off; 1025a7dfde8Smrg vblank->target_msc = target_msc; 1035a7dfde8Smrg vblank->exec_msc = target_msc; 1041b5d61b8Smrg vblank->crtc = target_crtc; 1051b5d61b8Smrg vblank->msc_offset = window_priv->msc_offset; 1061b5d61b8Smrg vblank->notifies = notifies; 1071b5d61b8Smrg vblank->num_notifies = num_notifies; 1081b5d61b8Smrg vblank->has_suboptimal = (options & PresentOptionSuboptimal); 1091b5d61b8Smrg 1101b5d61b8Smrg if (pixmap != NULL && 1111b5d61b8Smrg !(options & PresentOptionCopy) && 112ed6184dfSmrg screen_priv->check_flip) { 1135a7dfde8Smrg if (msc_is_after(target_msc, crtc_msc) && 1141b5d61b8Smrg screen_priv->check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason)) 1151b5d61b8Smrg { 1161b5d61b8Smrg vblank->flip = TRUE; 1171b5d61b8Smrg vblank->sync_flip = TRUE; 118ed6184dfSmrg } else if ((capabilities & PresentCapabilityAsync) && 1191b5d61b8Smrg screen_priv->check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason)) 1201b5d61b8Smrg { 1211b5d61b8Smrg vblank->flip = TRUE; 1221b5d61b8Smrg } 1231b5d61b8Smrg } 1241b5d61b8Smrg vblank->reason = reason; 1251b5d61b8Smrg 1261b5d61b8Smrg if (wait_fence) { 1271b5d61b8Smrg vblank->wait_fence = present_fence_create(wait_fence); 1281b5d61b8Smrg if (!vblank->wait_fence) 1291b5d61b8Smrg goto no_mem; 1301b5d61b8Smrg } 1311b5d61b8Smrg 1321b5d61b8Smrg if (idle_fence) { 1331b5d61b8Smrg vblank->idle_fence = present_fence_create(idle_fence); 1341b5d61b8Smrg if (!vblank->idle_fence) 1351b5d61b8Smrg goto no_mem; 1361b5d61b8Smrg } 1371b5d61b8Smrg 1381b5d61b8Smrg if (pixmap) 139e23ec014Smrg DebugPresent(("q %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p) flip %d vsync %d serial %d\n", 1405a7dfde8Smrg vblank->event_id, vblank, target_msc, 1411b5d61b8Smrg vblank->pixmap->drawable.id, vblank->window->drawable.id, 1421b5d61b8Smrg target_crtc, vblank->flip, vblank->sync_flip, vblank->serial)); 143ed6184dfSmrg return TRUE; 1441b5d61b8Smrg 1451b5d61b8Smrgno_mem: 1461b5d61b8Smrg vblank->notifies = NULL; 147ed6184dfSmrg return FALSE; 148ed6184dfSmrg} 149ed6184dfSmrg 150ed6184dfSmrgpresent_vblank_ptr 151ed6184dfSmrgpresent_vblank_create(WindowPtr window, 152ed6184dfSmrg PixmapPtr pixmap, 153ed6184dfSmrg CARD32 serial, 154ed6184dfSmrg RegionPtr valid, 155ed6184dfSmrg RegionPtr update, 156ed6184dfSmrg int16_t x_off, 157ed6184dfSmrg int16_t y_off, 158ed6184dfSmrg RRCrtcPtr target_crtc, 159ed6184dfSmrg SyncFence *wait_fence, 160ed6184dfSmrg SyncFence *idle_fence, 161ed6184dfSmrg uint32_t options, 162ed6184dfSmrg const uint32_t capabilities, 163ed6184dfSmrg present_notify_ptr notifies, 164ed6184dfSmrg int num_notifies, 165ed6184dfSmrg uint64_t target_msc, 166ed6184dfSmrg uint64_t crtc_msc) 167ed6184dfSmrg{ 168ed6184dfSmrg present_vblank_ptr vblank = calloc(1, sizeof(present_vblank_rec)); 169ed6184dfSmrg 170ed6184dfSmrg if (!vblank) 171ed6184dfSmrg return NULL; 172ed6184dfSmrg 173ed6184dfSmrg if (present_vblank_init(vblank, window, pixmap, serial, valid, update, 174ed6184dfSmrg x_off, y_off, target_crtc, wait_fence, idle_fence, 175ed6184dfSmrg options, capabilities, notifies, num_notifies, 176ed6184dfSmrg target_msc, crtc_msc)) 177ed6184dfSmrg return vblank; 178ed6184dfSmrg 1791b5d61b8Smrg present_vblank_destroy(vblank); 1801b5d61b8Smrg return NULL; 1811b5d61b8Smrg} 1821b5d61b8Smrg 1831b5d61b8Smrgvoid 1841b5d61b8Smrgpresent_vblank_scrap(present_vblank_ptr vblank) 1851b5d61b8Smrg{ 1865a7dfde8Smrg DebugPresent(("\tx %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p)\n", 1875a7dfde8Smrg vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 1881b5d61b8Smrg vblank->pixmap->drawable.id, vblank->window->drawable.id, 1891b5d61b8Smrg vblank->crtc)); 1901b5d61b8Smrg 1911b5d61b8Smrg present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); 1921b5d61b8Smrg present_fence_destroy(vblank->idle_fence); 1931b5d61b8Smrg dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 1941b5d61b8Smrg 1951b5d61b8Smrg vblank->pixmap = NULL; 1961b5d61b8Smrg vblank->idle_fence = NULL; 1971b5d61b8Smrg vblank->flip = FALSE; 1981b5d61b8Smrg} 1991b5d61b8Smrg 2001b5d61b8Smrgvoid 2011b5d61b8Smrgpresent_vblank_destroy(present_vblank_ptr vblank) 2021b5d61b8Smrg{ 2031b5d61b8Smrg /* Remove vblank from window and screen lists */ 2041b5d61b8Smrg xorg_list_del(&vblank->window_list); 2051b5d61b8Smrg /* Also make sure vblank is removed from event queue (wnmd) */ 2061b5d61b8Smrg xorg_list_del(&vblank->event_queue); 2071b5d61b8Smrg 2085a7dfde8Smrg DebugPresent(("\td %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", 2095a7dfde8Smrg vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 2101b5d61b8Smrg vblank->pixmap ? vblank->pixmap->drawable.id : 0, 2111b5d61b8Smrg vblank->window ? vblank->window->drawable.id : 0)); 2121b5d61b8Smrg 2131b5d61b8Smrg /* Drop pixmap reference */ 2141b5d61b8Smrg if (vblank->pixmap) 2151b5d61b8Smrg dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 2161b5d61b8Smrg 2171b5d61b8Smrg /* Free regions */ 2181b5d61b8Smrg if (vblank->valid) 2191b5d61b8Smrg RegionDestroy(vblank->valid); 2201b5d61b8Smrg if (vblank->update) 2211b5d61b8Smrg RegionDestroy(vblank->update); 2221b5d61b8Smrg 2231b5d61b8Smrg if (vblank->wait_fence) 2241b5d61b8Smrg present_fence_destroy(vblank->wait_fence); 2251b5d61b8Smrg 2261b5d61b8Smrg if (vblank->idle_fence) 2271b5d61b8Smrg present_fence_destroy(vblank->idle_fence); 2281b5d61b8Smrg 2291b5d61b8Smrg if (vblank->notifies) 2301b5d61b8Smrg present_destroy_notifies(vblank->notifies, vblank->num_notifies); 2311b5d61b8Smrg 2321b5d61b8Smrg free(vblank); 2331b5d61b8Smrg} 234