1706f2543Smrg/*
2706f2543Smrg * (C) Copyright IBM Corporation 2005
3706f2543Smrg * All Rights Reserved.
4706f2543Smrg *
5706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6706f2543Smrg * copy of this software and associated documentation files (the "Software"),
7706f2543Smrg * to deal in the Software without restriction, including without limitation
8706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
9706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
10706f2543Smrg * Software is furnished to do so, subject to the following conditions:
11706f2543Smrg *
12706f2543Smrg * The above copyright notice and this permission notice (including the next
13706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the
14706f2543Smrg * Software.
15706f2543Smrg *
16706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19706f2543Smrg * IBM,
20706f2543Smrg * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22706f2543Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23706f2543Smrg * SOFTWARE.
24706f2543Smrg */
25706f2543Smrg
26706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
27706f2543Smrg#include <dix-config.h>
28706f2543Smrg#endif
29706f2543Smrg
30706f2543Smrg#include <string.h>
31706f2543Smrg
32706f2543Smrg#include <X11/Xmd.h>
33706f2543Smrg#include <GL/gl.h>
34706f2543Smrg#include <GL/glxproto.h>
35706f2543Smrg#include <inttypes.h>
36706f2543Smrg#include "indirect_size.h"
37706f2543Smrg#include "indirect_size_get.h"
38706f2543Smrg#include "indirect_dispatch.h"
39706f2543Smrg#include "glxserver.h"
40706f2543Smrg#include "glxbyteorder.h"
41706f2543Smrg#include "singlesize.h"
42706f2543Smrg#include "glapitable.h"
43706f2543Smrg#include "glapi.h"
44706f2543Smrg#include "glthread.h"
45706f2543Smrg#include "dispatch.h"
46706f2543Smrg#include "glxext.h"
47706f2543Smrg#include "indirect_table.h"
48706f2543Smrg#include "indirect_util.h"
49706f2543Smrg
50706f2543Smrg
51706f2543Smrg#define __GLX_PAD(a) (((a)+3)&~3)
52706f2543Smrg
53706f2543Smrgextern xGLXSingleReply __glXReply;
54706f2543Smrg
55706f2543Smrg
56706f2543SmrgGLint
57706f2543Smrg__glGetBooleanv_variable_size( GLenum e )
58706f2543Smrg{
59706f2543Smrg    if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) {
60706f2543Smrg	GLint temp;
61706f2543Smrg
62706f2543Smrg	CALL_GetIntegerv( GET_DISPATCH(),
63706f2543Smrg			  (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) );
64706f2543Smrg	return temp;
65706f2543Smrg    }
66706f2543Smrg    else {
67706f2543Smrg	return 0;
68706f2543Smrg    }
69706f2543Smrg}
70706f2543Smrg
71706f2543Smrg
72706f2543Smrg/**
73706f2543Smrg * Get a properly aligned buffer to hold reply data.
74706f2543Smrg *
75706f2543Smrg * \warning
76706f2543Smrg * This function assumes that \c local_buffer is already properly aligned.
77706f2543Smrg * It also assumes that \c alignment is a power of two.
78706f2543Smrg */
79706f2543Smrgvoid *
80706f2543Smrg__glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size,
81706f2543Smrg    void * local_buffer, size_t local_size, unsigned alignment )
82706f2543Smrg{
83706f2543Smrg    void * buffer = local_buffer;
84706f2543Smrg    const intptr_t mask = alignment - 1;
85706f2543Smrg
86706f2543Smrg    if ( local_size < required_size ) {
87706f2543Smrg        size_t worst_case_size;
88706f2543Smrg        intptr_t  temp_buf;
89706f2543Smrg
90706f2543Smrg        if (required_size < SIZE_MAX - alignment)
91706f2543Smrg            worst_case_size = required_size + alignment;
92706f2543Smrg        else
93706f2543Smrg            return NULL;
94706f2543Smrg
95706f2543Smrg        if ( cl->returnBufSize < worst_case_size ) {
96706f2543Smrg	    void * temp = realloc( cl->returnBuf, worst_case_size );
97706f2543Smrg
98706f2543Smrg	    if ( temp == NULL ) {
99706f2543Smrg	        return NULL;
100706f2543Smrg	    }
101706f2543Smrg
102706f2543Smrg	    cl->returnBuf = temp;
103706f2543Smrg	    cl->returnBufSize = worst_case_size;
104706f2543Smrg	}
105706f2543Smrg
106706f2543Smrg	temp_buf = (intptr_t) cl->returnBuf;
107706f2543Smrg	temp_buf = (temp_buf + mask) & ~mask;
108706f2543Smrg	buffer = (void *) temp_buf;
109706f2543Smrg    }
110706f2543Smrg
111706f2543Smrg    return buffer;
112706f2543Smrg}
113706f2543Smrg
114706f2543Smrg
115706f2543Smrg/**
116706f2543Smrg * Send a GLX reply to the client.
117706f2543Smrg *
118706f2543Smrg * Technically speaking, there are several different ways to encode a GLX
119706f2543Smrg * reply.  The primary difference is whether or not certain fields (e.g.,
120706f2543Smrg * retval, size, and "pad3") are set.  This function gets around that by
121706f2543Smrg * always setting all of the fields to "reasonable" values.  This does no
122706f2543Smrg * harm to clients, but it does make the server-side code much more compact.
123706f2543Smrg */
124706f2543Smrgvoid
125706f2543Smrg__glXSendReply( ClientPtr client, const void * data, size_t elements,
126706f2543Smrg    size_t element_size, GLboolean always_array, CARD32 retval )
127706f2543Smrg{
128706f2543Smrg    size_t reply_ints = 0;
129706f2543Smrg
130706f2543Smrg    if ( __glXErrorOccured() ) {
131706f2543Smrg        elements = 0;
132706f2543Smrg    }
133706f2543Smrg    else if ( (elements > 1) || always_array ) {
134706f2543Smrg        reply_ints = bytes_to_int32(elements * element_size);
135706f2543Smrg    }
136706f2543Smrg
137706f2543Smrg    __glXReply.length =         reply_ints;
138706f2543Smrg    __glXReply.type =           X_Reply;
139706f2543Smrg    __glXReply.sequenceNumber = client->sequence;
140706f2543Smrg    __glXReply.size =           elements;
141706f2543Smrg    __glXReply.retval =         retval;
142706f2543Smrg
143706f2543Smrg
144706f2543Smrg    /* It is faster on almost always every architecture to just copy the 8
145706f2543Smrg     * bytes, even when not necessary, than check to see of the value of
146706f2543Smrg     * elements requires it.  Copying the data when not needed will do no
147706f2543Smrg     * harm.
148706f2543Smrg     */
149706f2543Smrg
150706f2543Smrg    (void) memcpy( & __glXReply.pad3, data, 8 );
151706f2543Smrg    WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
152706f2543Smrg
153706f2543Smrg    if ( reply_ints != 0 ) {
154706f2543Smrg        WriteToClient( client, reply_ints * 4, (char *) data );
155706f2543Smrg    }
156706f2543Smrg}
157706f2543Smrg
158706f2543Smrg
159706f2543Smrg/**
160706f2543Smrg * Send a GLX reply to the client.
161706f2543Smrg *
162706f2543Smrg * Technically speaking, there are several different ways to encode a GLX
163706f2543Smrg * reply.  The primary difference is whether or not certain fields (e.g.,
164706f2543Smrg * retval, size, and "pad3") are set.  This function gets around that by
165706f2543Smrg * always setting all of the fields to "reasonable" values.  This does no
166706f2543Smrg * harm to clients, but it does make the server-side code much more compact.
167706f2543Smrg *
168706f2543Smrg * \warning
169706f2543Smrg * This function assumes that values stored in \c data will be byte-swapped
170706f2543Smrg * by the caller if necessary.
171706f2543Smrg */
172706f2543Smrgvoid
173706f2543Smrg__glXSendReplySwap( ClientPtr client, const void * data, size_t elements,
174706f2543Smrg    size_t element_size, GLboolean always_array, CARD32 retval )
175706f2543Smrg{
176706f2543Smrg    size_t reply_ints = 0;
177706f2543Smrg
178706f2543Smrg    if ( __glXErrorOccured() ) {
179706f2543Smrg        elements = 0;
180706f2543Smrg    }
181706f2543Smrg    else if ( (elements > 1) || always_array ) {
182706f2543Smrg        reply_ints = bytes_to_int32(elements * element_size);
183706f2543Smrg    }
184706f2543Smrg
185706f2543Smrg    __glXReply.length =         bswap_32( reply_ints );
186706f2543Smrg    __glXReply.type =           X_Reply;
187706f2543Smrg    __glXReply.sequenceNumber = bswap_16( client->sequence );
188706f2543Smrg    __glXReply.size =           bswap_32( elements );
189706f2543Smrg    __glXReply.retval =         bswap_32( retval );
190706f2543Smrg
191706f2543Smrg
192706f2543Smrg    /* It is faster on almost always every architecture to just copy the 8
193706f2543Smrg     * bytes, even when not necessary, than check to see of the value of
194706f2543Smrg     * elements requires it.  Copying the data when not needed will do no
195706f2543Smrg     * harm.
196706f2543Smrg     */
197706f2543Smrg
198706f2543Smrg    (void) memcpy( & __glXReply.pad3, data, 8 );
199706f2543Smrg    WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
200706f2543Smrg
201706f2543Smrg    if ( reply_ints != 0 ) {
202706f2543Smrg        WriteToClient( client, reply_ints * 4, (char *) data );
203706f2543Smrg    }
204706f2543Smrg}
205706f2543Smrg
206706f2543Smrg
207706f2543Smrgstatic int
208706f2543Smrgget_decode_index(const struct __glXDispatchInfo *dispatch_info,
209706f2543Smrg		 unsigned opcode)
210706f2543Smrg{
211706f2543Smrg    int remaining_bits;
212706f2543Smrg    int next_remain;
213706f2543Smrg    const int_fast16_t * const tree = dispatch_info->dispatch_tree;
214706f2543Smrg    int_fast16_t index;
215706f2543Smrg
216706f2543Smrg
217706f2543Smrg    remaining_bits = dispatch_info->bits;
218706f2543Smrg    if (opcode >= (1U << remaining_bits)) {
219706f2543Smrg	return -1;
220706f2543Smrg    }
221706f2543Smrg
222706f2543Smrg    index = 0;
223706f2543Smrg    for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) {
224706f2543Smrg	unsigned mask;
225706f2543Smrg	unsigned child_index;
226706f2543Smrg
227706f2543Smrg
228706f2543Smrg	/* Calculate the slice of bits used by this node.
229706f2543Smrg	 *
230706f2543Smrg	 * If remaining_bits = 8 and tree[index] = 3, the mask of just the
231706f2543Smrg	 * remaining bits is 0x00ff and the mask for the remaining bits after
232706f2543Smrg	 * this node is 0x001f.  By taking 0x00ff & ~0x001f, we get 0x00e0.
233706f2543Smrg	 * This masks the 3 bits that we would want for this node.
234706f2543Smrg	 */
235706f2543Smrg
236706f2543Smrg	next_remain = remaining_bits - tree[index];
237706f2543Smrg	mask = ((1 << remaining_bits) - 1) &
238706f2543Smrg	  ~((1 << next_remain) - 1);
239706f2543Smrg
240706f2543Smrg
241706f2543Smrg	/* Using the mask, calculate the index of the opcode in the node.
242706f2543Smrg	 * With that index, fetch the index of the next node.
243706f2543Smrg	 */
244706f2543Smrg
245706f2543Smrg	child_index = (opcode & mask) >> next_remain;
246706f2543Smrg	index = tree[index + 1 + child_index];
247706f2543Smrg
248706f2543Smrg
249706f2543Smrg	/* If the next node is an empty leaf, the opcode is for a non-existant
250706f2543Smrg	 * function.  We're done.
251706f2543Smrg	 *
252706f2543Smrg	 * If the next node is a non-empty leaf, look up the function pointer
253706f2543Smrg	 * and return it.
254706f2543Smrg	 */
255706f2543Smrg
256706f2543Smrg	if (index == EMPTY_LEAF) {
257706f2543Smrg	    return -1;
258706f2543Smrg	}
259706f2543Smrg	else if (IS_LEAF_INDEX(index)) {
260706f2543Smrg	    unsigned func_index;
261706f2543Smrg
262706f2543Smrg
263706f2543Smrg	    /* The value stored in the tree for a leaf node is the base of
264706f2543Smrg	     * the function pointers for that leaf node.  The offset for the
265706f2543Smrg	     * function for a particular opcode is the remaining bits in the
266706f2543Smrg	     * opcode.
267706f2543Smrg	     */
268706f2543Smrg
269706f2543Smrg	    func_index = -index;
270706f2543Smrg	    func_index += opcode & ((1 << next_remain) - 1);
271706f2543Smrg	    return func_index;
272706f2543Smrg	}
273706f2543Smrg    }
274706f2543Smrg
275706f2543Smrg    /* We should *never* get here!!!
276706f2543Smrg     */
277706f2543Smrg    return -1;
278706f2543Smrg}
279706f2543Smrg
280706f2543Smrg
281706f2543Smrgvoid *
282706f2543Smrg__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
283706f2543Smrg			       int opcode, int swapped_version)
284706f2543Smrg{
285706f2543Smrg    const int func_index = get_decode_index(dispatch_info, opcode);
286706f2543Smrg
287706f2543Smrg    return (func_index < 0)
288706f2543Smrg	? NULL
289706f2543Smrg	: (void *) dispatch_info->dispatch_functions[func_index][swapped_version];
290706f2543Smrg}
291706f2543Smrg
292706f2543Smrg
293706f2543Smrgint
294706f2543Smrg__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
295706f2543Smrg			 int opcode, __GLXrenderSizeData *data)
296706f2543Smrg{
297706f2543Smrg    if (dispatch_info->size_table != NULL) {
298706f2543Smrg	const int func_index = get_decode_index(dispatch_info, opcode);
299706f2543Smrg
300706f2543Smrg	if ((func_index >= 0)
301706f2543Smrg	    && (dispatch_info->size_table[func_index][0] != 0)) {
302706f2543Smrg	    const int var_offset =
303706f2543Smrg		dispatch_info->size_table[func_index][1];
304706f2543Smrg
305706f2543Smrg	    data->bytes = dispatch_info->size_table[func_index][0];
306706f2543Smrg	    data->varsize = (var_offset != ~0)
307706f2543Smrg		? dispatch_info->size_func_table[var_offset]
308706f2543Smrg		: NULL;
309706f2543Smrg
310706f2543Smrg	    return 0;
311706f2543Smrg	}
312706f2543Smrg    }
313706f2543Smrg
314706f2543Smrg    return -1;
315706f2543Smrg}
316