Add code for generating fifo command packing.

Change-Id: I2d2ef095344b200b10457de96ae1d85821edc91e
diff --git a/Android.mk b/Android.mk
index c336c0d..ef00b30 100644
--- a/Android.mk
+++ b/Android.mk
@@ -91,6 +91,7 @@
 	rsDevice.cpp \
 	rsElement.cpp \
 	rsFBOCache.cpp \
+	rsFifoSocket.cpp \
 	rsFileA3D.cpp \
 	rsFont.cpp \
 	rsLocklessFifo.cpp \
diff --git a/rs.spec b/rs.spec
index 5370e25..00e3a0a 100644
--- a/rs.spec
+++ b/rs.spec
@@ -176,7 +176,6 @@
 ElementCreate2 {
 	param const RsElement * elements
 	param const char ** names
-	param const size_t * nameLengths
 	param const uint32_t * arraySize
 	ret RsElement
 	}
diff --git a/rsElement.cpp b/rsElement.cpp
index d5d5ca5..2b58e9e 100644
--- a/rsElement.cpp
+++ b/rsElement.cpp
@@ -347,13 +347,15 @@
     return (RsElement)e;
 }
 
+
 RsElement rsi_ElementCreate2(Context *rsc,
                              const RsElement * ein,
                              size_t ein_length,
+
                              const char ** names,
-                             size_t names_length,
-                             const size_t * nameLengths,
                              size_t nameLengths_length,
+                             const size_t * nameLengths,
+
                              const uint32_t * arraySizes,
                              size_t arraySizes_length) {
     const Element *e = Element::create(rsc, ein_length, (const Element **)ein, names, nameLengths, arraySizes);
diff --git a/rsFifo.cpp b/rsFifo.cpp
new file mode 100644
index 0000000..3d5d8c4
--- /dev/null
+++ b/rsFifo.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsFifoSocket.h"
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+Fifo::Fifo() {
+
+}
+
+Fifo::~Fifo() {
+
+}
+
diff --git a/rsFifo.h b/rsFifo.h
new file mode 100644
index 0000000..f924b95
--- /dev/null
+++ b/rsFifo.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_FIFO_H
+#define ANDROID_RS_FIFO_H
+
+
+#include "rsUtils.h"
+
+namespace android {
+namespace renderscript {
+
+
+// A simple FIFO to be used as a producer / consumer between two
+// threads.  One is writer and one is reader.  The common cases
+// will not require locking.  It is not threadsafe for multiple
+// readers or writers by design.
+
+class Fifo {
+protected:
+    Fifo();
+    virtual ~Fifo();
+
+public:
+    void virtual writeAsync(const void *data, size_t bytes) = 0;
+    void virtual writeWaitReturn(void *ret, size_t retSize) = 0;
+    size_t virtual read(void *data, size_t bytes) = 0;
+    void virtual readReturn(const void *data, size_t bytes) = 0;
+
+    void virtual flush() = 0;
+
+};
+
+}
+}
+#endif
diff --git a/rsFifoSocket.cpp b/rsFifoSocket.cpp
new file mode 100644
index 0000000..1ce57b9
--- /dev/null
+++ b/rsFifoSocket.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsFifoSocket.h"
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+FifoSocket::FifoSocket() {
+    sequence = 1;
+}
+
+FifoSocket::~FifoSocket() {
+
+}
+
+bool FifoSocket::init() {
+    int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
+    return false;
+}
+
+void FifoSocket::shutdown() {
+}
+
+void FifoSocket::writeAsync(const void *data, size_t bytes) {
+    size_t ret = ::write(sv[0], data, bytes);
+    rsAssert(ret == bytes);
+}
+
+void FifoSocket::writeWaitReturn(void *retData, size_t retBytes) {
+    size_t ret = ::read(sv[1], retData, retBytes);
+    rsAssert(ret == retBytes);
+}
+
+size_t FifoSocket::read(void *data, size_t bytes) {
+    size_t ret = ::read(sv[0], data, bytes);
+    rsAssert(ret == bytes);
+    return ret;
+}
+
+void FifoSocket::readReturn(const void *data, size_t bytes) {
+    size_t ret = ::write(sv[1], data, bytes);
+    rsAssert(ret == bytes);
+}
+
+
+void FifoSocket::flush() {
+}
+
+
diff --git a/rsFifoSocket.h b/rsFifoSocket.h
new file mode 100644
index 0000000..7df2b67
--- /dev/null
+++ b/rsFifoSocket.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_FIFO_SOCKET_H
+#define ANDROID_RS_FIFO_SOCKET_H
+
+
+#include "rsFifo.h"
+
+namespace android {
+namespace renderscript {
+
+
+class FifoSocket {
+public:
+    FifoSocket();
+    virtual ~FifoSocket();
+
+    bool init();
+    void shutdown();
+
+
+
+    void virtual writeAsync(const void *data, size_t bytes);
+    void virtual writeWaitReturn(void *ret, size_t retSize);
+    size_t virtual read(void *data, size_t bytes);
+    void virtual readReturn(const void *data, size_t bytes);
+
+    void virtual flush();
+
+protected:
+    int sv[2];
+    uint32_t sequence;
+
+
+};
+
+}
+}
+
+#endif
diff --git a/rsg_generator.c b/rsg_generator.c
index 1d8b9b5..d550712 100644
--- a/rsg_generator.c
+++ b/rsg_generator.c
@@ -189,6 +189,7 @@
     fprintf(f, "#include \"rsThreadIO.h\"\n");
     //fprintf(f, "#include \"rsgApiStructs.h\"\n");
     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
+    fprintf(f, "#include \"rsFifo.h\"\n");
     fprintf(f, "\n");
     fprintf(f, "using namespace android;\n");
     fprintf(f, "using namespace android::renderscript;\n");
@@ -290,11 +291,103 @@
 
             if (api->ret.typeName[0]) {
                 fprintf(f, "    return reinterpret_cast<");
-                printVarTypeAndName(f, &api->ret);
+                printVarType(f, &api->ret);
                 fprintf(f, ">(io->mToCoreRet);\n");
             }
         }
         fprintf(f, "};\n\n");
+
+
+        fprintf(f, "static ");
+        printFuncDecl(f, api, "RF_", 0, 0);
+        fprintf(f, "\n{\n");
+        fprintf(f, "    Fifo *f = NULL;\n");
+        fprintf(f, "    RS_CMD_%s cmd;\n", api->name);
+        fprintf(f, "    const uint32_t cmdSize = sizeof(cmd);\n");
+        fprintf(f, "    const uint32_t cmdID = RS_CMD_ID_%s;\n", api->name);
+        fprintf(f, "    f->writeAsync(&cmdID, sizeof(cmdID));\n");
+
+        if (api->handcodeApi) {
+            fprintf(f, "    rsHCAPI_%s(rsc", api->name);
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                if (ct2 > 0 || !api->nocontext) {
+                    fprintf(f, ", ");
+                }
+                fprintf(f, "%s", vt->name);
+            }
+            fprintf(f, ");\n");
+        } else {
+            fprintf(f, "    intptr_t offset = cmdSize;\n");
+            fprintf(f, "    uint32_t dataSize = 0;\n");
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                if (vt->isConst && vt->ptrLevel) {
+                    switch(vt->ptrLevel) {
+                    case 1:
+                        fprintf(f, "    dataSize += %s_length;\n", vt->name);
+                        break;
+                    case 2:
+                        fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+                        fprintf(f, "        dataSize += %s_length[ct];\n", vt->name);
+                        fprintf(f, "    }\n");
+                        break;
+                    default:
+                        printf("pointer level not handled!!");
+                    }
+                }
+            }
+            fprintf(f, "\n");
+
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                switch(vt->ptrLevel) {
+                case 0:
+                    fprintf(f, "    cmd.%s = %s;\n", vt->name, vt->name);
+                    break;
+                case 1:
+                    fprintf(f, "    cmd.%s = (", vt->name);
+                    printVarType(f, vt);
+                    fprintf(f, ")offset;\n");
+                    fprintf(f, "    offset += %s_length;\n", vt->name);
+                    break;
+                case 2:
+                    fprintf(f, "    cmd.%s = (", vt->name);
+                    printVarType(f, vt);
+                    fprintf(f, ")offset;\n");
+                    fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+                    fprintf(f, "        offset += %s_length[ct];\n", vt->name);
+                    fprintf(f, "    }\n");
+                    break;
+                default:
+                    printf("pointer level not handled!!");
+                }
+            }
+            fprintf(f, "\n");
+
+            fprintf(f, "    f->writeAsync(&cmd, cmdSize);\n");
+            for (ct2=0; ct2 < api->paramCount; ct2++) {
+                const VarType *vt = &api->params[ct2];
+                if (vt->ptrLevel == 1) {
+                    fprintf(f, "    f->writeAsync(%s, %s_length);\n", vt->name, vt->name);
+                }
+                if (vt->ptrLevel == 2) {
+                    fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
+                    fprintf(f, "        f->writeAsync(%s, %s_length[ct]);\n", vt->name, vt->name);
+                    fprintf(f, "        offset += %s_length[ct];\n", vt->name);
+                    fprintf(f, "    }\n");
+                }
+            }
+
+            if (api->ret.typeName[0]) {
+                fprintf(f, "    ");
+                printVarType(f, &api->ret);
+                fprintf(f, " retValue;\n");
+                fprintf(f, "    f->writeWaitReturn(&retValue, sizeof(retValue));\n");
+                fprintf(f, "    return retValue;\n");
+            }
+        }
+        fprintf(f, "}\n\n");
     }
 
     fprintf(f, "\n");
@@ -304,8 +397,14 @@
     }
     fprintf(f, "};\n");
 
-    fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
+    fprintf(f, "\n");
+    fprintf(f, "static RsApiEntrypoints_t s_RemoteTable = {\n");
+    for (ct=0; ct < apiCount; ct++) {
+        fprintf(f, "    RF_%s,\n", apis[ct].name);
+    }
+    fprintf(f, "};\n");
 
+    fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
     for (ct=0; ct < apiCount; ct++) {
         int needFlush = 0;
         const ApiEntry * api = &apis[ct];
@@ -357,8 +456,7 @@
             continue;
         }
 
-        fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes)\n", api->name);
-        fprintf(f, "{\n");
+        fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
 
         //fprintf(f, "    LOGE(\"play command %s\\n\");\n", api->name);
         fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
@@ -377,7 +475,63 @@
         fprintf(f, "};\n\n");
     }
 
-    fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
+    for (ct=0; ct < apiCount; ct++) {
+        const ApiEntry * api = &apis[ct];
+
+        fprintf(f, "void rspr_%s(Context *con, Fifo *f, uint8_t *scratch, size_t scratchSize) {\n", api->name);
+
+        //fprintf(f, "    LOGE(\"play command %s\\n\");\n", api->name);
+        fprintf(f, "    RS_CMD_%s cmd;\n", api->name);
+        fprintf(f, "    f->read(&cmd, sizeof(cmd));\n");
+
+        for (ct2=0; ct2 < api->paramCount; ct2++) {
+            const VarType *vt = &api->params[ct2];
+            if (vt->ptrLevel == 1) {
+                fprintf(f, "    cmd.%s = (", vt->name);
+                printVarType(f, vt);
+                fprintf(f, ")scratch;\n");
+                fprintf(f, "    f->read(scratch, cmd.%s_length);\n", vt->name);
+                fprintf(f, "    scratch += cmd.%s_length;\n", vt->name);
+            }
+            if (vt->ptrLevel == 2) {
+                fprintf(f, "    size_t sum_%s = 0;\n", vt->name);
+                fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
+                fprintf(f, "        ((size_t *)scratch)[ct] = cmd.%s_length[ct];\n", vt->name);
+                fprintf(f, "        sum_%s += cmd.%s_length[ct];\n", vt->name, vt->name);
+                fprintf(f, "    }\n");
+                fprintf(f, "    f->read(scratch, sum_%s);\n", vt->name);
+                fprintf(f, "    scratch += sum_%s;\n", vt->name);
+            }
+        }
+        fprintf(f, "\n");
+
+        if (api->ret.typeName[0]) {
+            fprintf(f, "    ");
+            printVarType(f, &api->ret);
+            fprintf(f, " ret =\n");
+        }
+
+        fprintf(f, "    rsi_%s(", api->name);
+        if (!api->nocontext) {
+            fprintf(f, "con");
+        }
+        for (ct2=0; ct2 < api->paramCount; ct2++) {
+            const VarType *vt = &api->params[ct2];
+            if (ct2 > 0 || !api->nocontext) {
+                fprintf(f, ",\n");
+            }
+            fprintf(f, "           cmd.%s", vt->name);
+        }
+        fprintf(f, ");\n");
+
+        if (api->ret.typeName[0]) {
+            fprintf(f, "    f->readReturn(&ret, sizeof(ret));\n");
+        }
+
+        fprintf(f, "};\n\n");
+    }
+
+    fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
     fprintf(f, "    NULL,\n");
     for (ct=0; ct < apiCount; ct++) {
         if (apis[ct].direct) {
@@ -388,6 +542,13 @@
     }
     fprintf(f, "};\n");
 
+    fprintf(f, "RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i] = {\n", apiCount + 1);
+    fprintf(f, "    NULL,\n");
+    for (ct=0; ct < apiCount; ct++) {
+        fprintf(f, "    %s%s,\n", "rspr_", apis[ct].name);
+    }
+    fprintf(f, "};\n");
+
     fprintf(f, "};\n");
     fprintf(f, "};\n");
 }
@@ -422,14 +583,21 @@
         {
             fprintf(f, "\n");
             fprintf(f, "#include \"rsContext.h\"\n");
+            fprintf(f, "#include \"rsFifo.h\"\n");
             fprintf(f, "\n");
             fprintf(f, "namespace android {\n");
             fprintf(f, "namespace renderscript {\n");
             printStructures(f);
             printFuncDecls(f, "rsi_", 1);
             printPlaybackFuncs(f, "rsp_");
-            fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *, size_t sizeBytes);\n");
-            fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[%i];\n", apiCount + 1);
+            fprintf(f, "\n\ntypedef struct RsPlaybackRemoteHeaderRec {\n");
+            fprintf(f, "    uint32_t command;\n");
+            fprintf(f, "    uint32_t size;\n");
+            fprintf(f, "} RsPlaybackRemoteHeader;\n\n");
+            fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
+            fprintf(f, "typedef void (*RsPlaybackRemoteFunc)(Context *, Fifo *, uint8_t *scratch, size_t scratchSize);\n");
+            fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
+            fprintf(f, "extern RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i];\n", apiCount + 1);
 
             fprintf(f, "}\n");
             fprintf(f, "}\n");
diff --git a/spec.l b/spec.l
index dcd4435..a24bfd3 100644
--- a/spec.l
+++ b/spec.l
@@ -21,15 +21,26 @@
    int typeNextState;
 
    void checkPointerType() {
-       VarType *lastType = currType;
-       if (lastType->ptrLevel) {
+       VarType *baseType = currType;
+       int curPtrLevel = 0;
+       while (curPtrLevel < baseType->ptrLevel) {
            currType = &apis[apiCount].params[apis[apiCount].paramCount];
            currType->type = 4;
+           currType->ptrLevel = curPtrLevel;
+           if (currType->ptrLevel > 0) {
+              currType->isConst = 1;
+           }
            sprintf(currType->typeName, "%s", "size_t");
-           if (lastType->name[0]) {
-               sprintf(currType->name, "%s_length", lastType->name);
+           switch(baseType->ptrLevel - curPtrLevel) {
+           case 1:
+              sprintf(currType->name, "%s_length", baseType->name);
+              break;
+           case 2:
+              sprintf(currType->name, "%s_length_length", baseType->name);
+              break;
            }
            apis[apiCount].paramCount++;
+           curPtrLevel ++;
        }
    }