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#include <gcstruct.h>
2535c4bbdfSmrg#include <misync.h>
2635c4bbdfSmrg#include <misyncstr.h>
2735c4bbdfSmrg
2835c4bbdfSmrg/*
2935c4bbdfSmrg * Wraps SyncFence objects so we can add a SyncTrigger to find out
3035c4bbdfSmrg * when the SyncFence gets destroyed and clean up appropriately
3135c4bbdfSmrg */
3235c4bbdfSmrg
3335c4bbdfSmrgstruct present_fence {
3435c4bbdfSmrg    SyncTrigger         trigger;
3535c4bbdfSmrg    SyncFence           *fence;
3635c4bbdfSmrg    void                (*callback)(void *param);
3735c4bbdfSmrg    void                *param;
3835c4bbdfSmrg};
3935c4bbdfSmrg
4035c4bbdfSmrg/*
4135c4bbdfSmrg * SyncTrigger callbacks
4235c4bbdfSmrg */
4335c4bbdfSmrgstatic Bool
441b5d61b8Smrgpresent_fence_sync_check_trigger(SyncTrigger *trigger, int64_t oldval)
4535c4bbdfSmrg{
4635c4bbdfSmrg    struct present_fence        *present_fence = container_of(trigger, struct present_fence, trigger);
4735c4bbdfSmrg
4835c4bbdfSmrg    return present_fence->callback != NULL;
4935c4bbdfSmrg}
5035c4bbdfSmrg
5135c4bbdfSmrgstatic void
5235c4bbdfSmrgpresent_fence_sync_trigger_fired(SyncTrigger *trigger)
5335c4bbdfSmrg{
5435c4bbdfSmrg    struct present_fence        *present_fence = container_of(trigger, struct present_fence, trigger);
5535c4bbdfSmrg
5635c4bbdfSmrg    if (present_fence->callback)
5735c4bbdfSmrg        (*present_fence->callback)(present_fence->param);
5835c4bbdfSmrg}
5935c4bbdfSmrg
6035c4bbdfSmrgstatic void
6135c4bbdfSmrgpresent_fence_sync_counter_destroyed(SyncTrigger *trigger)
6235c4bbdfSmrg{
6335c4bbdfSmrg    struct present_fence        *present_fence = container_of(trigger, struct present_fence, trigger);
6435c4bbdfSmrg
6535c4bbdfSmrg    present_fence->fence = NULL;
6635c4bbdfSmrg}
6735c4bbdfSmrg
6835c4bbdfSmrgstruct present_fence *
6935c4bbdfSmrgpresent_fence_create(SyncFence *fence)
7035c4bbdfSmrg{
7135c4bbdfSmrg    struct present_fence        *present_fence;
7235c4bbdfSmrg
7335c4bbdfSmrg    present_fence = calloc (1, sizeof (struct present_fence));
7435c4bbdfSmrg    if (!present_fence)
7535c4bbdfSmrg        return NULL;
7635c4bbdfSmrg
7735c4bbdfSmrg    present_fence->fence = fence;
7835c4bbdfSmrg    present_fence->trigger.pSync = (SyncObject *) fence;
7935c4bbdfSmrg    present_fence->trigger.CheckTrigger = present_fence_sync_check_trigger;
8035c4bbdfSmrg    present_fence->trigger.TriggerFired = present_fence_sync_trigger_fired;
8135c4bbdfSmrg    present_fence->trigger.CounterDestroyed = present_fence_sync_counter_destroyed;
8235c4bbdfSmrg
8335c4bbdfSmrg    if (SyncAddTriggerToSyncObject(&present_fence->trigger) != Success) {
8435c4bbdfSmrg        free (present_fence);
8535c4bbdfSmrg        return NULL;
8635c4bbdfSmrg    }
8735c4bbdfSmrg    return present_fence;
8835c4bbdfSmrg}
8935c4bbdfSmrg
9035c4bbdfSmrgvoid
9135c4bbdfSmrgpresent_fence_destroy(struct present_fence *present_fence)
9235c4bbdfSmrg{
9335c4bbdfSmrg    if (present_fence) {
9435c4bbdfSmrg        if (present_fence->fence)
9535c4bbdfSmrg            SyncDeleteTriggerFromSyncObject(&present_fence->trigger);
9635c4bbdfSmrg        free(present_fence);
9735c4bbdfSmrg    }
9835c4bbdfSmrg}
9935c4bbdfSmrg
10035c4bbdfSmrgvoid
10135c4bbdfSmrgpresent_fence_set_triggered(struct present_fence *present_fence)
10235c4bbdfSmrg{
10335c4bbdfSmrg    if (present_fence)
10435c4bbdfSmrg        if (present_fence->fence)
10535c4bbdfSmrg            (*present_fence->fence->funcs.SetTriggered) (present_fence->fence);
10635c4bbdfSmrg}
10735c4bbdfSmrg
10835c4bbdfSmrgBool
10935c4bbdfSmrgpresent_fence_check_triggered(struct present_fence *present_fence)
11035c4bbdfSmrg{
11135c4bbdfSmrg    if (!present_fence)
11235c4bbdfSmrg        return TRUE;
11335c4bbdfSmrg    if (!present_fence->fence)
11435c4bbdfSmrg        return TRUE;
11535c4bbdfSmrg    return (*present_fence->fence->funcs.CheckTriggered)(present_fence->fence);
11635c4bbdfSmrg}
11735c4bbdfSmrg
11835c4bbdfSmrgvoid
11935c4bbdfSmrgpresent_fence_set_callback(struct present_fence *present_fence,
12035c4bbdfSmrg                           void (*callback) (void *param),
12135c4bbdfSmrg                           void *param)
12235c4bbdfSmrg{
12335c4bbdfSmrg    present_fence->callback = callback;
12435c4bbdfSmrg    present_fence->param = param;
12535c4bbdfSmrg}
12635c4bbdfSmrg
12735c4bbdfSmrgXID
12835c4bbdfSmrgpresent_fence_id(struct present_fence *present_fence)
12935c4bbdfSmrg{
13035c4bbdfSmrg    if (!present_fence)
13135c4bbdfSmrg        return None;
13235c4bbdfSmrg    if (!present_fence->fence)
13335c4bbdfSmrg        return None;
13435c4bbdfSmrg    return present_fence->fence->sync.id;
13535c4bbdfSmrg}
136