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