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