1Introduction: 2------------- 3The emugen tool is a tool to generate a wire protocol implementation 4based on provided API. The tool generates c++ encoder code that takes 5API calls and encodes them into the wire and decoder code that decodes 6the wire stream and calls server matching API. 7The emugen tool includes additional functionality that enables to 8generate an wrapper library. The wrapper library provides entry points 9for the specified API, where each entry routes the call via a dispatch 10table. The dispatch table may be initialized as required by a specific application. 11 12The following paragraphs includes the following: 13 * Wire Protocol Description 14 * Input files description & format 15 * Generated code description. 16 17 18Note: In this document, the caller is referred to as Encoder or Client 19and the callee is referred to as the Decoder or Server. These terms 20are used interchangeably by the context. 21 22 23 24Wire Protocol packet structure: 25------------------------------- 26A general Encoder->Decoder packet is structured as following: 27struct Packet { 28 unsigned int opcode; 29 unsigned int packet_len; 30 … parameter 1 31 … parameter 2 32}; 33A general Decoder->Encoder reply is expected to be received in the 34context of the ‘call’ that triggered it, thus it includes the reply 35data only, with no context headers. In precise term terms, a reply 36packet will look like: 37 38struct { 39 ...// reply data 40}; 41 42consider the following function call: 43int foo(int p1, short s1) 44will be encoded into : 45{ 46 101, // foo opcode 47 14, // sizeof(opcode) + sizeof(packet_len) + sizeof(int) + sizeof(short) 48 p1, // 4 bytes 49 s1 // 2 bytes 50} 51 52Since ‘foo’ returns value, the caller is expected to read back the return packet from the server->client stream. The return value in this example is in thus the return packet is: 53{ 54 int retval; 55} 56 57 58Pointer decoding: 59---------------- 60The wire protocol also allows exchanging of pointer data 61(arrays). Pointers are defined with directions: 62 63 in : Data is sent from the caller to the calle 64 out: Data is sent from the callee to the caller 65 in_out: data is sent from the caller and return in place. 66 67‘in’ and ‘in_out’ encoded with their len: 68{ 69 unsinged int pointer_data_len; 70 unsigned char data[pointer_data_len];… // pointer data 71} 72 73‘out’ pointers are encoded by data length only: 74{ 75unsigned int pointer_data_len; 76} 77 78‘out’ and ‘in_out’ pointer’s data is returned in the return 79packet. For example, consider the following call: 80 81int foo(int n, int *ptr); // assume that ‘data’ is in_out pointer which contains ‘n’ ints 82 83The caller packet will have the following form: 84{ 85 101, // foo opcode 86 xx, sizeof(opcode) + sizeof(datalen) + sizeof(int) + sizeof(unsigned int) + n * sizeof(int); 87 n, // the n parameter 88 n * sizeof(int), // size of the data in ptr 89 … // n* sizeof(int) bytes 90} 91 92The return packet is; 93{ 94 …. // n * sizeof(int) bytes of data return in ptr 95 retval // sizeof(int) - the return value of the function; 96} 97 98Endianess 99--------- 100The Wire protocol is designed to impose minimum overhead on the client 101side. Thus, the data endianness that is sent across the wire is 102determined by the ‘client’ side. It is up to the server side to 103determine the client endianess and marshal the packets as required. 104 105 106 107Emugen input files - protocol specification 108------------------------------------------- 109The protocol generated by emugen consists of two input files: 110 1111. basename.in - A sepcification of the protocol RPC procedures. This 112part of the specification is expected to be generated automatically 113from c/c++ header files or similar. 114 115‘basename’ is the basename for the protocol and will be used to prefix 116the files that are generated for this protocol. A line in the .in 117file has the following format: 118 119[prefix](retvalType, FuncName, <param type> [param name],...) 120where 121 retvalType - The function return value type 122 FuncName - function name 123 <param type> mandatory parameter type 124 [param name] - optional parameter name 125Examples: 126GL_ENTRY(void, glVertex1f, float v) 127XXX(int *, foo, int n, float, short) 128XXX(void, glFlush, void) 129 130Note: Empty lines in the file are ignored. A line starts with # is a comment 131 1322. basename.attrib - Attributes information of the API. 133This file includes additional flags, pointers datalen information and 134global attributes of the protocol. For uptodate format of the file, 135please refer to the specification file in the project source 136tree. The format of the .attrib file is described below. 137 1383. basename.types - Types information 139 140This files describes the types that are described by the API. A type 141is defined as follows: 142<type name> <size in bits> <print format string> <is a pointer? true|false> 143where: 144<type name> is the name of the type as described in the API 145<size in bits> 0, 8, 16, 32 sizes are accepted 146<print format string> a string to format the value of the type, as 147acceted by printf(3) 148<is pointer?> true or false string species whether the type should be 149treated as a pointer. 150 151example: 152GLint 32 %d false 153GLint* 32 %p true 154GLptr 32 %p true 155 156Encoder generated code files 157---------------------------- 158In order to generate the encoder files, one should run the ‘emugen’ 159tool as follows: 160 161emugen -i <input directory> -E <encoder files output directory> <basename> 162where: 163 <input directory> containes the api specification files (basename.in + basename.attrib) 164 <encoder directory> - a directory name to generate the encoder output files 165 basename - The basename for the api. 166 167Assuming the basename is ‘api’, The following files are generated: 168 169api_opcodes.h - defines the protocol opcodes. The first opcode value 170is 0, unless defined otherwise in the .attrib file 171 172api_entry.cpp - defines entry points for the functions that are 173defined by the protocol. this File also includes a function call 174‘setContextAccessor(void *(*f)()). This function should be used to 175provide a callback function that is used by the functions to access 176the encoder context. For example, such callback could fetch the 177context from a Thread Local Storage (TLS) location. 178 179api_client_proc.h - type defintions for the protocol procedures. 180 181api_client_context.h - defines the client side dispatch table data 182structure that stores the encoding functions. This data structure also 183includes ‘accessors’ methods such that library user can override 184default entries for special case handling. 185 186api_client_context.cpp - defines an initialization function for 187dispatch table 188 189api_enc.h - This header file defines the encoder data strcuture. The 190encoder data structure inherits its functionality from the 191‘client_context’ class above and adds encoding and streaming 192functionality. 193 194api_enc.cpp - Encoder implementation. 195 196Decoder generated files 197----------------------- 198In order to generate the decoder files, one should run the ‘emugen’ 199tool as follows: 200emugen -i <input directory> -D <decoder files output directory> basename 201where: 202 <input directory> containes the api specification files (basename.in + basename.attrib) 203 <decoder directory> - a directory name to generate the decoder output files 204 basename - The basename for the api. 205 206With resepct to the example above, Emugen will generate the following 207files: 208 209api_opcodes.h - Protocol opcodes 210 211api_server_proc.h - type definitions for the server side procedures 212 213api_server_context.h - dispatch table the decoder functions 214 215api_server_context.cpp - dispatch table initialization function 216api_dec.h - Decoder header file 217 218api_dec.cpp - Decoder implementation. In addtion, this file includes 219an intiailization function that uses a user provided callback to 220initialize the API server implementation. An example for such 221initialization is loading a set of functions from a shared library 222module. 223 224Wrapper generated files 225----------------------- 226In order to generate a wrapper library files, one should run the 227'emugen' tool as follows: 228 229emugen -i <input directory> -W <wrapper files output directory> basename 230where: 231 <input directory> containes the api specification files (basename.in + basename.attrib) 232 <wrapper directory> - a directory name to generate the wrapper output files 233 basename - The basename for the api. 234 235With resepct to the example above, Emugen will generate the following 236files: 237 238api_wrapper_proc.h - type definitions for the wrapper procedures 239 240api_wrapper_context.h - dispatch table the wrapper functions 241 242api_wrapper_context.cpp - dispatch table initialization function 243api_wrapper_entry.cpp - entry points for the API 244 245 246.attrib file format description: 247------------------------------- 248The .attrib file is an input file to emugen and is used to provide 249 additional information that is required for the code generation. 250The file format is as follows: 251 252a line that starts with # is ignored (comment) 253a empty line just whitespace of (" " "\t" "\n") is ignored. 254 255The file is divided into 'sections', each describes a specific API 256function call. A section starts with the name of the function in 257column 0. 258 259A section that starts with the reserved word 'GLOBAL' provides global 260attributes. 261 262below are few sections examples: 263 264GLOBAL 265 encoder_headers string.h kuku.h 266 267glVertex3fv 268 len data (size) 269glTexImage2D 270 len pixels (pixels == NULL? 0 : (format_pixel_size(internalformat) * width * height * type_size(type))) 271 272 273Global section flags description: 274 275base_opcode 276 set the base opcode value for this api 277 format: base_opcode 100 278 279encoder_headers 280 a list of headers that will be included in the encoder header file 281 format: encoder_headers <stdio.h> "kuku.h" 282 283client_context_headers 284 a list of headers that will be included in the client context header file 285 format: client_context_headers <stdio.h> "kuku.h" 286 287decoder_headers 288 a list of headers that will be included in the decoder header file 289 format: decoder_headers <stdio.h> "kuku.h" 290 291server_context_headers 292 a list of headers that will be included in the server context header file 293 format: server_context_headers <stdio.h> "kuku.h" 294 295 296Entry point flags description: 297 298 len 299 desciption : provide an expression to calcualte an expression data len 300 format: len <var name> <c expression that calcluates the data len> 301 302custom_pack 303 description: provide an expression to pack data into the stream. 304 format: custom_pack <var name> <c++ expression that pack data from var into the stream> 305 The stream is represented by a (unsigned char *)ptr. The expression may also refer 306 to other function parameters. In addition, the expression may refer to 'void *self' which 307 is the encoding context as provided by the caller. 308 309 dir 310 description : set a pointer direction (in - for data that goes 311 to the codec, out from data that returns from the codec. 312 format: dir <varname> <[in | out | inout]> 313 314 var_flag 315 description : set variable flags 316 format: var_flag <varname> < nullAllowed | isLarge | ... > 317 318 nullAllowed -> for pointer variables, indicates that NULL is a valid value 319 isLarge -> for pointer variables, indicates that the data should be sent without an intermediate copy 320 321 flag 322 description: set entry point flag; 323 format: flag < unsupported | ... > 324 supported flags are: 325 unsupported - The encoder side implementation is pointed to "unsuppored reporting function". 326 custom_decoder - The decoder is expected to be provided with 327 custom implementation. The call to the 328 deocder function includes a pointer to the 329 context 330 not_api - the function is not native gl api 331 332 333