1706f2543Smrg/* 2706f2543Smrg * (C) Copyright IBM Corporation 2005 3706f2543Smrg * All Rights Reserved. 4706f2543Smrg * 5706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6706f2543Smrg * copy of this software and associated documentation files (the "Software"), 7706f2543Smrg * to deal in the Software without restriction, including without limitation 8706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license, 9706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 10706f2543Smrg * Software is furnished to do so, subject to the following conditions: 11706f2543Smrg * 12706f2543Smrg * The above copyright notice and this permission notice (including the next 13706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 14706f2543Smrg * Software. 15706f2543Smrg * 16706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19706f2543Smrg * IBM, 20706f2543Smrg * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22706f2543Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23706f2543Smrg * SOFTWARE. 24706f2543Smrg */ 25706f2543Smrg 26706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 27706f2543Smrg#include <dix-config.h> 28706f2543Smrg#endif 29706f2543Smrg 30706f2543Smrg#include <string.h> 31706f2543Smrg 32706f2543Smrg#include <X11/Xmd.h> 33706f2543Smrg#include <GL/gl.h> 34706f2543Smrg#include <GL/glxproto.h> 35706f2543Smrg#include <inttypes.h> 36706f2543Smrg#include "indirect_size.h" 37706f2543Smrg#include "indirect_size_get.h" 38706f2543Smrg#include "indirect_dispatch.h" 39706f2543Smrg#include "glxserver.h" 40706f2543Smrg#include "glxbyteorder.h" 41706f2543Smrg#include "singlesize.h" 42706f2543Smrg#include "glapitable.h" 43706f2543Smrg#include "glapi.h" 44706f2543Smrg#include "glthread.h" 45706f2543Smrg#include "dispatch.h" 46706f2543Smrg#include "glxext.h" 47706f2543Smrg#include "indirect_table.h" 48706f2543Smrg#include "indirect_util.h" 49706f2543Smrg 50706f2543Smrg 51706f2543Smrg#define __GLX_PAD(a) (((a)+3)&~3) 52706f2543Smrg 53706f2543Smrgextern xGLXSingleReply __glXReply; 54706f2543Smrg 55706f2543Smrg 56706f2543SmrgGLint 57706f2543Smrg__glGetBooleanv_variable_size( GLenum e ) 58706f2543Smrg{ 59706f2543Smrg if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) { 60706f2543Smrg GLint temp; 61706f2543Smrg 62706f2543Smrg CALL_GetIntegerv( GET_DISPATCH(), 63706f2543Smrg (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) ); 64706f2543Smrg return temp; 65706f2543Smrg } 66706f2543Smrg else { 67706f2543Smrg return 0; 68706f2543Smrg } 69706f2543Smrg} 70706f2543Smrg 71706f2543Smrg 72706f2543Smrg/** 73706f2543Smrg * Get a properly aligned buffer to hold reply data. 74706f2543Smrg * 75706f2543Smrg * \warning 76706f2543Smrg * This function assumes that \c local_buffer is already properly aligned. 77706f2543Smrg * It also assumes that \c alignment is a power of two. 78706f2543Smrg */ 79706f2543Smrgvoid * 80706f2543Smrg__glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size, 81706f2543Smrg void * local_buffer, size_t local_size, unsigned alignment ) 82706f2543Smrg{ 83706f2543Smrg void * buffer = local_buffer; 84706f2543Smrg const intptr_t mask = alignment - 1; 85706f2543Smrg 86706f2543Smrg if ( local_size < required_size ) { 87706f2543Smrg size_t worst_case_size; 88706f2543Smrg intptr_t temp_buf; 89706f2543Smrg 90706f2543Smrg if (required_size < SIZE_MAX - alignment) 91706f2543Smrg worst_case_size = required_size + alignment; 92706f2543Smrg else 93706f2543Smrg return NULL; 94706f2543Smrg 95706f2543Smrg if ( cl->returnBufSize < worst_case_size ) { 96706f2543Smrg void * temp = realloc( cl->returnBuf, worst_case_size ); 97706f2543Smrg 98706f2543Smrg if ( temp == NULL ) { 99706f2543Smrg return NULL; 100706f2543Smrg } 101706f2543Smrg 102706f2543Smrg cl->returnBuf = temp; 103706f2543Smrg cl->returnBufSize = worst_case_size; 104706f2543Smrg } 105706f2543Smrg 106706f2543Smrg temp_buf = (intptr_t) cl->returnBuf; 107706f2543Smrg temp_buf = (temp_buf + mask) & ~mask; 108706f2543Smrg buffer = (void *) temp_buf; 109706f2543Smrg } 110706f2543Smrg 111706f2543Smrg return buffer; 112706f2543Smrg} 113706f2543Smrg 114706f2543Smrg 115706f2543Smrg/** 116706f2543Smrg * Send a GLX reply to the client. 117706f2543Smrg * 118706f2543Smrg * Technically speaking, there are several different ways to encode a GLX 119706f2543Smrg * reply. The primary difference is whether or not certain fields (e.g., 120706f2543Smrg * retval, size, and "pad3") are set. This function gets around that by 121706f2543Smrg * always setting all of the fields to "reasonable" values. This does no 122706f2543Smrg * harm to clients, but it does make the server-side code much more compact. 123706f2543Smrg */ 124706f2543Smrgvoid 125706f2543Smrg__glXSendReply( ClientPtr client, const void * data, size_t elements, 126706f2543Smrg size_t element_size, GLboolean always_array, CARD32 retval ) 127706f2543Smrg{ 128706f2543Smrg size_t reply_ints = 0; 129706f2543Smrg 130706f2543Smrg if ( __glXErrorOccured() ) { 131706f2543Smrg elements = 0; 132706f2543Smrg } 133706f2543Smrg else if ( (elements > 1) || always_array ) { 134706f2543Smrg reply_ints = bytes_to_int32(elements * element_size); 135706f2543Smrg } 136706f2543Smrg 137706f2543Smrg __glXReply.length = reply_ints; 138706f2543Smrg __glXReply.type = X_Reply; 139706f2543Smrg __glXReply.sequenceNumber = client->sequence; 140706f2543Smrg __glXReply.size = elements; 141706f2543Smrg __glXReply.retval = retval; 142706f2543Smrg 143706f2543Smrg 144706f2543Smrg /* It is faster on almost always every architecture to just copy the 8 145706f2543Smrg * bytes, even when not necessary, than check to see of the value of 146706f2543Smrg * elements requires it. Copying the data when not needed will do no 147706f2543Smrg * harm. 148706f2543Smrg */ 149706f2543Smrg 150706f2543Smrg (void) memcpy( & __glXReply.pad3, data, 8 ); 151706f2543Smrg WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply ); 152706f2543Smrg 153706f2543Smrg if ( reply_ints != 0 ) { 154706f2543Smrg WriteToClient( client, reply_ints * 4, (char *) data ); 155706f2543Smrg } 156706f2543Smrg} 157706f2543Smrg 158706f2543Smrg 159706f2543Smrg/** 160706f2543Smrg * Send a GLX reply to the client. 161706f2543Smrg * 162706f2543Smrg * Technically speaking, there are several different ways to encode a GLX 163706f2543Smrg * reply. The primary difference is whether or not certain fields (e.g., 164706f2543Smrg * retval, size, and "pad3") are set. This function gets around that by 165706f2543Smrg * always setting all of the fields to "reasonable" values. This does no 166706f2543Smrg * harm to clients, but it does make the server-side code much more compact. 167706f2543Smrg * 168706f2543Smrg * \warning 169706f2543Smrg * This function assumes that values stored in \c data will be byte-swapped 170706f2543Smrg * by the caller if necessary. 171706f2543Smrg */ 172706f2543Smrgvoid 173706f2543Smrg__glXSendReplySwap( ClientPtr client, const void * data, size_t elements, 174706f2543Smrg size_t element_size, GLboolean always_array, CARD32 retval ) 175706f2543Smrg{ 176706f2543Smrg size_t reply_ints = 0; 177706f2543Smrg 178706f2543Smrg if ( __glXErrorOccured() ) { 179706f2543Smrg elements = 0; 180706f2543Smrg } 181706f2543Smrg else if ( (elements > 1) || always_array ) { 182706f2543Smrg reply_ints = bytes_to_int32(elements * element_size); 183706f2543Smrg } 184706f2543Smrg 185706f2543Smrg __glXReply.length = bswap_32( reply_ints ); 186706f2543Smrg __glXReply.type = X_Reply; 187706f2543Smrg __glXReply.sequenceNumber = bswap_16( client->sequence ); 188706f2543Smrg __glXReply.size = bswap_32( elements ); 189706f2543Smrg __glXReply.retval = bswap_32( retval ); 190706f2543Smrg 191706f2543Smrg 192706f2543Smrg /* It is faster on almost always every architecture to just copy the 8 193706f2543Smrg * bytes, even when not necessary, than check to see of the value of 194706f2543Smrg * elements requires it. Copying the data when not needed will do no 195706f2543Smrg * harm. 196706f2543Smrg */ 197706f2543Smrg 198706f2543Smrg (void) memcpy( & __glXReply.pad3, data, 8 ); 199706f2543Smrg WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply ); 200706f2543Smrg 201706f2543Smrg if ( reply_ints != 0 ) { 202706f2543Smrg WriteToClient( client, reply_ints * 4, (char *) data ); 203706f2543Smrg } 204706f2543Smrg} 205706f2543Smrg 206706f2543Smrg 207706f2543Smrgstatic int 208706f2543Smrgget_decode_index(const struct __glXDispatchInfo *dispatch_info, 209706f2543Smrg unsigned opcode) 210706f2543Smrg{ 211706f2543Smrg int remaining_bits; 212706f2543Smrg int next_remain; 213706f2543Smrg const int_fast16_t * const tree = dispatch_info->dispatch_tree; 214706f2543Smrg int_fast16_t index; 215706f2543Smrg 216706f2543Smrg 217706f2543Smrg remaining_bits = dispatch_info->bits; 218706f2543Smrg if (opcode >= (1U << remaining_bits)) { 219706f2543Smrg return -1; 220706f2543Smrg } 221706f2543Smrg 222706f2543Smrg index = 0; 223706f2543Smrg for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) { 224706f2543Smrg unsigned mask; 225706f2543Smrg unsigned child_index; 226706f2543Smrg 227706f2543Smrg 228706f2543Smrg /* Calculate the slice of bits used by this node. 229706f2543Smrg * 230706f2543Smrg * If remaining_bits = 8 and tree[index] = 3, the mask of just the 231706f2543Smrg * remaining bits is 0x00ff and the mask for the remaining bits after 232706f2543Smrg * this node is 0x001f. By taking 0x00ff & ~0x001f, we get 0x00e0. 233706f2543Smrg * This masks the 3 bits that we would want for this node. 234706f2543Smrg */ 235706f2543Smrg 236706f2543Smrg next_remain = remaining_bits - tree[index]; 237706f2543Smrg mask = ((1 << remaining_bits) - 1) & 238706f2543Smrg ~((1 << next_remain) - 1); 239706f2543Smrg 240706f2543Smrg 241706f2543Smrg /* Using the mask, calculate the index of the opcode in the node. 242706f2543Smrg * With that index, fetch the index of the next node. 243706f2543Smrg */ 244706f2543Smrg 245706f2543Smrg child_index = (opcode & mask) >> next_remain; 246706f2543Smrg index = tree[index + 1 + child_index]; 247706f2543Smrg 248706f2543Smrg 249706f2543Smrg /* If the next node is an empty leaf, the opcode is for a non-existant 250706f2543Smrg * function. We're done. 251706f2543Smrg * 252706f2543Smrg * If the next node is a non-empty leaf, look up the function pointer 253706f2543Smrg * and return it. 254706f2543Smrg */ 255706f2543Smrg 256706f2543Smrg if (index == EMPTY_LEAF) { 257706f2543Smrg return -1; 258706f2543Smrg } 259706f2543Smrg else if (IS_LEAF_INDEX(index)) { 260706f2543Smrg unsigned func_index; 261706f2543Smrg 262706f2543Smrg 263706f2543Smrg /* The value stored in the tree for a leaf node is the base of 264706f2543Smrg * the function pointers for that leaf node. The offset for the 265706f2543Smrg * function for a particular opcode is the remaining bits in the 266706f2543Smrg * opcode. 267706f2543Smrg */ 268706f2543Smrg 269706f2543Smrg func_index = -index; 270706f2543Smrg func_index += opcode & ((1 << next_remain) - 1); 271706f2543Smrg return func_index; 272706f2543Smrg } 273706f2543Smrg } 274706f2543Smrg 275706f2543Smrg /* We should *never* get here!!! 276706f2543Smrg */ 277706f2543Smrg return -1; 278706f2543Smrg} 279706f2543Smrg 280706f2543Smrg 281706f2543Smrgvoid * 282706f2543Smrg__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info, 283706f2543Smrg int opcode, int swapped_version) 284706f2543Smrg{ 285706f2543Smrg const int func_index = get_decode_index(dispatch_info, opcode); 286706f2543Smrg 287706f2543Smrg return (func_index < 0) 288706f2543Smrg ? NULL 289706f2543Smrg : (void *) dispatch_info->dispatch_functions[func_index][swapped_version]; 290706f2543Smrg} 291706f2543Smrg 292706f2543Smrg 293706f2543Smrgint 294706f2543Smrg__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info, 295706f2543Smrg int opcode, __GLXrenderSizeData *data) 296706f2543Smrg{ 297706f2543Smrg if (dispatch_info->size_table != NULL) { 298706f2543Smrg const int func_index = get_decode_index(dispatch_info, opcode); 299706f2543Smrg 300706f2543Smrg if ((func_index >= 0) 301706f2543Smrg && (dispatch_info->size_table[func_index][0] != 0)) { 302706f2543Smrg const int var_offset = 303706f2543Smrg dispatch_info->size_table[func_index][1]; 304706f2543Smrg 305706f2543Smrg data->bytes = dispatch_info->size_table[func_index][0]; 306706f2543Smrg data->varsize = (var_offset != ~0) 307706f2543Smrg ? dispatch_info->size_func_table[var_offset] 308706f2543Smrg : NULL; 309706f2543Smrg 310706f2543Smrg return 0; 311706f2543Smrg } 312706f2543Smrg } 313706f2543Smrg 314706f2543Smrg return -1; 315706f2543Smrg} 316