1706f2543Smrg/*
2706f2543Smrg * Copyright © 2010 NVIDIA Corporation
3706f2543Smrg *
4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5706f2543Smrg * copy of this software and associated documentation files (the "Software"),
6706f2543Smrg * to deal in the Software without restriction, including without limitation
7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
9706f2543Smrg * Software is furnished to do so, subject to the following conditions:
10706f2543Smrg *
11706f2543Smrg * The above copyright notice and this permission notice (including the next
12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the
13706f2543Smrg * Software.
14706f2543Smrg *
15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21706f2543Smrg * DEALINGS IN THE SOFTWARE.
22706f2543Smrg */
23706f2543Smrg
24706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
25706f2543Smrg#include <dix-config.h>
26706f2543Smrg#endif
27706f2543Smrg
28706f2543Smrg#include "scrnintstr.h"
29706f2543Smrg#include "misync.h"
30706f2543Smrg#include "misyncstr.h"
31706f2543Smrg
32706f2543Smrgstatic DevPrivateKeyRec syncScreenPrivateKeyRec;
33706f2543Smrgstatic DevPrivateKey syncScreenPrivateKey = &syncScreenPrivateKeyRec;
34706f2543Smrg
35706f2543Smrg#define SYNC_SCREEN_PRIV(pScreen) 				\
36706f2543Smrg    (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates,	\
37706f2543Smrg					 syncScreenPrivateKey)
38706f2543Smrg
39706f2543Smrgtypedef struct _syncScreenPriv {
40706f2543Smrg    /* Wrappable sync-specific screen functions */
41706f2543Smrg    SyncScreenFuncsRec		funcs;
42706f2543Smrg
43706f2543Smrg    /* Wrapped screen functions */
44706f2543Smrg    CloseScreenProcPtr		CloseScreen;
45706f2543Smrg} SyncScreenPrivRec, *SyncScreenPrivPtr;
46706f2543Smrg
47706f2543Smrg/* Default implementations of the sync screen functions */
48706f2543Smrgvoid
49706f2543SmrgmiSyncScreenCreateFence(ScreenPtr pScreen, SyncFence* pFence,
50706f2543Smrg                        Bool initially_triggered)
51706f2543Smrg{
52706f2543Smrg    (void)pScreen;
53706f2543Smrg
54706f2543Smrg    pFence->triggered = initially_triggered;
55706f2543Smrg}
56706f2543Smrg
57706f2543Smrgvoid miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence* pFence)
58706f2543Smrg{
59706f2543Smrg    (void)pScreen;
60706f2543Smrg    (void)pFence;
61706f2543Smrg}
62706f2543Smrg
63706f2543Smrg/* Default implementations of the per-object functions */
64706f2543Smrgstatic void
65706f2543SmrgmiSyncFenceSetTriggered(SyncFence* pFence)
66706f2543Smrg{
67706f2543Smrg    pFence->triggered = TRUE;
68706f2543Smrg}
69706f2543Smrg
70706f2543Smrgstatic void
71706f2543SmrgmiSyncFenceReset(SyncFence* pFence)
72706f2543Smrg{
73706f2543Smrg    pFence->triggered = FALSE;
74706f2543Smrg}
75706f2543Smrg
76706f2543Smrgstatic Bool
77706f2543SmrgmiSyncFenceCheckTriggered(SyncFence* pFence)
78706f2543Smrg{
79706f2543Smrg    return pFence->triggered;
80706f2543Smrg}
81706f2543Smrg
82706f2543Smrgstatic void
83706f2543SmrgmiSyncFenceAddTrigger(SyncTrigger* pTrigger)
84706f2543Smrg{
85706f2543Smrg    (void)pTrigger;
86706f2543Smrg
87706f2543Smrg    return;
88706f2543Smrg}
89706f2543Smrg
90706f2543Smrgstatic void
91706f2543SmrgmiSyncFenceDeleteTrigger(SyncTrigger* pTrigger)
92706f2543Smrg{
93706f2543Smrg    (void)pTrigger;
94706f2543Smrg
95706f2543Smrg    return;
96706f2543Smrg}
97706f2543Smrg
98706f2543Smrg/* Machine independent portion of the fence sync object implementation */
99706f2543Smrgvoid
100706f2543SmrgmiSyncInitFence(ScreenPtr pScreen, SyncFence* pFence, Bool initially_triggered)
101706f2543Smrg{
102706f2543Smrg    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
103706f2543Smrg    static const SyncFenceFuncsRec miSyncFenceFuncs = {
104706f2543Smrg	&miSyncFenceSetTriggered,
105706f2543Smrg	&miSyncFenceReset,
106706f2543Smrg	&miSyncFenceCheckTriggered,
107706f2543Smrg	&miSyncFenceAddTrigger,
108706f2543Smrg	&miSyncFenceDeleteTrigger
109706f2543Smrg    };
110706f2543Smrg
111706f2543Smrg    pFence->pScreen = pScreen;
112706f2543Smrg    pFence->funcs = miSyncFenceFuncs;
113706f2543Smrg
114706f2543Smrg    pScreenPriv->funcs.CreateFence(pScreen, pFence, initially_triggered);
115706f2543Smrg}
116706f2543Smrg
117706f2543Smrgvoid
118706f2543SmrgmiSyncDestroyFence(SyncFence* pFence)
119706f2543Smrg{
120706f2543Smrg    ScreenPtr pScreen = pFence->pScreen;
121706f2543Smrg    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
122706f2543Smrg    SyncTriggerList *ptl, *pNext;
123706f2543Smrg
124706f2543Smrg    pFence->sync.beingDestroyed = TRUE;
125706f2543Smrg    /* tell all the fence's triggers that the counter has been destroyed */
126706f2543Smrg    for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext)
127706f2543Smrg    {
128706f2543Smrg	(*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
129706f2543Smrg	pNext = ptl->next;
130706f2543Smrg	free(ptl); /* destroy the trigger list as we go */
131706f2543Smrg    }
132706f2543Smrg
133706f2543Smrg    pScreenPriv->funcs.DestroyFence(pScreen, pFence);
134706f2543Smrg
135706f2543Smrg    dixFreeObjectWithPrivates(pFence, PRIVATE_SYNC_FENCE);
136706f2543Smrg}
137706f2543Smrg
138706f2543Smrgvoid
139706f2543SmrgmiSyncTriggerFence(SyncFence* pFence)
140706f2543Smrg{
141706f2543Smrg    SyncTriggerList *ptl, *pNext;
142706f2543Smrg    CARD64 unused;
143706f2543Smrg
144706f2543Smrg    pFence->funcs.SetTriggered(pFence);
145706f2543Smrg
146706f2543Smrg    XSyncIntToValue(&unused, 0L);
147706f2543Smrg
148706f2543Smrg    /* run through triggers to see if any fired */
149706f2543Smrg    for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext)
150706f2543Smrg    {
151706f2543Smrg	pNext = ptl->next;
152706f2543Smrg	if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, unused))
153706f2543Smrg	    (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
154706f2543Smrg    }
155706f2543Smrg}
156706f2543Smrg
157706f2543SmrgSyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen)
158706f2543Smrg{
159706f2543Smrg    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
160706f2543Smrg
161706f2543Smrg    return &pScreenPriv->funcs;
162706f2543Smrg}
163706f2543Smrg
164706f2543Smrgstatic Bool
165706f2543SmrgSyncCloseScreen (int i, ScreenPtr pScreen)
166706f2543Smrg{
167706f2543Smrg    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
168706f2543Smrg
169706f2543Smrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
170706f2543Smrg
171706f2543Smrg    return (*pScreen->CloseScreen) (i, pScreen);
172706f2543Smrg}
173706f2543Smrg
174706f2543SmrgBool
175706f2543SmrgmiSyncSetup(ScreenPtr pScreen)
176706f2543Smrg{
177706f2543Smrg    SyncScreenPrivPtr	pScreenPriv;
178706f2543Smrg
179706f2543Smrg    static const SyncScreenFuncsRec miSyncScreenFuncs = {
180706f2543Smrg	&miSyncScreenCreateFence,
181706f2543Smrg	&miSyncScreenDestroyFence
182706f2543Smrg    };
183706f2543Smrg
184706f2543Smrg    if (dixPrivateKeyRegistered(syncScreenPrivateKey))
185706f2543Smrg	return TRUE;
186706f2543Smrg
187706f2543Smrg    if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN,
188706f2543Smrg			       sizeof(SyncScreenPrivRec)))
189706f2543Smrg	return FALSE;
190706f2543Smrg
191706f2543Smrg    pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
192706f2543Smrg
193706f2543Smrg    pScreenPriv->funcs = miSyncScreenFuncs;
194706f2543Smrg
195706f2543Smrg    /* Wrap CloseScreen to clean up */
196706f2543Smrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
197706f2543Smrg    pScreen->CloseScreen = SyncCloseScreen;
198706f2543Smrg
199706f2543Smrg    return TRUE;
200706f2543Smrg}
201