initial commit
[profile/ivi/xorg-x11-server.git] / glx / indirect_util.c
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 "glapitable.h"
43 #include "glapi.h"
44 #include "glthread.h"
45 #include "dispatch.h"
46 #include "glxext.h"
47 #include "indirect_table.h"
48 #include "indirect_util.h"
49
50
51 #define __GLX_PAD(a) (((a)+3)&~3)
52
53 extern xGLXSingleReply __glXReply;
54
55
56 GLint
57 __glGetBooleanv_variable_size( GLenum e )
58 {
59     if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) {
60         GLint temp;
61
62         CALL_GetIntegerv( GET_DISPATCH(),
63                           (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) );
64         return temp;
65     }
66     else {
67         return 0;
68     }
69 }
70
71
72 /**
73  * Get a properly aligned buffer to hold reply data.
74  *
75  * \warning
76  * This function assumes that \c local_buffer is already properly aligned.
77  * It also assumes that \c alignment is a power of two.
78  */
79 void *
80 __glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size,
81     void * local_buffer, size_t local_size, unsigned alignment )
82 {
83     void * buffer = local_buffer;
84     const unsigned mask = alignment - 1;
85
86     if ( local_size < required_size ) {
87         const size_t worst_case_size = required_size + alignment;
88         intptr_t  temp_buf;
89
90         if ( cl->returnBufSize < worst_case_size ) {
91             void * temp = realloc( cl->returnBuf, worst_case_size );
92             
93             if ( temp == NULL ) {
94                 return NULL;
95             }
96             
97             cl->returnBuf = temp;
98             cl->returnBufSize = worst_case_size;
99         }
100         
101         temp_buf = (intptr_t) cl->returnBuf;
102         temp_buf = (temp_buf + mask) & ~mask;
103         buffer = (void *) temp_buf;
104     }
105
106     return buffer;
107 }
108
109
110 /**
111  * Send a GLX reply to the client.
112  *
113  * Technically speaking, there are several different ways to encode a GLX
114  * reply.  The primary difference is whether or not certain fields (e.g.,
115  * retval, size, and "pad3") are set.  This function gets around that by
116  * always setting all of the fields to "reasonable" values.  This does no
117  * harm to clients, but it does make the server-side code much more compact.
118  */
119 void
120 __glXSendReply( ClientPtr client, const void * data, size_t elements,
121     size_t element_size, GLboolean always_array, CARD32 retval )
122 {
123     size_t reply_ints = 0;
124
125     if ( __glXErrorOccured() ) {
126         elements = 0;
127     }
128     else if ( (elements > 1) || always_array ) {
129         reply_ints = bytes_to_int32(elements * element_size);
130     }
131
132     __glXReply.length =         reply_ints;
133     __glXReply.type =           X_Reply;
134     __glXReply.sequenceNumber = client->sequence;
135     __glXReply.size =           elements;
136     __glXReply.retval =         retval;
137
138
139     /* It is faster on almost always every architecture to just copy the 8
140      * bytes, even when not necessary, than check to see of the value of
141      * elements requires it.  Copying the data when not needed will do no
142      * harm.
143      */
144
145     (void) memcpy( & __glXReply.pad3, data, 8 );
146     WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
147
148     if ( reply_ints != 0 ) {
149         WriteToClient( client, reply_ints * 4, (char *) data );
150     }
151 }
152
153
154 /**
155  * Send a GLX reply to the client.
156  *
157  * Technically speaking, there are several different ways to encode a GLX
158  * reply.  The primary difference is whether or not certain fields (e.g.,
159  * retval, size, and "pad3") are set.  This function gets around that by
160  * always setting all of the fields to "reasonable" values.  This does no
161  * harm to clients, but it does make the server-side code much more compact.
162  *
163  * \warning
164  * This function assumes that values stored in \c data will be byte-swapped
165  * by the caller if necessary.
166  */
167 void
168 __glXSendReplySwap( ClientPtr client, const void * data, size_t elements,
169     size_t element_size, GLboolean always_array, CARD32 retval )
170 {
171     size_t reply_ints = 0;
172
173     if ( __glXErrorOccured() ) {
174         elements = 0;
175     }
176     else if ( (elements > 1) || always_array ) {
177         reply_ints = bytes_to_int32(elements * element_size);
178     }
179
180     __glXReply.length =         bswap_32( reply_ints );
181     __glXReply.type =           X_Reply;
182     __glXReply.sequenceNumber = bswap_16( client->sequence );
183     __glXReply.size =           bswap_32( elements );
184     __glXReply.retval =         bswap_32( retval );
185
186
187     /* It is faster on almost always every architecture to just copy the 8
188      * bytes, even when not necessary, than check to see of the value of
189      * elements requires it.  Copying the data when not needed will do no
190      * harm.
191      */
192
193     (void) memcpy( & __glXReply.pad3, data, 8 );
194     WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
195
196     if ( reply_ints != 0 ) {
197         WriteToClient( client, reply_ints * 4, (char *) data );
198     }
199 }
200
201
202 static int
203 get_decode_index(const struct __glXDispatchInfo *dispatch_info,
204                  unsigned opcode)
205 {
206     int remaining_bits;
207     int next_remain;
208     const int_fast16_t * const tree = dispatch_info->dispatch_tree;
209     int_fast16_t index;
210
211
212     remaining_bits = dispatch_info->bits;
213     if (opcode >= (1U << remaining_bits)) {
214         return -1;
215     }
216     
217     index = 0;
218     for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) {
219         unsigned mask;
220         unsigned child_index;
221
222
223         /* Calculate the slice of bits used by this node.
224          * 
225          * If remaining_bits = 8 and tree[index] = 3, the mask of just the
226          * remaining bits is 0x00ff and the mask for the remaining bits after
227          * this node is 0x001f.  By taking 0x00ff & ~0x001f, we get 0x00e0.
228          * This masks the 3 bits that we would want for this node.
229          */
230
231         next_remain = remaining_bits - tree[index];
232         mask = ((1 << remaining_bits) - 1) &
233           ~((1 << next_remain) - 1);
234
235
236         /* Using the mask, calculate the index of the opcode in the node.
237          * With that index, fetch the index of the next node.
238          */
239
240         child_index = (opcode & mask) >> next_remain;
241         index = tree[index + 1 + child_index];
242
243
244         /* If the next node is an empty leaf, the opcode is for a non-existant
245          * function.  We're done.
246          *
247          * If the next node is a non-empty leaf, look up the function pointer
248          * and return it.
249          */
250
251         if (index == EMPTY_LEAF) {
252             return -1;
253         }
254         else if (IS_LEAF_INDEX(index)) {
255             unsigned func_index;
256
257
258             /* The value stored in the tree for a leaf node is the base of
259              * the function pointers for that leaf node.  The offset for the
260              * function for a particular opcode is the remaining bits in the
261              * opcode.
262              */
263
264             func_index = -index;
265             func_index += opcode & ((1 << next_remain) - 1);
266             return func_index;
267         }
268     }
269
270     /* We should *never* get here!!!
271      */
272     return -1;
273 }
274
275
276 void *
277 __glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
278                                int opcode, int swapped_version)
279 {
280     const int func_index = get_decode_index(dispatch_info, opcode);
281
282     return (func_index < 0) 
283         ? NULL 
284         : (void *) dispatch_info->dispatch_functions[func_index][swapped_version];
285 }
286
287
288 int
289 __glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
290                          int opcode, __GLXrenderSizeData *data)
291 {
292     if (dispatch_info->size_table != NULL) {
293         const int func_index = get_decode_index(dispatch_info, opcode);
294
295         if ((func_index >= 0) 
296             && (dispatch_info->size_table[func_index][0] != 0)) {
297             const int var_offset = 
298                 dispatch_info->size_table[func_index][1];
299
300             data->bytes = dispatch_info->size_table[func_index][0];
301             data->varsize = (var_offset != ~0)
302                 ? dispatch_info->size_func_table[var_offset]
303                 : NULL;
304
305             return 0;
306         }
307     }
308
309     return -1;
310 }