aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/opengl/host/tools/emugen/README
blob: 0fe85f941282b4d2986a0c3ecb9bcec936251a8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
Introduction:
-------------
The emugen tool is a tool to generate a wire protocol implementation
based on provided API.  The tool generates c++ encoder code that takes
API calls and encodes them into the wire and decoder code that decodes
the wire stream and calls server matching API.
The emugen tool includes additional functionality that enables to
generate an wrapper library. The wrapper library provides entry points
for the specified API, where each entry routes the call via a dispatch
table. The dispatch table may be initialized as required by a specific application.

The following paragraphs includes the following:
    * Wire Protocol Description
    * Input files description & format
    * Generated code description.


Note: In this document, the caller is referred to as Encoder or Client
and the callee is referred to as the Decoder or Server. These terms
are used interchangeably by the context.



Wire Protocol packet structure:
-------------------------------
A general Encoder->Decoder packet is structured as following:
struct Packet {
	unsigned int opcode;
	unsigned int packet_len;
	… parameter 1
	… parameter 2
};
A general Decoder->Encoder reply is expected to be received in the
context of the ‘call’ that triggered it, thus it includes the reply
data only, with no context headers. In precise term terms, a reply
packet will look like:

struct {
	...// reply data
};

consider the following function call:
int foo(int p1, short s1)
will be encoded into :
{
	101, // foo opcode
	14, // sizeof(opcode) + sizeof(packet_len) + sizeof(int) + sizeof(short)
	p1, // 4 bytes
	s1 // 2 bytes
}

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:
{
	int retval;
}


Pointer decoding:
----------------
The wire protocol also allows exchanging of pointer data
(arrays). Pointers are defined with directions:

	in : Data is sent from the caller to the calle
	out: Data is sent from the callee to the caller
	in_out: data is sent from the caller and return in place.

‘in’ and ‘in_out’ encoded with their len:
{
	unsinged int pointer_data_len;
	unsigned char data[pointer_data_len];… // pointer data
}

‘out’ pointers are encoded by data length only:
{
unsigned int pointer_data_len;
}

‘out’ and ‘in_out’ pointer’s data is returned in the return
packet. For example, consider the following call:

int foo(int n, int *ptr); // assume that ‘data’ is in_out pointer which contains ‘n’ ints

The caller packet will have the following form:
{
	101, // foo opcode
	xx, sizeof(opcode) + sizeof(datalen) + sizeof(int) + sizeof(unsigned int) + n * sizeof(int);
	n, // the n parameter
	n * sizeof(int), // size of the data in ptr
	… // n* sizeof(int) bytes
}

The return packet is;
{
	…. // n * sizeof(int) bytes of data return in ptr
	retval // sizeof(int) - the return value of the function;
}

Endianess
---------
The Wire protocol is designed to impose minimum overhead on the client
side. Thus, the data endianness that is sent across the wire is
determined by the ‘client’ side. It is up to the server side to
determine the client endianess and marshal the packets as required.



Emugen input files - protocol specification
-------------------------------------------
The protocol generated by emugen consists of two input files:

1. basename.in - A sepcification of the protocol RPC procedures. This
part of the specification is expected to be generated automatically
from c/c++ header files or similar.

‘basename’ is the basename for the protocol and will be used to prefix
the files that are generated for this protocol.  A line in the .in
file has the following format:

[prefix](retvalType, FuncName, <param type> [param name],...)
where 
	retvalType - The function return value type
	FuncName - function name
	<param type> mandatory parameter type
	[param name] - optional parameter name
Examples:
GL_ENTRY(void, glVertex1f, float v) 
XXX(int *, foo, int n, float, short)
XXX(void, glFlush, void)

Note: Empty lines in the file are ignored. A line starts with # is a comment

2. basename.attrib - Attributes information of the API. 
This file includes additional flags, pointers datalen information and
global attributes of the protocol. For uptodate format of the file,
please refer to the specification file in the project source
tree. The format of the .attrib file is described below.

3. basename.types - Types information

This files describes the types that are described by the API. A type
is defined as follows:
<type name> <size in bits> <print format string> <is a pointer? true|false>
where:
<type name> is the name of the type as described in the API
<size in bits> 0, 8, 16, 32 sizes are accepted
<print format string> a string to format the value of the type, as
acceted by printf(3)
<is pointer?> true or false string species whether the type should be
treated as a pointer.

example:
GLint 32 %d false
GLint* 32 %p true
GLptr  32 %p true

Encoder generated code files 
----------------------------
In order to generate the encoder files, one should run the ‘emugen’
tool as follows:

emugen -i <input directory> -E <encoder files output directory> <basename>
where:
	<input directory> containes the api specification files  (basename.in + basename.attrib)
	<encoder directory> - a directory name to generate the encoder output files
	basename - The basename for the api.

Assuming the basename is ‘api’, The following files are generated:

api_opcodes.h - defines the protocol opcodes. The first opcode value
is 0, unless defined otherwise in the .attrib file

api_entry.cpp - defines entry points for the functions that are
defined by the protocol. this File also includes a function call
‘setContextAccessor(void *(*f)()). This function should be used to
provide a callback function that is used by the functions to access
the encoder context. For example, such callback could fetch the
context from a Thread Local Storage (TLS) location.

api_client_proc.h - type defintions for the protocol procedures. 

api_client_context.h - defines the client side dispatch table data
structure that stores the encoding functions. This data structure also
includes ‘accessors’ methods such that library user can override
default entries for special case handling.

api_client_context.cpp - defines an initialization function for
dispatch table

api_enc.h - This header file defines the encoder data strcuture. The
encoder data structure inherits its functionality from the
‘client_context’ class above and adds encoding and streaming
functionality.

api_enc.cpp - Encoder implementation. 

Decoder generated files
-----------------------
In order to generate the decoder files, one should run the ‘emugen’
tool as follows:
emugen -i <input directory> -D <decoder files output directory> basename
where:
	<input directory> containes the api specification files  (basename.in + basename.attrib)
	<decoder directory> - a directory name to generate the decoder output files
	basename - The basename for the api.

With resepct to the example above, Emugen will generate the following
files:

api_opcodes.h - Protocol opcodes

api_server_proc.h - type definitions for the server side procedures

api_server_context.h - dispatch table the decoder functions

api_server_context.cpp - dispatch table initialization function
api_dec.h - Decoder header file

api_dec.cpp - Decoder implementation. In addtion, this file includes
an intiailization function that uses a user provided callback to
initialize the API server implementation. An example for such
initialization is loading a set of functions from a shared library
module.

Wrapper generated files
-----------------------
In order to generate a wrapper library files, one should run the
'emugen' tool as follows:

emugen -i <input directory> -W <wrapper files output directory> basename
where:
	<input directory> containes the api specification files  (basename.in + basename.attrib)
	<wrapper directory> - a directory name to generate the wrapper output files
	basename - The basename for the api.

With resepct to the example above, Emugen will generate the following
files:

api_wrapper_proc.h - type definitions for the wrapper procedures

api_wrapper_context.h - dispatch table the wrapper functions

api_wrapper_context.cpp - dispatch table initialization function
api_wrapper_entry.cpp - entry points for the API


.attrib file format description:
-------------------------------
The .attrib file is an input file to emugen and is used to provide
 additional information that is required for the code generation.
The file format is as follows:

a line that starts with # is ignored (comment)
a empty line just whitespace of (" " "\t" "\n") is ignored.

The file is divided into 'sections', each describes a specific API
function call. A section starts with the name of the function in
column 0.

A section that starts with the reserved word 'GLOBAL' provides global
attributes.

below are few sections examples:

GLOBAL
  encoder_headers string.h kuku.h

glVertex3fv
	len data (size)
glTexImage2D
       len pixels (pixels == NULL? 0 : (format_pixel_size(internalformat) * width * height * type_size(type)))


Global section flags description:

base_opcode
    set the base opcode value for this api
    format: base_opcode 100

encoder_headers
    a list of headers that will be included in the encoder header file
    format: encoder_headers <stdio.h> "kuku.h"

client_context_headers
    a list of headers that will be included in the client context header file
    format: client_context_headers <stdio.h> "kuku.h"

decoder_headers
    a list of headers that will be included in the decoder header file
    format: decoder_headers <stdio.h> "kuku.h"

server_context_headers
    a list of headers that will be included in the server context header file
    format: server_context_headers <stdio.h> "kuku.h"


Entry point flags description:

 len
	desciption : provide an expression to calcualte an expression data len
	format: len <var name> <c expression that calcluates the data len>

custom_pack
	description: provide an expression to pack data into the stream.
	format: custom_pack <var name> <c++ expression that pack data from var into the stream>
	The stream is represented by a (unsigned char *)ptr. The expression may also refer
	to other function parameters. In addition, the expression may refer to 'void *self' which
	is the encoding context as provided by the caller.

 dir
	description : set a pointer direction (in - for data that goes
	to the codec, out from data that returns from the codec.
     	format: dir <varname> <[in | out | inout]>

 var_flag 
 	 description : set variable flags
 	 format: var_flag <varname> < nullAllowed | isLarge | ... >

        nullAllowed -> for pointer variables, indicates that NULL is a valid value
        isLarge     -> for pointer variables, indicates that the data should be sent without an intermediate copy

 flag
	description: set entry point flag; 
	format: flag < unsupported | ... >
	supported flags are:
	unsupported - The encoder side implementation is pointed to "unsuppored reporting function". 
	custom_decoder - The decoder is expected to be provided with
		       	 custom implementation. The call to the
		       	 deocder function includes a pointer to the
		       	 context
    not_api - the function is not native gl api