xref: /OK3568_Linux_fs/external/xserver/glx/vndext.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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