present_vblank.c revision 5a7dfde8
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 vblank = calloc (1, sizeof (present_vblank_rec)); 70 if (!vblank) 71 return NULL; 72 73 xorg_list_append(&vblank->window_list, &window_priv->vblank); 74 xorg_list_init(&vblank->event_queue); 75 76 vblank->screen = screen; 77 vblank->window = window; 78 vblank->pixmap = pixmap; 79 80 screen_priv->create_event_id(window_priv, vblank); 81 82 if (pixmap) { 83 vblank->kind = PresentCompleteKindPixmap; 84 pixmap->refcnt++; 85 } else 86 vblank->kind = PresentCompleteKindNotifyMSC; 87 88 vblank->serial = serial; 89 90 if (valid) { 91 vblank->valid = RegionDuplicate(valid); 92 if (!vblank->valid) 93 goto no_mem; 94 } 95 if (update) { 96 vblank->update = RegionDuplicate(update); 97 if (!vblank->update) 98 goto no_mem; 99 } 100 101 vblank->x_off = x_off; 102 vblank->y_off = y_off; 103 vblank->target_msc = target_msc; 104 vblank->exec_msc = target_msc; 105 vblank->crtc = target_crtc; 106 vblank->msc_offset = window_priv->msc_offset; 107 vblank->notifies = notifies; 108 vblank->num_notifies = num_notifies; 109 vblank->has_suboptimal = (options & PresentOptionSuboptimal); 110 vblank->flip_idler = FALSE; 111 112 if (pixmap != NULL && 113 !(options & PresentOptionCopy) && 114 capabilities) { 115 if (msc_is_after(target_msc, crtc_msc) && 116 screen_priv->check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason)) 117 { 118 vblank->flip = TRUE; 119 vblank->sync_flip = TRUE; 120 } else if ((*capabilities & PresentCapabilityAsync) && 121 screen_priv->check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason)) 122 { 123 vblank->flip = TRUE; 124 } 125 } 126 vblank->reason = reason; 127 128 if (wait_fence) { 129 vblank->wait_fence = present_fence_create(wait_fence); 130 if (!vblank->wait_fence) 131 goto no_mem; 132 } 133 134 if (idle_fence) { 135 vblank->idle_fence = present_fence_create(idle_fence); 136 if (!vblank->idle_fence) 137 goto no_mem; 138 } 139 140 if (pixmap) 141 DebugPresent(("q %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p) flip %d vsync %d serial %d\n", 142 vblank->event_id, vblank, target_msc, 143 vblank->pixmap->drawable.id, vblank->window->drawable.id, 144 target_crtc, vblank->flip, vblank->sync_flip, vblank->serial)); 145 return vblank; 146 147no_mem: 148 vblank->notifies = NULL; 149 present_vblank_destroy(vblank); 150 return NULL; 151} 152 153void 154present_vblank_scrap(present_vblank_ptr vblank) 155{ 156 DebugPresent(("\tx %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p)\n", 157 vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 158 vblank->pixmap->drawable.id, vblank->window->drawable.id, 159 vblank->crtc)); 160 161 present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); 162 present_fence_destroy(vblank->idle_fence); 163 dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 164 165 vblank->pixmap = NULL; 166 vblank->idle_fence = NULL; 167 vblank->flip = FALSE; 168} 169 170void 171present_vblank_destroy(present_vblank_ptr vblank) 172{ 173 /* Remove vblank from window and screen lists */ 174 xorg_list_del(&vblank->window_list); 175 /* Also make sure vblank is removed from event queue (wnmd) */ 176 xorg_list_del(&vblank->event_queue); 177 178 DebugPresent(("\td %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", 179 vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, 180 vblank->pixmap ? vblank->pixmap->drawable.id : 0, 181 vblank->window ? vblank->window->drawable.id : 0)); 182 183 /* Drop pixmap reference */ 184 if (vblank->pixmap) 185 dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); 186 187 /* Free regions */ 188 if (vblank->valid) 189 RegionDestroy(vblank->valid); 190 if (vblank->update) 191 RegionDestroy(vblank->update); 192 193 if (vblank->wait_fence) 194 present_fence_destroy(vblank->wait_fence); 195 196 if (vblank->idle_fence) 197 present_fence_destroy(vblank->idle_fence); 198 199 if (vblank->notifies) 200 present_destroy_notifies(vblank->notifies, vblank->num_notifies); 201 202 free(vblank); 203} 204