present_event.c revision 1b5d61b8
135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2013 Keith Packard 335c4bbdfSmrg * 435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its 535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that 635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright 735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and 835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or 935c4bbdfSmrg * publicity pertaining to distribution of the software without specific, 1035c4bbdfSmrg * written prior permission. The copyright holders make no representations 1135c4bbdfSmrg * about the suitability of this software for any purpose. It is provided "as 1235c4bbdfSmrg * is" without express or implied warranty. 1335c4bbdfSmrg * 1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2035c4bbdfSmrg * OF THIS SOFTWARE. 2135c4bbdfSmrg */ 2235c4bbdfSmrg 2335c4bbdfSmrg#ifdef HAVE_XORG_CONFIG_H 2435c4bbdfSmrg#include <xorg-config.h> 2535c4bbdfSmrg#endif 2635c4bbdfSmrg 2735c4bbdfSmrg#include "present_priv.h" 2835c4bbdfSmrg 2935c4bbdfSmrgstatic RESTYPE present_event_type; 3035c4bbdfSmrg 3135c4bbdfSmrgstatic int 3235c4bbdfSmrgpresent_free_event(void *data, XID id) 3335c4bbdfSmrg{ 3435c4bbdfSmrg present_event_ptr present_event = (present_event_ptr) data; 3535c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(present_event->window); 3635c4bbdfSmrg present_event_ptr *previous, current; 3735c4bbdfSmrg 3835c4bbdfSmrg for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { 3935c4bbdfSmrg if (current == present_event) { 4035c4bbdfSmrg *previous = present_event->next; 4135c4bbdfSmrg break; 4235c4bbdfSmrg } 4335c4bbdfSmrg } 4435c4bbdfSmrg free((void *) present_event); 4535c4bbdfSmrg return 1; 4635c4bbdfSmrg 4735c4bbdfSmrg} 4835c4bbdfSmrg 4935c4bbdfSmrgvoid 5035c4bbdfSmrgpresent_free_events(WindowPtr window) 5135c4bbdfSmrg{ 5235c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 5335c4bbdfSmrg present_event_ptr event; 5435c4bbdfSmrg 5535c4bbdfSmrg if (!window_priv) 5635c4bbdfSmrg return; 5735c4bbdfSmrg 5835c4bbdfSmrg while ((event = window_priv->events)) 5935c4bbdfSmrg FreeResource(event->id, RT_NONE); 6035c4bbdfSmrg} 6135c4bbdfSmrg 6235c4bbdfSmrgstatic void 6335c4bbdfSmrgpresent_event_swap(xGenericEvent *from, xGenericEvent *to) 6435c4bbdfSmrg{ 6535c4bbdfSmrg *to = *from; 6635c4bbdfSmrg swaps(&to->sequenceNumber); 6735c4bbdfSmrg swapl(&to->length); 6835c4bbdfSmrg swaps(&to->evtype); 6935c4bbdfSmrg switch (from->evtype) { 7035c4bbdfSmrg case PresentConfigureNotify: { 7135c4bbdfSmrg xPresentConfigureNotify *c = (xPresentConfigureNotify *) to; 7235c4bbdfSmrg 7335c4bbdfSmrg swapl(&c->eid); 7435c4bbdfSmrg swapl(&c->window); 7535c4bbdfSmrg swaps(&c->x); 7635c4bbdfSmrg swaps(&c->y); 7735c4bbdfSmrg swaps(&c->width); 7835c4bbdfSmrg swaps(&c->height); 7935c4bbdfSmrg swaps(&c->off_x); 8035c4bbdfSmrg swaps(&c->off_y); 8135c4bbdfSmrg swaps(&c->pixmap_width); 8235c4bbdfSmrg swaps(&c->pixmap_height); 8335c4bbdfSmrg swapl(&c->pixmap_flags); 8435c4bbdfSmrg break; 8535c4bbdfSmrg } 8635c4bbdfSmrg case PresentCompleteNotify: 8735c4bbdfSmrg { 8835c4bbdfSmrg xPresentCompleteNotify *c = (xPresentCompleteNotify *) to; 8935c4bbdfSmrg swapl(&c->eid); 9035c4bbdfSmrg swapl(&c->window); 9135c4bbdfSmrg swapl(&c->serial); 9235c4bbdfSmrg swapll(&c->ust); 9335c4bbdfSmrg swapll(&c->msc); 941b5d61b8Smrg break; 9535c4bbdfSmrg } 9635c4bbdfSmrg case PresentIdleNotify: 9735c4bbdfSmrg { 9835c4bbdfSmrg xPresentIdleNotify *c = (xPresentIdleNotify *) to; 9935c4bbdfSmrg swapl(&c->eid); 10035c4bbdfSmrg swapl(&c->window); 10135c4bbdfSmrg swapl(&c->serial); 10235c4bbdfSmrg swapl(&c->idle_fence); 1031b5d61b8Smrg break; 10435c4bbdfSmrg } 10535c4bbdfSmrg } 10635c4bbdfSmrg} 10735c4bbdfSmrg 10835c4bbdfSmrgvoid 10935c4bbdfSmrgpresent_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) 11035c4bbdfSmrg{ 11135c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 11235c4bbdfSmrg 11335c4bbdfSmrg if (window_priv) { 11435c4bbdfSmrg xPresentConfigureNotify cn = { 11535c4bbdfSmrg .type = GenericEvent, 11635c4bbdfSmrg .extension = present_request, 11735c4bbdfSmrg .length = (sizeof(xPresentConfigureNotify) - 32) >> 2, 11835c4bbdfSmrg .evtype = PresentConfigureNotify, 11935c4bbdfSmrg .eid = 0, 12035c4bbdfSmrg .window = window->drawable.id, 12135c4bbdfSmrg .x = x, 12235c4bbdfSmrg .y = y, 12335c4bbdfSmrg .width = w, 12435c4bbdfSmrg .height = h, 12535c4bbdfSmrg .off_x = 0, 12635c4bbdfSmrg .off_y = 0, 12735c4bbdfSmrg .pixmap_width = w, 12835c4bbdfSmrg .pixmap_height = h, 12935c4bbdfSmrg .pixmap_flags = 0 13035c4bbdfSmrg }; 13135c4bbdfSmrg present_event_ptr event; 13235c4bbdfSmrg 13335c4bbdfSmrg for (event = window_priv->events; event; event = event->next) { 13435c4bbdfSmrg if (event->mask & (1 << PresentConfigureNotify)) { 13535c4bbdfSmrg cn.eid = event->id; 13635c4bbdfSmrg WriteEventsToClient(event->client, 1, (xEvent *) &cn); 13735c4bbdfSmrg } 13835c4bbdfSmrg } 13935c4bbdfSmrg } 14035c4bbdfSmrg} 14135c4bbdfSmrg 14235c4bbdfSmrgstatic present_complete_notify_proc complete_notify; 14335c4bbdfSmrg 14435c4bbdfSmrgvoid 14535c4bbdfSmrgpresent_register_complete_notify(present_complete_notify_proc proc) 14635c4bbdfSmrg{ 14735c4bbdfSmrg complete_notify = proc; 14835c4bbdfSmrg} 14935c4bbdfSmrg 15035c4bbdfSmrgvoid 15135c4bbdfSmrgpresent_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) 15235c4bbdfSmrg{ 15335c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 15435c4bbdfSmrg 15535c4bbdfSmrg if (window_priv) { 15635c4bbdfSmrg xPresentCompleteNotify cn = { 15735c4bbdfSmrg .type = GenericEvent, 15835c4bbdfSmrg .extension = present_request, 15935c4bbdfSmrg .length = (sizeof(xPresentCompleteNotify) - 32) >> 2, 16035c4bbdfSmrg .evtype = PresentCompleteNotify, 16135c4bbdfSmrg .kind = kind, 16235c4bbdfSmrg .mode = mode, 16335c4bbdfSmrg .eid = 0, 16435c4bbdfSmrg .window = window->drawable.id, 16535c4bbdfSmrg .serial = serial, 16635c4bbdfSmrg .ust = ust, 16735c4bbdfSmrg .msc = msc, 16835c4bbdfSmrg }; 16935c4bbdfSmrg present_event_ptr event; 17035c4bbdfSmrg 17135c4bbdfSmrg for (event = window_priv->events; event; event = event->next) { 17235c4bbdfSmrg if (event->mask & PresentCompleteNotifyMask) { 17335c4bbdfSmrg cn.eid = event->id; 17435c4bbdfSmrg WriteEventsToClient(event->client, 1, (xEvent *) &cn); 17535c4bbdfSmrg } 17635c4bbdfSmrg } 17735c4bbdfSmrg } 17835c4bbdfSmrg if (complete_notify) 17935c4bbdfSmrg (*complete_notify)(window, kind, mode, serial, ust, msc); 18035c4bbdfSmrg} 18135c4bbdfSmrg 18235c4bbdfSmrgvoid 18335c4bbdfSmrgpresent_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence) 18435c4bbdfSmrg{ 18535c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 18635c4bbdfSmrg 18735c4bbdfSmrg if (window_priv) { 18835c4bbdfSmrg xPresentIdleNotify in = { 18935c4bbdfSmrg .type = GenericEvent, 19035c4bbdfSmrg .extension = present_request, 19135c4bbdfSmrg .length = (sizeof(xPresentIdleNotify) - 32) >> 2, 19235c4bbdfSmrg .evtype = PresentIdleNotify, 19335c4bbdfSmrg .eid = 0, 19435c4bbdfSmrg .window = window->drawable.id, 19535c4bbdfSmrg .serial = serial, 19635c4bbdfSmrg .pixmap = pixmap->drawable.id, 19735c4bbdfSmrg .idle_fence = present_fence_id(idle_fence) 19835c4bbdfSmrg }; 19935c4bbdfSmrg present_event_ptr event; 20035c4bbdfSmrg 20135c4bbdfSmrg for (event = window_priv->events; event; event = event->next) { 20235c4bbdfSmrg if (event->mask & PresentIdleNotifyMask) { 20335c4bbdfSmrg in.eid = event->id; 20435c4bbdfSmrg WriteEventsToClient(event->client, 1, (xEvent *) &in); 20535c4bbdfSmrg } 20635c4bbdfSmrg } 20735c4bbdfSmrg } 20835c4bbdfSmrg} 20935c4bbdfSmrg 21035c4bbdfSmrgint 21135c4bbdfSmrgpresent_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) 21235c4bbdfSmrg{ 2131b5d61b8Smrg present_window_priv_ptr window_priv; 21435c4bbdfSmrg present_event_ptr event; 2151b5d61b8Smrg int ret; 2161b5d61b8Smrg 2171b5d61b8Smrg /* Check to see if we're modifying an existing event selection */ 2181b5d61b8Smrg ret = dixLookupResourceByType((void **) &event, eid, present_event_type, 2191b5d61b8Smrg client, DixWriteAccess); 2201b5d61b8Smrg if (ret == Success) { 2211b5d61b8Smrg /* Match error for the wrong window; also don't modify some other 2221b5d61b8Smrg * client's event selection 2231b5d61b8Smrg */ 2241b5d61b8Smrg if (event->window != window || event->client != client) 2251b5d61b8Smrg return BadMatch; 22635c4bbdfSmrg 22735c4bbdfSmrg if (mask) 2281b5d61b8Smrg event->mask = mask; 2291b5d61b8Smrg else 2301b5d61b8Smrg FreeResource(eid, RT_NONE); 23135c4bbdfSmrg return Success; 23235c4bbdfSmrg } 2331b5d61b8Smrg if (ret != BadValue) 2341b5d61b8Smrg return ret; 2351b5d61b8Smrg 2361b5d61b8Smrg if (mask == 0) 2371b5d61b8Smrg return Success; 2381b5d61b8Smrg 2391b5d61b8Smrg LEGAL_NEW_RESOURCE(eid, client); 2401b5d61b8Smrg 2411b5d61b8Smrg window_priv = present_get_window_priv(window, TRUE); 2421b5d61b8Smrg if (!window_priv) 2431b5d61b8Smrg return BadAlloc; 24435c4bbdfSmrg 24535c4bbdfSmrg event = calloc (1, sizeof (present_event_rec)); 24635c4bbdfSmrg if (!event) 24735c4bbdfSmrg return BadAlloc; 24835c4bbdfSmrg 24935c4bbdfSmrg event->client = client; 25035c4bbdfSmrg event->window = window; 25135c4bbdfSmrg event->id = eid; 25235c4bbdfSmrg event->mask = mask; 25335c4bbdfSmrg 25435c4bbdfSmrg event->next = window_priv->events; 25535c4bbdfSmrg window_priv->events = event; 25635c4bbdfSmrg 25735c4bbdfSmrg if (!AddResource(event->id, present_event_type, (void *) event)) 25835c4bbdfSmrg return BadAlloc; 25935c4bbdfSmrg 26035c4bbdfSmrg return Success; 26135c4bbdfSmrg} 26235c4bbdfSmrg 26335c4bbdfSmrgBool 26435c4bbdfSmrgpresent_event_init(void) 26535c4bbdfSmrg{ 26635c4bbdfSmrg present_event_type = CreateNewResourceType(present_free_event, "PresentEvent"); 26735c4bbdfSmrg if (!present_event_type) 26835c4bbdfSmrg return FALSE; 26935c4bbdfSmrg 27035c4bbdfSmrg GERegisterExtension(present_request, present_event_swap); 27135c4bbdfSmrg return TRUE; 27235c4bbdfSmrg} 273