1 #include "spec.h"
2 #include <stdio.h>
3 #include <string.h>
4 
5 #define LOCAL_FIFO_PREFIX "LF_"
6 #define RS_PLAYBACK_PREFIX "rsp_"
7 #define RS_INTERNAL_PREFIX "rsi_"
8 
9 #define RSG_API_CPP_DOC                                                     \
10 "/*\n"                                                                      \
11 " * rsgApi.cpp\n"                                                           \
12 " * This file implements the functions responsible for sending messages\n"  \
13 " * to the RS driver layer. The messages are sent through a FIFO that is\n" \
14 " * shared between the process's caller threads and driver thread.\n"       \
15 " */\n\n"
16 
17 #define RSG_API_REPLAY_CPP_DOC                                              \
18 "/*\n"                                                                      \
19 " * rsgApiReplay.cpp\n"                                                     \
20 " * This file implements the functions responsible for reading messages\n"  \
21 " * sent to the RS driver layer.\n"                                         \
22 " */\n\n"
23 
printFileHeader(FILE * f)24 void printFileHeader(FILE *f) {
25     fprintf(f, "/*\n");
26     fprintf(f, " * Copyright (C) 2015 The Android Open Source Project\n");
27     fprintf(f, " *\n");
28     fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
29     fprintf(f, " * you may not use this file except in compliance with the License.\n");
30     fprintf(f, " * You may obtain a copy of the License at\n");
31     fprintf(f, " *\n");
32     fprintf(f, " *      http://www.apache.org/licenses/LICENSE-2.0\n");
33     fprintf(f, " *\n");
34     fprintf(f, " * Unless required by applicable law or agreed to in writing, software\n");
35     fprintf(f, " * distributed under the License is distributed on an \"AS IS\" BASIS,\n");
36     fprintf(f, " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
37     fprintf(f, " * See the License for the specific language governing permissions and\n");
38     fprintf(f, " * limitations under the License.\n");
39     fprintf(f, " */\n\n");
40 }
41 
printVarType(FILE * f,const VarType * vt)42 void printVarType(FILE *f, const VarType *vt) {
43     int ct;
44     if (vt->isConst) {
45         fprintf(f, "const ");
46     }
47 
48     switch (vt->type) {
49     case 0:
50         fprintf(f, "void");
51         break;
52     case 1:
53         fprintf(f, "int%i_t", vt->bits);
54         break;
55     case 2:
56         fprintf(f, "uint%i_t", vt->bits);
57         break;
58     case 3:
59         if (vt->bits == 32)
60             fprintf(f, "float");
61         else
62             fprintf(f, "double");
63         break;
64     case 4:
65         fprintf(f, "%s", vt->typeName);
66         break;
67     }
68 
69     if (vt->ptrLevel) {
70         fprintf(f, " ");
71         for (ct=0; ct < vt->ptrLevel; ct++) {
72             fprintf(f, "*");
73         }
74     }
75 }
76 
printVarTypeAndName(FILE * f,const VarType * vt)77 void printVarTypeAndName(FILE *f, const VarType *vt) {
78     printVarType(f, vt);
79 
80     if (vt->name[0]) {
81         fprintf(f, " %s", vt->name);
82     }
83 }
84 
printArgList(FILE * f,const ApiEntry * api,int assumePrevious)85 void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) {
86     int ct;
87     for (ct=0; ct < api->paramCount; ct++) {
88         if (ct || assumePrevious) {
89             fprintf(f, ", ");
90         }
91         printVarTypeAndName(f, &api->params[ct]);
92     }
93 }
94 
printStructures(FILE * f)95 void printStructures(FILE *f) {
96     int ct;
97     int ct2;
98 
99     for (ct=0; ct < apiCount; ct++) {
100         fprintf(f, "typedef struct RS_CMD_%s_rec RS_CMD_%s;\n", apis[ct].name, apis[ct].name);
101     }
102     fprintf(f, "\n");
103 
104     for (ct=0; ct < apiCount; ct++) {
105         const ApiEntry * api = &apis[ct];
106         fprintf(f, "#define RS_CMD_ID_%s %i\n", api->name, ct+1);
107         fprintf(f, "struct __attribute__((packed)) RS_CMD_%s_rec {\n", api->name);
108         //fprintf(f, "    RsCommandHeader _hdr;\n");
109 
110         for (ct2=0; ct2 < api->paramCount; ct2++) {
111             fprintf(f, "    ");
112             printVarTypeAndName(f, &api->params[ct2]);
113             fprintf(f, ";\n");
114         }
115         fprintf(f, "};\n\n");
116     }
117 }
118 
printFuncDecl(FILE * f,const ApiEntry * api,const char * prefix,int addContext,int isFnPtr)119 void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext, int isFnPtr) {
120     printVarTypeAndName(f, &api->ret);
121     if (isFnPtr) {
122         char t[1024];
123         strncpy(t, api->name, sizeof(t)-1);
124         t[sizeof(t)-1] = '\0';
125         if (strlen(prefix) == 0) {
126             if (t[0] > 'A' && t[0] < 'Z') {
127                 t[0] -= 'A' - 'a';
128             }
129         }
130         fprintf(f, " (* %s%s) (", prefix, api->name);
131     } else {
132         fprintf(f, " %s%s (", prefix, api->name);
133     }
134     if (!api->nocontext) {
135         if (addContext) {
136             fprintf(f, "Context *");
137         } else {
138             fprintf(f, "RsContext rsc");
139         }
140     }
141     printArgList(f, api, !api->nocontext);
142     fprintf(f, ")");
143 }
144 
printFuncDecls(FILE * f,const char * prefix,int addContext,int externC)145 void printFuncDecls(FILE *f, const char *prefix, int addContext, int externC) {
146     int ct;
147     for (ct=0; ct < apiCount; ct++) {
148         if (externC) {
149             fprintf(f, "extern \"C\" ");
150         }
151         printFuncDecl(f, &apis[ct], prefix, addContext, 0);
152         fprintf(f,
153                 " __DEPRECATED_IN(31, \"RenderScript is deprecated. See "
154                 "https://developer.android.com/guide/topics/renderscript/"
155                 "migrate\");\n");
156     }
157     fprintf(f, "\n\n");
158 }
159 
printPlaybackFuncs(FILE * f,const char * prefix)160 void printPlaybackFuncs(FILE *f, const char *prefix) {
161     int ct;
162     for (ct=0; ct < apiCount; ct++) {
163         if (apis[ct].direct) {
164             continue;
165         }
166 
167         fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
168     }
169 }
170 
hasInlineDataPointers(const ApiEntry * api)171 static int hasInlineDataPointers(const ApiEntry * api) {
172     int ret = 0;
173     int ct;
174     if (api->sync || api->ret.typeName[0]) {
175         return 0;
176     }
177     for (ct=0; ct < api->paramCount; ct++) {
178         const VarType *vt = &api->params[ct];
179 
180         if (!vt->isConst && vt->ptrLevel) {
181             // Non-const pointers cannot be inlined.
182             return 0;
183         }
184         if (vt->ptrLevel > 1) {
185             // not handled yet.
186             return 0;
187         }
188 
189         if (vt->isConst && vt->ptrLevel) {
190             // Non-const pointers cannot be inlined.
191             ret = 1;
192         }
193     }
194     return ret;
195 }
196 
printApiCpp(FILE * f)197 void printApiCpp(FILE *f) {
198     int ct;
199     int ct2;
200 
201     fprintf(f, RSG_API_CPP_DOC);
202 
203     fprintf(f, "#include \"rsDevice.h\"\n");
204     fprintf(f, "#include \"rsContext.h\"\n");
205     fprintf(f, "#include \"rsThreadIO.h\"\n");
206     fprintf(f, "#include \"rsgApiStructs.h\"\n");
207     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
208     fprintf(f, "#include \"rsFifo.h\"\n");
209     fprintf(f, "\n");
210     fprintf(f, "using namespace android;  // NOLINT\n");
211     fprintf(f, "using namespace android::renderscript;  // NOLINT\n");
212     fprintf(f, "\n");
213 
214     // Generate RS funcs that send messages on the local FIFO.
215     for (ct=0; ct < apiCount; ct++) {
216         int needFlush = 0;
217         const ApiEntry * api = &apis[ct];
218 
219         fprintf(f, "static ");
220         printFuncDecl(f, api, LOCAL_FIFO_PREFIX, 0, 0);
221         fprintf(f, "\n{\n");
222         if (api->direct) {
223             fprintf(f, "    ");
224             if (api->ret.typeName[0]) {
225                 fprintf(f, "return ");
226             }
227             fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
228             if (!api->nocontext) {
229                 fprintf(f, "(Context *)rsc");
230             }
231             for (ct2=0; ct2 < api->paramCount; ct2++) {
232                 const VarType *vt = &api->params[ct2];
233                 if (ct2 > 0 || !api->nocontext) {
234                     fprintf(f, ", ");
235                 }
236                 fprintf(f, "%s", vt->name);
237             }
238             fprintf(f, ");\n");
239         } else if (api->handcodeApi) {
240             // handle handcode path
241             fprintf(f, "    " LOCAL_FIFO_PREFIX "%s_handcode(", api->name);
242             if (!api->nocontext) {
243                 fprintf(f, "(Context *)rsc");
244             }
245             for (ct2=0; ct2 < api->paramCount; ct2++) {
246                 const VarType *vt = &api->params[ct2];
247                 if (ct2 > 0 || !api->nocontext) {
248                     fprintf(f, ", ");
249                 }
250                 fprintf(f, "%s", vt->name);
251             }
252             fprintf(f, ");\n");
253 
254         } else {
255             // handle synchronous path
256             fprintf(f, "    if (((Context *)rsc)->isSynchronous()) {\n");
257             fprintf(f, "        ");
258             if (api->ret.typeName[0]) {
259                 fprintf(f, "return ");
260             }
261             fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
262             if (!api->nocontext) {
263                 fprintf(f, "(Context *)rsc");
264             }
265             for (ct2=0; ct2 < api->paramCount; ct2++) {
266                 const VarType *vt = &api->params[ct2];
267                 if (ct2 > 0 || !api->nocontext) {
268                     fprintf(f, ", ");
269                 }
270                 fprintf(f, "%s", vt->name);
271             }
272             fprintf(f, ");\n");
273             if (!api->ret.typeName[0]) {
274                 fprintf(f, "    return;");
275             }
276             fprintf(f, "    }\n\n");
277 
278             fprintf(f, "    ThreadIO *io = &((Context *)rsc)->mIO;\n");
279             fprintf(f, "    const size_t size = sizeof(RS_CMD_%s);\n", api->name);
280             if (hasInlineDataPointers(api)) {
281                 fprintf(f, "    size_t dataSize = 0;\n");
282                 for (ct2=0; ct2 < api->paramCount; ct2++) {
283                     const VarType *vt = &api->params[ct2];
284                     if (vt->isConst && vt->ptrLevel) {
285                         fprintf(f, "    dataSize += %s_length;\n", vt->name);
286                     }
287                 }
288             }
289 
290             //fprintf(f, "    ALOGE(\"add command %s\\n\");\n", api->name);
291             if (hasInlineDataPointers(api)) {
292                 fprintf(f, "    RS_CMD_%s *cmd = NULL;\n", api->name);
293                 fprintf(f, "    if (dataSize < io->getMaxInlineSize()) {;\n");
294                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, dataSize + size));\n", api->name, api->name);
295                 fprintf(f, "    } else {\n");
296                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name);
297                 fprintf(f, "    }\n");
298                 fprintf(f, "    uint8_t *payload = (uint8_t *)&cmd[1];\n");
299             } else {
300                 fprintf(f, "    RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name, api->name);
301             }
302 
303             for (ct2=0; ct2 < api->paramCount; ct2++) {
304                 const VarType *vt = &api->params[ct2];
305                 needFlush += vt->ptrLevel;
306                 if (vt->ptrLevel && hasInlineDataPointers(api)) {
307                     fprintf(f, "    if (%s_length == 0) {\n", vt->name);
308                     fprintf(f, "        cmd->%s = NULL;\n", vt->name);
309                     fprintf(f, "    } else if (dataSize < io->getMaxInlineSize()) {\n");
310                     fprintf(f, "        memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
311                     fprintf(f, "        cmd->%s = (", vt->name);
312                     printVarType(f, vt);
313                     fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n");
314                     fprintf(f, "        payload += %s_length;\n", vt->name);
315                     fprintf(f, "    } else {\n");
316                     fprintf(f, "        cmd->%s = %s;\n", vt->name, vt->name);
317                     fprintf(f, "    }\n");
318 
319                 } else {
320                     fprintf(f, "    cmd->%s = %s;\n", vt->name, vt->name);
321                 }
322             }
323             if (api->ret.typeName[0] || api->sync) {
324                 needFlush = 1;
325             }
326 
327             fprintf(f, "    io->coreCommit();\n");
328             if (hasInlineDataPointers(api)) {
329                 fprintf(f, "    if (dataSize >= io->getMaxInlineSize()) {\n");
330                 fprintf(f, "        io->coreGetReturn(NULL, 0);\n");
331                 fprintf(f, "    }\n");
332             } else if (api->ret.typeName[0]) {
333                 fprintf(f, "\n    ");
334                 printVarType(f, &api->ret);
335                 fprintf(f, " ret;\n");
336                 fprintf(f, "    io->coreGetReturn(&ret, sizeof(ret));\n");
337                 fprintf(f, "    return ret;\n");
338             } else if (needFlush) {
339                 fprintf(f, "    io->coreGetReturn(NULL, 0);\n");
340             }
341         }
342         fprintf(f, "};\n\n");
343     }
344 
345     fprintf(f, "\n");
346 
347     for (ct=0; ct < apiCount; ct++) {
348         const ApiEntry * api = &apis[ct];
349 
350         fprintf(f, "extern \"C\" ");
351 
352         printFuncDecl(f, api, "rs", 0, 0);
353         fprintf(f, "\n{\n");
354         fprintf(f, "    ");
355         if (api->ret.typeName[0]) {
356             fprintf(f, "return ");
357         }
358         fprintf(f, LOCAL_FIFO_PREFIX "%s(", api->name);
359 
360         if (!api->nocontext) {
361             fprintf(f, "(Context *)rsc");
362         }
363 
364         for (ct2=0; ct2 < api->paramCount; ct2++) {
365             const VarType *vt = &api->params[ct2];
366             if (ct2 > 0 || !api->nocontext) {
367                 fprintf(f, ", ");
368             }
369             fprintf(f, "%s", vt->name);
370         }
371         fprintf(f, ");\n");
372         fprintf(f, "}\n\n");
373     }
374 
375 }
376 
printPlaybackCpp(FILE * f)377 void printPlaybackCpp(FILE *f) {
378     int ct;
379     int ct2;
380 
381     fprintf(f, RSG_API_REPLAY_CPP_DOC);
382 
383     fprintf(f, "#include \"rsDevice.h\"\n");
384     fprintf(f, "#include \"rsContext.h\"\n");
385     fprintf(f, "#include \"rsThreadIO.h\"\n");
386     fprintf(f, "#include \"rsgApiStructs.h\"\n");
387     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
388     fprintf(f, "\n");
389     fprintf(f, "namespace android {\n");
390     fprintf(f, "namespace renderscript {\n");
391     fprintf(f, "\n");
392 
393     // Generate functions to play back messages sent from the local FIFO.
394     for (ct=0; ct < apiCount; ct++) {
395         const ApiEntry * api = &apis[ct];
396         int needFlush = 0;
397 
398         if (api->direct) {
399             continue;
400         }
401 
402         fprintf(f, "void " RS_PLAYBACK_PREFIX "%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
403         fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
404 
405         if (hasInlineDataPointers(api)) {
406             fprintf(f, "    const uint8_t *baseData = 0;\n");
407             fprintf(f, "    if (cmdSizeBytes != sizeof(RS_CMD_%s)) {\n", api->name);
408             fprintf(f, "        baseData = &((const uint8_t *)vp)[sizeof(*cmd)];\n");
409             fprintf(f, "    }\n");
410         }
411 
412         fprintf(f, "    ");
413         if (api->ret.typeName[0]) {
414             fprintf(f, "\n    ");
415             printVarType(f, &api->ret);
416             fprintf(f, " ret = ");
417         }
418         fprintf(f, RS_INTERNAL_PREFIX "%s(con", api->name);
419         for (ct2=0; ct2 < api->paramCount; ct2++) {
420             const VarType *vt = &api->params[ct2];
421             needFlush += vt->ptrLevel;
422 
423             if (hasInlineDataPointers(api) && vt->ptrLevel) {
424                 fprintf(f, ",\n           cmd->%s_length == 0 ? NULL : (const %s *)&baseData[(intptr_t)cmd->%s]",
425                         vt->name, vt->typeName, vt->name);
426             } else {
427                 fprintf(f, ",\n           cmd->%s", vt->name);
428             }
429         }
430         fprintf(f, ");\n");
431 
432         if (hasInlineDataPointers(api)) {
433             fprintf(f, "    size_t totalSize = 0;\n");
434             for (ct2=0; ct2 < api->paramCount; ct2++) {
435                 if (api->params[ct2].ptrLevel) {
436                     fprintf(f, "    totalSize += cmd->%s_length;\n", api->params[ct2].name);
437                 }
438             }
439 
440             fprintf(f, "    if ((totalSize != 0) && (cmdSizeBytes == sizeof(RS_CMD_%s))) {\n", api->name);
441             fprintf(f, "        con->mIO.coreSetReturn(NULL, 0);\n");
442             fprintf(f, "    }\n");
443         } else if (api->ret.typeName[0]) {
444             fprintf(f, "    con->mIO.coreSetReturn(&ret, sizeof(ret));\n");
445         } else if (api->sync || needFlush) {
446             fprintf(f, "    con->mIO.coreSetReturn(NULL, 0);\n");
447         }
448 
449         fprintf(f, "};\n\n");
450     }
451 
452     // Generate the globally accessible table of playback functions.
453     fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
454     fprintf(f, "    NULL,\n");
455     for (ct=0; ct < apiCount; ct++) {
456         if (apis[ct].direct) {
457             fprintf(f, "    NULL,\n");
458         } else {
459             fprintf(f, "    %s%s,\n", RS_PLAYBACK_PREFIX, apis[ct].name);
460         }
461     }
462     fprintf(f, "};\n");
463 
464     fprintf(f, "};\n");
465     fprintf(f, "};\n");
466 }
467 
468 void yylex();
469 
main(int argc,char ** argv)470 int main(int argc, char **argv) {
471     if (argc != 3) {
472         fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
473         return 1;
474     }
475     const char* rsgFile = argv[1];
476     const char* outFile = argv[2];
477     FILE* input = fopen(rsgFile, "re");
478 
479     char choice = fgetc(input);
480     fclose(input);
481 
482     if (choice < '0' || choice > '3') {
483         fprintf(stderr, "Uknown command: \'%c\'\n", choice);
484         return -2;
485     }
486 
487     yylex();
488     // printf("# of lines = %d\n", num_lines);
489 
490     FILE *f = fopen(outFile, "we");
491 
492     printFileHeader(f);
493     switch (choice) {
494         case '0': // rsgApiStructs.h
495         {
496             fprintf(f, "\n");
497             fprintf(f, "#include \"rsContext.h\"\n");
498             fprintf(f, "#include \"rsFifo.h\"\n");
499             fprintf(f, "\n");
500             fprintf(f, "namespace android {\n");
501             fprintf(f, "namespace renderscript {\n");
502             printStructures(f);
503             printFuncDecls(f, RS_INTERNAL_PREFIX, 1, 0);
504             printPlaybackFuncs(f, RS_PLAYBACK_PREFIX);
505             fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
506             fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
507 
508             fprintf(f, "}\n");
509             fprintf(f, "}\n");
510         }
511         break;
512 
513         case '1': // rsgApiFuncDecl.h
514         {
515             printFuncDecls(f, "rs", 0, 1);
516         }
517         break;
518 
519         case '2': // rsgApi.cpp
520         {
521             printApiCpp(f);
522         }
523         break;
524 
525         case '3': // rsgApiReplay.cpp
526         {
527             printPlaybackCpp(f);
528         }
529         break;
530     }
531     fclose(f);
532     return 0;
533 }
534