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