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#include "present_priv.h"
2435c4bbdfSmrg
2535c4bbdfSmrgstatic RESTYPE present_event_type;
2635c4bbdfSmrg
2735c4bbdfSmrgstatic int
2835c4bbdfSmrgpresent_free_event(void *data, XID id)
2935c4bbdfSmrg{
3035c4bbdfSmrg    present_event_ptr present_event = (present_event_ptr) data;
3135c4bbdfSmrg    present_window_priv_ptr window_priv = present_window_priv(present_event->window);
3235c4bbdfSmrg    present_event_ptr *previous, current;
3335c4bbdfSmrg
3435c4bbdfSmrg    for (previous = &window_priv->events; (current = *previous); previous = &current->next) {
3535c4bbdfSmrg        if (current == present_event) {
3635c4bbdfSmrg            *previous = present_event->next;
3735c4bbdfSmrg            break;
3835c4bbdfSmrg        }
3935c4bbdfSmrg    }
4035c4bbdfSmrg    free((void *) present_event);
4135c4bbdfSmrg    return 1;
4235c4bbdfSmrg
4335c4bbdfSmrg}
4435c4bbdfSmrg
4535c4bbdfSmrgvoid
4635c4bbdfSmrgpresent_free_events(WindowPtr window)
4735c4bbdfSmrg{
4835c4bbdfSmrg    present_window_priv_ptr window_priv = present_window_priv(window);
4935c4bbdfSmrg    present_event_ptr event;
5035c4bbdfSmrg
5135c4bbdfSmrg    if (!window_priv)
5235c4bbdfSmrg        return;
5335c4bbdfSmrg
5435c4bbdfSmrg    while ((event = window_priv->events))
5535c4bbdfSmrg        FreeResource(event->id, RT_NONE);
5635c4bbdfSmrg}
5735c4bbdfSmrg
5835c4bbdfSmrgstatic void
5935c4bbdfSmrgpresent_event_swap(xGenericEvent *from, xGenericEvent *to)
6035c4bbdfSmrg{
6135c4bbdfSmrg    *to = *from;
6235c4bbdfSmrg    swaps(&to->sequenceNumber);
6335c4bbdfSmrg    swapl(&to->length);
6435c4bbdfSmrg    swaps(&to->evtype);
6535c4bbdfSmrg    switch (from->evtype) {
6635c4bbdfSmrg    case PresentConfigureNotify: {
6735c4bbdfSmrg        xPresentConfigureNotify *c = (xPresentConfigureNotify *) to;
6835c4bbdfSmrg
6935c4bbdfSmrg        swapl(&c->eid);
7035c4bbdfSmrg        swapl(&c->window);
7135c4bbdfSmrg        swaps(&c->x);
7235c4bbdfSmrg        swaps(&c->y);
7335c4bbdfSmrg        swaps(&c->width);
7435c4bbdfSmrg        swaps(&c->height);
7535c4bbdfSmrg        swaps(&c->off_x);
7635c4bbdfSmrg        swaps(&c->off_y);
7735c4bbdfSmrg        swaps(&c->pixmap_width);
7835c4bbdfSmrg        swaps(&c->pixmap_height);
7935c4bbdfSmrg        swapl(&c->pixmap_flags);
8035c4bbdfSmrg        break;
8135c4bbdfSmrg    }
8235c4bbdfSmrg    case PresentCompleteNotify:
8335c4bbdfSmrg    {
8435c4bbdfSmrg        xPresentCompleteNotify *c = (xPresentCompleteNotify *) to;
8535c4bbdfSmrg        swapl(&c->eid);
8635c4bbdfSmrg        swapl(&c->window);
8735c4bbdfSmrg        swapl(&c->serial);
8835c4bbdfSmrg        swapll(&c->ust);
8935c4bbdfSmrg        swapll(&c->msc);
901b5d61b8Smrg        break;
9135c4bbdfSmrg    }
9235c4bbdfSmrg    case PresentIdleNotify:
9335c4bbdfSmrg    {
9435c4bbdfSmrg        xPresentIdleNotify *c = (xPresentIdleNotify *) to;
9535c4bbdfSmrg        swapl(&c->eid);
9635c4bbdfSmrg        swapl(&c->window);
9735c4bbdfSmrg        swapl(&c->serial);
9835c4bbdfSmrg        swapl(&c->idle_fence);
991b5d61b8Smrg        break;
10035c4bbdfSmrg    }
10135c4bbdfSmrg    }
10235c4bbdfSmrg}
10335c4bbdfSmrg
10435c4bbdfSmrgvoid
105eee80088Smrgpresent_send_config_notify(WindowPtr window, int x, int y, int w, int h,
106eee80088Smrg                           int bw, WindowPtr sibling, CARD32 flags)
10735c4bbdfSmrg{
10835c4bbdfSmrg    present_window_priv_ptr window_priv = present_window_priv(window);
10935c4bbdfSmrg
11035c4bbdfSmrg    if (window_priv) {
11135c4bbdfSmrg        xPresentConfigureNotify cn = {
11235c4bbdfSmrg            .type = GenericEvent,
11335c4bbdfSmrg            .extension = present_request,
11435c4bbdfSmrg            .length = (sizeof(xPresentConfigureNotify) - 32) >> 2,
11535c4bbdfSmrg            .evtype = PresentConfigureNotify,
11635c4bbdfSmrg            .eid = 0,
11735c4bbdfSmrg            .window = window->drawable.id,
11835c4bbdfSmrg            .x = x,
11935c4bbdfSmrg            .y = y,
12035c4bbdfSmrg            .width = w,
12135c4bbdfSmrg            .height = h,
12235c4bbdfSmrg            .off_x = 0,
12335c4bbdfSmrg            .off_y = 0,
12435c4bbdfSmrg            .pixmap_width = w,
12535c4bbdfSmrg            .pixmap_height = h,
126eee80088Smrg            .pixmap_flags = flags
12735c4bbdfSmrg        };
12835c4bbdfSmrg        present_event_ptr event;
12935c4bbdfSmrg
13035c4bbdfSmrg        for (event = window_priv->events; event; event = event->next) {
13135c4bbdfSmrg            if (event->mask & (1 << PresentConfigureNotify)) {
13235c4bbdfSmrg                cn.eid = event->id;
13335c4bbdfSmrg                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
13435c4bbdfSmrg            }
13535c4bbdfSmrg        }
13635c4bbdfSmrg    }
13735c4bbdfSmrg}
13835c4bbdfSmrg
13935c4bbdfSmrgstatic present_complete_notify_proc complete_notify;
14035c4bbdfSmrg
14135c4bbdfSmrgvoid
14235c4bbdfSmrgpresent_register_complete_notify(present_complete_notify_proc proc)
14335c4bbdfSmrg{
14435c4bbdfSmrg    complete_notify = proc;
14535c4bbdfSmrg}
14635c4bbdfSmrg
14735c4bbdfSmrgvoid
14835c4bbdfSmrgpresent_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc)
14935c4bbdfSmrg{
15035c4bbdfSmrg    present_window_priv_ptr window_priv = present_window_priv(window);
15135c4bbdfSmrg
15235c4bbdfSmrg    if (window_priv) {
15335c4bbdfSmrg        xPresentCompleteNotify cn = {
15435c4bbdfSmrg            .type = GenericEvent,
15535c4bbdfSmrg            .extension = present_request,
15635c4bbdfSmrg            .length = (sizeof(xPresentCompleteNotify) - 32) >> 2,
15735c4bbdfSmrg            .evtype = PresentCompleteNotify,
15835c4bbdfSmrg            .kind = kind,
15935c4bbdfSmrg            .mode = mode,
16035c4bbdfSmrg            .eid = 0,
16135c4bbdfSmrg            .window = window->drawable.id,
16235c4bbdfSmrg            .serial = serial,
16335c4bbdfSmrg            .ust = ust,
16435c4bbdfSmrg            .msc = msc,
16535c4bbdfSmrg        };
16635c4bbdfSmrg        present_event_ptr event;
16735c4bbdfSmrg
16835c4bbdfSmrg        for (event = window_priv->events; event; event = event->next) {
16935c4bbdfSmrg            if (event->mask & PresentCompleteNotifyMask) {
17035c4bbdfSmrg                cn.eid = event->id;
17135c4bbdfSmrg                WriteEventsToClient(event->client, 1, (xEvent *) &cn);
17235c4bbdfSmrg            }
17335c4bbdfSmrg        }
17435c4bbdfSmrg    }
17535c4bbdfSmrg    if (complete_notify)
17635c4bbdfSmrg        (*complete_notify)(window, kind, mode, serial, ust, msc);
17735c4bbdfSmrg}
17835c4bbdfSmrg
17935c4bbdfSmrgvoid
18035c4bbdfSmrgpresent_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence)
18135c4bbdfSmrg{
18235c4bbdfSmrg    present_window_priv_ptr window_priv = present_window_priv(window);
18335c4bbdfSmrg
18435c4bbdfSmrg    if (window_priv) {
18535c4bbdfSmrg        xPresentIdleNotify in = {
18635c4bbdfSmrg            .type = GenericEvent,
18735c4bbdfSmrg            .extension = present_request,
18835c4bbdfSmrg            .length = (sizeof(xPresentIdleNotify) - 32) >> 2,
18935c4bbdfSmrg            .evtype = PresentIdleNotify,
19035c4bbdfSmrg            .eid = 0,
19135c4bbdfSmrg            .window = window->drawable.id,
19235c4bbdfSmrg            .serial = serial,
19335c4bbdfSmrg            .pixmap = pixmap->drawable.id,
19435c4bbdfSmrg            .idle_fence = present_fence_id(idle_fence)
19535c4bbdfSmrg        };
19635c4bbdfSmrg        present_event_ptr event;
19735c4bbdfSmrg
19835c4bbdfSmrg        for (event = window_priv->events; event; event = event->next) {
19935c4bbdfSmrg            if (event->mask & PresentIdleNotifyMask) {
20035c4bbdfSmrg                in.eid = event->id;
20135c4bbdfSmrg                WriteEventsToClient(event->client, 1, (xEvent *) &in);
20235c4bbdfSmrg            }
20335c4bbdfSmrg        }
20435c4bbdfSmrg    }
20535c4bbdfSmrg}
20635c4bbdfSmrg
20735c4bbdfSmrgint
20835c4bbdfSmrgpresent_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask)
20935c4bbdfSmrg{
2101b5d61b8Smrg    present_window_priv_ptr window_priv;
21135c4bbdfSmrg    present_event_ptr event;
2121b5d61b8Smrg    int ret;
2131b5d61b8Smrg
2141b5d61b8Smrg    /* Check to see if we're modifying an existing event selection */
2151b5d61b8Smrg    ret = dixLookupResourceByType((void **) &event, eid, present_event_type,
2161b5d61b8Smrg                                 client, DixWriteAccess);
2171b5d61b8Smrg    if (ret == Success) {
2181b5d61b8Smrg        /* Match error for the wrong window; also don't modify some other
2191b5d61b8Smrg         * client's event selection
2201b5d61b8Smrg         */
2211b5d61b8Smrg        if (event->window != window || event->client != client)
2221b5d61b8Smrg            return BadMatch;
22335c4bbdfSmrg
22435c4bbdfSmrg        if (mask)
2251b5d61b8Smrg            event->mask = mask;
2261b5d61b8Smrg        else
2271b5d61b8Smrg            FreeResource(eid, RT_NONE);
22835c4bbdfSmrg        return Success;
22935c4bbdfSmrg    }
2301b5d61b8Smrg    if (ret != BadValue)
2311b5d61b8Smrg        return ret;
2321b5d61b8Smrg
2331b5d61b8Smrg    if (mask == 0)
2341b5d61b8Smrg        return Success;
2351b5d61b8Smrg
2361b5d61b8Smrg    LEGAL_NEW_RESOURCE(eid, client);
2371b5d61b8Smrg
2381b5d61b8Smrg    window_priv = present_get_window_priv(window, TRUE);
2391b5d61b8Smrg    if (!window_priv)
2401b5d61b8Smrg        return BadAlloc;
24135c4bbdfSmrg
24235c4bbdfSmrg    event = calloc (1, sizeof (present_event_rec));
24335c4bbdfSmrg    if (!event)
24435c4bbdfSmrg        return BadAlloc;
24535c4bbdfSmrg
24635c4bbdfSmrg    event->client = client;
24735c4bbdfSmrg    event->window = window;
24835c4bbdfSmrg    event->id = eid;
24935c4bbdfSmrg    event->mask = mask;
25035c4bbdfSmrg
25135c4bbdfSmrg    event->next = window_priv->events;
25235c4bbdfSmrg    window_priv->events = event;
25335c4bbdfSmrg
25435c4bbdfSmrg    if (!AddResource(event->id, present_event_type, (void *) event))
25535c4bbdfSmrg        return BadAlloc;
25635c4bbdfSmrg
25735c4bbdfSmrg    return Success;
25835c4bbdfSmrg}
25935c4bbdfSmrg
26035c4bbdfSmrgBool
26135c4bbdfSmrgpresent_event_init(void)
26235c4bbdfSmrg{
26335c4bbdfSmrg    present_event_type = CreateNewResourceType(present_free_event, "PresentEvent");
26435c4bbdfSmrg    if (!present_event_type)
26535c4bbdfSmrg        return FALSE;
26635c4bbdfSmrg
26735c4bbdfSmrg    GERegisterExtension(present_request, present_event_swap);
26835c4bbdfSmrg    return TRUE;
26935c4bbdfSmrg}
270