Imported Upstream version 1.15.1
[deb_xorg-server.git] / glx / indirect_util.c
CommitLineData
a09e091a
JB
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
48extern xGLXSingleReply __glXReply;
49
50GLint
51__glGetBooleanv_variable_size(GLenum e)
52{
53 if (e == GL_COMPRESSED_TEXTURE_FORMATS) {
54 GLint temp;
55
56 glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &temp);
57 return temp;
58 }
59 else {
60 return 0;
61 }
62}
63
64/**
65 * Get a properly aligned buffer to hold reply data.
66 *
67 * \warning
68 * This function assumes that \c local_buffer is already properly aligned.
69 * It also assumes that \c alignment is a power of two.
70 */
71void *
72__glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size,
73 void *local_buffer, size_t local_size, unsigned alignment)
74{
75 void *buffer = local_buffer;
76 const unsigned mask = alignment - 1;
77
78 if (local_size < required_size) {
79 const size_t worst_case_size = required_size + alignment;
80 intptr_t temp_buf;
81
82 if (cl->returnBufSize < worst_case_size) {
83 void *temp = realloc(cl->returnBuf, worst_case_size);
84
85 if (temp == NULL) {
86 return NULL;
87 }
88
89 cl->returnBuf = temp;
90 cl->returnBufSize = worst_case_size;
91 }
92
93 temp_buf = (intptr_t) cl->returnBuf;
94 temp_buf = (temp_buf + mask) & ~mask;
95 buffer = (void *) temp_buf;
96 }
97
98 return buffer;
99}
100
101/**
102 * Send a GLX reply to the client.
103 *
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.
109 */
110void
111__glXSendReply(ClientPtr client, const void *data, size_t elements,
112 size_t element_size, GLboolean always_array, CARD32 retval)
113{
114 size_t reply_ints = 0;
115
116 if (__glXErrorOccured()) {
117 elements = 0;
118 }
119 else if ((elements > 1) || always_array) {
120 reply_ints = bytes_to_int32(elements * element_size);
121 }
122
123 __glXReply.length = reply_ints;
124 __glXReply.type = X_Reply;
125 __glXReply.sequenceNumber = client->sequence;
126 __glXReply.size = elements;
127 __glXReply.retval = retval;
128
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
132 * harm.
133 */
134
135 (void) memcpy(&__glXReply.pad3, data, 8);
136 WriteToClient(client, sz_xGLXSingleReply, &__glXReply);
137
138 if (reply_ints != 0) {
139 WriteToClient(client, reply_ints * 4, data);
140 }
141}
142
143/**
144 * Send a GLX reply to the client.
145 *
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.
151 *
152 * \warning
153 * This function assumes that values stored in \c data will be byte-swapped
154 * by the caller if necessary.
155 */
156void
157__glXSendReplySwap(ClientPtr client, const void *data, size_t elements,
158 size_t element_size, GLboolean always_array, CARD32 retval)
159{
160 size_t reply_ints = 0;
161
162 if (__glXErrorOccured()) {
163 elements = 0;
164 }
165 else if ((elements > 1) || always_array) {
166 reply_ints = bytes_to_int32(elements * element_size);
167 }
168
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);
174
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
178 * harm.
179 */
180
181 (void) memcpy(&__glXReply.pad3, data, 8);
182 WriteToClient(client, sz_xGLXSingleReply, &__glXReply);
183
184 if (reply_ints != 0) {
185 WriteToClient(client, reply_ints * 4, data);
186 }
187}
188
189static int
190get_decode_index(const struct __glXDispatchInfo *dispatch_info, unsigned opcode)
191{
192 int remaining_bits;
193 int next_remain;
194 const int_fast16_t *const tree = dispatch_info->dispatch_tree;
195 int_fast16_t index;
196
197 remaining_bits = dispatch_info->bits;
198 if (opcode >= (1U << remaining_bits)) {
199 return -1;
200 }
201
202 index = 0;
203 for ( /* empty */ ; remaining_bits > 0; remaining_bits = next_remain) {
204 unsigned mask;
205 unsigned child_index;
206
207 /* Calculate the slice of bits used by this node.
208 *
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.
213 */
214
215 next_remain = remaining_bits - tree[index];
216 mask = ((1 << remaining_bits) - 1) & ~((1 << next_remain) - 1);
217
218 /* Using the mask, calculate the index of the opcode in the node.
219 * With that index, fetch the index of the next node.
220 */
221
222 child_index = (opcode & mask) >> next_remain;
223 index = tree[index + 1 + child_index];
224
225 /* If the next node is an empty leaf, the opcode is for a non-existant
226 * function. We're done.
227 *
228 * If the next node is a non-empty leaf, look up the function pointer
229 * and return it.
230 */
231
232 if (index == EMPTY_LEAF) {
233 return -1;
234 }
235 else if (IS_LEAF_INDEX(index)) {
236 unsigned func_index;
237
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
241 * opcode.
242 */
243
244 func_index = -index;
245 func_index += opcode & ((1 << next_remain) - 1);
246 return func_index;
247 }
248 }
249
250 /* We should *never* get here!!!
251 */
252 return -1;
253}
254
255void *
256__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
257 int opcode, int swapped_version)
258{
259 const int func_index = get_decode_index(dispatch_info, opcode);
260
261 return (func_index < 0)
262 ? NULL
263 : (void *) dispatch_info->
264 dispatch_functions[func_index][swapped_version];
265}
266
267int
268__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
269 int opcode, __GLXrenderSizeData * data)
270{
271 if (dispatch_info->size_table != NULL) {
272 const int func_index = get_decode_index(dispatch_info, opcode);
273
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];
277
278 data->bytes = dispatch_info->size_table[func_index][0];
279 data->varsize = (var_offset != ~0)
280 ? dispatch_info->size_func_table[var_offset]
281 : NULL;
282
283 return 0;
284 }
285 }
286
287 return -1;
288}