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