1 /*
2 * Copyright (c) 2016, NVIDIA CORPORATION.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and/or associated documentation files (the
6 * "Materials"), to deal in the Materials without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Materials, and to
9 * permit persons to whom the Materials are furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * unaltered in all copies or substantial portions of the Materials.
14 * Any additions, deletions, or changes to the original source files
15 * must be clearly indicated in accompanying documentation.
16 *
17 * If only executable code is distributed, then the accompanying
18 * documentation must state that "this software is based in part on the
19 * work of the Khronos Group."
20 *
21 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
28 */
29
30 #include "vndserver.h"
31
32 #include <string.h>
33 #include <scrnintstr.h>
34 #include <windowstr.h>
35 #include <dixstruct.h>
36 #include <extnsionst.h>
37 #include <glx_extinit.h>
38
39 #include <GL/glxproto.h>
40 #include "vndservervendor.h"
41
42 ExtensionEntry *GlxExtensionEntry;
43 int GlxErrorBase = 0;
44 static CallbackListRec vndInitCallbackList;
45 static CallbackListPtr vndInitCallbackListPtr = &vndInitCallbackList;
46 static DevPrivateKeyRec glvXGLVScreenPrivKey;
47 static DevPrivateKeyRec glvXGLVClientPrivKey;
48
49 // The resource type used to keep track of the vendor library for XID's.
50 RESTYPE idResource;
51
52 static int
idResourceDeleteCallback(void * value,XID id)53 idResourceDeleteCallback(void *value, XID id)
54 {
55 return 0;
56 }
57
58 static GlxScreenPriv *
xglvGetScreenPrivate(ScreenPtr pScreen)59 xglvGetScreenPrivate(ScreenPtr pScreen)
60 {
61 return dixLookupPrivate(&pScreen->devPrivates, &glvXGLVScreenPrivKey);
62 }
63
64 static void
xglvSetScreenPrivate(ScreenPtr pScreen,void * priv)65 xglvSetScreenPrivate(ScreenPtr pScreen, void *priv)
66 {
67 dixSetPrivate(&pScreen->devPrivates, &glvXGLVScreenPrivKey, priv);
68 }
69
70 GlxScreenPriv *
GlxGetScreen(ScreenPtr pScreen)71 GlxGetScreen(ScreenPtr pScreen)
72 {
73 if (pScreen != NULL) {
74 GlxScreenPriv *priv = xglvGetScreenPrivate(pScreen);
75 if (priv == NULL) {
76 priv = calloc(1, sizeof(GlxScreenPriv));
77 if (priv == NULL) {
78 return NULL;
79 }
80
81 xglvSetScreenPrivate(pScreen, priv);
82 }
83 return priv;
84 } else {
85 return NULL;
86 }
87 }
88
89 static void
GlxMappingReset(void)90 GlxMappingReset(void)
91 {
92 int i;
93
94 for (i=0; i<screenInfo.numScreens; i++) {
95 GlxScreenPriv *priv = xglvGetScreenPrivate(screenInfo.screens[i]);
96 if (priv != NULL) {
97 xglvSetScreenPrivate(screenInfo.screens[i], NULL);
98 free(priv);
99 }
100 }
101 }
102
103 static Bool
GlxMappingInit(void)104 GlxMappingInit(void)
105 {
106 int i;
107
108 for (i=0; i<screenInfo.numScreens; i++) {
109 if (GlxGetScreen(screenInfo.screens[i]) == NULL) {
110 GlxMappingReset();
111 return FALSE;
112 }
113 }
114
115 idResource = CreateNewResourceType(idResourceDeleteCallback,
116 "GLXServerIDRes");
117 if (idResource == RT_NONE)
118 {
119 GlxMappingReset();
120 return FALSE;
121 }
122 return TRUE;
123 }
124
125 static GlxClientPriv *
xglvGetClientPrivate(ClientPtr pClient)126 xglvGetClientPrivate(ClientPtr pClient)
127 {
128 return dixLookupPrivate(&pClient->devPrivates, &glvXGLVClientPrivKey);
129 }
130
131 static void
xglvSetClientPrivate(ClientPtr pClient,void * priv)132 xglvSetClientPrivate(ClientPtr pClient, void *priv)
133 {
134 dixSetPrivate(&pClient->devPrivates, &glvXGLVClientPrivKey, priv);
135 }
136
137 GlxClientPriv *
GlxGetClientData(ClientPtr client)138 GlxGetClientData(ClientPtr client)
139 {
140 GlxClientPriv *cl = xglvGetClientPrivate(client);
141 if (cl == NULL) {
142 cl = calloc(1, sizeof(GlxClientPriv)
143 + screenInfo.numScreens * sizeof(GlxServerVendor *));
144 if (cl != NULL) {
145 int i;
146
147 cl->vendors = (GlxServerVendor **) (cl + 1);
148 for (i=0; i<screenInfo.numScreens; i++)
149 {
150 cl->vendors[i] = GlxGetVendorForScreen(NULL, screenInfo.screens[i]);
151 }
152
153 xglvSetClientPrivate(client, cl);
154 }
155 }
156 return cl;
157 }
158
159 void
GlxFreeClientData(ClientPtr client)160 GlxFreeClientData(ClientPtr client)
161 {
162 GlxClientPriv *cl = xglvGetClientPrivate(client);
163 if (cl != NULL) {
164 unsigned int i;
165 for (i = 0; i < cl->contextTagCount; i++) {
166 GlxContextTagInfo *tag = &cl->contextTags[i];
167 if (tag->vendor != NULL) {
168 tag->vendor->glxvc.makeCurrent(client, tag->tag,
169 None, None, None, 0);
170 }
171 }
172 xglvSetClientPrivate(client, NULL);
173 free(cl->contextTags);
174 free(cl);
175 }
176 }
177
178 static void
GLXClientCallback(CallbackListPtr * list,void * closure,void * data)179 GLXClientCallback(CallbackListPtr *list, void *closure, void *data)
180 {
181 NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
182 ClientPtr client = clientinfo->client;
183
184 switch (client->clientState)
185 {
186 case ClientStateRetained:
187 case ClientStateGone:
188 GlxFreeClientData(client);
189 break;
190 }
191 }
192
193 static void
GLXReset(ExtensionEntry * extEntry)194 GLXReset(ExtensionEntry *extEntry)
195 {
196 // xf86Msg(X_INFO, "GLX: GLXReset\n");
197
198 GlxVendorExtensionReset(extEntry);
199 GlxDispatchReset();
200 GlxMappingReset();
201
202 if ((dispatchException & DE_TERMINATE) == DE_TERMINATE) {
203 while (vndInitCallbackList.list != NULL) {
204 CallbackPtr next = vndInitCallbackList.list->next;
205 free(vndInitCallbackList.list);
206 vndInitCallbackList.list = next;
207 }
208 }
209 }
210
211 void
GlxExtensionInit(void)212 GlxExtensionInit(void)
213 {
214 ExtensionEntry *extEntry;
215 GlxExtensionEntry = NULL;
216
217 // Init private keys, per-screen data
218 if (!dixRegisterPrivateKey(&glvXGLVScreenPrivKey, PRIVATE_SCREEN, 0))
219 return;
220 if (!dixRegisterPrivateKey(&glvXGLVClientPrivKey, PRIVATE_CLIENT, 0))
221 return;
222
223 if (!GlxMappingInit()) {
224 return;
225 }
226
227 if (!GlxDispatchInit()) {
228 return;
229 }
230
231 if (!AddCallback(&ClientStateCallback, GLXClientCallback, NULL)) {
232 return;
233 }
234
235 extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS,
236 __GLX_NUMBER_ERRORS, GlxDispatchRequest,
237 GlxDispatchRequest, GLXReset, StandardMinorOpcode);
238 if (!extEntry) {
239 return;
240 }
241
242 GlxExtensionEntry = extEntry;
243 GlxErrorBase = extEntry->errorBase;
244 CallCallbacks(&vndInitCallbackListPtr, extEntry);
245
246 /* We'd better have found at least one vendor */
247 for (int i = 0; i < screenInfo.numScreens; i++)
248 if (GlxGetVendorForScreen(serverClient, screenInfo.screens[i]))
249 return;
250 extEntry->base = 0;
251 }
252
253 static int
GlxForwardRequest(GlxServerVendor * vendor,ClientPtr client)254 GlxForwardRequest(GlxServerVendor *vendor, ClientPtr client)
255 {
256 return vendor->glxvc.handleRequest(client);
257 }
258
259 static GlxServerVendor *
GlxGetContextTag(ClientPtr client,GLXContextTag tag)260 GlxGetContextTag(ClientPtr client, GLXContextTag tag)
261 {
262 GlxContextTagInfo *tagInfo = GlxLookupContextTag(client, tag);
263
264 if (tagInfo != NULL) {
265 return tagInfo->vendor;
266 } else {
267 return NULL;
268 }
269 }
270
271 static Bool
GlxSetContextTagPrivate(ClientPtr client,GLXContextTag tag,void * data)272 GlxSetContextTagPrivate(ClientPtr client, GLXContextTag tag, void *data)
273 {
274 GlxContextTagInfo *tagInfo = GlxLookupContextTag(client, tag);
275 if (tagInfo != NULL) {
276 tagInfo->data = data;
277 return TRUE;
278 } else {
279 return FALSE;
280 }
281 }
282
283 static void *
GlxGetContextTagPrivate(ClientPtr client,GLXContextTag tag)284 GlxGetContextTagPrivate(ClientPtr client, GLXContextTag tag)
285 {
286 GlxContextTagInfo *tagInfo = GlxLookupContextTag(client, tag);
287 if (tagInfo != NULL) {
288 return tagInfo->data;
289 } else {
290 return NULL;
291 }
292 }
293
294 static GlxServerImports *
GlxAllocateServerImports(void)295 GlxAllocateServerImports(void)
296 {
297 return calloc(1, sizeof(GlxServerImports));
298 }
299
300 static void
GlxFreeServerImports(GlxServerImports * imports)301 GlxFreeServerImports(GlxServerImports *imports)
302 {
303 free(imports);
304 }
305
306 _X_EXPORT const GlxServerExports glxServer = {
307 .majorVersion = GLXSERVER_VENDOR_ABI_MAJOR_VERSION,
308 .minorVersion = GLXSERVER_VENDOR_ABI_MINOR_VERSION,
309
310 .extensionInitCallback = &vndInitCallbackListPtr,
311
312 .allocateServerImports = GlxAllocateServerImports,
313 .freeServerImports = GlxFreeServerImports,
314
315 .createVendor = GlxCreateVendor,
316 .destroyVendor = GlxDestroyVendor,
317 .setScreenVendor = GlxSetScreenVendor,
318
319 .addXIDMap = GlxAddXIDMap,
320 .getXIDMap = GlxGetXIDMap,
321 .removeXIDMap = GlxRemoveXIDMap,
322 .getContextTag = GlxGetContextTag,
323 .setContextTagPrivate = GlxSetContextTagPrivate,
324 .getContextTagPrivate = GlxGetContextTagPrivate,
325 .getVendorForScreen = GlxGetVendorForScreen,
326 .forwardRequest = GlxForwardRequest,
327 .setClientScreenVendor = GlxSetClientScreenVendor,
328 };
329
330 const GlxServerExports *
glvndGetExports(void)331 glvndGetExports(void)
332 {
333 return &glxServer;
334 }
335