indirect_util.c revision 4642e01f
14642e01fSmrg/*
24642e01fSmrg * (C) Copyright IBM Corporation 2005
34642e01fSmrg * All Rights Reserved.
44642e01fSmrg *
54642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
64642e01fSmrg * copy of this software and associated documentation files (the "Software"),
74642e01fSmrg * to deal in the Software without restriction, including without limitation
84642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
94642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
104642e01fSmrg * Software is furnished to do so, subject to the following conditions:
114642e01fSmrg *
124642e01fSmrg * The above copyright notice and this permission notice (including the next
134642e01fSmrg * paragraph) shall be included in all copies or substantial portions of the
144642e01fSmrg * Software.
154642e01fSmrg *
164642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
174642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
184642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
194642e01fSmrg * IBM,
204642e01fSmrg * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
214642e01fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
224642e01fSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
234642e01fSmrg * SOFTWARE.
244642e01fSmrg */
254642e01fSmrg
264642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
274642e01fSmrg#include <dix-config.h>
284642e01fSmrg#endif
294642e01fSmrg
304642e01fSmrg#include <string.h>
314642e01fSmrg
324642e01fSmrg#include <X11/Xmd.h>
334642e01fSmrg#include <GL/gl.h>
344642e01fSmrg#include <GL/glxproto.h>
354642e01fSmrg#include <inttypes.h>
364642e01fSmrg#include "indirect_size.h"
374642e01fSmrg#include "indirect_size_get.h"
384642e01fSmrg#include "indirect_dispatch.h"
394642e01fSmrg#include "glxserver.h"
404642e01fSmrg#include "glxbyteorder.h"
414642e01fSmrg#include "singlesize.h"
424642e01fSmrg#include "glapitable.h"
434642e01fSmrg#include "glapi.h"
444642e01fSmrg#include "glthread.h"
454642e01fSmrg#include "dispatch.h"
464642e01fSmrg#include "glxext.h"
474642e01fSmrg#include "indirect_table.h"
484642e01fSmrg#include "indirect_util.h"
494642e01fSmrg
504642e01fSmrg
514642e01fSmrg#define __GLX_PAD(a) (((a)+3)&~3)
524642e01fSmrg
534642e01fSmrgextern xGLXSingleReply __glXReply;
544642e01fSmrg
554642e01fSmrg
564642e01fSmrgGLint
574642e01fSmrg__glGetBooleanv_variable_size( GLenum e )
584642e01fSmrg{
594642e01fSmrg    if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) {
604642e01fSmrg	GLint temp;
614642e01fSmrg
624642e01fSmrg	CALL_GetIntegerv( GET_DISPATCH(),
634642e01fSmrg			  (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) );
644642e01fSmrg	return temp;
654642e01fSmrg    }
664642e01fSmrg    else {
674642e01fSmrg	return 0;
684642e01fSmrg    }
694642e01fSmrg}
704642e01fSmrg
714642e01fSmrg
724642e01fSmrg/**
734642e01fSmrg * Get a properly aligned buffer to hold reply data.
744642e01fSmrg *
754642e01fSmrg * \warning
764642e01fSmrg * This function assumes that \c local_buffer is already properly aligned.
774642e01fSmrg * It also assumes that \c alignment is a power of two.
784642e01fSmrg */
794642e01fSmrgvoid *
804642e01fSmrg__glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size,
814642e01fSmrg    void * local_buffer, size_t local_size, unsigned alignment )
824642e01fSmrg{
834642e01fSmrg    void * buffer = local_buffer;
844642e01fSmrg    const unsigned mask = alignment - 1;
854642e01fSmrg
864642e01fSmrg    if ( local_size < required_size ) {
874642e01fSmrg        const size_t worst_case_size = required_size + alignment;
884642e01fSmrg        intptr_t  temp_buf;
894642e01fSmrg
904642e01fSmrg        if ( cl->returnBufSize < worst_case_size ) {
914642e01fSmrg	    void * temp = xrealloc( cl->returnBuf, worst_case_size );
924642e01fSmrg
934642e01fSmrg	    if ( temp == NULL ) {
944642e01fSmrg	        return NULL;
954642e01fSmrg	    }
964642e01fSmrg
974642e01fSmrg	    cl->returnBuf = temp;
984642e01fSmrg	    cl->returnBufSize = worst_case_size;
994642e01fSmrg	}
1004642e01fSmrg
1014642e01fSmrg	temp_buf = (intptr_t) cl->returnBuf;
1024642e01fSmrg	temp_buf = (temp_buf + mask) & ~mask;
1034642e01fSmrg	buffer = (void *) temp_buf;
1044642e01fSmrg    }
1054642e01fSmrg
1064642e01fSmrg    return buffer;
1074642e01fSmrg}
1084642e01fSmrg
1094642e01fSmrg
1104642e01fSmrg/**
1114642e01fSmrg * Send a GLX reply to the client.
1124642e01fSmrg *
1134642e01fSmrg * Technically speaking, there are several different ways to encode a GLX
1144642e01fSmrg * reply.  The primary difference is whether or not certain fields (e.g.,
1154642e01fSmrg * retval, size, and "pad3") are set.  This function gets around that by
1164642e01fSmrg * always setting all of the fields to "reasonable" values.  This does no
1174642e01fSmrg * harm to clients, but it does make the server-side code much more compact.
1184642e01fSmrg */
1194642e01fSmrgvoid
1204642e01fSmrg__glXSendReply( ClientPtr client, const void * data, size_t elements,
1214642e01fSmrg    size_t element_size, GLboolean always_array, CARD32 retval )
1224642e01fSmrg{
1234642e01fSmrg    size_t reply_ints = 0;
1244642e01fSmrg
1254642e01fSmrg    if ( __glXErrorOccured() ) {
1264642e01fSmrg        elements = 0;
1274642e01fSmrg    }
1284642e01fSmrg    else if ( (elements > 1) || always_array ) {
1294642e01fSmrg        reply_ints = ((elements * element_size) + 3) >> 2;
1304642e01fSmrg    }
1314642e01fSmrg
1324642e01fSmrg    __glXReply.length =         reply_ints;
1334642e01fSmrg    __glXReply.type =           X_Reply;
1344642e01fSmrg    __glXReply.sequenceNumber = client->sequence;
1354642e01fSmrg    __glXReply.size =           elements;
1364642e01fSmrg    __glXReply.retval =         retval;
1374642e01fSmrg
1384642e01fSmrg
1394642e01fSmrg    /* It is faster on almost always every architecture to just copy the 8
1404642e01fSmrg     * bytes, even when not necessary, than check to see of the value of
1414642e01fSmrg     * elements requires it.  Copying the data when not needed will do no
1424642e01fSmrg     * harm.
1434642e01fSmrg     */
1444642e01fSmrg
1454642e01fSmrg    (void) memcpy( & __glXReply.pad3, data, 8 );
1464642e01fSmrg    WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
1474642e01fSmrg
1484642e01fSmrg    if ( reply_ints != 0 ) {
1494642e01fSmrg        WriteToClient( client, reply_ints * 4, (char *) data );
1504642e01fSmrg    }
1514642e01fSmrg}
1524642e01fSmrg
1534642e01fSmrg
1544642e01fSmrg/**
1554642e01fSmrg * Send a GLX reply to the client.
1564642e01fSmrg *
1574642e01fSmrg * Technically speaking, there are several different ways to encode a GLX
1584642e01fSmrg * reply.  The primary difference is whether or not certain fields (e.g.,
1594642e01fSmrg * retval, size, and "pad3") are set.  This function gets around that by
1604642e01fSmrg * always setting all of the fields to "reasonable" values.  This does no
1614642e01fSmrg * harm to clients, but it does make the server-side code much more compact.
1624642e01fSmrg *
1634642e01fSmrg * \warning
1644642e01fSmrg * This function assumes that values stored in \c data will be byte-swapped
1654642e01fSmrg * by the caller if necessary.
1664642e01fSmrg */
1674642e01fSmrgvoid
1684642e01fSmrg__glXSendReplySwap( ClientPtr client, const void * data, size_t elements,
1694642e01fSmrg    size_t element_size, GLboolean always_array, CARD32 retval )
1704642e01fSmrg{
1714642e01fSmrg    size_t reply_ints = 0;
1724642e01fSmrg
1734642e01fSmrg    if ( __glXErrorOccured() ) {
1744642e01fSmrg        elements = 0;
1754642e01fSmrg    }
1764642e01fSmrg    else if ( (elements > 1) || always_array ) {
1774642e01fSmrg        reply_ints = ((elements * element_size) + 3) >> 2;
1784642e01fSmrg    }
1794642e01fSmrg
1804642e01fSmrg    __glXReply.length =         bswap_32( reply_ints );
1814642e01fSmrg    __glXReply.type =           X_Reply;
1824642e01fSmrg    __glXReply.sequenceNumber = bswap_16( client->sequence );
1834642e01fSmrg    __glXReply.size =           bswap_32( elements );
1844642e01fSmrg    __glXReply.retval =         bswap_32( retval );
1854642e01fSmrg
1864642e01fSmrg
1874642e01fSmrg    /* It is faster on almost always every architecture to just copy the 8
1884642e01fSmrg     * bytes, even when not necessary, than check to see of the value of
1894642e01fSmrg     * elements requires it.  Copying the data when not needed will do no
1904642e01fSmrg     * harm.
1914642e01fSmrg     */
1924642e01fSmrg
1934642e01fSmrg    (void) memcpy( & __glXReply.pad3, data, 8 );
1944642e01fSmrg    WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
1954642e01fSmrg
1964642e01fSmrg    if ( reply_ints != 0 ) {
1974642e01fSmrg        WriteToClient( client, reply_ints * 4, (char *) data );
1984642e01fSmrg    }
1994642e01fSmrg}
2004642e01fSmrg
2014642e01fSmrg
2024642e01fSmrgstatic int
2034642e01fSmrgget_decode_index(const struct __glXDispatchInfo *dispatch_info,
2044642e01fSmrg		 unsigned opcode)
2054642e01fSmrg{
2064642e01fSmrg    int remaining_bits;
2074642e01fSmrg    int next_remain;
2084642e01fSmrg    const int_fast16_t * const tree = dispatch_info->dispatch_tree;
2094642e01fSmrg    int_fast16_t index;
2104642e01fSmrg
2114642e01fSmrg
2124642e01fSmrg    remaining_bits = dispatch_info->bits;
2134642e01fSmrg    if (opcode >= (1U << remaining_bits)) {
2144642e01fSmrg	return -1;
2154642e01fSmrg    }
2164642e01fSmrg
2174642e01fSmrg    index = 0;
2184642e01fSmrg    for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) {
2194642e01fSmrg	unsigned mask;
2204642e01fSmrg	unsigned child_index;
2214642e01fSmrg
2224642e01fSmrg
2234642e01fSmrg	/* Calculate the slice of bits used by this node.
2244642e01fSmrg	 *
2254642e01fSmrg	 * If remaining_bits = 8 and tree[index] = 3, the mask of just the
2264642e01fSmrg	 * remaining bits is 0x00ff and the mask for the remaining bits after
2274642e01fSmrg	 * this node is 0x001f.  By taking 0x00ff & ~0x001f, we get 0x00e0.
2284642e01fSmrg	 * This masks the 3 bits that we would want for this node.
2294642e01fSmrg	 */
2304642e01fSmrg
2314642e01fSmrg	next_remain = remaining_bits - tree[index];
2324642e01fSmrg	mask = ((1 << remaining_bits) - 1) &
2334642e01fSmrg	  ~((1 << next_remain) - 1);
2344642e01fSmrg
2354642e01fSmrg
2364642e01fSmrg	/* Using the mask, calculate the index of the opcode in the node.
2374642e01fSmrg	 * With that index, fetch the index of the next node.
2384642e01fSmrg	 */
2394642e01fSmrg
2404642e01fSmrg	child_index = (opcode & mask) >> next_remain;
2414642e01fSmrg	index = tree[index + 1 + child_index];
2424642e01fSmrg
2434642e01fSmrg
2444642e01fSmrg	/* If the next node is an empty leaf, the opcode is for a non-existant
2454642e01fSmrg	 * function.  We're done.
2464642e01fSmrg	 *
2474642e01fSmrg	 * If the next node is a non-empty leaf, look up the function pointer
2484642e01fSmrg	 * and return it.
2494642e01fSmrg	 */
2504642e01fSmrg
2514642e01fSmrg	if (index == EMPTY_LEAF) {
2524642e01fSmrg	    return -1;
2534642e01fSmrg	}
2544642e01fSmrg	else if (IS_LEAF_INDEX(index)) {
2554642e01fSmrg	    unsigned func_index;
2564642e01fSmrg
2574642e01fSmrg
2584642e01fSmrg	    /* The value stored in the tree for a leaf node is the base of
2594642e01fSmrg	     * the function pointers for that leaf node.  The offset for the
2604642e01fSmrg	     * function for a particular opcode is the remaining bits in the
2614642e01fSmrg	     * opcode.
2624642e01fSmrg	     */
2634642e01fSmrg
2644642e01fSmrg	    func_index = -index;
2654642e01fSmrg	    func_index += opcode & ((1 << next_remain) - 1);
2664642e01fSmrg	    return func_index;
2674642e01fSmrg	}
2684642e01fSmrg    }
2694642e01fSmrg
2704642e01fSmrg    /* We should *never* get here!!!
2714642e01fSmrg     */
2724642e01fSmrg    return -1;
2734642e01fSmrg}
2744642e01fSmrg
2754642e01fSmrg
2764642e01fSmrgvoid *
2774642e01fSmrg__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
2784642e01fSmrg			       int opcode, int swapped_version)
2794642e01fSmrg{
2804642e01fSmrg    const int func_index = get_decode_index(dispatch_info, opcode);
2814642e01fSmrg
2824642e01fSmrg    return (func_index < 0)
2834642e01fSmrg	? NULL
2844642e01fSmrg	: (void *) dispatch_info->dispatch_functions[func_index][swapped_version];
2854642e01fSmrg}
2864642e01fSmrg
2874642e01fSmrg
2884642e01fSmrgint
2894642e01fSmrg__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
2904642e01fSmrg			 int opcode, __GLXrenderSizeData *data)
2914642e01fSmrg{
2924642e01fSmrg    if (dispatch_info->size_table != NULL) {
2934642e01fSmrg	const int func_index = get_decode_index(dispatch_info, opcode);
2944642e01fSmrg
2954642e01fSmrg	if ((func_index >= 0)
2964642e01fSmrg	    && (dispatch_info->size_table[func_index][0] != 0)) {
2974642e01fSmrg	    const int var_offset =
2984642e01fSmrg		dispatch_info->size_table[func_index][1];
2994642e01fSmrg
3004642e01fSmrg	    data->bytes = dispatch_info->size_table[func_index][0];
3014642e01fSmrg	    data->varsize = (var_offset != ~0)
3024642e01fSmrg		? dispatch_info->size_func_table[var_offset]
3034642e01fSmrg		: NULL;
3044642e01fSmrg
3054642e01fSmrg	    return 0;
3064642e01fSmrg	}
3074642e01fSmrg    }
3084642e01fSmrg
3094642e01fSmrg    return -1;
3104642e01fSmrg}
311