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