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