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