present_vblank.c revision a035e2b2
1/* 2 * Copyright © 2013 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_XORG_CONFIG_H 24#include <xorg-config.h> 25#endif 26 27#include "present_priv.h" 28 29void 30present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc) 31{ 32 int n; 33 34 if (vblank->window) 35 present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); 36 for (n = 0; n < vblank->num_notifies; n++) { 37 WindowPtr window = vblank->notifies[n].window; 38 CARD32 serial = vblank->notifies[n].serial; 39 40 if (window) 41 present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset); 42 } 43} 44 45present_vblank_ptr 46present_vblank_create(WindowPtr window, 47 PixmapPtr pixmap, 48 CARD32 serial, 49 RegionPtr valid, 50 RegionPtr update, 51 int16_t x_off, 52 int16_t y_off, 53 RRCrtcPtr target_crtc, 54 SyncFence *wait_fence, 55 SyncFence *idle_fence, 56 uint32_t options, 57 const uint32_t *capabilities, 58 present_notify_ptr notifies, 59 int num_notifies, 60 uint64_t target_msc, 61 uint64_t crtc_msc) 62{ 63 ScreenPtr screen = window->drawable.pScreen; 64 present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); 65 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 66 present_vblank_ptr vblank; 67 PresentFlipReason reason = PRESENT_FLIP_REASON_UNKNOWN; 68 69 if (target_crtc) { 70 screen_priv = present_screen_priv(target_crtc->pScreen); 71 } 72 73 vblank = calloc (1, sizeof (present_vblank_rec)); 74 if (!vblank) 75 return NULL; 76 77 xorg_list_append(&vblank->window_list, &window_priv->vblank); 78 xorg_list_init(&vblank->event_queue); 79 80 vblank->screen = screen; 81 vblank->window = window; 82 vblank->pixmap = pixmap; 83 84 screen_priv->create_event_id(window_priv, vblank); 85 86 if (pixmap) { 87 vblank->kind = PresentCompleteKindPixmap; 88 pixmap->refcnt++; 89 } else 90 vblank->kind = PresentCompleteKindNotifyMSC; 91 92 vblank->serial = serial; 93 94 if (valid) { 95 vblank->valid = RegionDuplicate(valid); 96 if (!vblank->valid) 97 goto no_mem; 98 } 99 if (update) { 100 vblank->update = RegionDuplicate(update); 101 if (!vblank->update) 102 goto no_mem; 103 } 104 105 vblank->x_off = x_off; 106 vblank->y_off = y_off; 107 vblank->target_msc = target_msc; 108 vblank->exec_msc = target_msc; 109 vblank->crtc = target_crtc; 110 vblank->msc_offset = window_priv->msc_offset; 111 vblank->notifies = notifies; 112 vblank->num_notifies = num_notifies; 113 vblank->has_suboptimal = (options & PresentOptionSuboptimal); 114 vblank->flip_idler = FALSE; 115 116 if (pixmap != NULL && 117 !(options & PresentOptionCopy) && 118 capabilities) { 119 if (msc_is_after(target_msc, crtc_msc) && 120 screen_priv->check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason)) 121 { 122 vblank->flip = TRUE; 123 vblank->sync_flip = TRUE; 124 } else if ((*capabilities & PresentCapabilityAsync) && 125 screen_priv->check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason)) 126 { 127 vblank->flip = TRUE; 128 } 129 } 130 vblank->reason = reason; 131 132 if (wait_fence) { 133 vblank->wait_fence = present_fence_create(wait_fence); 134 if (!vblank->wait_fence) 135 goto no_mem; 136 } 137 138 if (idle_fence) { 139 vblank->idle_fence = present_fence_create(idle_fence); 140 if (!vblank->idle_fence) 141 goto no_mem; 142 } 143 144 if (pixmap) 145 DebugPresent(("q %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p) flip %d vsync %d serial %d\n", 146 vblank->event_id, vblank, target_msc, 147 vblank->pixmap->drawable.id, vblank->window->drawable.id, 148 target_crtc, vblank->flip, vblank->sync_flip, vblank->serial)); 149 return vblank; 150 151no_mem: 152 vblank->notifies = NULL; 153 present_vblank_destroy(vblank); 154 return NULL; 155} 156 157void 158present_vblank_scrap(present_vblank_ptr vblank) 159{ 160 DebugPresent(("\tx %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p)\n", 161 vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 162 vblank->pixmap->drawable.id, vblank->window->drawable.id, 163 vblank->crtc)); 164 165 present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); 166 present_fence_destroy(vblank->idle_fence); 167 dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 168 169 vblank->pixmap = NULL; 170 vblank->idle_fence = NULL; 171 vblank->flip = FALSE; 172} 173 174void 175present_vblank_destroy(present_vblank_ptr vblank) 176{ 177 /* Remove vblank from window and screen lists */ 178 xorg_list_del(&vblank->window_list); 179 /* Also make sure vblank is removed from event queue (wnmd) */ 180 xorg_list_del(&vblank->event_queue); 181 182 DebugPresent(("\td %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", 183 vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 184 vblank->pixmap ? vblank->pixmap->drawable.id : 0, 185 vblank->window ? vblank->window->drawable.id : 0)); 186 187 /* Drop pixmap reference */ 188 if (vblank->pixmap) 189 dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 190 191 /* Free regions */ 192 if (vblank->valid) 193 RegionDestroy(vblank->valid); 194 if (vblank->update) 195 RegionDestroy(vblank->update); 196 197 if (vblank->wait_fence) 198 present_fence_destroy(vblank->wait_fence); 199 200 if (vblank->idle_fence) 201 present_fence_destroy(vblank->idle_fence); 202 203 if (vblank->notifies) 204 present_destroy_notifies(vblank->notifies, vblank->num_notifies); 205 206 free(vblank); 207} 208