#define PEX_TXM_NUM_TEXELS(_domain, _level, _texel_arrays ) \ ( (PEXEnumTypeIndex)_domain == PEXExtTMDomainColor1D ? \ _texel_arrays[_level].dimension.t0 : \ ( (PEXEnumTypeIndex)_domain == PEXExtTMDomainColor2D ? \ _texel_arrays[_level].dimension.t0 * \ _texel_arrays[_level].dimension.t1 : \ _texel_arrays[_level].dimension.t0 * \ _texel_arrays[_level].dimension.t1 * \ _texel_arrays[_level].dimension.t2 )) typedef struct { INT16 float_format; CARD16 num_arrays; CARD32 tm_id; INT16 tm_domain; INT16 tm_type; INT16 texel_type; CARD16 num_levels; CARD32 texel_array_size; /* variable list of domain data and texel data follows here in reply data */ } pexExtEscapeCreateTMData; typedef struct { CARD16 t0; CARD16 t1; CARD16 t2; CARD16 unused; } pexExtTexelDimension; /**************************************************************************** ** Global variable to use when receiving large texture maps in chunks. Since ** the entire texture map is not contained in one packet this global ** is needed to allow additions. ***************************************************************************** */ PEXExtTextureMap PEXExtCreateTM ( INPUT Display *display, INPUT int domain, INPUT PEXExtTMDomainData *domain_data, INPUT PEXExtTexelArray *texel_arrays) /* ******************************************************************************* ** Description: ** This function saves the given texture map and it's domain ** description returning an id that can be used for future ** reference. DHA or protocol connections are handled automatically. ** ** ** Input parameters: ** display -Display structure from XOpenDisplay ** domain -domain type of data, currently supported: ** PEXExtTMDomainColor1D, ** PEXExtTMDomainColor2D, ** PEXExtTMDomainColor3D ** domain_data -domain specific data record ** texel_arrays -list of texel arrays describing texture map ** ** Output parameters: ** Returns a PEXExtTextureMap reference identifier, if sucessful. ** ** Entry Conditions: ** 1) Assumes pointers reference data conforming to PEX 5.1v2 spec ** TM features that are supported. ** Exit Conditions: ** 1) Internal resource allocated and initialized with texel data. ** 2) Resource identifier returned if sucessful, 0 on failure. ** ** Error Conditions: ** When possible errors are deferred to the lowest level ** to support future extensions using the imp dep features. ** 1) BadAlloc if unable to allocate resource block ** ** Algorithm: ** 1) Get an id from the X display ** 2) Find the maximum transfer size the display supports and adjust ** for header size and word alignment. ** 3) Find the sizes of data and total bytes to send. ** 4) Allocate transport memory that will be filled with protocol. ** 5) Transfer the given create data to start of protocol memory. ** 6) Loop on levels of texels, transfering them to transport memory ** until data is exhausted. ** 7) Send the first full block of data with CreateTM escape, ** emptying memory. ** 8) Send further full blocks with CreateTMExtraData escape, ** emptying memory. ** ** Referenced by: ** Globally available. ** ** Procedure/FunctionDependencies: ** ** Comments: ** Several changes have been accepted since the original spec was ** published. ** A) The size of the texel data was added to the create structure. ** B) The TM id is the first entry in CreateTMExtraData data. ** C) Texels are padded in protocol the same as in API. ** D) Very large TMs are possible because chunks can be sent. ** E) The data structure pexExtDomainColorData is no longer needed. ** ** Change History: ** 31 Jan 94 - Dave Luttropp created to handle large blocks ******************************************************************************* */ { int copy_size; /* All these sizes are */ int create_byte_size; /* in protocol bytes */ int dimension_byte_size; int levels_texel_bytes; int max_transfer_size; int space_available; int texel_bytes_sent; int texel_byte_size; int total_byte_size; int transfer_size; char *escape_data; /* protocol variables */ pexExtEscapeCreateTMData *req; pexExtTexelDimension *dim_level; char *pbuf; unsigned short int num_levels; /* Misc variables */ int num_texels; unsigned short int domain_is_color; PEXExtTextureMap tm_ident; int i; int first_time = True; int fp_convert; int fp_format; /* Get a unique identifier from the display to label this texture map */ tm_ident = XAllocID( display ); /* Determine size of maximum transfer adjusting to word size. Note: The maximum size is reduced by the header as specified by XMaxRequestSize() */ max_transfer_size = (XMaxRequestSize(display) - 4 ); max_transfer_size += PAD(max_transfer_size) -4; domain_is_color = ( (PEXEnumTypeIndex)domain == PEXExtTMDomainColor1D || (PEXEnumTypeIndex)domain == PEXExtTMDomainColor2D || (PEXEnumTypeIndex)domain == PEXExtTMDomainColor3D ) ? 1:0; if( !domain_is_color ){ return 0; } num_levels = (domain_is_color) ? domain_data->data.color.num_levels : 0; dimension_byte_size = SIZEOF( pexExtTexelDimension ); /* Check for a texel type in the defined range */ if( domain_data->data.color.texel_type > PEXExtTexelRGBAlphaInt16 || domain_data->data.color.texel_type < PEXExtTexelLuminanceFloat ){ return 0; } num_texels = 0; texel_byte_size = 0; if( domain_is_color ){ for(i=0; idata.color.texel_type)); } create_byte_size = SIZEOF(pexExtEscapeCreateTMData); total_byte_size = texel_byte_size + create_byte_size; transfer_size = (total_byte_size > max_transfer_size)? max_transfer_size: total_byte_size; /* Create a memory block to hold protocol data */ escape_data = PEXAllocBuf( transfer_size ); if(escape_data == NULL){ return 0; } fp_format = PEXGetProtocolFloatFormat( display ); fp_convert = (fp_format != NATIVE_FP_FORMAT); /* Create TM data loaded into the protocol structure */ req = (pexExtEscapeCreateTMData *)escape_data; req->float_format = fp_format; req->tm_domain = domain; req->tm_id = tm_ident; req->num_arrays = num_levels; req->texel_array_size = texel_byte_size; req->texel_type = domain_data->data.color.texel_type; req->num_levels = num_levels; req->tm_type = domain_data->data.color.tm_type; if( req->tm_type != PEXExtTMTypeMipMap ){ free(escape_data); return 0; } /* Texels are loaded one level at a time since the arrays may not be in contigous memory. When the buffer is full the texels are sent and the buffer is flushed. */ texel_bytes_sent = 0; space_available = transfer_size - create_byte_size; pbuf = escape_data + create_byte_size; for(i=0; i< num_levels; i++) { num_texels =PEX_TXM_NUM_TEXELS(domain, i, texel_arrays ); levels_texel_bytes = dimension_byte_size + num_texels * GetTexelSize( domain_data->data.color.texel_type ); dim_level = (pexExtTexelDimension *)pbuf; dim_level->t0 = texel_arrays[i].dimension.t0; dim_level->t1 = texel_arrays[i].dimension.t1; dim_level->t2 = texel_arrays[i].dimension.t2; /* Check on out of range dimensions */ if( dim_level->t0 <= 0 || dim_level->t1 <= 0 || dim_level->t2 <= 0 ){ free(escape_data); return 0; } levels_texel_bytes -= dimension_byte_size; texel_bytes_sent += dimension_byte_size; space_available -= dimension_byte_size; pbuf += dimension_byte_size; /* Loop on this level until all texels have been loaded in buffer */ while( levels_texel_bytes > 0 ){ copy_size = (levels_texel_bytes > space_available )? space_available: levels_texel_bytes; COPY_AREA(texel_arrays[i].array.luminance, pbuf, copy_size ); space_available -= copy_size; levels_texel_bytes -= copy_size; texel_bytes_sent += copy_size; pbuf += copy_size; /* Send Escape when the buffer is full or at end of texels */ if(( space_available <=0 )||(texel_byte_size == texel_bytes_sent)){ if( first_time ){ PEXEscape(display, PEXExtEscapeOpcodeCreateTM, pbuf - escape_data, (char *)escape_data); first_time = False; } else { PEXEscape(display, PEXExtEscapeOpcodeCreateTMExtraData, pbuf - escape_data, (char *)escape_data); } pbuf = escape_data; COPY_AREA( &tm_ident, pbuf, PADDED_BYTES(SIZEOF(PEXExtTextureMap))); pbuf += PADDED_BYTES(SIZEOF(PEXExtTextureMap)); space_available = transfer_size - dimension_byte_size - PADDED_BYTES(SIZEOF(PEXExtTextureMap)); } } } PEXFreeBuf(escape_data); return (tm_ident); } } /* PEXExtCreateTM */