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