1/*
2 * Copyright © 2010 NVIDIA Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#ifdef HAVE_DIX_CONFIG_H
25#include <dix-config.h>
26#endif
27
28#include "scrnintstr.h"
29#include "misync.h"
30#include "misyncstr.h"
31
32static DevPrivateKeyRec syncScreenPrivateKeyRec;
33static DevPrivateKey syncScreenPrivateKey = &syncScreenPrivateKeyRec;
34
35#define SYNC_SCREEN_PRIV(pScreen) 				\
36    (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates,	\
37					 syncScreenPrivateKey)
38
39typedef struct _syncScreenPriv {
40    /* Wrappable sync-specific screen functions */
41    SyncScreenFuncsRec		funcs;
42
43    /* Wrapped screen functions */
44    CloseScreenProcPtr		CloseScreen;
45} SyncScreenPrivRec, *SyncScreenPrivPtr;
46
47/* Default implementations of the sync screen functions */
48void
49miSyncScreenCreateFence(ScreenPtr pScreen, SyncFence* pFence,
50                        Bool initially_triggered)
51{
52    (void)pScreen;
53
54    pFence->triggered = initially_triggered;
55}
56
57void miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence* pFence)
58{
59    (void)pScreen;
60    (void)pFence;
61}
62
63/* Default implementations of the per-object functions */
64static void
65miSyncFenceSetTriggered(SyncFence* pFence)
66{
67    pFence->triggered = TRUE;
68}
69
70static void
71miSyncFenceReset(SyncFence* pFence)
72{
73    pFence->triggered = FALSE;
74}
75
76static Bool
77miSyncFenceCheckTriggered(SyncFence* pFence)
78{
79    return pFence->triggered;
80}
81
82static void
83miSyncFenceAddTrigger(SyncTrigger* pTrigger)
84{
85    (void)pTrigger;
86
87    return;
88}
89
90static void
91miSyncFenceDeleteTrigger(SyncTrigger* pTrigger)
92{
93    (void)pTrigger;
94
95    return;
96}
97
98/* Machine independent portion of the fence sync object implementation */
99void
100miSyncInitFence(ScreenPtr pScreen, SyncFence* pFence, Bool initially_triggered)
101{
102    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
103    static const SyncFenceFuncsRec miSyncFenceFuncs = {
104	&miSyncFenceSetTriggered,
105	&miSyncFenceReset,
106	&miSyncFenceCheckTriggered,
107	&miSyncFenceAddTrigger,
108	&miSyncFenceDeleteTrigger
109    };
110
111    pFence->pScreen = pScreen;
112    pFence->funcs = miSyncFenceFuncs;
113
114    pScreenPriv->funcs.CreateFence(pScreen, pFence, initially_triggered);
115}
116
117void
118miSyncDestroyFence(SyncFence* pFence)
119{
120    ScreenPtr pScreen = pFence->pScreen;
121    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
122    SyncTriggerList *ptl, *pNext;
123
124    pFence->sync.beingDestroyed = TRUE;
125    /* tell all the fence's triggers that the counter has been destroyed */
126    for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext)
127    {
128	(*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
129	pNext = ptl->next;
130	free(ptl); /* destroy the trigger list as we go */
131    }
132
133    pScreenPriv->funcs.DestroyFence(pScreen, pFence);
134
135    dixFreeObjectWithPrivates(pFence, PRIVATE_SYNC_FENCE);
136}
137
138void
139miSyncTriggerFence(SyncFence* pFence)
140{
141    SyncTriggerList *ptl, *pNext;
142    CARD64 unused;
143
144    pFence->funcs.SetTriggered(pFence);
145
146    XSyncIntToValue(&unused, 0L);
147
148    /* run through triggers to see if any fired */
149    for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext)
150    {
151	pNext = ptl->next;
152	if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, unused))
153	    (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
154    }
155}
156
157SyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen)
158{
159    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
160
161    return &pScreenPriv->funcs;
162}
163
164static Bool
165SyncCloseScreen (int i, ScreenPtr pScreen)
166{
167    SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
168
169    pScreen->CloseScreen = pScreenPriv->CloseScreen;
170
171    return (*pScreen->CloseScreen) (i, pScreen);
172}
173
174Bool
175miSyncSetup(ScreenPtr pScreen)
176{
177    SyncScreenPrivPtr	pScreenPriv;
178
179    static const SyncScreenFuncsRec miSyncScreenFuncs = {
180	&miSyncScreenCreateFence,
181	&miSyncScreenDestroyFence
182    };
183
184    if (dixPrivateKeyRegistered(syncScreenPrivateKey))
185	return TRUE;
186
187    if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN,
188			       sizeof(SyncScreenPrivRec)))
189	return FALSE;
190
191    pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
192
193    pScreenPriv->funcs = miSyncScreenFuncs;
194
195    /* Wrap CloseScreen to clean up */
196    pScreenPriv->CloseScreen = pScreen->CloseScreen;
197    pScreen->CloseScreen = SyncCloseScreen;
198
199    return TRUE;
200}
201