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