Initial work
This commit is contained in:
commit
3222551702
374 changed files with 40290 additions and 0 deletions
332
external/android-emugl/host/tools/emugen/README
vendored
Normal file
332
external/android-emugl/host/tools/emugen/README
vendored
Normal file
|
|
@ -0,0 +1,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
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue