indirect_util.c revision 6747b715
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 "glapitable.h" 43#include "glapi.h" 44#include "glthread.h" 45#include "dispatch.h" 46#include "glxext.h" 47#include "indirect_table.h" 48#include "indirect_util.h" 49 50 51#define __GLX_PAD(a) (((a)+3)&~3) 52 53extern xGLXSingleReply __glXReply; 54 55 56GLint 57__glGetBooleanv_variable_size( GLenum e ) 58{ 59 if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) { 60 GLint temp; 61 62 CALL_GetIntegerv( GET_DISPATCH(), 63 (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) ); 64 return temp; 65 } 66 else { 67 return 0; 68 } 69} 70 71 72/** 73 * Get a properly aligned buffer to hold reply data. 74 * 75 * \warning 76 * This function assumes that \c local_buffer is already properly aligned. 77 * It also assumes that \c alignment is a power of two. 78 */ 79void * 80__glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size, 81 void * local_buffer, size_t local_size, unsigned alignment ) 82{ 83 void * buffer = local_buffer; 84 const unsigned mask = alignment - 1; 85 86 if ( local_size < required_size ) { 87 const size_t worst_case_size = required_size + alignment; 88 intptr_t temp_buf; 89 90 if ( cl->returnBufSize < worst_case_size ) { 91 void * temp = realloc( cl->returnBuf, worst_case_size ); 92 93 if ( temp == NULL ) { 94 return NULL; 95 } 96 97 cl->returnBuf = temp; 98 cl->returnBufSize = worst_case_size; 99 } 100 101 temp_buf = (intptr_t) cl->returnBuf; 102 temp_buf = (temp_buf + mask) & ~mask; 103 buffer = (void *) temp_buf; 104 } 105 106 return buffer; 107} 108 109 110/** 111 * Send a GLX reply to the client. 112 * 113 * Technically speaking, there are several different ways to encode a GLX 114 * reply. The primary difference is whether or not certain fields (e.g., 115 * retval, size, and "pad3") are set. This function gets around that by 116 * always setting all of the fields to "reasonable" values. This does no 117 * harm to clients, but it does make the server-side code much more compact. 118 */ 119void 120__glXSendReply( ClientPtr client, const void * data, size_t elements, 121 size_t element_size, GLboolean always_array, CARD32 retval ) 122{ 123 size_t reply_ints = 0; 124 125 if ( __glXErrorOccured() ) { 126 elements = 0; 127 } 128 else if ( (elements > 1) || always_array ) { 129 reply_ints = bytes_to_int32(elements * element_size); 130 } 131 132 __glXReply.length = reply_ints; 133 __glXReply.type = X_Reply; 134 __glXReply.sequenceNumber = client->sequence; 135 __glXReply.size = elements; 136 __glXReply.retval = retval; 137 138 139 /* It is faster on almost always every architecture to just copy the 8 140 * bytes, even when not necessary, than check to see of the value of 141 * elements requires it. Copying the data when not needed will do no 142 * harm. 143 */ 144 145 (void) memcpy( & __glXReply.pad3, data, 8 ); 146 WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply ); 147 148 if ( reply_ints != 0 ) { 149 WriteToClient( client, reply_ints * 4, (char *) data ); 150 } 151} 152 153 154/** 155 * Send a GLX reply to the client. 156 * 157 * Technically speaking, there are several different ways to encode a GLX 158 * reply. The primary difference is whether or not certain fields (e.g., 159 * retval, size, and "pad3") are set. This function gets around that by 160 * always setting all of the fields to "reasonable" values. This does no 161 * harm to clients, but it does make the server-side code much more compact. 162 * 163 * \warning 164 * This function assumes that values stored in \c data will be byte-swapped 165 * by the caller if necessary. 166 */ 167void 168__glXSendReplySwap( ClientPtr client, const void * data, size_t elements, 169 size_t element_size, GLboolean always_array, CARD32 retval ) 170{ 171 size_t reply_ints = 0; 172 173 if ( __glXErrorOccured() ) { 174 elements = 0; 175 } 176 else if ( (elements > 1) || always_array ) { 177 reply_ints = bytes_to_int32(elements * element_size); 178 } 179 180 __glXReply.length = bswap_32( reply_ints ); 181 __glXReply.type = X_Reply; 182 __glXReply.sequenceNumber = bswap_16( client->sequence ); 183 __glXReply.size = bswap_32( elements ); 184 __glXReply.retval = bswap_32( retval ); 185 186 187 /* It is faster on almost always every architecture to just copy the 8 188 * bytes, even when not necessary, than check to see of the value of 189 * elements requires it. Copying the data when not needed will do no 190 * harm. 191 */ 192 193 (void) memcpy( & __glXReply.pad3, data, 8 ); 194 WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply ); 195 196 if ( reply_ints != 0 ) { 197 WriteToClient( client, reply_ints * 4, (char *) data ); 198 } 199} 200 201 202static int 203get_decode_index(const struct __glXDispatchInfo *dispatch_info, 204 unsigned opcode) 205{ 206 int remaining_bits; 207 int next_remain; 208 const int_fast16_t * const tree = dispatch_info->dispatch_tree; 209 int_fast16_t index; 210 211 212 remaining_bits = dispatch_info->bits; 213 if (opcode >= (1U << remaining_bits)) { 214 return -1; 215 } 216 217 index = 0; 218 for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) { 219 unsigned mask; 220 unsigned child_index; 221 222 223 /* Calculate the slice of bits used by this node. 224 * 225 * If remaining_bits = 8 and tree[index] = 3, the mask of just the 226 * remaining bits is 0x00ff and the mask for the remaining bits after 227 * this node is 0x001f. By taking 0x00ff & ~0x001f, we get 0x00e0. 228 * This masks the 3 bits that we would want for this node. 229 */ 230 231 next_remain = remaining_bits - tree[index]; 232 mask = ((1 << remaining_bits) - 1) & 233 ~((1 << next_remain) - 1); 234 235 236 /* Using the mask, calculate the index of the opcode in the node. 237 * With that index, fetch the index of the next node. 238 */ 239 240 child_index = (opcode & mask) >> next_remain; 241 index = tree[index + 1 + child_index]; 242 243 244 /* If the next node is an empty leaf, the opcode is for a non-existant 245 * function. We're done. 246 * 247 * If the next node is a non-empty leaf, look up the function pointer 248 * and return it. 249 */ 250 251 if (index == EMPTY_LEAF) { 252 return -1; 253 } 254 else if (IS_LEAF_INDEX(index)) { 255 unsigned func_index; 256 257 258 /* The value stored in the tree for a leaf node is the base of 259 * the function pointers for that leaf node. The offset for the 260 * function for a particular opcode is the remaining bits in the 261 * opcode. 262 */ 263 264 func_index = -index; 265 func_index += opcode & ((1 << next_remain) - 1); 266 return func_index; 267 } 268 } 269 270 /* We should *never* get here!!! 271 */ 272 return -1; 273} 274 275 276void * 277__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info, 278 int opcode, int swapped_version) 279{ 280 const int func_index = get_decode_index(dispatch_info, opcode); 281 282 return (func_index < 0) 283 ? NULL 284 : (void *) dispatch_info->dispatch_functions[func_index][swapped_version]; 285} 286 287 288int 289__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info, 290 int opcode, __GLXrenderSizeData *data) 291{ 292 if (dispatch_info->size_table != NULL) { 293 const int func_index = get_decode_index(dispatch_info, opcode); 294 295 if ((func_index >= 0) 296 && (dispatch_info->size_table[func_index][0] != 0)) { 297 const int var_offset = 298 dispatch_info->size_table[func_index][1]; 299 300 data->bytes = dispatch_info->size_table[func_index][0]; 301 data->varsize = (var_offset != ~0) 302 ? dispatch_info->size_func_table[var_offset] 303 : NULL; 304 305 return 0; 306 } 307 } 308 309 return -1; 310} 311