First import
[xorg_rtime.git] / xorg-server-1.4 / GL / glx / indirect_util.c
blob58c194c994635100028012529a1855b280c5bedc
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:
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.
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.
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
28 #endif
30 #include <string.h>
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"
51 #define __GLX_PAD(a) (((a)+3)&~3)
53 extern xGLXSingleReply __glXReply;
56 GLint
57 __glGetBooleanv_variable_size( GLenum e )
59 if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) {
60 GLint temp;
62 CALL_GetIntegerv( GET_DISPATCH(),
63 (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) );
64 return temp;
66 else {
67 return 0;
72 /**
73 * Get a properly aligned buffer to hold reply data.
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.
79 void *
80 __glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size,
81 void * local_buffer, size_t local_size, unsigned alignment )
83 void * buffer = local_buffer;
84 const unsigned mask = alignment - 1;
86 if ( local_size < required_size ) {
87 const size_t worst_case_size = required_size + alignment;
88 intptr_t temp_buf;
90 if ( cl->returnBufSize < worst_case_size ) {
91 void * temp = xrealloc( cl->returnBuf, worst_case_size );
93 if ( temp == NULL ) {
94 return NULL;
97 cl->returnBuf = temp;
98 cl->returnBufSize = worst_case_size;
101 temp_buf = (intptr_t) cl->returnBuf;
102 temp_buf = (temp_buf + mask) & ~mask;
103 buffer = (void *) temp_buf;
106 return buffer;
111 * Send a GLX reply to the client.
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.
119 void
120 __glXSendReply( ClientPtr client, const void * data, size_t elements,
121 size_t element_size, GLboolean always_array, CARD32 retval )
123 size_t reply_ints = 0;
125 if ( __glXErrorOccured() ) {
126 elements = 0;
128 else if ( (elements > 1) || always_array ) {
129 reply_ints = ((elements * element_size) + 3) >> 2;
132 __glXReply.length = reply_ints;
133 __glXReply.type = X_Reply;
134 __glXReply.sequenceNumber = client->sequence;
135 __glXReply.size = elements;
136 __glXReply.retval = retval;
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.
145 (void) memcpy( & __glXReply.pad3, data, 8 );
146 WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
148 if ( reply_ints != 0 ) {
149 WriteToClient( client, reply_ints * 4, (char *) data );
155 * Send a GLX reply to the client.
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.
163 * \warning
164 * This function assumes that values stored in \c data will be byte-swapped
165 * by the caller if necessary.
167 void
168 __glXSendReplySwap( ClientPtr client, const void * data, size_t elements,
169 size_t element_size, GLboolean always_array, CARD32 retval )
171 size_t reply_ints = 0;
173 if ( __glXErrorOccured() ) {
174 elements = 0;
176 else if ( (elements > 1) || always_array ) {
177 reply_ints = ((elements * element_size) + 3) >> 2;
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 );
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.
193 (void) memcpy( & __glXReply.pad3, data, 8 );
194 WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
196 if ( reply_ints != 0 ) {
197 WriteToClient( client, reply_ints * 4, (char *) data );
202 static int
203 get_decode_index(const struct __glXDispatchInfo *dispatch_info,
204 unsigned opcode)
206 int remaining_bits;
207 int next_remain;
208 const int_fast16_t * const tree = dispatch_info->dispatch_tree;
209 int_fast16_t index;
212 remaining_bits = dispatch_info->bits;
213 if (opcode >= (1U << remaining_bits)) {
214 return -1;
217 index = 0;
218 for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) {
219 unsigned mask;
220 unsigned child_index;
223 /* Calculate the slice of bits used by this node.
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.
231 next_remain = remaining_bits - tree[index];
232 mask = ((1 << remaining_bits) - 1) &
233 ~((1 << next_remain) - 1);
236 /* Using the mask, calculate the index of the opcode in the node.
237 * With that index, fetch the index of the next node.
240 child_index = (opcode & mask) >> next_remain;
241 index = tree[index + 1 + child_index];
244 /* If the next node is an empty leaf, the opcode is for a non-existant
245 * function. We're done.
247 * If the next node is a non-empty leaf, look up the function pointer
248 * and return it.
251 if (index == EMPTY_LEAF) {
252 return -1;
254 else if (IS_LEAF_INDEX(index)) {
255 unsigned func_index;
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.
264 func_index = -index;
265 func_index += opcode & ((1 << next_remain) - 1);
266 return func_index;
270 /* We should *never* get here!!!
272 return -1;
276 void *
277 __glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
278 int opcode, int swapped_version)
280 const int func_index = get_decode_index(dispatch_info, opcode);
282 return (func_index < 0)
283 ? NULL
284 : (void *) dispatch_info->dispatch_functions[func_index][swapped_version];
289 __glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
290 int opcode, __GLXrenderSizeData *data)
292 if (dispatch_info->size_table != NULL) {
293 const int func_index = get_decode_index(dispatch_info, opcode);
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];
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;
305 return 0;
309 return -1;