vndext.c revision 1b5d61b8
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
42ExtensionEntry *GlxExtensionEntry;
43int GlxErrorBase = 0;
44static CallbackListRec vndInitCallbackList;
45static CallbackListPtr vndInitCallbackListPtr = &vndInitCallbackList;
46static DevPrivateKeyRec glvXGLVScreenPrivKey;
47static DevPrivateKeyRec glvXGLVClientPrivKey;
48
49// The resource type used to keep track of the vendor library for XID's.
50RESTYPE idResource;
51
52static int
53idResourceDeleteCallback(void *value, XID id)
54{
55    return 0;
56}
57
58static GlxScreenPriv *
59xglvGetScreenPrivate(ScreenPtr pScreen)
60{
61    return dixLookupPrivate(&pScreen->devPrivates, &glvXGLVScreenPrivKey);
62}
63
64static void
65xglvSetScreenPrivate(ScreenPtr pScreen, void *priv)
66{
67    dixSetPrivate(&pScreen->devPrivates, &glvXGLVScreenPrivKey, priv);
68}
69
70GlxScreenPriv *
71GlxGetScreen(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
89static void
90GlxMappingReset(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
103static Bool
104GlxMappingInit(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
125static GlxClientPriv *
126xglvGetClientPrivate(ClientPtr pClient)
127{
128    return dixLookupPrivate(&pClient->devPrivates, &glvXGLVClientPrivKey);
129}
130
131static void
132xglvSetClientPrivate(ClientPtr pClient, void *priv)
133{
134    dixSetPrivate(&pClient->devPrivates, &glvXGLVClientPrivKey, priv);
135}
136
137GlxClientPriv *
138GlxGetClientData(ClientPtr client)
139{
140    GlxClientPriv *cl = xglvGetClientPrivate(client);
141    if (cl == NULL) {
142        cl = calloc(1, sizeof(GlxClientPriv));
143        if (cl != NULL) {
144            xglvSetClientPrivate(client, cl);
145        }
146    }
147    return cl;
148}
149
150void
151GlxFreeClientData(ClientPtr client)
152{
153    GlxClientPriv *cl = xglvGetClientPrivate(client);
154    if (cl != NULL) {
155        unsigned int i;
156        for (i = 0; i < cl->contextTagCount; i++) {
157            GlxContextTagInfo *tag = &cl->contextTags[i];
158            if (tag->vendor != NULL) {
159                tag->vendor->glxvc.makeCurrent(client, tag->tag,
160                                               None, None, None, 0);
161            }
162        }
163        xglvSetClientPrivate(client, NULL);
164        free(cl->contextTags);
165        free(cl);
166    }
167}
168
169static void
170GLXClientCallback(CallbackListPtr *list, void *closure, void *data)
171{
172    NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
173    ClientPtr client = clientinfo->client;
174
175    switch (client->clientState)
176    {
177        case ClientStateRetained:
178        case ClientStateGone:
179            GlxFreeClientData(client);
180            break;
181    }
182}
183
184static void
185GLXReset(ExtensionEntry *extEntry)
186{
187    // xf86Msg(X_INFO, "GLX: GLXReset\n");
188
189    GlxVendorExtensionReset(extEntry);
190    GlxDispatchReset();
191    GlxMappingReset();
192
193    if ((dispatchException & DE_TERMINATE) == DE_TERMINATE) {
194        while (vndInitCallbackList.list != NULL) {
195            CallbackPtr next = vndInitCallbackList.list->next;
196            free(vndInitCallbackList.list);
197            vndInitCallbackList.list = next;
198        }
199    }
200}
201
202void
203GlxExtensionInit(void)
204{
205    ExtensionEntry *extEntry;
206    GlxExtensionEntry = NULL;
207
208    // Init private keys, per-screen data
209    if (!dixRegisterPrivateKey(&glvXGLVScreenPrivKey, PRIVATE_SCREEN, 0))
210        return;
211    if (!dixRegisterPrivateKey(&glvXGLVClientPrivKey, PRIVATE_CLIENT, 0))
212        return;
213
214    if (!GlxMappingInit()) {
215        return;
216    }
217
218    if (!GlxDispatchInit()) {
219        return;
220    }
221
222    if (!AddCallback(&ClientStateCallback, GLXClientCallback, NULL)) {
223        return;
224    }
225
226    extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS,
227                            __GLX_NUMBER_ERRORS, GlxDispatchRequest,
228                            GlxDispatchRequest, GLXReset, StandardMinorOpcode);
229    if (!extEntry) {
230        return;
231    }
232
233    GlxExtensionEntry = extEntry;
234    GlxErrorBase = extEntry->errorBase;
235    CallCallbacks(&vndInitCallbackListPtr, extEntry);
236
237    /* We'd better have found at least one vendor */
238    for (int i = 0; i < screenInfo.numScreens; i++)
239        if (GlxGetVendorForScreen(serverClient, screenInfo.screens[i]))
240            return;
241    extEntry->base = 0;
242}
243
244static int
245GlxForwardRequest(GlxServerVendor *vendor, ClientPtr client)
246{
247    return vendor->glxvc.handleRequest(client);
248}
249
250static GlxServerVendor *
251GlxGetContextTag(ClientPtr client, GLXContextTag tag)
252{
253    GlxContextTagInfo *tagInfo = GlxLookupContextTag(client, tag);
254
255    if (tagInfo != NULL) {
256        return tagInfo->vendor;
257    } else {
258        return NULL;
259    }
260}
261
262static Bool
263GlxSetContextTagPrivate(ClientPtr client, GLXContextTag tag, void *data)
264{
265    GlxContextTagInfo *tagInfo = GlxLookupContextTag(client, tag);
266    if (tagInfo != NULL) {
267        tagInfo->data = data;
268        return TRUE;
269    } else {
270        return FALSE;
271    }
272}
273
274static void *
275GlxGetContextTagPrivate(ClientPtr client, GLXContextTag tag)
276{
277    GlxContextTagInfo *tagInfo = GlxLookupContextTag(client, tag);
278    if (tagInfo != NULL) {
279        return tagInfo->data;
280    } else {
281        return NULL;
282    }
283}
284
285static GlxServerImports *
286GlxAllocateServerImports(void)
287{
288    return calloc(1, sizeof(GlxServerImports));
289}
290
291static void
292GlxFreeServerImports(GlxServerImports *imports)
293{
294    free(imports);
295}
296
297_X_EXPORT const GlxServerExports glxServer = {
298    .majorVersion = 0,
299    .minorVersion = 0,
300
301    .extensionInitCallback = &vndInitCallbackListPtr,
302
303    .allocateServerImports = GlxAllocateServerImports,
304    .freeServerImports = GlxFreeServerImports,
305
306    .createVendor = GlxCreateVendor,
307    .destroyVendor = GlxDestroyVendor,
308    .setScreenVendor = GlxSetScreenVendor,
309
310    .addXIDMap = GlxAddXIDMap,
311    .getXIDMap = GlxGetXIDMap,
312    .removeXIDMap = GlxRemoveXIDMap,
313    .getContextTag = GlxGetContextTag,
314    .setContextTagPrivate = GlxSetContextTagPrivate,
315    .getContextTagPrivate = GlxGetContextTagPrivate,
316    .getVendorForScreen = GlxGetVendorForScreen,
317    .forwardRequest =  GlxForwardRequest,
318};
319
320const GlxServerExports *
321glvndGetExports(void)
322{
323    return &glxServer;
324}
325