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
36 static ClientPtr requestClient = NULL;
37
GlxSetRequestClient(ClientPtr client)38 void GlxSetRequestClient(ClientPtr client)
39 {
40 requestClient = client;
41 }
42
LookupXIDMapResource(XID id)43 static 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
GlxGetXIDMap(XID id)56 GlxServerVendor *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
GlxAddXIDMap(XID id,GlxServerVendor * vendor)75 Bool 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
GlxRemoveXIDMap(XID id)86 void GlxRemoveXIDMap(XID id)
87 {
88 FreeResourceByType(id, idResource, FALSE);
89 }
90
GlxAllocContextTag(ClientPtr client,GlxServerVendor * vendor)91 GlxContextTagInfo *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
GlxLookupContextTag(ClientPtr client,GLXContextTag tag)143 GlxContextTagInfo *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
GlxFreeContextTag(GlxContextTagInfo * tagInfo)159 void 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
GlxSetScreenVendor(ScreenPtr screen,GlxServerVendor * vendor)171 Bool 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
GlxSetClientScreenVendor(ClientPtr client,ScreenPtr screen,GlxServerVendor * vendor)192 Bool 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
GlxGetVendorForScreen(ClientPtr client,ScreenPtr screen)213 GlxServerVendor *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