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 48GLint 49__glGetBooleanv_variable_size(GLenum e) 50{ 51 if (e == GL_COMPRESSED_TEXTURE_FORMATS) { 52 GLint temp; 53 54 glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &temp); 55 return temp; 56 } 57 else { 58 return 0; 59 } 60} 61 62/** 63 * Get a properly aligned buffer to hold reply data. 64 * 65 * \warning 66 * This function assumes that \c local_buffer is already properly aligned. 67 * It also assumes that \c alignment is a power of two. 68 */ 69void * 70__glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size, 71 void *local_buffer, size_t local_size, unsigned alignment) 72{ 73 void *buffer = local_buffer; 74 const intptr_t mask = alignment - 1; 75 76 if (local_size < required_size) { 77 size_t worst_case_size; 78 intptr_t temp_buf; 79 80 if (required_size < SIZE_MAX - alignment) 81 worst_case_size = required_size + alignment; 82 else 83 return NULL; 84 85 if (cl->returnBufSize < worst_case_size) { 86 void *temp = realloc(cl->returnBuf, worst_case_size); 87 88 if (temp == NULL) { 89 return NULL; 90 } 91 92 cl->returnBuf = temp; 93 cl->returnBufSize = worst_case_size; 94 } 95 96 temp_buf = (intptr_t) cl->returnBuf; 97 temp_buf = (temp_buf + mask) & ~mask; 98 buffer = (void *) temp_buf; 99 } 100 101 return buffer; 102} 103 104/** 105 * Send a GLX reply to the client. 106 * 107 * Technically speaking, there are several different ways to encode a GLX 108 * reply. The primary difference is whether or not certain fields (e.g., 109 * retval, size, and "pad3") are set. This function gets around that by 110 * always setting all of the fields to "reasonable" values. This does no 111 * harm to clients, but it does make the server-side code much more compact. 112 */ 113void 114__glXSendReply(ClientPtr client, const void *data, size_t elements, 115 size_t element_size, GLboolean always_array, CARD32 retval) 116{ 117 size_t reply_ints = 0; 118 xGLXSingleReply reply = { 0, }; 119 120 if (__glXErrorOccured()) { 121 elements = 0; 122 } 123 else if ((elements > 1) || always_array) { 124 reply_ints = bytes_to_int32(elements * element_size); 125 } 126 127 reply.length = reply_ints; 128 reply.type = X_Reply; 129 reply.sequenceNumber = client->sequence; 130 reply.size = elements; 131 reply.retval = retval; 132 133 /* It is faster on almost always every architecture to just copy the 8 134 * bytes, even when not necessary, than check to see of the value of 135 * elements requires it. Copying the data when not needed will do no 136 * harm. 137 */ 138 139 (void) memcpy(&reply.pad3, data, 8); 140 WriteToClient(client, sz_xGLXSingleReply, &reply); 141 142 if (reply_ints != 0) { 143 WriteToClient(client, reply_ints * 4, data); 144 } 145} 146 147/** 148 * Send a GLX reply to the client. 149 * 150 * Technically speaking, there are several different ways to encode a GLX 151 * reply. The primary difference is whether or not certain fields (e.g., 152 * retval, size, and "pad3") are set. This function gets around that by 153 * always setting all of the fields to "reasonable" values. This does no 154 * harm to clients, but it does make the server-side code much more compact. 155 * 156 * \warning 157 * This function assumes that values stored in \c data will be byte-swapped 158 * by the caller if necessary. 159 */ 160void 161__glXSendReplySwap(ClientPtr client, const void *data, size_t elements, 162 size_t element_size, GLboolean always_array, CARD32 retval) 163{ 164 size_t reply_ints = 0; 165 xGLXSingleReply reply = { 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 reply.length = bswap_32(reply_ints); 175 reply.type = X_Reply; 176 reply.sequenceNumber = bswap_16(client->sequence); 177 reply.size = bswap_32(elements); 178 reply.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(&reply.pad3, data, 8); 187 WriteToClient(client, sz_xGLXSingleReply, &reply); 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-existent 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