slang_rs_reflection.cpp revision 68e8e9f98730b3672fb96d49e33b9db70a90ed3f
1#include "slang_rs_context.hpp"
2#include "slang_rs_export_var.hpp"
3#include "slang_rs_reflection.hpp"
4#include "slang_rs_export_func.hpp"
5
6#include <ctype.h>
7
8#include <utility>
9#include <cstdarg>
10
11#include <sys/stat.h>
12
13using std::make_pair;
14using std::endl;
15
16
17#define RS_SCRIPT_CLASS_NAME_PREFIX         "ScriptC_"
18#define RS_SCRIPT_CLASS_SUPER_CLASS_NAME    "ScriptC"
19
20#define RS_TYPE_CLASS_NAME_PREFIX           "ScriptField_"
21#define RS_TYPE_CLASS_SUPER_CLASS_NAME      "android.renderscript.Script.FieldBase"
22
23#define RS_TYPE_ITEM_CLASS_NAME             "Item"
24
25#define RS_TYPE_ITEM_BUFFER_NAME            "mItemArray"
26#define RS_TYPE_ITEM_BUFFER_PACKER_NAME     "mIOBuffer"
27
28#define RS_EXPORT_VAR_INDEX_PREFIX          "mExportVarIdx_"
29#define RS_EXPORT_VAR_PREFIX                "mExportVar_"
30
31#define RS_EXPORT_FUNC_INDEX_PREFIX         "mExportFuncIdx_"
32
33#define RS_EXPORT_VAR_ALLOCATION_PREFIX     "mAlloction_"
34#define RS_EXPORT_VAR_DATA_STORAGE_PREFIX   "mData_"
35
36namespace slang {
37
38/* Some utility function using internal in RSReflection */
39static bool GetFileNameWithoutExtension(const std::string& FileName, std::string& OutFileName) {
40    OutFileName.clear();
41
42    if(FileName.empty() || (FileName == "-"))
43        return true;
44
45    /* find last component in given path */
46    size_t SlashPos = FileName.find_last_of("/\\");
47
48    if((SlashPos != std::string::npos) && ((SlashPos + 1) < FileName.length()))
49        OutFileName = FileName.substr(SlashPos + 1);
50    else
51        OutFileName = FileName;
52
53    size_t DotPos = OutFileName.find_first_of('.');
54    if(DotPos != std::string::npos)
55        OutFileName.erase(DotPos);
56
57    return true;
58}
59
60static const char* GetPrimitiveTypeName(const RSExportPrimitiveType* EPT) {
61    static const char* PrimitiveTypeJavaNameMap[] = {
62        "",
63        "",
64        "float",    /* RSExportPrimitiveType::DataTypeFloat32 */
65        "double",   /* RSExportPrimitiveType::DataTypeFloat64 */
66        "byte",     /* RSExportPrimitiveType::DataTypeSigned8 */
67        "short",    /* RSExportPrimitiveType::DataTypeSigned16 */
68        "int",      /* RSExportPrimitiveType::DataTypeSigned32 */
69        "long",     /* RSExportPrimitiveType::DataTypeSigned64 */
70        "short",    /* RSExportPrimitiveType::DataTypeUnsigned8 */
71        "int",      /* RSExportPrimitiveType::DataTypeUnsigned16 */
72        "long",     /* RSExportPrimitiveType::DataTypeUnsigned32 */
73        "long",     /* RSExportPrimitiveType::DataTypeUnsigned64 */
74
75        "int",      /* RSExportPrimitiveType::DataTypeUnsigned565 */
76        "int",      /* RSExportPrimitiveType::DataTypeUnsigned5551 */
77        "int",      /* RSExportPrimitiveType::DataTypeUnsigned4444 */
78
79        "boolean",  /* RSExportPrimitiveType::DataTypeBool */
80
81        "Element",  /* RSExportPrimitiveType::DataTypeRSElement */
82        "Type",     /* RSExportPrimitiveType::DataTypeRSType */
83        "Allocation",   /* RSExportPrimitiveType::DataTypeRSAllocation */
84        "Sampler",  /* RSExportPrimitiveType::DataTypeRSSampler */
85        "Script",   /* RSExportPrimitiveType::DataTypeRSScript */
86        "Mesh",       /* RSExportPrimitiveType::DataTypeRSMesh */
87        "ProgramFragment",  /* RSExportPrimitiveType::DataTypeRSProgramFragment */
88        "ProgramVertex",    /* RSExportPrimitiveType::DataTypeRSProgramVertex */
89        "ProgramRaster",    /* RSExportPrimitiveType::DataTypeRSProgramRaster */
90        "ProgramStore",     /* RSExportPrimitiveType::DataTypeRSProgramStore */
91        "Font",     /* RSExportPrimitiveType::DataTypeRSFont */
92    };
93
94    if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveTypeJavaNameMap) / sizeof(const char*)))) {
95        // printf("Type %d\n", EPT->getType());
96        return PrimitiveTypeJavaNameMap[ EPT->getType() ];
97    }
98
99    assert(false && "GetPrimitiveTypeName : Unknown primitive data type");
100    return NULL;
101}
102
103static const char* GetVectorTypeName(const RSExportVectorType* EVT) {
104    static const char* VectorTypeJavaNameMap[][3] = {
105        /* 0 */ { "Byte2",  "Byte3",    "Byte4" },
106        /* 1 */ { "Short2", "Short3",   "Short4" },
107        /* 2 */ { "Int2",   "Int3",     "Int4" },
108        /* 3 */ { "Long2",  "Long3",    "Long4" },
109        /* 4 */ { "Float2", "Float3",   "Float4" },
110    };
111
112    const char** BaseElement;
113
114    switch(EVT->getType()) {
115        case RSExportPrimitiveType::DataTypeSigned8:
116            BaseElement = VectorTypeJavaNameMap[0];
117        break;
118
119        case RSExportPrimitiveType::DataTypeSigned16:
120        case RSExportPrimitiveType::DataTypeUnsigned8:
121            BaseElement = VectorTypeJavaNameMap[1];
122        break;
123
124        case RSExportPrimitiveType::DataTypeSigned32:
125        case RSExportPrimitiveType::DataTypeUnsigned16:
126            BaseElement = VectorTypeJavaNameMap[2];
127        break;
128
129        case RSExportPrimitiveType::DataTypeUnsigned32:
130            BaseElement = VectorTypeJavaNameMap[3];
131        break;
132
133        case RSExportPrimitiveType::DataTypeFloat32:
134            BaseElement = VectorTypeJavaNameMap[4];
135        break;
136
137        case RSExportPrimitiveType::DataTypeBool:
138            BaseElement = VectorTypeJavaNameMap[0];
139        break;
140
141        default:
142            assert(false && "RSReflection::genElementTypeName : Unsupported vector element data type");
143        break;
144    }
145
146    assert((EVT->getNumElement() > 1) && (EVT->getNumElement() <= 4) && "Number of element in vector type is invalid");
147
148    return BaseElement[EVT->getNumElement() - 2];
149}
150
151static const char* GetVectorAccessor(int Index) {
152    static const char* VectorAccessorMap[] = {
153        /* 0 */ "x",
154        /* 1 */ "y",
155        /* 2 */ "z",
156        /* 3 */ "w",
157    };
158
159    assert((Index >= 0) && (Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) && "Out-of-bound index to access vector member");
160
161    return VectorAccessorMap[Index];
162}
163
164static const char* GetPackerAPIName(const RSExportPrimitiveType* EPT) {
165    static const char* PrimitiveTypePackerAPINameMap[] = {
166        "",
167        "",
168        "addF32",   /* RSExportPrimitiveType::DataTypeFloat32 */
169        "addF64",   /* RSExportPrimitiveType::DataTypeFloat64 */
170        "addI8",    /* RSExportPrimitiveType::DataTypeSigned8 */
171        "addI16",   /* RSExportPrimitiveType::DataTypeSigned16 */
172        "addI32",   /* RSExportPrimitiveType::DataTypeSigned32 */
173        "addI64",   /* RSExportPrimitiveType::DataTypeSigned64 */
174        "addU8",    /* RSExportPrimitiveType::DataTypeUnsigned8 */
175        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned16 */
176        "addU32",   /* RSExportPrimitiveType::DataTypeUnsigned32 */
177        "addU64",   /* RSExportPrimitiveType::DataTypeUnsigned64 */
178
179        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
180        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
181        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
182
183        "addBoolean",  /* RSExportPrimitiveType::DataTypeBool */
184
185        "addObj",   /* RSExportPrimitiveType::DataTypeRSElement */
186        "addObj",   /* RSExportPrimitiveType::DataTypeRSType */
187        "addObj",   /* RSExportPrimitiveType::DataTypeRSAllocation */
188        "addObj",   /* RSExportPrimitiveType::DataTypeRSSampler */
189        "addObj",   /* RSExportPrimitiveType::DataTypeRSScript */
190        "addObj",   /* RSExportPrimitiveType::DataTypeRSMesh */
191        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramFragment */
192        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
193        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
194        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramStore */
195        "addObj",   /* RSExportPrimitiveType::DataTypeRSFont */
196    };
197
198    if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char*))))
199        return PrimitiveTypePackerAPINameMap[ EPT->getType() ];
200
201    assert(false && "GetPackerAPIName : Unknown primitive data type");
202    return NULL;
203}
204
205static std::string GetTypeName(const RSExportType* ET) {
206    switch(ET->getClass()) {
207        case RSExportType::ExportClassPrimitive:
208            return GetPrimitiveTypeName(static_cast<const RSExportPrimitiveType*>(ET));
209        break;
210
211        case RSExportType::ExportClassPointer:
212        {
213            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
214
215            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
216                return "Allocation";
217            else
218                return RS_TYPE_CLASS_NAME_PREFIX + PointeeType->getName();
219        }
220        break;
221
222        case RSExportType::ExportClassVector:
223            return GetVectorTypeName(static_cast<const RSExportVectorType*>(ET));
224        break;
225
226        case RSExportType::ExportClassRecord:
227            return RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
228        break;
229
230        default:
231            assert(false && "Unknown class of type");
232        break;
233    }
234
235    return "";
236}
237
238static const char* GetBuiltinElementConstruct(const RSExportType* ET) {
239    if(ET->getClass() == RSExportType::ExportClassPrimitive) {
240        const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
241        if(EPT->getKind() == RSExportPrimitiveType::DataKindUser) {
242            static const char* PrimitiveBuiltinElementConstructMap[] = {
243                NULL,
244                NULL,
245                "F32", /* RSExportPrimitiveType::DataTypeFloat32 */
246                NULL,       /* RSExportPrimitiveType::DataTypeFloat64 */
247                "I8",  /* RSExportPrimitiveType::DataTypeSigned8 */
248                NULL,       /* RSExportPrimitiveType::DataTypeSigned16 */
249                "I32", /* RSExportPrimitiveType::DataTypeSigned32 */
250                NULL,       /* RSExportPrimitiveType::DataTypeSigned64 */
251                "U8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
252                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned16 */
253                "U32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
254                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned64 */
255
256                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned565 */
257                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
258                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
259
260                "BOOLEAN",  /* RSExportPrimitiveType::DataTypeBool */
261
262                "ELEMENT", /* RSExportPrimitiveType::DataTypeRSElement */
263                "TYPE",    /* RSExportPrimitiveType::DataTypeRSType */
264                "ALLOCATION",  /* RSExportPrimitiveType::DataTypeRSAllocation */
265                "SAMPLER",     /* RSExportPrimitiveType::DataTypeRSSampler */
266                "SCRIPT",      /* RSExportPrimitiveType::DataTypeRSScript */
267                "MESH",        /* RSExportPrimitiveType::DataTypeRSMesh */
268                "PROGRAM_FRAGMENT",    /* RSExportPrimitiveType::DataTypeRSProgramFragment */
269                "PROGRAM_VERTEX",      /* RSExportPrimitiveType::DataTypeRSProgramVertex */
270                "PROGRAM_RASTER",      /* RSExportPrimitiveType::DataTypeRSProgramRaster */
271                "PROGRAM_STORE",       /* RSExportPrimitiveType::DataTypeRSProgramStore */
272                "FONT",       /* RSExportPrimitiveType::DataTypeRSFont */
273            };
274
275            if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveBuiltinElementConstructMap) / sizeof(const char*))))
276                return PrimitiveBuiltinElementConstructMap[ EPT->getType() ];
277        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelA) {
278            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
279                return "A_8";
280        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGB) {
281            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned565)
282                return "RGB_565";
283            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
284                return "RGB_888";
285        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGBA) {
286            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned5551)
287                return "RGB_5551";
288            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned4444)
289                return "RGB_4444";
290            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
291                return "RGB_8888";
292        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindIndex) {
293            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned16)
294                return "INDEX_16";
295        }
296    } else if(ET->getClass() == RSExportType::ExportClassVector) {
297        const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(ET);
298        if(EVT->getKind() == RSExportPrimitiveType::DataKindPosition) {
299            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
300                if(EVT->getNumElement() == 2)
301                    return "ATTRIB_POSITION_2";
302                else if(EVT->getNumElement() == 3)
303                    return "ATTRIB_POSITION_3";
304            }
305        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindTexture) {
306            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
307                if(EVT->getNumElement() == 2)
308                    return "ATTRIB_TEXTURE_2";
309            }
310        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindNormal) {
311            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
312                if(EVT->getNumElement() == 3)
313                    return "ATTRIB_NORMAL_3";
314            }
315        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindColor) {
316            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
317                if(EVT->getNumElement() == 4)
318                    return "ATTRIB_COLOR_F32_4";
319            } else if(EVT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) {
320                if(EVT->getNumElement() == 4)
321                    return "ATTRIB_COLOR_U8_4";
322            }
323        }
324    } else if(ET->getClass() == RSExportType::ExportClassPointer) {
325        return "USER_I32";  /* tread pointer type variable as unsigned int (TODO: this is target dependent) */
326    }
327
328    return NULL;
329}
330
331static const char* GetElementDataKindName(RSExportPrimitiveType::DataKind DK) {
332    static const char* ElementDataKindNameMap[] = {
333        "Element.DataKind.USER",        /* RSExportPrimitiveType::DataKindUser */
334        "Element.DataKind.COLOR",       /* RSExportPrimitiveType::DataKindColor */
335        "Element.DataKind.POSITION",    /* RSExportPrimitiveType::DataKindPosition */
336        "Element.DataKind.TEXTURE",     /* RSExportPrimitiveType::DataKindTexture */
337        "Element.DataKind.NORMAL",      /* RSExportPrimitiveType::DataKindNormal */
338        "Element.DataKind.INDEX",       /* RSExportPrimitiveType::DataKindIndex */
339        "Element.DataKind.POINT_SIZE",  /* RSExportPrimitiveType::DataKindPointSize */
340        "Element.DataKind.PIXEL_L",     /* RSExportPrimitiveType::DataKindPixelL */
341        "Element.DataKind.PIXEL_A",     /* RSExportPrimitiveType::DataKindPixelA */
342        "Element.DataKind.PIXEL_LA",    /* RSExportPrimitiveType::DataKindPixelLA */
343        "Element.DataKind.PIXEL_RGB",   /* RSExportPrimitiveType::DataKindPixelRGB */
344        "Element.DataKind.PIXEL_RGBA",  /* RSExportPrimitiveType::DataKindPixelRGBA */
345    };
346
347    if((DK >= 0) && (DK < (sizeof(ElementDataKindNameMap) / sizeof(const char*))))
348        return ElementDataKindNameMap[ DK ];
349    else
350        return NULL;
351}
352
353static const char* GetElementDataTypeName(RSExportPrimitiveType::DataType DT) {
354    static const char* ElementDataTypeNameMap[] = {
355        NULL,
356        NULL,
357        "Element.DataType.FLOAT_32",    /* RSExportPrimitiveType::DataTypeFloat32 */
358        NULL,                           /* RSExportPrimitiveType::DataTypeFloat64 */
359        "Element.DataType.SIGNED_8",    /* RSExportPrimitiveType::DataTypeSigned8 */
360        "Element.DataType.SIGNED_16",   /* RSExportPrimitiveType::DataTypeSigned16 */
361        "Element.DataType.SIGNED_32",   /* RSExportPrimitiveType::DataTypeSigned32 */
362        NULL,                           /* RSExportPrimitiveType::DataTypeSigned64 */
363        "Element.DataType.UNSIGNED_8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
364        "Element.DataType.UNSIGNED_16", /* RSExportPrimitiveType::DataTypeUnsigned16 */
365        "Element.DataType.UNSIGNED_32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
366        NULL,                           /* RSExportPrimitiveType::DataTypeUnsigned64 */
367
368        "Element.DataType.UNSIGNED_5_6_5",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
369        "Element.DataType.UNSIGNED_5_5_5_1", /* RSExportPrimitiveType::DataTypeUnsigned5551 */
370        "Element.DataType.UNSIGNED_4_4_4_4", /* RSExportPrimitiveType::DataTypeUnsigned4444 */
371
372        "Element.DataType.BOOLEAN",     /* RSExportPrimitiveType::DataTypeBool */
373
374        "Element.DataType.RS_ELEMENT",  /* RSExportPrimitiveType::DataTypeRSElement */
375        "Element.DataType.RS_TYPE",     /* RSExportPrimitiveType::DataTypeRSType */
376        "Element.DataType.RS_ALLOCATION",   /* RSExportPrimitiveType::DataTypeRSAllocation */
377        "Element.DataType.RS_SAMPLER",      /* RSExportPrimitiveType::DataTypeRSSampler */
378        "Element.DataType.RS_SCRIPT",       /* RSExportPrimitiveType::DataTypeRSScript */
379        "Element.DataType.RS_MESH",         /* RSExportPrimitiveType::DataTypeRSMesh */
380        "Element.DataType.RS_PROGRAM_FRAGMENT", /* RSExportPrimitiveType::DataTypeRSProgramFragment */
381        "Element.DataType.RS_PROGRAM_VERTEX",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
382        "Element.DataType.RS_PROGRAM_RASTER",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
383        "Element.DataType.RS_PROGRAM_STORE",    /* RSExportPrimitiveType::DataTypeRSProgramStore */
384        "Element.DataType.RS_FONT",    /* RSExportPrimitiveType::DataTypeRSFont */
385    };
386
387    if((DT >= 0) && (DT < (sizeof(ElementDataTypeNameMap) / sizeof(const char*))))
388        return ElementDataTypeNameMap[ DT ];
389    else
390        return NULL;
391}
392
393static void _mkdir(const std::string &path) {
394    char buf[256];
395    char *tmp, *p = NULL;
396    size_t len = path.size();
397
398    if (len + 1 <= sizeof(buf))
399        tmp = buf;
400    else
401        tmp = new char [len + 1];
402
403    strcpy(tmp, path.c_str());
404
405    if (tmp[len - 1] == '/')
406        tmp[len - 1] = 0;
407
408    for (p = tmp + 1; *p; p++) {
409        if (*p == '/') {
410            *p = 0;
411            mkdir(tmp, S_IRWXU);
412            *p = '/';
413        }
414    }
415    mkdir(tmp, S_IRWXU);
416
417    if (tmp != buf)
418        delete[] tmp;
419}
420
421bool RSReflection::openScriptFile(Context&C, const std::string& ClassName, std::string& ErrorMsg) {
422    if(!C.mUseStdout) {
423        C.mOF.clear();
424        std::string _path = "/" + C.getPackageName();
425        for (std::string::iterator it = _path.begin(); it != _path.end(); it++ ) {
426            if ( *it == '.') {
427                *it = '/';
428            }
429        }
430
431        std::string prefix = mRSContext->getReflectJavaPathName();
432        if (prefix.empty()) {
433            _path.insert(0, 1, '.');
434        } else {
435            _path.insert(0, mRSContext->getReflectJavaPathName());
436        }
437
438        _mkdir(_path);
439        C.mOF.open(( _path + "/" + ClassName + ".java" ).c_str());
440        if(!C.mOF.good()) {
441            ErrorMsg = "failed to open file '" + _path + "/" + ClassName + ".java' for write";
442
443            return false;
444        }
445    }
446    return true;
447}
448
449/****************************** Methods to generate script class ******************************/
450bool RSReflection::genScriptClass(Context& C, const std::string& ClassName, std::string& ErrorMsg) {
451    /* Open the file */
452    if (!openScriptFile(C, ClassName, ErrorMsg)) {
453        return false;
454    }
455
456    if(!C.startClass(Context::AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME, ErrorMsg))
457        return false;
458
459    genScriptClassConstructor(C);
460
461    /* Reflect export variable */
462    for(RSContext::const_export_var_iterator I = mRSContext->export_vars_begin();
463        I != mRSContext->export_vars_end();
464        I++)
465        genExportVariable(C, *I);
466
467    /* Reflect export function */
468    for(RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin();
469        I != mRSContext->export_funcs_end();
470        I++)
471        genExportFunction(C, *I);
472
473    C.endClass();
474
475    return true;
476}
477
478void RSReflection::genScriptClassConstructor(Context& C) {
479    C.indent() << "// Constructor" << endl;
480    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 4, "RenderScript", "rs",
481                                                                          "Resources", "resources",
482                                                                          "int", "id",
483                                                                          "boolean", "isRoot");
484    /* Call constructor of super class */
485    C.indent() << "super(rs, resources, id, isRoot);" << endl;
486
487    /* If an exported variable has initial value, reflect it */
488
489    for(RSContext::const_export_var_iterator I = mRSContext->export_vars_begin();
490        I != mRSContext->export_vars_end();
491        I++)
492    {
493        const RSExportVar* EV = *I;
494        if(!EV->getInit().isUninit())
495            genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
496    }
497
498    C.endFunction();
499    return;
500}
501
502void RSReflection::genInitBoolExportVariable(Context& C, const std::string& VarName, const APValue& Val) {
503    assert(!Val.isUninit() && "Not a valid initializer");
504
505    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
506    assert((Val.getKind() == APValue::Int) && "Bool type has wrong initial APValue");
507
508    if (Val.getInt().getSExtValue() == 0) {
509        C.out() << "false";
510    } else {
511        C.out() << "true";
512    }
513    C.out() << ";" << endl;
514
515    return;
516}
517
518void RSReflection::genInitPrimitiveExportVariable(Context& C, const std::string& VarName, const APValue& Val) {
519    assert(!Val.isUninit() && "Not a valid initializer");
520
521    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
522    switch(Val.getKind()) {
523        case APValue::Int: C.out() << Val.getInt().getSExtValue(); break;
524        case APValue::Float: C.out() << Val.getFloat().convertToDouble(); break;
525
526        case APValue::ComplexInt:
527        case APValue::ComplexFloat:
528        case APValue::LValue:
529        case APValue::Vector:
530            assert(false && "Primitive type cannot have such kind of initializer");
531        break;
532
533        default:
534            assert(false && "Unknown kind of initializer");
535        break;
536    }
537    C.out() << ";" << endl;
538
539    return;
540}
541
542void RSReflection::genInitExportVariable(Context& C, const RSExportType* ET, const std::string& VarName, const APValue& Val) {
543    assert(!Val.isUninit() && "Not a valid initializer");
544
545    switch(ET->getClass()) {
546        case RSExportType::ExportClassPrimitive: {
547            const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
548            if (EPT->getType() == RSExportPrimitiveType::DataTypeBool) {
549                genInitBoolExportVariable(C, VarName, Val);
550            } else {
551                genInitPrimitiveExportVariable(C, VarName, Val);
552            }
553            break;
554        }
555
556        case RSExportType::ExportClassPointer:
557            if(!Val.isInt() || Val.getInt().getSExtValue() != 0)
558                std::cout << "Initializer which is non-NULL to pointer type variable will be ignored" << endl;
559        break;
560
561        case RSExportType::ExportClassVector:
562        {
563            const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(ET);
564            switch(Val.getKind()) {
565                case APValue::Int:
566                case APValue::Float:
567                    for(int i=0;i<EVT->getNumElement();i++) {
568                        std::string Name =  VarName + "." + GetVectorAccessor(i);
569                        genInitPrimitiveExportVariable(C, Name, Val);
570                    }
571                break;
572
573                case APValue::Vector:
574                {
575                    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new " << GetVectorTypeName(EVT) << "();" << endl;
576
577                    unsigned NumElements = std::min(static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
578                    for(unsigned i=0;i<NumElements;i++) {
579                        const APValue& ElementVal = Val.getVectorElt(i);
580                        std::string Name =  VarName + "." + GetVectorAccessor(i);
581                        genInitPrimitiveExportVariable(C, Name, ElementVal);
582                    }
583                }
584                break;
585            }
586        }
587        break;
588
589        /* TODO: Resolving initializer of a record type variable is complex. It cannot obtain by just simply evaluating the initializer expression. */
590        case RSExportType::ExportClassRecord:
591        {
592            /*
593            unsigned InitIndex = 0;
594            const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
595
596            assert((Val.getKind() == APValue::Vector) && "Unexpected type of initializer for record type variable");
597
598            C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "RS_TYPE_CLASS_NAME_PREFIX << ERT->getName() <<  "."RS_TYPE_ITEM_CLASS_NAME"();" << endl;
599
600            for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
601                I != ERT->fields_end();
602                I++)
603            {
604                const RSExportRecordType::Field* F = *I;
605                std::string FieldName = VarName + "." + F->getName();
606
607                if(InitIndex > Val.getVectorLength())
608                    break;
609
610                genInitPrimitiveExportVariable(C, FieldName, Val.getVectorElt(InitIndex++));
611            }
612            */
613            assert(false && "Unsupported initializer for record type variable currently");
614        }
615        break;
616
617        default:
618            assert(false && "Unknown class of type");
619        break;
620    }
621    return;
622}
623
624void RSReflection::genExportVariable(Context& C, const RSExportVar* EV) {
625    const RSExportType* ET = EV->getType();
626
627    C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << " = " << C.getNextExportVarSlot() << ";" << endl;
628
629    switch(ET->getClass()) {
630        case RSExportType::ExportClassPrimitive:
631            genPrimitiveTypeExportVariable(C, EV);
632        break;
633
634        case RSExportType::ExportClassPointer:
635            genPointerTypeExportVariable(C, EV);
636        break;
637
638        case RSExportType::ExportClassVector:
639            genVectorTypeExportVariable(C, EV);
640        break;
641
642        case RSExportType::ExportClassRecord:
643            genRecordTypeExportVariable(C, EV);
644        break;
645
646        default:
647            assert(false && "Unknown class of type");
648        break;
649    }
650
651    return;
652}
653
654void RSReflection::genExportFunction(Context& C, const RSExportFunc* EF) {
655    C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << " = " << C.getNextExportFuncSlot() << ";" << endl;
656
657    /* invoke_*() */
658    Context::ArgTy Args;
659
660    for(RSExportFunc::const_param_iterator I = EF->params_begin();
661        I != EF->params_end();
662        I++)
663    {
664        const RSExportFunc::Parameter* P = *I;
665        Args.push_back( make_pair(GetTypeName(P->getType()), P->getName()) );
666    }
667
668    C.startFunction(Context::AM_Public, false, "void", "invoke_" + EF->getName(), Args);
669
670    if(!EF->hasParam()) {
671        C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");" << endl;
672    } else {
673        const RSExportRecordType* ERT = EF->getParamPacketType();
674        std::string FieldPackerName = EF->getName() + "_fp";
675
676        if(genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
677            genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
678
679        C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", " << FieldPackerName << ");" << endl;
680    }
681
682    C.endFunction();
683    return;
684}
685
686void RSReflection::genPrimitiveTypeExportVariable(Context& C, const RSExportVar* EV) {
687    assert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive) && "Variable should be type of primitive here");
688
689    const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(EV->getType());
690    const char* TypeName = GetPrimitiveTypeName(EPT);
691
692    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
693
694    /* set_*() */
695    if(!EV->isConst()) {
696        C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
697        C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
698
699        if(EPT->isRSObjectType())
700            C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", (v == null) ? 0 : v.getID());" << endl;
701        else
702            C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", v);" << endl;
703
704        C.endFunction();
705    }
706
707    genGetExportVariable(C, TypeName, EV->getName());
708
709    return;
710}
711
712void RSReflection::genPointerTypeExportVariable(Context& C, const RSExportVar* EV) {
713    const RSExportType* ET = EV->getType();
714    const RSExportType* PointeeType;
715    std::string TypeName;
716
717    assert((ET->getClass() == RSExportType::ExportClassPointer) && "Variable should be type of pointer here");
718
719    PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
720    TypeName = GetTypeName(ET);
721
722    /* bind_*() */
723    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
724
725    C.startFunction(Context::AM_Public, false, "void", "bind_" + EV->getName(), 1, TypeName.c_str(), "v");
726
727    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
728    C.indent() << "if(v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
729
730    if(PointeeType->getClass() == RSExportType::ExportClassRecord)
731        C.indent() << "else bindAllocation(v.getAllocation(), "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
732    else
733        C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
734
735    C.endFunction();
736
737    genGetExportVariable(C, TypeName, EV->getName());
738
739    return;
740}
741
742void RSReflection::genVectorTypeExportVariable(Context& C, const RSExportVar* EV) {
743    assert((EV->getType()->getClass() == RSExportType::ExportClassVector) && "Variable should be type of vector here");
744
745    const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(EV->getType());
746    const char* TypeName = GetVectorTypeName(EVT);
747    const char* FieldPackerName = "fp";
748
749    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
750
751    /* set_*() */
752    if(!EV->isConst()) {
753        C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
754        C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
755
756        if(genCreateFieldPacker(C, EVT, FieldPackerName))
757            genPackVarOfType(C, EVT, "v", FieldPackerName);
758        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
759
760        C.endFunction();
761    }
762
763    genGetExportVariable(C, TypeName, EV->getName());
764    return;
765}
766
767void RSReflection::genRecordTypeExportVariable(Context& C, const RSExportVar* EV) {
768    assert((EV->getType()->getClass() == RSExportType::ExportClassRecord) && "Variable should be type of struct here");
769
770    const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(EV->getType());
771    std::string TypeName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
772    const char* FieldPackerName = "fp";
773
774    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
775
776    /* set_*() */
777    if(!EV->isConst()) {
778        C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName.c_str(), "v");
779        C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
780
781        if(genCreateFieldPacker(C, ERT, FieldPackerName))
782            genPackVarOfType(C, ERT, "v", FieldPackerName);
783        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
784
785        C.endFunction();
786    }
787
788    genGetExportVariable(C, TypeName.c_str(), EV->getName());
789    return;
790}
791
792void RSReflection::genGetExportVariable(Context& C, const std::string& TypeName, const std::string& VarName) {
793    C.startFunction(Context::AM_Public, false, TypeName.c_str(), "get_" + VarName, 0);
794
795    C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << endl;
796
797    C.endFunction();
798    return;
799}
800
801/****************************** Methods to generate script class /end ******************************/
802
803bool RSReflection::genCreateFieldPacker(Context& C, const RSExportType* ET, const char* FieldPackerName) {
804    size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
805    if(AllocSize > 0)
806        C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(" << AllocSize << ");" << endl;
807    else
808        return false;
809    return true;
810}
811
812void RSReflection::genPackVarOfType(Context& C, const RSExportType* ET, const char* VarName, const char* FieldPackerName) {
813    switch(ET->getClass()) {
814        case RSExportType::ExportClassPrimitive:
815        case RSExportType::ExportClassVector:
816            C.indent() << FieldPackerName << "." << GetPackerAPIName(static_cast<const RSExportPrimitiveType*>(ET)) << "(" << VarName << ");" << endl;
817        break;
818
819        case RSExportType::ExportClassPointer:
820        {
821            /* Must reflect as type Allocation in Java */
822            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
823
824            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
825                C.indent() << FieldPackerName << ".addI32(" << VarName << ".getPtr());" << endl;
826            else
827                C.indent() << FieldPackerName << ".addI32(" << VarName << ".getAllocation().getPtr());" << endl;
828        }
829        break;
830
831        case RSExportType::ExportClassRecord:
832        {
833            const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
834            int Pos = 0;    /* relative pos from now on in field packer */
835
836            for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
837                I != ERT->fields_end();
838                I++)
839            {
840                const RSExportRecordType::Field* F = *I;
841                std::string FieldName;
842                size_t FieldOffset = F->getOffsetInParent();
843                size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
844                size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
845
846                if(VarName != NULL)
847                    FieldName = VarName + ("." + F->getName());
848                else
849                    FieldName = F->getName();
850
851                if(FieldOffset > Pos)
852                    C.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos) << ");" << endl;
853
854                genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
855
856                if(FieldAllocSize > FieldStoreSize)  /* there's padding in the field type */
857                    C.indent() << FieldPackerName << ".skip(" << (FieldAllocSize - FieldStoreSize) << ");" << endl;
858
859                Pos = FieldOffset + FieldAllocSize;
860            }
861
862            /* There maybe some padding after the struct */
863            size_t Padding = RSExportType::GetTypeAllocSize(ERT) - Pos;
864            if(Padding > 0)
865                C.indent() << FieldPackerName << ".skip(" << Padding << ");" << endl;
866        }
867        break;
868
869        default:
870            assert(false && "Unknown class of type");
871        break;
872    }
873
874    return;
875}
876
877/****************************** Methods to generate type class  ******************************/
878bool RSReflection::genTypeClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
879    std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
880
881    /* Open the file */
882    if (!openScriptFile(C, ClassName, ErrorMsg)) {
883        return false;
884    }
885
886    if(!C.startClass(Context::AM_Public, false, ClassName, RS_TYPE_CLASS_SUPER_CLASS_NAME, ErrorMsg))
887        return false;
888
889    if(!genTypeItemClass(C, ERT, ErrorMsg))
890        return false;
891
892    /* Declare item buffer and item buffer packer */
893    C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[];" << endl;
894    C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";" << endl;
895
896    genTypeClassConstructor(C, ERT);
897    genTypeClassCopyToArray(C, ERT);
898    genTypeClasSet(C, ERT);
899    genTypeClasCopyAll(C, ERT);
900
901    C.endClass();
902
903    return true;
904}
905
906bool RSReflection::genTypeItemClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
907    C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
908    C.startBlock();
909
910    C.indent() << "public static final int sizeof = " << RSExportType::GetTypeAllocSize(ERT) << ";" << endl;
911
912    /* Member elements */
913    C.out() << endl;
914    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
915        FI != ERT->fields_end();
916        FI++)
917        C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName() << ";" << endl;
918
919    /* Constructor */
920    C.out() << endl;
921    C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
922    C.startBlock();
923
924    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
925        FI != ERT->fields_end();
926        FI++)
927    {
928        const RSExportRecordType::Field* F = *FI;
929        if((F->getType()->getClass() == RSExportType::ExportClassVector) || (F->getType()->getClass() == RSExportType::ExportClassRecord))
930        C.indent() << F->getName() << " = new " << GetTypeName(F->getType()) << "();" << endl;
931    }
932
933    C.endBlock();   /* end Constructor */
934
935    C.endBlock();   /* end Item class */
936
937
938    return true;
939}
940
941void RSReflection::genTypeClassConstructor(Context& C, const RSExportRecordType* ERT) {
942    const char* RenderScriptVar = "rs";
943
944    C.startFunction(Context::AM_Public, true, "Element", "createElement", 1, "RenderScript", RenderScriptVar);
945    genBuildElement(C, ERT, RenderScriptVar);
946    C.endFunction();
947
948    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 2, "RenderScript", RenderScriptVar,
949                                                                          "int", "count");
950
951    C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << endl;
952    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << endl;
953    C.indent() << "mElement = createElement(" << RenderScriptVar << ");" << endl;
954    /* Call init() in super class */
955    C.indent() << "init(" << RenderScriptVar << ", count);" << endl;
956    C.endFunction();
957
958    return;
959}
960
961void RSReflection::genTypeClassCopyToArray(Context& C, const RSExportRecordType* ERT) {
962    C.startFunction(Context::AM_Private, false, "void", "copyToArray", 2, RS_TYPE_ITEM_CLASS_NAME, "i",
963                                                                          "int", "index");
964
965    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_PACKER_NAME" == null) "RS_TYPE_ITEM_BUFFER_PACKER_NAME" = new FieldPacker("RS_TYPE_ITEM_CLASS_NAME".sizeof * mType.getX() /* count */);" << endl;
966    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" << endl;
967
968    genPackVarOfType(C, ERT, "i", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
969
970    C.endFunction();
971    return;
972}
973
974void RSReflection::genTypeClasSet(Context& C, const RSExportRecordType* ERT) {
975    C.startFunction(Context::AM_Public, false, "void", "set", 3, RS_TYPE_ITEM_CLASS_NAME, "i",
976                                                                 "int", "index",
977                                                                 "boolean", "copyNow");
978    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) "RS_TYPE_ITEM_BUFFER_NAME" = new "RS_TYPE_ITEM_CLASS_NAME"[mType.getX() /* count */];" << endl;
979    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << endl;
980
981    C.indent() << "if (copyNow) ";
982    C.startBlock();
983
984    C.indent() << "copyToArray(i, index);" << endl;
985    //C.indent() << "mAllocation.subData1D(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof, "RS_TYPE_ITEM_CLASS_NAME".sizeof, "RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
986    C.indent() << "mAllocation.subData1D(index, 1, "RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
987
988    C.endBlock();   /* end if (copyNow) */
989
990    C.endFunction();
991    return;
992}
993
994void RSReflection::genTypeClasCopyAll(Context& C, const RSExportRecordType* ERT) {
995    C.startFunction(Context::AM_Public, false, "void", "copyAll", 0);
996
997    C.indent() << "for (int ct=0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++) copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);" << endl;
998    C.indent() << "mAllocation.data("RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
999
1000    C.endFunction();
1001    return;
1002}
1003
1004/****************************** Methods to generate type class /end ******************************/
1005
1006/******************** Methods to create Element in Java of given record type ********************/
1007void RSReflection::genBuildElement(Context& C, const RSExportRecordType* ERT, const char* RenderScriptVar) {
1008    const char* ElementBuilderName = "eb";
1009
1010    /* Create element builder */
1011    //    C.startBlock(true);
1012
1013    C.indent() << "Element.Builder " << ElementBuilderName << " = new Element.Builder(" << RenderScriptVar << ");" << endl;
1014
1015    /* eb.add(...) */
1016    genAddElementToElementBuilder(C, ERT, "", ElementBuilderName, RenderScriptVar);
1017
1018    C.indent() << "return " << ElementBuilderName << ".create();" << endl;
1019
1020    //   C.endBlock();
1021    return;
1022}
1023
1024#define EB_ADD(x, ...)  \
1025    C.indent() << ElementBuilderName << ".add(Element." << x ##__VA_ARGS__ ", \"" << VarName << "\");" << endl
1026
1027void RSReflection::genAddElementToElementBuilder(Context& C, const RSExportType* ET, const std::string& VarName, const char* ElementBuilderName, const char* RenderScriptVar) {
1028    const char* ElementConstruct = GetBuiltinElementConstruct(ET);
1029
1030    if(ElementConstruct != NULL) {
1031      EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
1032    } else {
1033      if((ET->getClass() == RSExportType::ExportClassPrimitive) || (ET->getClass() == RSExportType::ExportClassVector)) {
1034        const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
1035        const char* DataKindName = GetElementDataKindName(EPT->getKind());
1036        const char* DataTypeName = GetElementDataTypeName(EPT->getType());
1037        int Size = (ET->getClass() == RSExportType::ExportClassVector) ? static_cast<const RSExportVectorType*>(ET)->getNumElement() : 1;
1038
1039        switch(EPT->getKind()) {
1040          case RSExportPrimitiveType::DataKindColor:
1041          case RSExportPrimitiveType::DataKindPosition:
1042          case RSExportPrimitiveType::DataKindTexture:
1043          case RSExportPrimitiveType::DataKindNormal:
1044          case RSExportPrimitiveType::DataKindPointSize:
1045            /* Element.createAttrib() */
1046            EB_ADD("createAttrib(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ", " << Size << ")");
1047            break;
1048
1049          case RSExportPrimitiveType::DataKindIndex:
1050            /* Element.createIndex() */
1051            EB_ADD("createAttrib(" << RenderScriptVar << ")");
1052            break;
1053
1054          case RSExportPrimitiveType::DataKindPixelL:
1055          case RSExportPrimitiveType::DataKindPixelA:
1056          case RSExportPrimitiveType::DataKindPixelLA:
1057          case RSExportPrimitiveType::DataKindPixelRGB:
1058          case RSExportPrimitiveType::DataKindPixelRGBA:
1059            /* Element.createPixel() */
1060            EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ")");
1061            break;
1062
1063          case RSExportPrimitiveType::DataKindUser:
1064          default:
1065            if(EPT->getClass() == RSExportType::ExportClassPrimitive)
1066              /* Element.createUser() */
1067              EB_ADD("createUser(" << RenderScriptVar << ", " << DataTypeName << ")");
1068            else /* (ET->getClass() == RSExportType::ExportClassVector) must hold here */
1069              /* Element.createVector() */
1070              EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << Size << ")");
1071            break;
1072        }
1073      } else if(ET->getClass() == RSExportType::ExportClassPointer) {
1074        /* Pointer type variable should be resolved in GetBuiltinElementConstruct()  */
1075        assert(false && "??");
1076      } else if(ET->getClass() == RSExportType::ExportClassRecord) {
1077        /*
1078         * Simalar to genPackVarOfType.
1079         *
1080         * TODO: Generalize these two function such that there's no duplicated codes.
1081         */
1082        const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
1083        int Pos = 0;    /* relative pos from now on */
1084
1085        for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
1086            I != ERT->fields_end();
1087            I++)
1088        {
1089          const RSExportRecordType::Field* F = *I;
1090          std::string FieldName;
1091          size_t FieldOffset = F->getOffsetInParent();
1092          size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1093          size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
1094
1095          if(!VarName.empty())
1096            FieldName = VarName + "." + F->getName();
1097          else
1098            FieldName = F->getName();
1099
1100          /* alignment */
1101          genAddPaddingToElementBuiler(C, (FieldOffset - Pos), ElementBuilderName, RenderScriptVar);
1102
1103          /* eb.add(...) */
1104          genAddElementToElementBuilder(C, (*I)->getType(), FieldName, ElementBuilderName, RenderScriptVar);
1105
1106          /* there's padding within the field type */
1107          genAddPaddingToElementBuiler(C, (FieldAllocSize - FieldStoreSize), ElementBuilderName, RenderScriptVar);
1108
1109          Pos = FieldOffset + FieldAllocSize;
1110        }
1111
1112        /* There maybe some padding after the struct */
1113        genAddPaddingToElementBuiler(C, (RSExportType::GetTypeAllocSize(ERT) - Pos), ElementBuilderName, RenderScriptVar);
1114      } else {
1115        assert(false && "Unknown class of type");
1116      }
1117    }
1118}
1119
1120void RSReflection::genAddPaddingToElementBuiler(Context& C, size_t PaddingSize, const char* ElementBuilderName, const char* RenderScriptVar) {
1121    while(PaddingSize > 0) {
1122        const std::string& VarName = C.createPaddingField();
1123        if(PaddingSize >= 4) {
1124          EB_ADD("U32(" << RenderScriptVar << ")");
1125          PaddingSize -= 4;
1126        } else if(PaddingSize >= 2) {
1127            EB_ADD("U16(" << RenderScriptVar << ")");
1128            PaddingSize -= 2;
1129        } else if(PaddingSize >= 1) {
1130            EB_ADD("U8(" << RenderScriptVar << ")");
1131            PaddingSize -= 1;
1132        }
1133    }
1134    return;
1135}
1136
1137#undef EB_ADD
1138/******************** Methods to create Element in Java of given record type /end ********************/
1139
1140bool RSReflection::reflect(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) {
1141    Context *C = NULL;
1142    std::string ResourceId = "";
1143
1144    if(!GetFileNameWithoutExtension(OutputBCFileName, ResourceId))
1145        return false;
1146
1147    if(ResourceId.empty())
1148        ResourceId = "<Resource ID>";
1149
1150    if((OutputPackageName == NULL) || (*OutputPackageName == '\0') || strcmp(OutputPackageName, "-") == 0)
1151        C = new Context("<Package Name>", ResourceId, true);
1152    else
1153        C = new Context(OutputPackageName, ResourceId, false);
1154
1155    if(C != NULL) {
1156        std::string ErrorMsg, ScriptClassName;
1157        /* class ScriptC_<ScriptName> */
1158        if(!GetFileNameWithoutExtension(InputFileName, ScriptClassName))
1159            return false;
1160
1161        if(ScriptClassName.empty())
1162            ScriptClassName = "<Input Script Name>";
1163
1164        ScriptClassName.at(0) = toupper(ScriptClassName.at(0));
1165        ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
1166
1167        if (mRSContext->getLicenseNote() != NULL)
1168            C->setLicenseNote(*mRSContext->getLicenseNote());
1169
1170        if(!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
1171            std::cerr << "Failed to generate class " << ScriptClassName << " (" << ErrorMsg << ")" << endl;
1172            return false;
1173        }
1174
1175        /* class ScriptField_<TypeName> */
1176        for(RSContext::const_export_type_iterator TI = mRSContext->export_types_begin();
1177            TI != mRSContext->export_types_end();
1178            TI++)
1179        {
1180            const RSExportType* ET = TI->getValue();
1181
1182            if(ET->getClass() == RSExportType::ExportClassRecord) {
1183                const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
1184
1185                if(!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
1186                    std::cerr << "Failed to generate type class for struct '" << ERT->getName() << "' (" << ErrorMsg << ")" << endl;
1187                    return false;
1188                }
1189            }
1190        }
1191    }
1192
1193    return true;
1194}
1195
1196/****************************** RSReflection::Context ******************************/
1197const char* const RSReflection::Context::ApacheLicenseNote =
1198    "/*\n"
1199	" * Copyright (C) 2010 The Android Open Source Project\n"
1200	" *\n"
1201	" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
1202	" * you may not use this file except in compliance with the License.\n"
1203	" * You may obtain a copy of the License at\n"
1204	" *\n"
1205	" *      http://www.apache.org/licenses/LICENSE-2.0\n"
1206	" *\n"
1207	" * Unless required by applicable law or agreed to in writing, software\n"
1208	" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
1209	" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
1210	" * See the License for the specific language governing permissions and\n"
1211	" * limitations under the License.\n"
1212	" */\n"
1213	"\n";
1214
1215const char* const RSReflection::Context::Import[] = {
1216    /* RenderScript java class */
1217    "android.renderscript.*",
1218    /* Import R */
1219    "android.content.res.Resources",
1220    /* Import for debugging */
1221    "android.util.Log",
1222};
1223
1224const char* RSReflection::Context::AccessModifierStr(AccessModifier AM) {
1225    switch(AM) {
1226        case AM_Public: return "public"; break;
1227        case AM_Protected: return "protected"; break;
1228        case AM_Private: return "private"; break;
1229        default: return ""; break;
1230    }
1231}
1232
1233bool RSReflection::Context::startClass(AccessModifier AM, bool IsStatic, const std::string& ClassName, const char* SuperClassName, std::string& ErrorMsg) {
1234    if(mVerbose)
1235        std::cout << "Generating " << ClassName << ".java ..." << endl;
1236
1237    /* License */
1238    out() << mLicenseNote;
1239
1240    /* Package */
1241    if(!mPackageName.empty())
1242        out() << "package " << mPackageName << ";" << endl;
1243    out() << endl;
1244
1245    /* Imports */
1246    for(int i=0;i<(sizeof(Import)/sizeof(const char*));i++)
1247        out() << "import " << Import[i] << ";" << endl;
1248    out() << endl;
1249
1250    out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class " << ClassName;
1251    if(SuperClassName != NULL)
1252        out() << " extends " << SuperClassName;
1253
1254    startBlock();
1255
1256    mClassName = ClassName;
1257
1258    return true;
1259}
1260
1261void RSReflection::Context::endClass() {
1262    endBlock();
1263    if(!mUseStdout)
1264        mOF.close();
1265    clear();
1266    return;
1267}
1268
1269void RSReflection::Context::startBlock(bool ShouldIndent) {
1270    if(ShouldIndent)
1271        indent() << "{" << endl;
1272    else
1273        out() << " {" << endl;
1274    incIndentLevel();
1275    return;
1276}
1277
1278void RSReflection::Context::endBlock() {
1279    decIndentLevel();
1280    indent() << "}" << endl << endl;
1281    return;
1282}
1283
1284void RSReflection::Context::startTypeClass(const std::string& ClassName) {
1285    indent() << "public static class " << ClassName;
1286    startBlock();
1287    return;
1288}
1289
1290void RSReflection::Context::endTypeClass() {
1291    endBlock();
1292    return;
1293}
1294
1295void RSReflection::Context::startFunction(AccessModifier AM, bool IsStatic, const char* ReturnType, const std::string& FunctionName, int Argc, ...) {
1296    ArgTy Args;
1297    va_list vl;
1298    va_start(vl, Argc);
1299
1300    for(int i=0;i<Argc;i++) {
1301        const char* ArgType = va_arg(vl, const char*);
1302        const char* ArgName = va_arg(vl, const char*);
1303
1304        Args.push_back( make_pair(ArgType, ArgName) );
1305    }
1306    va_end(vl);
1307
1308    startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
1309
1310    return;
1311}
1312
1313void RSReflection::Context::startFunction(AccessModifier AM,
1314                                          bool IsStatic,
1315                                          const char* ReturnType,
1316                                          const std::string& FunctionName,
1317                                          const ArgTy& Args)
1318{
1319    indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ") << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
1320
1321    bool FirstArg = true;
1322    for(ArgTy::const_iterator I = Args.begin();
1323        I != Args.end();
1324        I++)
1325    {
1326        if(!FirstArg)
1327            out() << ", ";
1328        else
1329            FirstArg = false;
1330
1331        out() << I->first << " " << I->second;
1332    }
1333
1334    out() << ")";
1335    startBlock();
1336
1337    return;
1338}
1339
1340void RSReflection::Context::endFunction() {
1341    endBlock();
1342    return;
1343}
1344
1345}   /* namespace slang */
1346