2 * (C) Copyright IBM Corporation 2005
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
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
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
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
34 #include <GL/glxproto.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"
43 #include "indirect_table.h"
44 #include "indirect_util.h"
46 #define __GLX_PAD(a) (((a)+3)&~3)
48 extern xGLXSingleReply __glXReply
;
51 __glGetBooleanv_variable_size(GLenum e
)
53 if (e
== GL_COMPRESSED_TEXTURE_FORMATS
) {
56 glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
, &temp
);
65 * Get a properly aligned buffer to hold reply data.
68 * This function assumes that \c local_buffer is already properly aligned.
69 * It also assumes that \c alignment is a power of two.
72 __glXGetAnswerBuffer(__GLXclientState
* cl
, size_t required_size
,
73 void *local_buffer
, size_t local_size
, unsigned alignment
)
75 void *buffer
= local_buffer
;
76 const unsigned mask
= alignment
- 1;
78 if (local_size
< required_size
) {
79 const size_t worst_case_size
= required_size
+ alignment
;
82 if (cl
->returnBufSize
< worst_case_size
) {
83 void *temp
= realloc(cl
->returnBuf
, worst_case_size
);
90 cl
->returnBufSize
= worst_case_size
;
93 temp_buf
= (intptr_t) cl
->returnBuf
;
94 temp_buf
= (temp_buf
+ mask
) & ~mask
;
95 buffer
= (void *) temp_buf
;
102 * Send a GLX reply to the client.
104 * Technically speaking, there are several different ways to encode a GLX
105 * reply. The primary difference is whether or not certain fields (e.g.,
106 * retval, size, and "pad3") are set. This function gets around that by
107 * always setting all of the fields to "reasonable" values. This does no
108 * harm to clients, but it does make the server-side code much more compact.
111 __glXSendReply(ClientPtr client
, const void *data
, size_t elements
,
112 size_t element_size
, GLboolean always_array
, CARD32 retval
)
114 size_t reply_ints
= 0;
116 if (__glXErrorOccured()) {
119 else if ((elements
> 1) || always_array
) {
120 reply_ints
= bytes_to_int32(elements
* element_size
);
123 __glXReply
.length
= reply_ints
;
124 __glXReply
.type
= X_Reply
;
125 __glXReply
.sequenceNumber
= client
->sequence
;
126 __glXReply
.size
= elements
;
127 __glXReply
.retval
= retval
;
129 /* It is faster on almost always every architecture to just copy the 8
130 * bytes, even when not necessary, than check to see of the value of
131 * elements requires it. Copying the data when not needed will do no
135 (void) memcpy(&__glXReply
.pad3
, data
, 8);
136 WriteToClient(client
, sz_xGLXSingleReply
, &__glXReply
);
138 if (reply_ints
!= 0) {
139 WriteToClient(client
, reply_ints
* 4, data
);
144 * Send a GLX reply to the client.
146 * Technically speaking, there are several different ways to encode a GLX
147 * reply. The primary difference is whether or not certain fields (e.g.,
148 * retval, size, and "pad3") are set. This function gets around that by
149 * always setting all of the fields to "reasonable" values. This does no
150 * harm to clients, but it does make the server-side code much more compact.
153 * This function assumes that values stored in \c data will be byte-swapped
154 * by the caller if necessary.
157 __glXSendReplySwap(ClientPtr client
, const void *data
, size_t elements
,
158 size_t element_size
, GLboolean always_array
, CARD32 retval
)
160 size_t reply_ints
= 0;
162 if (__glXErrorOccured()) {
165 else if ((elements
> 1) || always_array
) {
166 reply_ints
= bytes_to_int32(elements
* element_size
);
169 __glXReply
.length
= bswap_32(reply_ints
);
170 __glXReply
.type
= X_Reply
;
171 __glXReply
.sequenceNumber
= bswap_16(client
->sequence
);
172 __glXReply
.size
= bswap_32(elements
);
173 __glXReply
.retval
= bswap_32(retval
);
175 /* It is faster on almost always every architecture to just copy the 8
176 * bytes, even when not necessary, than check to see of the value of
177 * elements requires it. Copying the data when not needed will do no
181 (void) memcpy(&__glXReply
.pad3
, data
, 8);
182 WriteToClient(client
, sz_xGLXSingleReply
, &__glXReply
);
184 if (reply_ints
!= 0) {
185 WriteToClient(client
, reply_ints
* 4, data
);
190 get_decode_index(const struct __glXDispatchInfo
*dispatch_info
, unsigned opcode
)
194 const int_fast16_t *const tree
= dispatch_info
->dispatch_tree
;
197 remaining_bits
= dispatch_info
->bits
;
198 if (opcode
>= (1U << remaining_bits
)) {
203 for ( /* empty */ ; remaining_bits
> 0; remaining_bits
= next_remain
) {
205 unsigned child_index
;
207 /* Calculate the slice of bits used by this node.
209 * If remaining_bits = 8 and tree[index] = 3, the mask of just the
210 * remaining bits is 0x00ff and the mask for the remaining bits after
211 * this node is 0x001f. By taking 0x00ff & ~0x001f, we get 0x00e0.
212 * This masks the 3 bits that we would want for this node.
215 next_remain
= remaining_bits
- tree
[index
];
216 mask
= ((1 << remaining_bits
) - 1) & ~((1 << next_remain
) - 1);
218 /* Using the mask, calculate the index of the opcode in the node.
219 * With that index, fetch the index of the next node.
222 child_index
= (opcode
& mask
) >> next_remain
;
223 index
= tree
[index
+ 1 + child_index
];
225 /* If the next node is an empty leaf, the opcode is for a non-existant
226 * function. We're done.
228 * If the next node is a non-empty leaf, look up the function pointer
232 if (index
== EMPTY_LEAF
) {
235 else if (IS_LEAF_INDEX(index
)) {
238 /* The value stored in the tree for a leaf node is the base of
239 * the function pointers for that leaf node. The offset for the
240 * function for a particular opcode is the remaining bits in the
245 func_index
+= opcode
& ((1 << next_remain
) - 1);
250 /* We should *never* get here!!!
256 __glXGetProtocolDecodeFunction(const struct __glXDispatchInfo
*dispatch_info
,
257 int opcode
, int swapped_version
)
259 const int func_index
= get_decode_index(dispatch_info
, opcode
);
261 return (func_index
< 0)
263 : (void *) dispatch_info
->
264 dispatch_functions
[func_index
][swapped_version
];
268 __glXGetProtocolSizeData(const struct __glXDispatchInfo
*dispatch_info
,
269 int opcode
, __GLXrenderSizeData
* data
)
271 if (dispatch_info
->size_table
!= NULL
) {
272 const int func_index
= get_decode_index(dispatch_info
, opcode
);
274 if ((func_index
>= 0)
275 && (dispatch_info
->size_table
[func_index
][0] != 0)) {
276 const int var_offset
= dispatch_info
->size_table
[func_index
][1];
278 data
->bytes
= dispatch_info
->size_table
[func_index
][0];
279 data
->varsize
= (var_offset
!= ~0)
280 ? dispatch_info
->size_func_table
[var_offset
]