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 = &current->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