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 <pixmapstr.h> 33 34#include "vndservervendor.h" 35 36static ClientPtr requestClient = NULL; 37 38void GlxSetRequestClient(ClientPtr client) 39{ 40 requestClient = client; 41} 42 43static GlxServerVendor *LookupXIDMapResource(XID id) 44{ 45 void *ptr = NULL; 46 int rv; 47 48 rv = dixLookupResourceByType(&ptr, id, idResource, NULL, DixReadAccess); 49 if (rv == Success) { 50 return (GlxServerVendor *) ptr; 51 } else { 52 return NULL; 53 } 54} 55 56GlxServerVendor *GlxGetXIDMap(XID id) 57{ 58 GlxServerVendor *vendor = LookupXIDMapResource(id); 59 60 if (vendor == NULL) { 61 // If we haven't seen this XID before, then it may be a drawable that 62 // wasn't created through GLX, like a regular X window or pixmap. Try 63 // to look up a matching drawable to find a screen number for it. 64 void *ptr = NULL; 65 int rv = dixLookupResourceByClass(&ptr, id, RC_DRAWABLE, NULL, 66 DixGetAttrAccess); 67 if (rv == Success && ptr != NULL) { 68 DrawablePtr draw = (DrawablePtr) ptr; 69 vendor = GlxGetVendorForScreen(requestClient, draw->pScreen); 70 } 71 } 72 return vendor; 73} 74 75Bool GlxAddXIDMap(XID id, GlxServerVendor *vendor) 76{ 77 if (id == 0 || vendor == NULL) { 78 return FALSE; 79 } 80 if (LookupXIDMapResource(id) != NULL) { 81 return FALSE; 82 } 83 return AddResource(id, idResource, vendor); 84} 85 86void GlxRemoveXIDMap(XID id) 87{ 88 FreeResourceByType(id, idResource, FALSE); 89} 90 91GlxContextTagInfo *GlxAllocContextTag(ClientPtr client, GlxServerVendor *vendor) 92{ 93 GlxClientPriv *cl; 94 unsigned int index; 95 96 if (vendor == NULL) { 97 return NULL; 98 } 99 100 cl = GlxGetClientData(client); 101 if (cl == NULL) { 102 return NULL; 103 } 104 105 // Look for a free tag index. 106 for (index=0; index<cl->contextTagCount; index++) { 107 if (cl->contextTags[index].vendor == NULL) { 108 break; 109 } 110 } 111 if (index >= cl->contextTagCount) { 112 // We didn't find a free entry, so grow the array. 113 GlxContextTagInfo *newTags; 114 unsigned int newSize = cl->contextTagCount * 2; 115 if (newSize == 0) { 116 // TODO: What's a good starting size for this? 117 newSize = 16; 118 } 119 120 newTags = (GlxContextTagInfo *) 121 realloc(cl->contextTags, newSize * sizeof(GlxContextTagInfo)); 122 if (newTags == NULL) { 123 return NULL; 124 } 125 126 memset(&newTags[cl->contextTagCount], 0, 127 (newSize - cl->contextTagCount) * sizeof(GlxContextTagInfo)); 128 129 index = cl->contextTagCount; 130 cl->contextTags = newTags; 131 cl->contextTagCount = newSize; 132 } 133 134 assert(index >= 0); 135 assert(index < cl->contextTagCount); 136 memset(&cl->contextTags[index], 0, sizeof(GlxContextTagInfo)); 137 cl->contextTags[index].tag = (GLXContextTag) (index + 1); 138 cl->contextTags[index].client = client; 139 cl->contextTags[index].vendor = vendor; 140 return &cl->contextTags[index]; 141} 142 143GlxContextTagInfo *GlxLookupContextTag(ClientPtr client, GLXContextTag tag) 144{ 145 GlxClientPriv *cl = GlxGetClientData(client); 146 if (cl == NULL) { 147 return NULL; 148 } 149 150 if (tag > 0 && (tag - 1) < cl->contextTagCount) { 151 if (cl->contextTags[tag - 1].vendor != NULL) { 152 assert(cl->contextTags[tag - 1].client == client); 153 return &cl->contextTags[tag - 1]; 154 } 155 } 156 return NULL; 157} 158 159void GlxFreeContextTag(GlxContextTagInfo *tagInfo) 160{ 161 if (tagInfo != NULL) { 162 tagInfo->vendor = NULL; 163 tagInfo->vendor = NULL; 164 tagInfo->data = NULL; 165 tagInfo->context = None; 166 tagInfo->drawable = None; 167 tagInfo->readdrawable = None; 168 } 169} 170 171Bool GlxSetScreenVendor(ScreenPtr screen, GlxServerVendor *vendor) 172{ 173 GlxScreenPriv *priv; 174 175 if (vendor == NULL) { 176 return FALSE; 177 } 178 179 priv = GlxGetScreen(screen); 180 if (priv == NULL) { 181 return FALSE; 182 } 183 184 if (priv->vendor != NULL) { 185 return FALSE; 186 } 187 188 priv->vendor = vendor; 189 return TRUE; 190} 191 192Bool GlxSetClientScreenVendor(ClientPtr client, ScreenPtr screen, GlxServerVendor *vendor) 193{ 194 GlxClientPriv *cl; 195 196 if (screen == NULL || screen->isGPU) { 197 return FALSE; 198 } 199 200 cl = GlxGetClientData(client); 201 if (cl == NULL) { 202 return FALSE; 203 } 204 205 if (vendor != NULL) { 206 cl->vendors[screen->myNum] = vendor; 207 } else { 208 cl->vendors[screen->myNum] = GlxGetVendorForScreen(NULL, screen); 209 } 210 return TRUE; 211} 212 213GlxServerVendor *GlxGetVendorForScreen(ClientPtr client, ScreenPtr screen) 214{ 215 // Note that the client won't be sending GPU screen numbers, so we don't 216 // need per-client mappings for them. 217 if (client != NULL && !screen->isGPU) { 218 GlxClientPriv *cl = GlxGetClientData(client); 219 if (cl != NULL) { 220 return cl->vendors[screen->myNum]; 221 } else { 222 return NULL; 223 } 224 } else { 225 GlxScreenPriv *priv = GlxGetScreen(screen); 226 if (priv != NULL) { 227 return priv->vendor; 228 } else { 229 return NULL; 230 } 231 } 232} 233