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 
32 DevPrivateKeyRec miSyncScreenPrivateKey;
33 
34 /* Default implementations of the sync screen functions */
35 void
miSyncScreenCreateFence(ScreenPtr pScreen,SyncFence * pFence,Bool initially_triggered)36 miSyncScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence,
37                         Bool initially_triggered)
38 {
39     (void) pScreen;
40 
41     pFence->triggered = initially_triggered;
42 }
43 
44 void
miSyncScreenDestroyFence(ScreenPtr pScreen,SyncFence * pFence)45 miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
46 {
47     (void) pScreen;
48     (void) pFence;
49 }
50 
51 /* Default implementations of the per-object functions */
52 void
miSyncFenceSetTriggered(SyncFence * pFence)53 miSyncFenceSetTriggered(SyncFence * pFence)
54 {
55     pFence->triggered = TRUE;
56 }
57 
58 void
miSyncFenceReset(SyncFence * pFence)59 miSyncFenceReset(SyncFence * pFence)
60 {
61     pFence->triggered = FALSE;
62 }
63 
64 Bool
miSyncFenceCheckTriggered(SyncFence * pFence)65 miSyncFenceCheckTriggered(SyncFence * pFence)
66 {
67     return pFence->triggered;
68 }
69 
70 void
miSyncFenceAddTrigger(SyncTrigger * pTrigger)71 miSyncFenceAddTrigger(SyncTrigger * pTrigger)
72 {
73     (void) pTrigger;
74 
75     return;
76 }
77 
78 void
miSyncFenceDeleteTrigger(SyncTrigger * pTrigger)79 miSyncFenceDeleteTrigger(SyncTrigger * pTrigger)
80 {
81     (void) pTrigger;
82 
83     return;
84 }
85 
86 /* Machine independent portion of the fence sync object implementation */
87 void
miSyncInitFence(ScreenPtr pScreen,SyncFence * pFence,Bool initially_triggered)88 miSyncInitFence(ScreenPtr pScreen, SyncFence * pFence, Bool initially_triggered)
89 {
90     SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
91 
92     static const SyncFenceFuncsRec miSyncFenceFuncs = {
93         &miSyncFenceSetTriggered,
94         &miSyncFenceReset,
95         &miSyncFenceCheckTriggered,
96         &miSyncFenceAddTrigger,
97         &miSyncFenceDeleteTrigger
98     };
99 
100     pFence->pScreen = pScreen;
101     pFence->funcs = miSyncFenceFuncs;
102 
103     pScreenPriv->funcs.CreateFence(pScreen, pFence, initially_triggered);
104 
105     pFence->sync.initialized = TRUE;
106 }
107 
108 void
miSyncDestroyFence(SyncFence * pFence)109 miSyncDestroyFence(SyncFence * pFence)
110 {
111     pFence->sync.beingDestroyed = TRUE;
112 
113     if (pFence->sync.initialized) {
114         ScreenPtr pScreen = pFence->pScreen;
115         SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
116         SyncTriggerList *ptl, *pNext;
117 
118         /* tell all the fence's triggers that the counter has been destroyed */
119         for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext) {
120             (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
121             pNext = ptl->next;
122             free(ptl); /* destroy the trigger list as we go */
123         }
124 
125         pScreenPriv->funcs.DestroyFence(pScreen, pFence);
126     }
127 
128     dixFreeObjectWithPrivates(pFence, PRIVATE_SYNC_FENCE);
129 }
130 
131 void
miSyncTriggerFence(SyncFence * pFence)132 miSyncTriggerFence(SyncFence * pFence)
133 {
134     SyncTriggerList *ptl, *pNext;
135 
136     pFence->funcs.SetTriggered(pFence);
137 
138     /* run through triggers to see if any fired */
139     for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext) {
140         pNext = ptl->next;
141         if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, 0))
142             (*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
143     }
144 }
145 
146 SyncScreenFuncsPtr
miSyncGetScreenFuncs(ScreenPtr pScreen)147 miSyncGetScreenFuncs(ScreenPtr pScreen)
148 {
149     SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
150 
151     return &pScreenPriv->funcs;
152 }
153 
154 static Bool
SyncCloseScreen(ScreenPtr pScreen)155 SyncCloseScreen(ScreenPtr pScreen)
156 {
157     SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
158 
159     pScreen->CloseScreen = pScreenPriv->CloseScreen;
160 
161     return (*pScreen->CloseScreen) (pScreen);
162 }
163 
164 Bool
miSyncSetup(ScreenPtr pScreen)165 miSyncSetup(ScreenPtr pScreen)
166 {
167     SyncScreenPrivPtr pScreenPriv;
168 
169     static const SyncScreenFuncsRec miSyncScreenFuncs = {
170         &miSyncScreenCreateFence,
171         &miSyncScreenDestroyFence
172     };
173 
174     if (!dixPrivateKeyRegistered(&miSyncScreenPrivateKey)) {
175         if (!dixRegisterPrivateKey(&miSyncScreenPrivateKey, PRIVATE_SCREEN,
176                                    sizeof(SyncScreenPrivRec)))
177             return FALSE;
178     }
179 
180     pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
181 
182     if (!pScreenPriv->funcs.CreateFence) {
183         pScreenPriv->funcs = miSyncScreenFuncs;
184 
185         /* Wrap CloseScreen to clean up */
186         pScreenPriv->CloseScreen = pScreen->CloseScreen;
187         pScreen->CloseScreen = SyncCloseScreen;
188     }
189 
190     return TRUE;
191 }
192