vndext.c (8944B)
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 53 idResourceDeleteCallback(void *value, XID id) 54 { 55 return 0; 56 } 57 58 static GlxScreenPriv * 59 xglvGetScreenPrivate(ScreenPtr pScreen) 60 { 61 return dixLookupPrivate(&pScreen->devPrivates, &glvXGLVScreenPrivKey); 62 } 63 64 static void 65 xglvSetScreenPrivate(ScreenPtr pScreen, void *priv) 66 { 67 dixSetPrivate(&pScreen->devPrivates, &glvXGLVScreenPrivKey, priv); 68 } 69 70 GlxScreenPriv * 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 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 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 * 126 xglvGetClientPrivate(ClientPtr pClient) 127 { 128 return dixLookupPrivate(&pClient->devPrivates, &glvXGLVClientPrivKey); 129 } 130 131 static void 132 xglvSetClientPrivate(ClientPtr pClient, void *priv) 133 { 134 dixSetPrivate(&pClient->devPrivates, &glvXGLVClientPrivKey, priv); 135 } 136 137 GlxClientPriv * 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 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 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 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 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 254 GlxForwardRequest(GlxServerVendor *vendor, ClientPtr client) 255 { 256 return vendor->glxvc.handleRequest(client); 257 } 258 259 static GlxServerVendor * 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 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 * 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 * 295 GlxAllocateServerImports(void) 296 { 297 return calloc(1, sizeof(GlxServerImports)); 298 } 299 300 static void 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 * 331 glvndGetExports(void) 332 { 333 return &glxServer; 334 }