1 Introduction: 2 ------------- 3 The emugen tool is a tool to generate a wire protocol implementation 4 based on provided API. The tool generates c++ encoder code that takes 5 API calls and encodes them into the wire and decoder code that decodes 6 the wire stream and calls server matching API. 7 The emugen tool includes additional functionality that enables to 8 generate an wrapper library. The wrapper library provides entry points 9 for the specified API, where each entry routes the call via a dispatch 10 table. The dispatch table may be initialized as required by a specific application. 11 12 The following paragraphs includes the following: 13 * Wire Protocol Description 14 * Input files description & format 15 * Generated code description. 16 17 18 Note: In this document, the caller is referred to as Encoder or Client 19 and the callee is referred to as the Decoder or Server. These terms 20 are used interchangeably by the context. 21 22 23 24 Wire Protocol packet structure: 25 ------------------------------- 26 A general Encoder->Decoder packet is structured as following: 27 struct Packet { 28 unsigned int opcode; 29 unsigned int packet_len; 30 parameter 1 31 parameter 2 32 }; 33 A general Decoder->Encoder reply is expected to be received in the 34 context of the call that triggered it, thus it includes the reply 35 data only, with no context headers. In precise term terms, a reply 36 packet will look like: 37 38 struct { 39 ...// reply data 40 }; 41 42 consider the following function call: 43 int foo(int p1, short s1) 44 will 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 52 Since 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 58 Pointer decoding: 59 ---------------- 60 The 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 { 75 unsigned int pointer_data_len; 76 } 77 78 out and in_out pointers data is returned in the return 79 packet. For example, consider the following call: 80 81 int foo(int n, int *ptr); // assume that data is in_out pointer which contains n ints 82 83 The 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 92 The 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 98 Endianess 99 --------- 100 The Wire protocol is designed to impose minimum overhead on the client 101 side. Thus, the data endianness that is sent across the wire is 102 determined by the client side. It is up to the server side to 103 determine the client endianess and marshal the packets as required. 104 105 106 107 Emugen input files - protocol specification 108 ------------------------------------------- 109 The protocol generated by emugen consists of two input files: 110 111 1. basename.in - A sepcification of the protocol RPC procedures. This 112 part of the specification is expected to be generated automatically 113 from c/c++ header files or similar. 114 115 basename is the basename for the protocol and will be used to prefix 116 the files that are generated for this protocol. A line in the .in 117 file has the following format: 118 119 [prefix](retvalType, FuncName, <param type> [param name],...) 120 where 121 retvalType - The function return value type 122 FuncName - function name 123 <param type> mandatory parameter type 124 [param name] - optional parameter name 125 Examples: 126 GL_ENTRY(void, glVertex1f, float v) 127 XXX(int *, foo, int n, float, short) 128 XXX(void, glFlush, void) 129 130 Note: Empty lines in the file are ignored. A line starts with # is a comment 131 132 2. basename.attrib - Attributes information of the API. 133 This file includes additional flags, pointers datalen information and 134 global attributes of the protocol. For uptodate format of the file, 135 please refer to the specification file in the project source 136 tree. The format of the .attrib file is described below. 137 138 3. basename.types - Types information 139 140 This files describes the types that are described by the API. A type 141 is defined as follows: 142 <type name> <size in bits> <print format string> <is a pointer? true|false> 143 where: 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 147 acceted by printf(3) 148 <is pointer?> true or false string species whether the type should be 149 treated as a pointer. 150 151 example: 152 GLint 32 %d false 153 GLint* 32 %p true 154 GLptr 32 %p true 155 156 Encoder generated code files 157 ---------------------------- 158 In order to generate the encoder files, one should run the emugen 159 tool as follows: 160 161 emugen -i <input directory> -E <encoder files output directory> <basename> 162 where: 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 167 Assuming the basename is api, The following files are generated: 168 169 api_opcodes.h - defines the protocol opcodes. The first opcode value 170 is 0, unless defined otherwise in the .attrib file 171 172 api_entry.cpp - defines entry points for the functions that are 173 defined by the protocol. this File also includes a function call 174 setContextAccessor(void *(*f)()). This function should be used to 175 provide a callback function that is used by the functions to access 176 the encoder context. For example, such callback could fetch the 177 context from a Thread Local Storage (TLS) location. 178 179 api_client_proc.h - type defintions for the protocol procedures. 180 181 api_client_context.h - defines the client side dispatch table data 182 structure that stores the encoding functions. This data structure also 183 includes accessors methods such that library user can override 184 default entries for special case handling. 185 186 api_client_context.cpp - defines an initialization function for 187 dispatch table 188 189 api_enc.h - This header file defines the encoder data strcuture. The 190 encoder data structure inherits its functionality from the 191 client_context class above and adds encoding and streaming 192 functionality. 193 194 api_enc.cpp - Encoder implementation. 195 196 Decoder generated files 197 ----------------------- 198 In order to generate the decoder files, one should run the emugen 199 tool as follows: 200 emugen -i <input directory> -D <decoder files output directory> basename 201 where: 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 206 With resepct to the example above, Emugen will generate the following 207 files: 208 209 api_opcodes.h - Protocol opcodes 210 211 api_server_proc.h - type definitions for the server side procedures 212 213 api_server_context.h - dispatch table the decoder functions 214 215 api_server_context.cpp - dispatch table initialization function 216 api_dec.h - Decoder header file 217 218 api_dec.cpp - Decoder implementation. In addtion, this file includes 219 an intiailization function that uses a user provided callback to 220 initialize the API server implementation. An example for such 221 initialization is loading a set of functions from a shared library 222 module. 223 224 Wrapper generated files 225 ----------------------- 226 In order to generate a wrapper library files, one should run the 227 'emugen' tool as follows: 228 229 emugen -i <input directory> -W <wrapper files output directory> basename 230 where: 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 235 With resepct to the example above, Emugen will generate the following 236 files: 237 238 api_wrapper_proc.h - type definitions for the wrapper procedures 239 240 api_wrapper_context.h - dispatch table the wrapper functions 241 242 api_wrapper_context.cpp - dispatch table initialization function 243 api_wrapper_entry.cpp - entry points for the API 244 245 246 .attrib file format description: 247 ------------------------------- 248 The .attrib file is an input file to emugen and is used to provide 249 additional information that is required for the code generation. 250 The file format is as follows: 251 252 a line that starts with # is ignored (comment) 253 a empty line just whitespace of (" " "\t" "\n") is ignored. 254 255 The file is divided into 'sections', each describes a specific API 256 function call. A section starts with the name of the function in 257 column 0. 258 259 A section that starts with the reserved word 'GLOBAL' provides global 260 attributes. 261 262 below are few sections examples: 263 264 GLOBAL 265 encoder_headers string.h kuku.h 266 267 glVertex3fv 268 len data (size) 269 glTexImage2D 270 len pixels (pixels == NULL? 0 : (format_pixel_size(internalformat) * width * height * type_size(type))) 271 272 273 Global section flags description: 274 275 base_opcode 276 set the base opcode value for this api 277 format: base_opcode 100 278 279 encoder_headers 280 a list of headers that will be included in the encoder header file 281 format: encoder_headers <stdio.h> "kuku.h" 282 283 client_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 287 decoder_headers 288 a list of headers that will be included in the decoder header file 289 format: decoder_headers <stdio.h> "kuku.h" 290 291 server_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 296 Entry 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 302 custom_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