present_event.c revision 1b5d61b8
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 29static RESTYPE present_event_type; 30 31static int 32present_free_event(void *data, XID id) 33{ 34 present_event_ptr present_event = (present_event_ptr) data; 35 present_window_priv_ptr window_priv = present_window_priv(present_event->window); 36 present_event_ptr *previous, current; 37 38 for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { 39 if (current == present_event) { 40 *previous = present_event->next; 41 break; 42 } 43 } 44 free((void *) present_event); 45 return 1; 46 47} 48 49void 50present_free_events(WindowPtr window) 51{ 52 present_window_priv_ptr window_priv = present_window_priv(window); 53 present_event_ptr event; 54 55 if (!window_priv) 56 return; 57 58 while ((event = window_priv->events)) 59 FreeResource(event->id, RT_NONE); 60} 61 62static void 63present_event_swap(xGenericEvent *from, xGenericEvent *to) 64{ 65 *to = *from; 66 swaps(&to->sequenceNumber); 67 swapl(&to->length); 68 swaps(&to->evtype); 69 switch (from->evtype) { 70 case PresentConfigureNotify: { 71 xPresentConfigureNotify *c = (xPresentConfigureNotify *) to; 72 73 swapl(&c->eid); 74 swapl(&c->window); 75 swaps(&c->x); 76 swaps(&c->y); 77 swaps(&c->width); 78 swaps(&c->height); 79 swaps(&c->off_x); 80 swaps(&c->off_y); 81 swaps(&c->pixmap_width); 82 swaps(&c->pixmap_height); 83 swapl(&c->pixmap_flags); 84 break; 85 } 86 case PresentCompleteNotify: 87 { 88 xPresentCompleteNotify *c = (xPresentCompleteNotify *) to; 89 swapl(&c->eid); 90 swapl(&c->window); 91 swapl(&c->serial); 92 swapll(&c->ust); 93 swapll(&c->msc); 94 break; 95 } 96 case PresentIdleNotify: 97 { 98 xPresentIdleNotify *c = (xPresentIdleNotify *) to; 99 swapl(&c->eid); 100 swapl(&c->window); 101 swapl(&c->serial); 102 swapl(&c->idle_fence); 103 break; 104 } 105 } 106} 107 108void 109present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) 110{ 111 present_window_priv_ptr window_priv = present_window_priv(window); 112 113 if (window_priv) { 114 xPresentConfigureNotify cn = { 115 .type = GenericEvent, 116 .extension = present_request, 117 .length = (sizeof(xPresentConfigureNotify) - 32) >> 2, 118 .evtype = PresentConfigureNotify, 119 .eid = 0, 120 .window = window->drawable.id, 121 .x = x, 122 .y = y, 123 .width = w, 124 .height = h, 125 .off_x = 0, 126 .off_y = 0, 127 .pixmap_width = w, 128 .pixmap_height = h, 129 .pixmap_flags = 0 130 }; 131 present_event_ptr event; 132 133 for (event = window_priv->events; event; event = event->next) { 134 if (event->mask & (1 << PresentConfigureNotify)) { 135 cn.eid = event->id; 136 WriteEventsToClient(event->client, 1, (xEvent *) &cn); 137 } 138 } 139 } 140} 141 142static present_complete_notify_proc complete_notify; 143 144void 145present_register_complete_notify(present_complete_notify_proc proc) 146{ 147 complete_notify = proc; 148} 149 150void 151present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) 152{ 153 present_window_priv_ptr window_priv = present_window_priv(window); 154 155 if (window_priv) { 156 xPresentCompleteNotify cn = { 157 .type = GenericEvent, 158 .extension = present_request, 159 .length = (sizeof(xPresentCompleteNotify) - 32) >> 2, 160 .evtype = PresentCompleteNotify, 161 .kind = kind, 162 .mode = mode, 163 .eid = 0, 164 .window = window->drawable.id, 165 .serial = serial, 166 .ust = ust, 167 .msc = msc, 168 }; 169 present_event_ptr event; 170 171 for (event = window_priv->events; event; event = event->next) { 172 if (event->mask & PresentCompleteNotifyMask) { 173 cn.eid = event->id; 174 WriteEventsToClient(event->client, 1, (xEvent *) &cn); 175 } 176 } 177 } 178 if (complete_notify) 179 (*complete_notify)(window, kind, mode, serial, ust, msc); 180} 181 182void 183present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence) 184{ 185 present_window_priv_ptr window_priv = present_window_priv(window); 186 187 if (window_priv) { 188 xPresentIdleNotify in = { 189 .type = GenericEvent, 190 .extension = present_request, 191 .length = (sizeof(xPresentIdleNotify) - 32) >> 2, 192 .evtype = PresentIdleNotify, 193 .eid = 0, 194 .window = window->drawable.id, 195 .serial = serial, 196 .pixmap = pixmap->drawable.id, 197 .idle_fence = present_fence_id(idle_fence) 198 }; 199 present_event_ptr event; 200 201 for (event = window_priv->events; event; event = event->next) { 202 if (event->mask & PresentIdleNotifyMask) { 203 in.eid = event->id; 204 WriteEventsToClient(event->client, 1, (xEvent *) &in); 205 } 206 } 207 } 208} 209 210int 211present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) 212{ 213 present_window_priv_ptr window_priv; 214 present_event_ptr event; 215 int ret; 216 217 /* Check to see if we're modifying an existing event selection */ 218 ret = dixLookupResourceByType((void **) &event, eid, present_event_type, 219 client, DixWriteAccess); 220 if (ret == Success) { 221 /* Match error for the wrong window; also don't modify some other 222 * client's event selection 223 */ 224 if (event->window != window || event->client != client) 225 return BadMatch; 226 227 if (mask) 228 event->mask = mask; 229 else 230 FreeResource(eid, RT_NONE); 231 return Success; 232 } 233 if (ret != BadValue) 234 return ret; 235 236 if (mask == 0) 237 return Success; 238 239 LEGAL_NEW_RESOURCE(eid, client); 240 241 window_priv = present_get_window_priv(window, TRUE); 242 if (!window_priv) 243 return BadAlloc; 244 245 event = calloc (1, sizeof (present_event_rec)); 246 if (!event) 247 return BadAlloc; 248 249 event->client = client; 250 event->window = window; 251 event->id = eid; 252 event->mask = mask; 253 254 event->next = window_priv->events; 255 window_priv->events = event; 256 257 if (!AddResource(event->id, present_event_type, (void *) event)) 258 return BadAlloc; 259 260 return Success; 261} 262 263Bool 264present_event_init(void) 265{ 266 present_event_type = CreateNewResourceType(present_free_event, "PresentEvent"); 267 if (!present_event_type) 268 return FALSE; 269 270 GERegisterExtension(present_request, present_event_swap); 271 return TRUE; 272} 273