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