/* * (C) Copyright IBM Corporation 2005 * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * IBM, * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifdef HAVE_DIX_CONFIG_H #include #endif #include #include #include #include #include #include "indirect_size.h" #include "indirect_size_get.h" #include "indirect_dispatch.h" #include "glxserver.h" #include "glxbyteorder.h" #include "singlesize.h" #include "glapitable.h" #include "glapi.h" #include "glthread.h" #include "dispatch.h" #include "glxext.h" #include "indirect_table.h" #include "indirect_util.h" #define __GLX_PAD(a) (((a)+3)&~3) extern xGLXSingleReply __glXReply; GLint __glGetBooleanv_variable_size( GLenum e ) { if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) { GLint temp; CALL_GetIntegerv( GET_DISPATCH(), (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) ); return temp; } else { return 0; } } /** * Get a properly aligned buffer to hold reply data. * * \warning * This function assumes that \c local_buffer is already properly aligned. * It also assumes that \c alignment is a power of two. */ void * __glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size, void * local_buffer, size_t local_size, unsigned alignment ) { void * buffer = local_buffer; const unsigned mask = alignment - 1; if ( local_size < required_size ) { const size_t worst_case_size = required_size + alignment; intptr_t temp_buf; if ( cl->returnBufSize < worst_case_size ) { void * temp = realloc( cl->returnBuf, worst_case_size ); if ( temp == NULL ) { return NULL; } cl->returnBuf = temp; cl->returnBufSize = worst_case_size; } temp_buf = (intptr_t) cl->returnBuf; temp_buf = (temp_buf + mask) & ~mask; buffer = (void *) temp_buf; } return buffer; } /** * Send a GLX reply to the client. * * Technically speaking, there are several different ways to encode a GLX * reply. The primary difference is whether or not certain fields (e.g., * retval, size, and "pad3") are set. This function gets around that by * always setting all of the fields to "reasonable" values. This does no * harm to clients, but it does make the server-side code much more compact. */ void __glXSendReply( ClientPtr client, const void * data, size_t elements, size_t element_size, GLboolean always_array, CARD32 retval ) { size_t reply_ints = 0; if ( __glXErrorOccured() ) { elements = 0; } else if ( (elements > 1) || always_array ) { reply_ints = bytes_to_int32(elements * element_size); } __glXReply.length = reply_ints; __glXReply.type = X_Reply; __glXReply.sequenceNumber = client->sequence; __glXReply.size = elements; __glXReply.retval = retval; /* It is faster on almost always every architecture to just copy the 8 * bytes, even when not necessary, than check to see of the value of * elements requires it. Copying the data when not needed will do no * harm. */ (void) memcpy( & __glXReply.pad3, data, 8 ); WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply ); if ( reply_ints != 0 ) { WriteToClient( client, reply_ints * 4, (char *) data ); } } /** * Send a GLX reply to the client. * * Technically speaking, there are several different ways to encode a GLX * reply. The primary difference is whether or not certain fields (e.g., * retval, size, and "pad3") are set. This function gets around that by * always setting all of the fields to "reasonable" values. This does no * harm to clients, but it does make the server-side code much more compact. * * \warning * This function assumes that values stored in \c data will be byte-swapped * by the caller if necessary. */ void __glXSendReplySwap( ClientPtr client, const void * data, size_t elements, size_t element_size, GLboolean always_array, CARD32 retval ) { size_t reply_ints = 0; if ( __glXErrorOccured() ) { elements = 0; } else if ( (elements > 1) || always_array ) { reply_ints = bytes_to_int32(elements * element_size); } __glXReply.length = bswap_32( reply_ints ); __glXReply.type = X_Reply; __glXReply.sequenceNumber = bswap_16( client->sequence ); __glXReply.size = bswap_32( elements ); __glXReply.retval = bswap_32( retval ); /* It is faster on almost always every architecture to just copy the 8 * bytes, even when not necessary, than check to see of the value of * elements requires it. Copying the data when not needed will do no * harm. */ (void) memcpy( & __glXReply.pad3, data, 8 ); WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply ); if ( reply_ints != 0 ) { WriteToClient( client, reply_ints * 4, (char *) data ); } } static int get_decode_index(const struct __glXDispatchInfo *dispatch_info, unsigned opcode) { int remaining_bits; int next_remain; const int_fast16_t * const tree = dispatch_info->dispatch_tree; int_fast16_t index; remaining_bits = dispatch_info->bits; if (opcode >= (1U << remaining_bits)) { return -1; } index = 0; for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) { unsigned mask; unsigned child_index; /* Calculate the slice of bits used by this node. * * If remaining_bits = 8 and tree[index] = 3, the mask of just the * remaining bits is 0x00ff and the mask for the remaining bits after * this node is 0x001f. By taking 0x00ff & ~0x001f, we get 0x00e0. * This masks the 3 bits that we would want for this node. */ next_remain = remaining_bits - tree[index]; mask = ((1 << remaining_bits) - 1) & ~((1 << next_remain) - 1); /* Using the mask, calculate the index of the opcode in the node. * With that index, fetch the index of the next node. */ child_index = (opcode & mask) >> next_remain; index = tree[index + 1 + child_index]; /* If the next node is an empty leaf, the opcode is for a non-existant * function. We're done. * * If the next node is a non-empty leaf, look up the function pointer * and return it. */ if (index == EMPTY_LEAF) { return -1; } else if (IS_LEAF_INDEX(index)) { unsigned func_index; /* The value stored in the tree for a leaf node is the base of * the function pointers for that leaf node. The offset for the * function for a particular opcode is the remaining bits in the * opcode. */ func_index = -index; func_index += opcode & ((1 << next_remain) - 1); return func_index; } } /* We should *never* get here!!! */ return -1; } void * __glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info, int opcode, int swapped_version) { const int func_index = get_decode_index(dispatch_info, opcode); return (func_index < 0) ? NULL : (void *) dispatch_info->dispatch_functions[func_index][swapped_version]; } int __glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info, int opcode, __GLXrenderSizeData *data) { if (dispatch_info->size_table != NULL) { const int func_index = get_decode_index(dispatch_info, opcode); if ((func_index >= 0) && (dispatch_info->size_table[func_index][0] != 0)) { const int var_offset = dispatch_info->size_table[func_index][1]; data->bytes = dispatch_info->size_table[func_index][0]; data->varsize = (var_offset != ~0) ? dispatch_info->size_func_table[var_offset] : NULL; return 0; } } return -1; }