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#include "present_priv.h" 24 25void 26present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc) 27{ 28 int n; 29 30 if (vblank->window) 31 present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); 32 for (n = 0; n < vblank->num_notifies; n++) { 33 WindowPtr window = vblank->notifies[n].window; 34 CARD32 serial = vblank->notifies[n].serial; 35 36 if (window) 37 present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset); 38 } 39} 40 41/* The memory vblank points to must be 0-initialized before calling this function. 42 * 43 * If this function returns FALSE, present_vblank_destroy must be called to clean 44 * up. 45 */ 46Bool 47present_vblank_init(present_vblank_ptr vblank, 48 WindowPtr window, 49 PixmapPtr pixmap, 50 CARD32 serial, 51 RegionPtr valid, 52 RegionPtr update, 53 int16_t x_off, 54 int16_t y_off, 55 RRCrtcPtr target_crtc, 56 SyncFence *wait_fence, 57 SyncFence *idle_fence, 58 uint32_t options, 59 const uint32_t capabilities, 60 present_notify_ptr notifies, 61 int num_notifies, 62 uint64_t target_msc, 63 uint64_t crtc_msc) 64{ 65 ScreenPtr screen = window->drawable.pScreen; 66 present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); 67 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 68 PresentFlipReason reason = PRESENT_FLIP_REASON_UNKNOWN; 69 70 if (target_crtc) { 71 screen_priv = present_screen_priv(target_crtc->pScreen); 72 } 73 74 xorg_list_append(&vblank->window_list, &window_priv->vblank); 75 xorg_list_init(&vblank->event_queue); 76 77 vblank->screen = screen; 78 vblank->window = window; 79 vblank->pixmap = pixmap; 80 81 if (pixmap) { 82 vblank->kind = PresentCompleteKindPixmap; 83 pixmap->refcnt++; 84 } else 85 vblank->kind = PresentCompleteKindNotifyMSC; 86 87 vblank->serial = serial; 88 89 if (valid) { 90 vblank->valid = RegionDuplicate(valid); 91 if (!vblank->valid) 92 goto no_mem; 93 } 94 if (update) { 95 vblank->update = RegionDuplicate(update); 96 if (!vblank->update) 97 goto no_mem; 98 } 99 100 vblank->x_off = x_off; 101 vblank->y_off = y_off; 102 vblank->target_msc = target_msc; 103 vblank->exec_msc = target_msc; 104 vblank->crtc = target_crtc; 105 vblank->msc_offset = window_priv->msc_offset; 106 vblank->notifies = notifies; 107 vblank->num_notifies = num_notifies; 108 vblank->has_suboptimal = (options & PresentOptionSuboptimal); 109 110 if (pixmap != NULL && 111 !(options & PresentOptionCopy) && 112 screen_priv->check_flip) { 113 if (msc_is_after(target_msc, crtc_msc) && 114 screen_priv->check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason)) 115 { 116 vblank->flip = TRUE; 117 vblank->sync_flip = TRUE; 118 } else if ((capabilities & PresentCapabilityAsync) && 119 screen_priv->check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason)) 120 { 121 vblank->flip = TRUE; 122 } 123 } 124 vblank->reason = reason; 125 126 if (wait_fence) { 127 vblank->wait_fence = present_fence_create(wait_fence); 128 if (!vblank->wait_fence) 129 goto no_mem; 130 } 131 132 if (idle_fence) { 133 vblank->idle_fence = present_fence_create(idle_fence); 134 if (!vblank->idle_fence) 135 goto no_mem; 136 } 137 138 if (pixmap) 139 DebugPresent(("q %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p) flip %d vsync %d serial %d\n", 140 vblank->event_id, vblank, target_msc, 141 vblank->pixmap->drawable.id, vblank->window->drawable.id, 142 target_crtc, vblank->flip, vblank->sync_flip, vblank->serial)); 143 return TRUE; 144 145no_mem: 146 vblank->notifies = NULL; 147 return FALSE; 148} 149 150present_vblank_ptr 151present_vblank_create(WindowPtr window, 152 PixmapPtr pixmap, 153 CARD32 serial, 154 RegionPtr valid, 155 RegionPtr update, 156 int16_t x_off, 157 int16_t y_off, 158 RRCrtcPtr target_crtc, 159 SyncFence *wait_fence, 160 SyncFence *idle_fence, 161 uint32_t options, 162 const uint32_t capabilities, 163 present_notify_ptr notifies, 164 int num_notifies, 165 uint64_t target_msc, 166 uint64_t crtc_msc) 167{ 168 present_vblank_ptr vblank = calloc(1, sizeof(present_vblank_rec)); 169 170 if (!vblank) 171 return NULL; 172 173 if (present_vblank_init(vblank, window, pixmap, serial, valid, update, 174 x_off, y_off, target_crtc, wait_fence, idle_fence, 175 options, capabilities, notifies, num_notifies, 176 target_msc, crtc_msc)) 177 return vblank; 178 179 present_vblank_destroy(vblank); 180 return NULL; 181} 182 183void 184present_vblank_scrap(present_vblank_ptr vblank) 185{ 186 DebugPresent(("\tx %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p)\n", 187 vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 188 vblank->pixmap->drawable.id, vblank->window->drawable.id, 189 vblank->crtc)); 190 191 present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); 192 present_fence_destroy(vblank->idle_fence); 193 dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 194 195 vblank->pixmap = NULL; 196 vblank->idle_fence = NULL; 197 vblank->flip = FALSE; 198} 199 200void 201present_vblank_destroy(present_vblank_ptr vblank) 202{ 203 /* Remove vblank from window and screen lists */ 204 xorg_list_del(&vblank->window_list); 205 /* Also make sure vblank is removed from event queue (wnmd) */ 206 xorg_list_del(&vblank->event_queue); 207 208 DebugPresent(("\td %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", 209 vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 210 vblank->pixmap ? vblank->pixmap->drawable.id : 0, 211 vblank->window ? vblank->window->drawable.id : 0)); 212 213 /* Drop pixmap reference */ 214 if (vblank->pixmap) 215 dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 216 217 /* Free regions */ 218 if (vblank->valid) 219 RegionDestroy(vblank->valid); 220 if (vblank->update) 221 RegionDestroy(vblank->update); 222 223 if (vblank->wait_fence) 224 present_fence_destroy(vblank->wait_fence); 225 226 if (vblank->idle_fence) 227 present_fence_destroy(vblank->idle_fence); 228 229 if (vblank->notifies) 230 present_destroy_notifies(vblank->notifies, vblank->num_notifies); 231 232 free(vblank); 233} 234