summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingfeng Yang <lfy@google.com>2017-05-11 07:54:43 -0700
committerGreg Hartman <ghartman@google.com>2018-08-23 17:30:51 -0700
commit9c7aff1e6963ba734a9cf7a8c24506fcaeee5fc7 (patch)
tree2f15143e496a89fae3780b23559c07d7e2cf776d
parent64f12142f8409da9ecc0d52828e5a9fec8fcb5bc (diff)
downloadopengl-transport-9c7aff1e6963ba734a9cf7a8c24506fcaeee5fc7.tar.gz
[gl] Fix 'inout' variable qualification + complex readback
- Can use variables with both input and output qualities - Allow readback of complex structures. 3 phases: - host_pack_tmp_alloc: custom expression to allocate aligned temporaries for the output structs - host_pack: custom expression to pack into stream (losing alignment) - guest_unpack: custom expression to unpack into object on guest (regaining alignment) Change-Id: I9073325efe6847762e8b2d42fd9803d81ff67374
-rw-r--r--host/commands/emugen/ApiGen.cpp70
-rw-r--r--host/commands/emugen/EntryPoint.cpp167
-rw-r--r--host/commands/emugen/EntryPoint.h2
-rw-r--r--host/commands/emugen/Var.h15
-rw-r--r--host/commands/emugen/tests/t.001/expected/decoder/foo_dec.cpp60
-rw-r--r--host/commands/emugen/tests/t.001/expected/decoder/foo_opcodes.h5
-rw-r--r--host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.cpp3
-rw-r--r--host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.h3
-rw-r--r--host/commands/emugen/tests/t.001/expected/decoder/foo_server_proc.h3
-rw-r--r--host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.cpp3
-rw-r--r--host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.h3
-rw-r--r--host/commands/emugen/tests/t.001/expected/encoder/foo_client_proc.h3
-rw-r--r--host/commands/emugen/tests/t.001/expected/encoder/foo_enc.cpp109
-rw-r--r--host/commands/emugen/tests/t.001/expected/encoder/foo_entry.cpp21
-rw-r--r--host/commands/emugen/tests/t.001/expected/encoder/foo_ftable.h3
-rw-r--r--host/commands/emugen/tests/t.001/expected/encoder/foo_opcodes.h5
-rw-r--r--host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.cpp3
-rw-r--r--host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.h3
-rw-r--r--host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_entry.cpp21
-rw-r--r--host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_proc.h3
-rw-r--r--host/commands/emugen/tests/t.001/input/foo.attrib17
-rw-r--r--host/commands/emugen/tests/t.001/input/foo.in3
-rw-r--r--host/commands/emugen/tests/t.001/input/foo.types2
23 files changed, 439 insertions, 88 deletions
diff --git a/host/commands/emugen/ApiGen.cpp b/host/commands/emugen/ApiGen.cpp
index e343b83ab..4b40dc677 100644
--- a/host/commands/emugen/ApiGen.cpp
+++ b/host/commands/emugen/ApiGen.cpp
@@ -542,6 +542,7 @@ int ApiGen::genEncoderImpl(const std::string &filename)
fprintf(fp, "#include <string.h>\n");
fprintf(fp, "#include \"%s_opcodes.h\"\n\n", m_basename.c_str());
fprintf(fp, "#include \"%s_enc.h\"\n\n\n", m_basename.c_str());
+ fprintf(fp, "#include <vector>\n\n");
fprintf(fp, "#include <stdio.h>\n\n");
fprintf(fp, "namespace {\n\n");
@@ -778,8 +779,12 @@ int ApiGen::genEncoderImpl(const std::string &filename)
indent = "\t\t";
}
- fprintf(fp, "%sstream->readback(%s, __size_%s);\n",
- indent, varname, varname);
+ if (evars[j].guestUnpackExpression() != "") {
+ fprintf(fp, "%s%s;\n", indent, evars[j].guestUnpackExpression().c_str());
+ } else {
+ fprintf(fp, "%sstream->readback(%s, __size_%s);\n",
+ indent, varname, varname);
+ }
fprintf(fp, "%sif (useChecksum) checksumCalculator->addBuffer(%s, __size_%s);\n",
indent, varname, varname);
if (evars[j].nullAllowed()) {
@@ -1154,8 +1159,7 @@ R"( // Do this on every iteration, as some commands may change the checks
}
if (!v->isDMA()) {
- if (v->pointerDir() == Var::POINTER_IN ||
- v->pointerDir() == Var::POINTER_INOUT) {
+ if (v->pointerDir() & Var::POINTER_IN) {
if (pass == PASS_VariableDeclarations) {
#if USE_ALIGNED_BUFFERS
fprintf(fp,
@@ -1172,7 +1176,8 @@ R"( // Do this on every iteration, as some commands may change the checks
}
}
- if (pass == PASS_FunctionCall) {
+ if (pass == PASS_FunctionCall &&
+ v->pointerDir() == Var::POINTER_IN) {
if (v->nullAllowed()) {
fprintf(fp,
"size_%s == 0 ? nullptr : (%s)(inptr_%s.get())",
@@ -1192,7 +1197,8 @@ R"( // Do this on every iteration, as some commands may change the checks
var_name);
}
}
- } else if (pass == PASS_DebugPrint) {
+ } else if (pass == PASS_DebugPrint &&
+ v->pointerDir() == Var::POINTER_IN) {
fprintf(fp,
"(%s)(inptr_%s.get()), size_%s",
var_type_name,
@@ -1205,7 +1211,8 @@ R"( // Do this on every iteration, as some commands may change the checks
var_name,
varoffset.c_str());
}
- if (pass == PASS_FunctionCall) {
+ if (pass == PASS_FunctionCall &&
+ v->pointerDir() == Var::POINTER_IN) {
if (v->nullAllowed()) {
fprintf(fp,
"size_%s == 0 ? NULL : (%s)(inptr_%s)",
@@ -1218,7 +1225,8 @@ R"( // Do this on every iteration, as some commands may change the checks
var_type_name,
var_name);
}
- } else if (pass == PASS_DebugPrint) {
+ } else if (pass == PASS_DebugPrint &&
+ v->pointerDir() == Var::POINTER_IN) {
fprintf(fp,
"(%s)(inptr_%s), size_%s",
var_type_name,
@@ -1228,7 +1236,8 @@ R"( // Do this on every iteration, as some commands may change the checks
#endif // !USE_ALIGNED_BUFFERS
varoffset += " + 4 + size_";
varoffset += var_name;
- } else { // out pointer;
+ }
+ if (v->pointerDir() & Var::POINTER_OUT) { // out pointer;
if (pass == PASS_TmpBuffAlloc) {
if (!totalTmpBuffExist) {
fprintf(fp,
@@ -1250,18 +1259,40 @@ R"( // Do this on every iteration, as some commands may change the checks
var_name,
tmpBufOffset[j].c_str(),
var_name);
- } else if (pass == PASS_FunctionCall) {
- if (v->nullAllowed()) {
+ // If both input and output variable, initialize with the input.
+ if (v->pointerDir() == Var::POINTER_INOUT) {
fprintf(fp,
- "size_%s == 0 ? nullptr : (%s)(outptr_%s.get())",
+ "\t\t\tmemcpy(outptr_%s.get(), inptr_%s.get(), size_%s);\n",
+ var_name,
var_name,
- var_type_name,
var_name);
- } else {
+ }
+
+ if (v->hostPackExpression() != "") {
+ fprintf(fp, "\t\t\tvoid* forPacking_%s = nullptr;\n", var_name);
+ }
+ if (v->hostPackTmpAllocExpression() != "") {
+ fprintf(fp, "\t\t\t%s;\n", v->hostPackTmpAllocExpression().c_str());
+ }
+ } else if (pass == PASS_FunctionCall) {
+ if (v->hostPackExpression() != "") {
fprintf(fp,
- "(%s)(outptr_%s.get())",
+ "(%s)(forPacking_%s)",
var_type_name,
var_name);
+ } else {
+ if (v->nullAllowed()) {
+ fprintf(fp,
+ "size_%s == 0 ? nullptr : (%s)(outptr_%s.get())",
+ var_name,
+ var_type_name,
+ var_name);
+ } else {
+ fprintf(fp,
+ "(%s)(outptr_%s.get())",
+ var_type_name,
+ var_name);
+ }
}
} else if (pass == PASS_DebugPrint) {
fprintf(fp,
@@ -1271,6 +1302,13 @@ R"( // Do this on every iteration, as some commands may change the checks
var_name);
}
if (pass == PASS_FlushOutput) {
+ if (v->hostPackExpression() != "") {
+ fprintf(fp,
+ "\t\t\tif (size_%s) {\n"
+ "\t\t\t%s; }\n",
+ var_name,
+ v->hostPackExpression().c_str());
+ }
fprintf(fp,
"\t\t\toutptr_%s.flush();\n",
var_name);
@@ -1305,8 +1343,10 @@ R"( // Do this on every iteration, as some commands may change the checks
varoffset.c_str());
}
#endif // !USE_ALIGNED_BUFFERS
+ if (v->pointerDir() == Var::POINTER_OUT) {
varoffset += " + 4";
}
+ }
}
}
diff --git a/host/commands/emugen/EntryPoint.cpp b/host/commands/emugen/EntryPoint.cpp
index 6aecac16c..d7ce63566 100644
--- a/host/commands/emugen/EntryPoint.cpp
+++ b/host/commands/emugen/EntryPoint.cpp
@@ -159,6 +159,18 @@ Var * EntryPoint::var(const std::string & name)
return v;
}
+const Var * EntryPoint::var(const std::string & name) const
+{
+ const Var *v = NULL;
+ for (size_t i = 0; i < m_vars.size(); i++) {
+ if (m_vars[i].name() == name) {
+ v = &m_vars[i];
+ break;
+ }
+ }
+ return v;
+}
+
bool EntryPoint::hasPointers()
{
bool pointers = false;
@@ -174,62 +186,57 @@ bool EntryPoint::hasPointers()
return pointers;
}
+int EntryPoint::validateVarAttr(const std::string& varname, size_t lc) const {
+ if (varname.size() == 0) {
+ fprintf(stderr, "ERROR: %u: Missing variable name in attribute\n", (unsigned int)lc);
+ return -1;
+ }
+ const Var * v = var(varname);
+ if (v == NULL) {
+ fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
+ (unsigned int)lc, varname.c_str(), name().c_str());
+ return -2;
+ }
+ return 0;
+}
+
int EntryPoint::setAttribute(const std::string &line, size_t lc)
{
size_t pos = 0;
size_t last;
std::string token = getNextToken(line, 0, &last, WHITESPACE);
+ int err = 0;
+ Var* v = nullptr;
if (token == "len") {
pos = last;
std::string varname = getNextToken(line, pos, &last, WHITESPACE);
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
- if (varname.size() == 0) {
- fprintf(stderr, "ERROR: %u: Missing variable name in 'len' attribute\n", (unsigned int)lc);
- return -1;
- }
- Var * v = var(varname);
- if (v == NULL) {
- fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
- (unsigned int)lc, varname.c_str(), name().c_str());
- return -2;
- }
// set the size expression into var
+ v = var(varname);
pos = last;
v->setLenExpression(line.substr(pos));
} else if (token == "param_check") {
pos = last;
std::string varname = getNextToken(line, pos, &last, WHITESPACE);
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
- if (varname.size() == 0) {
- fprintf(stderr, "ERROR: %u: Missing variable name in 'param_check' attribute\n", (unsigned int)lc);
- return -1;
- }
- Var * v = var(varname);
- if (v == NULL) {
- fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
- (unsigned int)lc, varname.c_str(), name().c_str());
- return -2;
- }
- // set the size expression into var
+ v = var(varname);
pos = last;
v->setParamCheckExpression(line.substr(pos));
} else if (token == "dir") {
pos = last;
std::string varname = getNextToken(line, pos, &last, WHITESPACE);
- if (varname.size() == 0) {
- fprintf(stderr, "ERROR: %u: Missing variable name in 'dir' attribute\n", (unsigned int)lc);
- return -1;
- }
- Var * v = var(varname);
- if (v == NULL) {
- fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
- (unsigned int)lc, varname.c_str(), name().c_str());
- return -2;
- }
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
+ v = var(varname);
pos = last;
+
std::string pointerDirStr = getNextToken(line, pos, &last, WHITESPACE);
if (pointerDirStr.size() == 0) {
fprintf(stderr, "ERROR: %u: missing pointer directions\n", (unsigned int)lc);
@@ -243,21 +250,16 @@ int EntryPoint::setAttribute(const std::string &line, size_t lc)
} else if (pointerDirStr == "in") {
v->setPointerDir(Var::POINTER_IN);
} else {
- fprintf(stderr, "ERROR: %u: unknow pointer direction %s\n", (unsigned int)lc, pointerDirStr.c_str());
+ fprintf(stderr, "ERROR: %u: unknown pointer direction %s\n",
+ (unsigned int)lc, pointerDirStr.c_str());
}
} else if (token == "var_flag") {
pos = last;
std::string varname = getNextToken(line, pos, &last, WHITESPACE);
- if (varname.size() == 0) {
- fprintf(stderr, "ERROR: %u: Missing variable name in 'var_flag' attribute\n", (unsigned int)lc);
- return -1;
- }
- Var * v = var(varname);
- if (v == NULL) {
- fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
- (unsigned int)lc, varname.c_str(), name().c_str());
- return -2;
- }
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
+
+ v = var(varname);
int count = 0;
for (;;) {
pos = last;
@@ -294,52 +296,75 @@ int EntryPoint::setAttribute(const std::string &line, size_t lc)
} else if (token == "custom_pack") {
pos = last;
std::string varname = getNextToken(line, pos, &last, WHITESPACE);
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
- if (varname.size() == 0) {
- fprintf(stderr, "ERROR: %u: Missing variable name in 'custom_pack' attribute\n", (unsigned int)lc);
- return -1;
- }
- Var * v = var(varname);
- if (v == NULL) {
- fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
- (unsigned int)lc, varname.c_str(), name().c_str());
- return -2;
- }
- // set the size expression into var
+ v = var(varname);
pos = last;
v->setPackExpression(line.substr(pos));
} else if (token == "custom_unpack") {
pos = last;
std::string varname = getNextToken(line, pos, &last, WHITESPACE);
- if (varname.size() == 0) {
- fprintf(stderr, "ERROR: %u: Missing variable name in 'custom_unpack' attribute\n", (unsigned int)lc);
- return -1;
- }
- Var * v = var(varname);
- if (v == NULL) {
- fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
- (unsigned int)lc, varname.c_str(), name().c_str());
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
+
+ v = var(varname);
+ pos = last;
+ v->setUnpackExpression(line.substr(pos));
+ } else if (token == "custom_host_pack_tmp_alloc") {
+ pos = last;
+ std::string varname = getNextToken(line, pos, &last, WHITESPACE);
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
+
+ v = var(varname);
+ if (v->pointerDir() == Var::POINTER_IN) {
+ fprintf(stderr, "ERROR: %u: variable %s is not an output or inout\n",
+ (unsigned int)lc, varname.c_str());
return -2;
}
- // set the size expression into var
+
pos = last;
- v->setUnpackExpression(line.substr(pos));
- } else if (token == "custom_write") {
+ v->setHostPackTmpAllocExpression(line.substr(pos));
+ } else if (token == "custom_host_pack") {
pos = last;
std::string varname = getNextToken(line, pos, &last, WHITESPACE);
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
- if (varname.size() == 0) {
- fprintf(stderr, "ERROR: %u: Missing variable name in 'custom_write' attribute\n", (unsigned int)lc);
- return -1;
+ v = var(varname);
+ if (v->pointerDir() == Var::POINTER_IN) {
+ fprintf(stderr, "ERROR: %u: variable %s is not an output or inout\n",
+ (unsigned int)lc, varname.c_str());
+ return -2;
}
- Var * v = var(varname);
- if (v == NULL) {
- fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
- (unsigned int)lc, varname.c_str(), name().c_str());
+
+ pos = last;
+ v->setHostPackExpression(line.substr(pos));
+ } else if (token == "custom_guest_unpack") {
+ pos = last;
+ std::string varname = getNextToken(line, pos, &last, WHITESPACE);
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
+
+ v = var(varname);
+ if (v->pointerDir() == Var::POINTER_IN) {
+ fprintf(stderr, "ERROR: %u: variable %s is not an output or inout\n",
+ (unsigned int)lc, varname.c_str());
return -2;
}
+
+ pos = last;
+ v->setGuestUnpackExpression(line.substr(pos));
+ } else if (token == "custom_write") {
+ pos = last;
+ std::string varname = getNextToken(line, pos, &last, WHITESPACE);
+ err = validateVarAttr(varname, lc);
+ if (err < 0) return err;
+
// set the size expression into var
+ v = var(varname);
pos = last;
v->setWriteExpression(line.substr(pos));
} else if (token == "flag") {
diff --git a/host/commands/emugen/EntryPoint.h b/host/commands/emugen/EntryPoint.h
index a50fda041..bc3fd6937 100644
--- a/host/commands/emugen/EntryPoint.h
+++ b/host/commands/emugen/EntryPoint.h
@@ -40,6 +40,7 @@ public:
VarsArray & vars() { return m_vars; }
Var & retval() { return m_retval; }
Var * var(const std::string & name);
+ const Var * var(const std::string & name) const;
bool hasPointers();
bool unsupported() const { return m_unsupported; }
void setUnsupported(bool state) { m_unsupported = state; }
@@ -49,6 +50,7 @@ public:
void setNotApi(bool state) { m_notApi = state; }
bool flushOnEncode() const { return m_flushOnEncode; }
void setFlushOnEncode(bool state) { m_flushOnEncode = state; }
+ int validateVarAttr(const std::string& varname, size_t lc) const;
int setAttribute(const std::string &line, size_t lc);
private:
diff --git a/host/commands/emugen/Var.h b/host/commands/emugen/Var.h
index 3b50bccf6..823058d6e 100644
--- a/host/commands/emugen/Var.h
+++ b/host/commands/emugen/Var.h
@@ -39,6 +39,9 @@ public:
m_pointerDir(dir),
m_packExpression(packExpression),
m_unpackExpression(unpackExpression),
+ m_host_packTmpAllocExpression(""),
+ m_host_packExpression(""),
+ m_guest_unpackExpression(""),
m_writeExpression(writeExpression)
{
}
@@ -54,6 +57,9 @@ public:
m_lenExpression = lenExpression;
m_packExpression = packExpression;
m_unpackExpression = unpackExpression;
+ m_host_packTmpAllocExpression = "";
+ m_host_packExpression = "";
+ m_guest_unpackExpression = "";
m_writeExpression = writeExpression;
m_pointerDir = dir;
m_nullAllowed = false;
@@ -68,11 +74,17 @@ public:
const std::string & lenExpression() const { return m_lenExpression; }
const std::string & packExpression() const { return(m_packExpression); }
const std::string & unpackExpression() const { return(m_unpackExpression); }
+ const std::string & hostPackTmpAllocExpression() const { return(m_host_packTmpAllocExpression); }
+ const std::string & hostPackExpression() const { return(m_host_packExpression); }
+ const std::string & guestUnpackExpression() const { return(m_guest_unpackExpression); }
const std::string & writeExpression() const { return(m_writeExpression); }
const std::string & paramCheckExpression() const { return m_paramCheckExpression; }
void setLenExpression(const std::string & lenExpression) { m_lenExpression = lenExpression; }
void setPackExpression(const std::string & packExpression) { m_packExpression = packExpression; }
void setUnpackExpression(const std::string & unpackExpression) { m_unpackExpression = unpackExpression; }
+ void setHostPackTmpAllocExpression(const std::string & expr) { m_host_packTmpAllocExpression = expr; }
+ void setHostPackExpression(const std::string & expr) { m_host_packExpression = expr; }
+ void setGuestUnpackExpression(const std::string & expr) { m_guest_unpackExpression = expr; }
void setWriteExpression(const std::string & writeExpression) { m_writeExpression = writeExpression; }
void setParamCheckExpression(const std::string & paramCheckExpression) { m_paramCheckExpression = paramCheckExpression; }
void setPointerDir(PointerDir dir) { m_pointerDir = dir; }
@@ -96,6 +108,9 @@ private:
bool m_isDMA = false;
std::string m_packExpression; // an expression to pack data into the stream
std::string m_unpackExpression; // an expression to unpack data that has arrived from the stream
+ std::string m_host_packTmpAllocExpression; // an expression to create temporaries for getting into packed form for readbacks
+ std::string m_host_packExpression; // an expression to pack data into the stream but for readbacks
+ std::string m_guest_unpackExpression; // an expression to unpack readbacks on the guest
std::string m_writeExpression; // an expression to write data into the stream
std::string m_paramCheckExpression; //an expression to check parameter value
};
diff --git a/host/commands/emugen/tests/t.001/expected/decoder/foo_dec.cpp b/host/commands/emugen/tests/t.001/expected/decoder/foo_dec.cpp
index 174bdf551..ec16b177f 100644
--- a/host/commands/emugen/tests/t.001/expected/decoder/foo_dec.cpp
+++ b/host/commands/emugen/tests/t.001/expected/decoder/foo_dec.cpp
@@ -109,6 +109,66 @@ size_t foo_decoder_context_t::decode(void *buf, size_t len, IOStream *stream, Ch
SET_LASTCALL("fooTakeConstVoidPtrConstPtr");
break;
}
+ case OP_fooSetComplexStruct: {
+ uint32_t size_obj __attribute__((unused)) = Unpack<uint32_t,uint32_t>(ptr + 8);
+ InputBuffer inptr_obj(ptr + 8 + 4, size_obj);
+ void* inptr_obj_unpacked;
+ FooStruct unpacked; inptr_obj_unpacked = (void*)(&unpacked); fooStructUnpack((unsigned char*)(inptr_obj.get()), size_obj, inptr_obj_unpacked);
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::validOrDie(checksumCalc, ptr, 8 + 4 + size_obj, ptr + 8 + 4 + size_obj, checksumSize,
+ "foo_decoder_context_t::decode, OP_fooSetComplexStruct: GL checksumCalculator failure\n");
+ }
+ DEBUG("foo(%p): fooSetComplexStruct(%p(%u) )\n", stream, (const FooStruct*)(inptr_obj.get()), size_obj);
+ this->fooSetComplexStruct((const FooStruct*)(inptr_obj_unpacked));
+ SET_LASTCALL("fooSetComplexStruct");
+ break;
+ }
+ case OP_fooGetComplexStruct: {
+ uint32_t size_obj __attribute__((unused)) = Unpack<uint32_t,uint32_t>(ptr + 8);
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::validOrDie(checksumCalc, ptr, 8 + 4, ptr + 8 + 4, checksumSize,
+ "foo_decoder_context_t::decode, OP_fooGetComplexStruct: GL checksumCalculator failure\n");
+ }
+ size_t totalTmpSize = size_obj;
+ totalTmpSize += checksumSize;
+ unsigned char *tmpBuf = stream->alloc(totalTmpSize);
+ OutputBuffer outptr_obj(&tmpBuf[0], size_obj);
+ void* forPacking_obj = nullptr;
+ FooStruct tmp; forPacking_obj = (void*)tmp;
+ DEBUG("foo(%p): fooGetComplexStruct(%p(%u) )\n", stream, (FooStruct*)(outptr_obj.get()), size_obj);
+ this->fooGetComplexStruct((FooStruct*)(forPacking_obj));
+ if (size_obj) {
+ fooStructPack((unsigned char*)outptr_obj.get(), (FooStruct*)forPacking_obj); }
+ outptr_obj.flush();
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::writeChecksum(checksumCalc, &tmpBuf[0], totalTmpSize - checksumSize, &tmpBuf[totalTmpSize - checksumSize], checksumSize);
+ }
+ stream->flush();
+ SET_LASTCALL("fooGetComplexStruct");
+ break;
+ }
+ case OP_fooInout: {
+ uint32_t size_count __attribute__((unused)) = Unpack<uint32_t,uint32_t>(ptr + 8);
+ InputBuffer inptr_count(ptr + 8 + 4, size_count);
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::validOrDie(checksumCalc, ptr, 8 + 4 + size_count, ptr + 8 + 4 + size_count, checksumSize,
+ "foo_decoder_context_t::decode, OP_fooInout: GL checksumCalculator failure\n");
+ }
+ size_t totalTmpSize = size_count;
+ totalTmpSize += checksumSize;
+ unsigned char *tmpBuf = stream->alloc(totalTmpSize);
+ OutputBuffer outptr_count(&tmpBuf[0], size_count);
+ memcpy(outptr_count.get(), inptr_count.get(), size_count);
+ DEBUG("foo(%p): fooInout(%p(%u) )\n", stream, (uint32_t*)(outptr_count.get()), size_count);
+ this->fooInout((uint32_t*)(outptr_count.get()));
+ outptr_count.flush();
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::writeChecksum(checksumCalc, &tmpBuf[0], totalTmpSize - checksumSize, &tmpBuf[totalTmpSize - checksumSize], checksumSize);
+ }
+ stream->flush();
+ SET_LASTCALL("fooInout");
+ break;
+ }
default:
return ptr - (unsigned char*)buf;
} //switch
diff --git a/host/commands/emugen/tests/t.001/expected/decoder/foo_opcodes.h b/host/commands/emugen/tests/t.001/expected/decoder/foo_opcodes.h
index 7219caaf1..ee453406f 100644
--- a/host/commands/emugen/tests/t.001/expected/decoder/foo_opcodes.h
+++ b/host/commands/emugen/tests/t.001/expected/decoder/foo_opcodes.h
@@ -8,7 +8,10 @@
#define OP_fooUnsupported 202
#define OP_fooDoEncoderFlush 203
#define OP_fooTakeConstVoidPtrConstPtr 204
-#define OP_last 205
+#define OP_fooSetComplexStruct 205
+#define OP_fooGetComplexStruct 206
+#define OP_fooInout 207
+#define OP_last 208
#endif
diff --git a/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.cpp b/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.cpp
index 22ff47f9d..5371fff2f 100644
--- a/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.cpp
+++ b/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.cpp
@@ -15,6 +15,9 @@ int foo_server_context_t::initDispatchByName(void *(*getProc)(const char *, void
fooUnsupported = (fooUnsupported_server_proc_t) getProc("fooUnsupported", userData);
fooDoEncoderFlush = (fooDoEncoderFlush_server_proc_t) getProc("fooDoEncoderFlush", userData);
fooTakeConstVoidPtrConstPtr = (fooTakeConstVoidPtrConstPtr_server_proc_t) getProc("fooTakeConstVoidPtrConstPtr", userData);
+ fooSetComplexStruct = (fooSetComplexStruct_server_proc_t) getProc("fooSetComplexStruct", userData);
+ fooGetComplexStruct = (fooGetComplexStruct_server_proc_t) getProc("fooGetComplexStruct", userData);
+ fooInout = (fooInout_server_proc_t) getProc("fooInout", userData);
return 0;
}
diff --git a/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.h b/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.h
index 713ff5fe3..4f4491925 100644
--- a/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.h
+++ b/host/commands/emugen/tests/t.001/expected/decoder/foo_server_context.h
@@ -15,6 +15,9 @@ struct foo_server_context_t {
fooUnsupported_server_proc_t fooUnsupported;
fooDoEncoderFlush_server_proc_t fooDoEncoderFlush;
fooTakeConstVoidPtrConstPtr_server_proc_t fooTakeConstVoidPtrConstPtr;
+ fooSetComplexStruct_server_proc_t fooSetComplexStruct;
+ fooGetComplexStruct_server_proc_t fooGetComplexStruct;
+ fooInout_server_proc_t fooInout;
virtual ~foo_server_context_t() {}
int initDispatchByName( void *(*getProc)(const char *name, void *userData), void *userData);
};
diff --git a/host/commands/emugen/tests/t.001/expected/decoder/foo_server_proc.h b/host/commands/emugen/tests/t.001/expected/decoder/foo_server_proc.h
index da104a13b..593e4c411 100644
--- a/host/commands/emugen/tests/t.001/expected/decoder/foo_server_proc.h
+++ b/host/commands/emugen/tests/t.001/expected/decoder/foo_server_proc.h
@@ -14,6 +14,9 @@ typedef FooBoolean (foo_APIENTRY *fooIsBuffer_server_proc_t) (void*);
typedef void (foo_APIENTRY *fooUnsupported_server_proc_t) (void*);
typedef void (foo_APIENTRY *fooDoEncoderFlush_server_proc_t) (FooInt);
typedef void (foo_APIENTRY *fooTakeConstVoidPtrConstPtr_server_proc_t) (const void* const*);
+typedef void (foo_APIENTRY *fooSetComplexStruct_server_proc_t) (const FooStruct*);
+typedef void (foo_APIENTRY *fooGetComplexStruct_server_proc_t) (FooStruct*);
+typedef void (foo_APIENTRY *fooInout_server_proc_t) (uint32_t*);
#endif
diff --git a/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.cpp b/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.cpp
index f09e8811c..d28b5a054 100644
--- a/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.cpp
+++ b/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.cpp
@@ -15,6 +15,9 @@ int foo_client_context_t::initDispatchByName(void *(*getProc)(const char *, void
fooUnsupported = (fooUnsupported_client_proc_t) getProc("fooUnsupported", userData);
fooDoEncoderFlush = (fooDoEncoderFlush_client_proc_t) getProc("fooDoEncoderFlush", userData);
fooTakeConstVoidPtrConstPtr = (fooTakeConstVoidPtrConstPtr_client_proc_t) getProc("fooTakeConstVoidPtrConstPtr", userData);
+ fooSetComplexStruct = (fooSetComplexStruct_client_proc_t) getProc("fooSetComplexStruct", userData);
+ fooGetComplexStruct = (fooGetComplexStruct_client_proc_t) getProc("fooGetComplexStruct", userData);
+ fooInout = (fooInout_client_proc_t) getProc("fooInout", userData);
return 0;
}
diff --git a/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.h b/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.h
index ce60329c5..d1c1675c0 100644
--- a/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.h
+++ b/host/commands/emugen/tests/t.001/expected/encoder/foo_client_context.h
@@ -15,6 +15,9 @@ struct foo_client_context_t {
fooUnsupported_client_proc_t fooUnsupported;
fooDoEncoderFlush_client_proc_t fooDoEncoderFlush;
fooTakeConstVoidPtrConstPtr_client_proc_t fooTakeConstVoidPtrConstPtr;
+ fooSetComplexStruct_client_proc_t fooSetComplexStruct;
+ fooGetComplexStruct_client_proc_t fooGetComplexStruct;
+ fooInout_client_proc_t fooInout;
virtual ~foo_client_context_t() {}
typedef foo_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/host/commands/emugen/tests/t.001/expected/encoder/foo_client_proc.h b/host/commands/emugen/tests/t.001/expected/encoder/foo_client_proc.h
index 6fc27f060..d9bbcb666 100644
--- a/host/commands/emugen/tests/t.001/expected/encoder/foo_client_proc.h
+++ b/host/commands/emugen/tests/t.001/expected/encoder/foo_client_proc.h
@@ -14,6 +14,9 @@ typedef FooBoolean (foo_APIENTRY *fooIsBuffer_client_proc_t) (void * ctx, void*)
typedef void (foo_APIENTRY *fooUnsupported_client_proc_t) (void * ctx, void*);
typedef void (foo_APIENTRY *fooDoEncoderFlush_client_proc_t) (void * ctx, FooInt);
typedef void (foo_APIENTRY *fooTakeConstVoidPtrConstPtr_client_proc_t) (void * ctx, const void* const*);
+typedef void (foo_APIENTRY *fooSetComplexStruct_client_proc_t) (void * ctx, const FooStruct*);
+typedef void (foo_APIENTRY *fooGetComplexStruct_client_proc_t) (void * ctx, FooStruct*);
+typedef void (foo_APIENTRY *fooInout_client_proc_t) (void * ctx, uint32_t*);
#endif
diff --git a/host/commands/emugen/tests/t.001/expected/encoder/foo_enc.cpp b/host/commands/emugen/tests/t.001/expected/encoder/foo_enc.cpp
index c922783e4..13a4dd56b 100644
--- a/host/commands/emugen/tests/t.001/expected/encoder/foo_enc.cpp
+++ b/host/commands/emugen/tests/t.001/expected/encoder/foo_enc.cpp
@@ -8,6 +8,8 @@
#include "foo_enc.h"
+#include <vector>
+
#include <stdio.h>
namespace {
@@ -138,6 +140,110 @@ void fooTakeConstVoidPtrConstPtr_enc(void *self , const void* const* param)
}
+void fooSetComplexStruct_enc(void *self , const FooStruct* obj)
+{
+
+ foo_encoder_context_t *ctx = (foo_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ const unsigned int __size_obj = fooStructEncodingSize(obj);
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8 + __size_obj + 1*4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_fooSetComplexStruct;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+ *(unsigned int *)(ptr) = __size_obj; ptr += 4;
+ fooStructPack(ptr, obj);ptr += __size_obj;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+}
+
+void fooGetComplexStruct_enc(void *self , FooStruct* obj)
+{
+
+ foo_encoder_context_t *ctx = (foo_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ const unsigned int __size_obj = fooStructEncodingSize(obj);
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8 + 0 + 1*4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_fooGetComplexStruct;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+ *(unsigned int *)(ptr) = __size_obj; ptr += 4;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+ std::vector<unsigned char> forUnpacking_obj(__size_obj); stream->readback(&forUnpacking_obj[0], __size_obj); fooStructUnpack(&forUnpacking_obj[0], obj);
+ if (useChecksum) checksumCalculator->addBuffer(obj, __size_obj);
+ if (useChecksum) {
+ unsigned char *checksumBufPtr = NULL;
+ unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+ if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+ stream->readback(checksumBufPtr, checksumSize);
+ if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+ ALOGE("fooGetComplexStruct: GL communication error, please report this issue to b.android.com.\n");
+ abort();
+ }
+ }
+}
+
+void fooInout_enc(void *self , uint32_t* count)
+{
+
+ foo_encoder_context_t *ctx = (foo_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ const unsigned int __size_count = sizeof(uint32_t);
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8 + __size_count + 1*4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_fooInout;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+ *(unsigned int *)(ptr) = __size_count; ptr += 4;
+ memcpy(ptr, count, __size_count);ptr += __size_count;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+ stream->readback(count, __size_count);
+ if (useChecksum) checksumCalculator->addBuffer(count, __size_count);
+ if (useChecksum) {
+ unsigned char *checksumBufPtr = NULL;
+ unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+ if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+ stream->readback(checksumBufPtr, checksumSize);
+ if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+ ALOGE("fooInout: GL communication error, please report this issue to b.android.com.\n");
+ abort();
+ }
+ }
+}
+
} // namespace
foo_encoder_context_t::foo_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -150,5 +256,8 @@ foo_encoder_context_t::foo_encoder_context_t(IOStream *stream, ChecksumCalculato
this->fooUnsupported = (fooUnsupported_client_proc_t) &enc_unsupported;
this->fooDoEncoderFlush = &fooDoEncoderFlush_enc;
this->fooTakeConstVoidPtrConstPtr = &fooTakeConstVoidPtrConstPtr_enc;
+ this->fooSetComplexStruct = &fooSetComplexStruct_enc;
+ this->fooGetComplexStruct = &fooGetComplexStruct_enc;
+ this->fooInout = &fooInout_enc;
}
diff --git a/host/commands/emugen/tests/t.001/expected/encoder/foo_entry.cpp b/host/commands/emugen/tests/t.001/expected/encoder/foo_entry.cpp
index 05bf3bb6e..92e8ef43a 100644
--- a/host/commands/emugen/tests/t.001/expected/encoder/foo_entry.cpp
+++ b/host/commands/emugen/tests/t.001/expected/encoder/foo_entry.cpp
@@ -10,6 +10,9 @@ extern "C" {
void fooUnsupported(void* params);
void fooDoEncoderFlush(FooInt param);
void fooTakeConstVoidPtrConstPtr(const void* const* param);
+ void fooSetComplexStruct(const FooStruct* obj);
+ void fooGetComplexStruct(FooStruct* obj);
+ void fooInout(uint32_t* count);
};
#ifndef GET_CONTEXT
@@ -49,3 +52,21 @@ void fooTakeConstVoidPtrConstPtr(const void* const* param)
ctx->fooTakeConstVoidPtrConstPtr(ctx, param);
}
+void fooSetComplexStruct(const FooStruct* obj)
+{
+ GET_CONTEXT;
+ ctx->fooSetComplexStruct(ctx, obj);
+}
+
+void fooGetComplexStruct(FooStruct* obj)
+{
+ GET_CONTEXT;
+ ctx->fooGetComplexStruct(ctx, obj);
+}
+
+void fooInout(uint32_t* count)
+{
+ GET_CONTEXT;
+ ctx->fooInout(ctx, count);
+}
+
diff --git a/host/commands/emugen/tests/t.001/expected/encoder/foo_ftable.h b/host/commands/emugen/tests/t.001/expected/encoder/foo_ftable.h
index e397e50e2..0b759b52c 100644
--- a/host/commands/emugen/tests/t.001/expected/encoder/foo_ftable.h
+++ b/host/commands/emugen/tests/t.001/expected/encoder/foo_ftable.h
@@ -13,6 +13,9 @@ static const struct _foo_funcs_by_name {
{"fooUnsupported", (void*)fooUnsupported},
{"fooDoEncoderFlush", (void*)fooDoEncoderFlush},
{"fooTakeConstVoidPtrConstPtr", (void*)fooTakeConstVoidPtrConstPtr},
+ {"fooSetComplexStruct", (void*)fooSetComplexStruct},
+ {"fooGetComplexStruct", (void*)fooGetComplexStruct},
+ {"fooInout", (void*)fooInout},
};
static const int foo_num_funcs = sizeof(foo_funcs_by_name) / sizeof(struct _foo_funcs_by_name);
diff --git a/host/commands/emugen/tests/t.001/expected/encoder/foo_opcodes.h b/host/commands/emugen/tests/t.001/expected/encoder/foo_opcodes.h
index 7219caaf1..ee453406f 100644
--- a/host/commands/emugen/tests/t.001/expected/encoder/foo_opcodes.h
+++ b/host/commands/emugen/tests/t.001/expected/encoder/foo_opcodes.h
@@ -8,7 +8,10 @@
#define OP_fooUnsupported 202
#define OP_fooDoEncoderFlush 203
#define OP_fooTakeConstVoidPtrConstPtr 204
-#define OP_last 205
+#define OP_fooSetComplexStruct 205
+#define OP_fooGetComplexStruct 206
+#define OP_fooInout 207
+#define OP_last 208
#endif
diff --git a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.cpp b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.cpp
index 6e132b104..e8781cccb 100644
--- a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.cpp
+++ b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.cpp
@@ -15,6 +15,9 @@ int foo_wrapper_context_t::initDispatchByName(void *(*getProc)(const char *, voi
fooUnsupported = (fooUnsupported_wrapper_proc_t) getProc("fooUnsupported", userData);
fooDoEncoderFlush = (fooDoEncoderFlush_wrapper_proc_t) getProc("fooDoEncoderFlush", userData);
fooTakeConstVoidPtrConstPtr = (fooTakeConstVoidPtrConstPtr_wrapper_proc_t) getProc("fooTakeConstVoidPtrConstPtr", userData);
+ fooSetComplexStruct = (fooSetComplexStruct_wrapper_proc_t) getProc("fooSetComplexStruct", userData);
+ fooGetComplexStruct = (fooGetComplexStruct_wrapper_proc_t) getProc("fooGetComplexStruct", userData);
+ fooInout = (fooInout_wrapper_proc_t) getProc("fooInout", userData);
return 0;
}
diff --git a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.h b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.h
index 52db4b6fb..c9853d298 100644
--- a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.h
+++ b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_context.h
@@ -15,6 +15,9 @@ struct foo_wrapper_context_t {
fooUnsupported_wrapper_proc_t fooUnsupported;
fooDoEncoderFlush_wrapper_proc_t fooDoEncoderFlush;
fooTakeConstVoidPtrConstPtr_wrapper_proc_t fooTakeConstVoidPtrConstPtr;
+ fooSetComplexStruct_wrapper_proc_t fooSetComplexStruct;
+ fooGetComplexStruct_wrapper_proc_t fooGetComplexStruct;
+ fooInout_wrapper_proc_t fooInout;
virtual ~foo_wrapper_context_t() {}
typedef foo_wrapper_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_entry.cpp b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_entry.cpp
index 284c1c855..733c8248d 100644
--- a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_entry.cpp
+++ b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_entry.cpp
@@ -10,6 +10,9 @@ extern "C" {
void fooUnsupported(void* params);
void fooDoEncoderFlush(FooInt param);
void fooTakeConstVoidPtrConstPtr(const void* const* param);
+ void fooSetComplexStruct(const FooStruct* obj);
+ void fooGetComplexStruct(FooStruct* obj);
+ void fooInout(uint32_t* count);
};
#ifndef GET_CONTEXT
@@ -48,3 +51,21 @@ void fooTakeConstVoidPtrConstPtr(const void* const* param)
ctx->fooTakeConstVoidPtrConstPtr( param);
}
+void fooSetComplexStruct(const FooStruct* obj)
+{
+ GET_CONTEXT;
+ ctx->fooSetComplexStruct( obj);
+}
+
+void fooGetComplexStruct(FooStruct* obj)
+{
+ GET_CONTEXT;
+ ctx->fooGetComplexStruct( obj);
+}
+
+void fooInout(uint32_t* count)
+{
+ GET_CONTEXT;
+ ctx->fooInout( count);
+}
+
diff --git a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_proc.h b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_proc.h
index 294b9587d..66ced3138 100644
--- a/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_proc.h
+++ b/host/commands/emugen/tests/t.001/expected/wrapper/foo_wrapper_proc.h
@@ -14,6 +14,9 @@ typedef FooBoolean (foo_APIENTRY *fooIsBuffer_wrapper_proc_t) (void*);
typedef void (foo_APIENTRY *fooUnsupported_wrapper_proc_t) (void*);
typedef void (foo_APIENTRY *fooDoEncoderFlush_wrapper_proc_t) (FooInt);
typedef void (foo_APIENTRY *fooTakeConstVoidPtrConstPtr_wrapper_proc_t) (const void* const*);
+typedef void (foo_APIENTRY *fooSetComplexStruct_wrapper_proc_t) (const FooStruct*);
+typedef void (foo_APIENTRY *fooGetComplexStruct_wrapper_proc_t) (FooStruct*);
+typedef void (foo_APIENTRY *fooInout_wrapper_proc_t) (uint32_t*);
#endif
diff --git a/host/commands/emugen/tests/t.001/input/foo.attrib b/host/commands/emugen/tests/t.001/input/foo.attrib
index 80644d8bb..9b66c5796 100644
--- a/host/commands/emugen/tests/t.001/input/foo.attrib
+++ b/host/commands/emugen/tests/t.001/input/foo.attrib
@@ -13,3 +13,20 @@ fooUnsupported
fooDoEncoderFlush
flag flushOnEncode
+
+fooSetComplexStruct
+ dir obj in
+ len obj fooStructEncodingSize(obj)
+ custom_pack obj fooStructPack(ptr, obj)
+ custom_unpack obj FooStruct unpacked; inptr_obj_unpacked = (void*)(&unpacked); fooStructUnpack((unsigned char*)(inptr_obj.get()), size_obj, inptr_obj_unpacked)
+
+fooGetComplexStruct
+ dir obj out
+ len obj fooStructEncodingSize(obj)
+ custom_host_pack_tmp_alloc obj FooStruct tmp; forPacking_obj = (void*)tmp
+ custom_host_pack obj fooStructPack((unsigned char*)outptr_obj.get(), (FooStruct*)forPacking_obj)
+ custom_guest_unpack obj std::vector<unsigned char> forUnpacking_obj(__size_obj); stream->readback(&forUnpacking_obj[0], __size_obj); fooStructUnpack(&forUnpacking_obj[0], obj)
+
+fooInout
+ dir count inout
+ len count sizeof(uint32_t)
diff --git a/host/commands/emugen/tests/t.001/input/foo.in b/host/commands/emugen/tests/t.001/input/foo.in
index 4e98f88b6..b12ad99f9 100644
--- a/host/commands/emugen/tests/t.001/input/foo.in
+++ b/host/commands/emugen/tests/t.001/input/foo.in
@@ -3,3 +3,6 @@ FOO_ENTRY(FooBoolean, fooIsBuffer, void* stuff)
FOO_ENTRY(void, fooUnsupported, void* params)
FOO_ENTRY(void, fooDoEncoderFlush, FooInt param)
FOO_ENTRY(void, fooTakeConstVoidPtrConstPtr, const void* const* param)
+FOO_ENTRY(void, fooSetComplexStruct, const FooStruct* obj)
+FOO_ENTRY(void, fooGetComplexStruct, FooStruct* obj)
+FOO_ENTRY(void, fooInout, uint32_t* count)
diff --git a/host/commands/emugen/tests/t.001/input/foo.types b/host/commands/emugen/tests/t.001/input/foo.types
index 05d72fbe2..45e17c913 100644
--- a/host/commands/emugen/tests/t.001/input/foo.types
+++ b/host/commands/emugen/tests/t.001/input/foo.types
@@ -8,3 +8,5 @@ FooChar 8 %d
FooChar* 32 0x%08x
void* 32 0x%08x
void*const* 32 0x%08x
+FooStruct* 32 0x%08x
+uint32_t* 32 0x%08x