1 /*
2  * (C) Copyright IBM Corporation 2005
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * IBM,
20  * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
28 #endif
29 
30 #include <string.h>
31 
32 #include <X11/Xmd.h>
33 #include <GL/gl.h>
34 #include <GL/glxproto.h>
35 #include <inttypes.h>
36 #include "indirect_size.h"
37 #include "indirect_size_get.h"
38 #include "indirect_dispatch.h"
39 #include "glxserver.h"
40 #include "glxbyteorder.h"
41 #include "singlesize.h"
42 #include "glxext.h"
43 #include "indirect_table.h"
44 #include "indirect_util.h"
45 
46 #define __GLX_PAD(a) (((a)+3)&~3)
47 
48 GLint
__glGetBooleanv_variable_size(GLenum e)49 __glGetBooleanv_variable_size(GLenum e)
50 {
51     if (e == GL_COMPRESSED_TEXTURE_FORMATS) {
52         GLint temp;
53 
54         glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &temp);
55         return temp;
56     }
57     else {
58         return 0;
59     }
60 }
61 
62 /**
63  * Get a properly aligned buffer to hold reply data.
64  *
65  * \warning
66  * This function assumes that \c local_buffer is already properly aligned.
67  * It also assumes that \c alignment is a power of two.
68  */
69 void *
__glXGetAnswerBuffer(__GLXclientState * cl,size_t required_size,void * local_buffer,size_t local_size,unsigned alignment)70 __glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size,
71                      void *local_buffer, size_t local_size, unsigned alignment)
72 {
73     void *buffer = local_buffer;
74     const intptr_t mask = alignment - 1;
75 
76     if (local_size < required_size) {
77         size_t worst_case_size;
78         intptr_t temp_buf;
79 
80         if (required_size < SIZE_MAX - alignment)
81             worst_case_size = required_size + alignment;
82         else
83             return NULL;
84 
85         if (cl->returnBufSize < worst_case_size) {
86             void *temp = realloc(cl->returnBuf, worst_case_size);
87 
88             if (temp == NULL) {
89                 return NULL;
90             }
91 
92             cl->returnBuf = temp;
93             cl->returnBufSize = worst_case_size;
94         }
95 
96         temp_buf = (intptr_t) cl->returnBuf;
97         temp_buf = (temp_buf + mask) & ~mask;
98         buffer = (void *) temp_buf;
99     }
100 
101     return buffer;
102 }
103 
104 /**
105  * Send a GLX reply to the client.
106  *
107  * Technically speaking, there are several different ways to encode a GLX
108  * reply.  The primary difference is whether or not certain fields (e.g.,
109  * retval, size, and "pad3") are set.  This function gets around that by
110  * always setting all of the fields to "reasonable" values.  This does no
111  * harm to clients, but it does make the server-side code much more compact.
112  */
113 void
__glXSendReply(ClientPtr client,const void * data,size_t elements,size_t element_size,GLboolean always_array,CARD32 retval)114 __glXSendReply(ClientPtr client, const void *data, size_t elements,
115                size_t element_size, GLboolean always_array, CARD32 retval)
116 {
117     size_t reply_ints = 0;
118     xGLXSingleReply reply = { 0, };
119 
120     if (__glXErrorOccured()) {
121         elements = 0;
122     }
123     else if ((elements > 1) || always_array) {
124         reply_ints = bytes_to_int32(elements * element_size);
125     }
126 
127     reply.length = reply_ints;
128     reply.type = X_Reply;
129     reply.sequenceNumber = client->sequence;
130     reply.size = elements;
131     reply.retval = retval;
132 
133     /* It is faster on almost always every architecture to just copy the 8
134      * bytes, even when not necessary, than check to see of the value of
135      * elements requires it.  Copying the data when not needed will do no
136      * harm.
137      */
138 
139     (void) memcpy(&reply.pad3, data, 8);
140     WriteToClient(client, sz_xGLXSingleReply, &reply);
141 
142     if (reply_ints != 0) {
143         WriteToClient(client, reply_ints * 4, data);
144     }
145 }
146 
147 /**
148  * Send a GLX reply to the client.
149  *
150  * Technically speaking, there are several different ways to encode a GLX
151  * reply.  The primary difference is whether or not certain fields (e.g.,
152  * retval, size, and "pad3") are set.  This function gets around that by
153  * always setting all of the fields to "reasonable" values.  This does no
154  * harm to clients, but it does make the server-side code much more compact.
155  *
156  * \warning
157  * This function assumes that values stored in \c data will be byte-swapped
158  * by the caller if necessary.
159  */
160 void
__glXSendReplySwap(ClientPtr client,const void * data,size_t elements,size_t element_size,GLboolean always_array,CARD32 retval)161 __glXSendReplySwap(ClientPtr client, const void *data, size_t elements,
162                    size_t element_size, GLboolean always_array, CARD32 retval)
163 {
164     size_t reply_ints = 0;
165     xGLXSingleReply reply = { 0, };
166 
167     if (__glXErrorOccured()) {
168         elements = 0;
169     }
170     else if ((elements > 1) || always_array) {
171         reply_ints = bytes_to_int32(elements * element_size);
172     }
173 
174     reply.length = bswap_32(reply_ints);
175     reply.type = X_Reply;
176     reply.sequenceNumber = bswap_16(client->sequence);
177     reply.size = bswap_32(elements);
178     reply.retval = bswap_32(retval);
179 
180     /* It is faster on almost always every architecture to just copy the 8
181      * bytes, even when not necessary, than check to see of the value of
182      * elements requires it.  Copying the data when not needed will do no
183      * harm.
184      */
185 
186     (void) memcpy(&reply.pad3, data, 8);
187     WriteToClient(client, sz_xGLXSingleReply, &reply);
188 
189     if (reply_ints != 0) {
190         WriteToClient(client, reply_ints * 4, data);
191     }
192 }
193 
194 static int
get_decode_index(const struct __glXDispatchInfo * dispatch_info,unsigned opcode)195 get_decode_index(const struct __glXDispatchInfo *dispatch_info, unsigned opcode)
196 {
197     int remaining_bits;
198     int next_remain;
199     const int_fast16_t *const tree = dispatch_info->dispatch_tree;
200     int_fast16_t index;
201 
202     remaining_bits = dispatch_info->bits;
203     if (opcode >= (1U << remaining_bits)) {
204         return -1;
205     }
206 
207     index = 0;
208     for ( /* empty */ ; remaining_bits > 0; remaining_bits = next_remain) {
209         unsigned mask;
210         unsigned child_index;
211 
212         /* Calculate the slice of bits used by this node.
213          *
214          * If remaining_bits = 8 and tree[index] = 3, the mask of just the
215          * remaining bits is 0x00ff and the mask for the remaining bits after
216          * this node is 0x001f.  By taking 0x00ff & ~0x001f, we get 0x00e0.
217          * This masks the 3 bits that we would want for this node.
218          */
219 
220         next_remain = remaining_bits - tree[index];
221         mask = ((1 << remaining_bits) - 1) & ~((1 << next_remain) - 1);
222 
223         /* Using the mask, calculate the index of the opcode in the node.
224          * With that index, fetch the index of the next node.
225          */
226 
227         child_index = (opcode & mask) >> next_remain;
228         index = tree[index + 1 + child_index];
229 
230         /* If the next node is an empty leaf, the opcode is for a non-existent
231          * function.  We're done.
232          *
233          * If the next node is a non-empty leaf, look up the function pointer
234          * and return it.
235          */
236 
237         if (index == EMPTY_LEAF) {
238             return -1;
239         }
240         else if (IS_LEAF_INDEX(index)) {
241             unsigned func_index;
242 
243             /* The value stored in the tree for a leaf node is the base of
244              * the function pointers for that leaf node.  The offset for the
245              * function for a particular opcode is the remaining bits in the
246              * opcode.
247              */
248 
249             func_index = -index;
250             func_index += opcode & ((1 << next_remain) - 1);
251             return func_index;
252         }
253     }
254 
255     /* We should *never* get here!!!
256      */
257     return -1;
258 }
259 
260 void *
__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo * dispatch_info,int opcode,int swapped_version)261 __glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
262                                int opcode, int swapped_version)
263 {
264     const int func_index = get_decode_index(dispatch_info, opcode);
265 
266     return (func_index < 0)
267         ? NULL
268         : (void *) dispatch_info->
269         dispatch_functions[func_index][swapped_version];
270 }
271 
272 int
__glXGetProtocolSizeData(const struct __glXDispatchInfo * dispatch_info,int opcode,__GLXrenderSizeData * data)273 __glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
274                          int opcode, __GLXrenderSizeData * data)
275 {
276     if (dispatch_info->size_table != NULL) {
277         const int func_index = get_decode_index(dispatch_info, opcode);
278 
279         if ((func_index >= 0)
280             && (dispatch_info->size_table[func_index][0] != 0)) {
281             const int var_offset = dispatch_info->size_table[func_index][1];
282 
283             data->bytes = dispatch_info->size_table[func_index][0];
284             data->varsize = (var_offset != ~0)
285                 ? dispatch_info->size_func_table[var_offset]
286                 : NULL;
287 
288             return 0;
289         }
290     }
291 
292     return -1;
293 }
294