slang_rs_reflection.cpp revision 2e205d071c86981a8dd301a8612d17b251b3b973
1/* 2 * Copyright 2010-2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "slang_rs_reflection.h" 18 19#include <sys/stat.h> 20 21#include <cstdarg> 22#include <cctype> 23 24#include <algorithm> 25#include <sstream> 26#include <string> 27#include <utility> 28 29#include "llvm/ADT/APFloat.h" 30#include "llvm/ADT/StringExtras.h" 31 32#include "os_sep.h" 33#include "slang_rs_context.h" 34#include "slang_rs_export_var.h" 35#include "slang_rs_export_foreach.h" 36#include "slang_rs_export_func.h" 37#include "slang_rs_reflect_utils.h" 38#include "slang_version.h" 39#include "slang_utils.h" 40 41#include "slang_rs_reflection_base.h" 42 43#define RS_SCRIPT_CLASS_NAME_PREFIX "ScriptC_" 44#define RS_SCRIPT_CLASS_SUPER_CLASS_NAME "ScriptC" 45 46#define RS_TYPE_CLASS_SUPER_CLASS_NAME ".Script.FieldBase" 47 48#define RS_TYPE_ITEM_CLASS_NAME "Item" 49 50#define RS_TYPE_ITEM_BUFFER_NAME "mItemArray" 51#define RS_TYPE_ITEM_BUFFER_PACKER_NAME "mIOBuffer" 52#define RS_TYPE_ELEMENT_REF_NAME "mElementCache" 53 54#define RS_EXPORT_VAR_INDEX_PREFIX "mExportVarIdx_" 55#define RS_EXPORT_VAR_PREFIX "mExportVar_" 56#define RS_EXPORT_VAR_ELEM_PREFIX "mExportVarElem_" 57#define RS_EXPORT_VAR_DIM_PREFIX "mExportVarDim_" 58#define RS_EXPORT_VAR_CONST_PREFIX "const_" 59 60#define RS_ELEM_PREFIX "__" 61 62#define RS_FP_PREFIX "__rs_fp_" 63 64#define RS_RESOURCE_NAME "__rs_resource_name" 65 66#define RS_EXPORT_FUNC_INDEX_PREFIX "mExportFuncIdx_" 67#define RS_EXPORT_FOREACH_INDEX_PREFIX "mExportForEachIdx_" 68 69#define RS_EXPORT_VAR_ALLOCATION_PREFIX "mAlloction_" 70#define RS_EXPORT_VAR_DATA_STORAGE_PREFIX "mData_" 71 72namespace slang { 73 74// Some utility function using internal in RSReflectionJava 75static bool GetClassNameFromFileName(const std::string &FileName, 76 std::string &ClassName) { 77 ClassName.clear(); 78 79 if (FileName.empty() || (FileName == "-")) 80 return true; 81 82 ClassName = 83 RSSlangReflectUtils::JavaClassNameFromRSFileName(FileName.c_str()); 84 85 return true; 86} 87 88static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) { 89 static const char *MatrixTypeJavaNameMap[] = {/* 2x2 */ "Matrix2f", 90 /* 3x3 */ "Matrix3f", 91 /* 4x4 */ "Matrix4f", 92 }; 93 unsigned Dim = EMT->getDim(); 94 95 if ((Dim - 2) < (sizeof(MatrixTypeJavaNameMap) / sizeof(const char *))) 96 return MatrixTypeJavaNameMap[EMT->getDim() - 2]; 97 98 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension"); 99 return NULL; 100} 101 102static const char *GetVectorAccessor(unsigned Index) { 103 static const char *VectorAccessorMap[] = {/* 0 */ "x", 104 /* 1 */ "y", 105 /* 2 */ "z", 106 /* 3 */ "w", 107 }; 108 109 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) && 110 "Out-of-bound index to access vector member"); 111 112 return VectorAccessorMap[Index]; 113} 114 115static const char *GetPackerAPIName(const RSExportPrimitiveType *EPT) { 116 static const char *PrimitiveTypePackerAPINameMap[] = { 117 "", // DataTypeFloat16 118 "addF32", // DataTypeFloat32 119 "addF64", // DataTypeFloat64 120 "addI8", // DataTypeSigned8 121 "addI16", // DataTypeSigned16 122 "addI32", // DataTypeSigned32 123 "addI64", // DataTypeSigned64 124 "addU8", // DataTypeUnsigned8 125 "addU16", // DataTypeUnsigned16 126 "addU32", // DataTypeUnsigned32 127 "addU64", // DataTypeUnsigned64 128 "addBoolean", // DataTypeBoolean 129 "addU16", // DataTypeUnsigned565 130 "addU16", // DataTypeUnsigned5551 131 "addU16", // DataTypeUnsigned4444 132 "addMatrix", // DataTypeRSMatrix2x2 133 "addMatrix", // DataTypeRSMatrix3x3 134 "addMatrix", // DataTypeRSMatrix4x4 135 "addObj", // DataTypeRSElement 136 "addObj", // DataTypeRSType 137 "addObj", // DataTypeRSAllocation 138 "addObj", // DataTypeRSSampler 139 "addObj", // DataTypeRSScript 140 "addObj", // DataTypeRSMesh 141 "addObj", // DataTypeRSPath 142 "addObj", // DataTypeRSProgramFragment 143 "addObj", // DataTypeRSProgramVertex 144 "addObj", // DataTypeRSProgramRaster 145 "addObj", // DataTypeRSProgramStore 146 "addObj", // DataTypeRSFont 147 }; 148 unsigned TypeId = EPT->getType(); 149 150 if (TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char *))) 151 return PrimitiveTypePackerAPINameMap[EPT->getType()]; 152 153 slangAssert(false && "GetPackerAPIName : Unknown primitive data type"); 154 return NULL; 155} 156 157static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) { 158 switch (ET->getClass()) { 159 case RSExportType::ExportClassPrimitive: { 160 return RSExportPrimitiveType::getRSReflectionType( 161 static_cast<const RSExportPrimitiveType *>(ET))->java_name; 162 } 163 case RSExportType::ExportClassPointer: { 164 const RSExportType *PointeeType = 165 static_cast<const RSExportPointerType *>(ET)->getPointeeType(); 166 167 if (PointeeType->getClass() != RSExportType::ExportClassRecord) 168 return "Allocation"; 169 else 170 return PointeeType->getElementName(); 171 } 172 case RSExportType::ExportClassVector: { 173 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET); 174 std::stringstream VecName; 175 VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix 176 << EVT->getNumElement(); 177 return VecName.str(); 178 } 179 case RSExportType::ExportClassMatrix: { 180 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET)); 181 } 182 case RSExportType::ExportClassConstantArray: { 183 const RSExportConstantArrayType *CAT = 184 static_cast<const RSExportConstantArrayType *>(ET); 185 std::string ElementTypeName = GetTypeName(CAT->getElementType()); 186 if (Brackets) { 187 ElementTypeName.append("[]"); 188 } 189 return ElementTypeName; 190 } 191 case RSExportType::ExportClassRecord: { 192 return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME; 193 } 194 default: { slangAssert(false && "Unknown class of type"); } 195 } 196 197 return ""; 198} 199 200static const char *GetTypeNullValue(const RSExportType *ET) { 201 switch (ET->getClass()) { 202 case RSExportType::ExportClassPrimitive: { 203 const RSExportPrimitiveType *EPT = 204 static_cast<const RSExportPrimitiveType *>(ET); 205 if (EPT->isRSObjectType()) 206 return "null"; 207 else if (EPT->getType() == DataTypeBoolean) 208 return "false"; 209 else 210 return "0"; 211 break; 212 } 213 case RSExportType::ExportClassPointer: 214 case RSExportType::ExportClassVector: 215 case RSExportType::ExportClassMatrix: 216 case RSExportType::ExportClassConstantArray: 217 case RSExportType::ExportClassRecord: { 218 return "null"; 219 break; 220 } 221 default: { slangAssert(false && "Unknown class of type"); } 222 } 223 return ""; 224} 225 226static std::string GetBuiltinElementConstruct(const RSExportType *ET) { 227 if (ET->getClass() == RSExportType::ExportClassPrimitive) { 228 return std::string("Element.") + ET->getElementName(); 229 } else if (ET->getClass() == RSExportType::ExportClassVector) { 230 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET); 231 if (EVT->getType() == DataTypeFloat32) { 232 if (EVT->getNumElement() == 2) 233 return "Element.F32_2"; 234 else if (EVT->getNumElement() == 3) 235 return "Element.F32_3"; 236 else if (EVT->getNumElement() == 4) 237 return "Element.F32_4"; 238 } else if (EVT->getType() == DataTypeUnsigned8) { 239 if (EVT->getNumElement() == 4) 240 return "Element.U8_4"; 241 } 242 } else if (ET->getClass() == RSExportType::ExportClassMatrix) { 243 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType *>(ET); 244 switch (EMT->getDim()) { 245 case 2: 246 return "Element.MATRIX_2X2"; 247 case 3: 248 return "Element.MATRIX_3X3"; 249 case 4: 250 return "Element.MATRIX_4X4"; 251 default: 252 slangAssert(false && "Unsupported dimension of matrix"); 253 } 254 } 255 // RSExportType::ExportClassPointer can't be generated in a struct. 256 257 return ""; 258} 259 260// Replace all instances of "\" with "\\" in a single string to prevent 261// formatting errors due to unicode. 262static std::string SanitizeString(std::string s) { 263 size_t p = 0; 264 while ((p = s.find('\\', p)) != std::string::npos) { 265 s.replace(p, 1, "\\\\"); 266 p += 2; 267 } 268 return s; 269} 270 271/********************** Methods to generate script class **********************/ 272bool RSReflectionJava::genScriptClass(const std::string &ClassName, 273 std::string &ErrorMsg) { 274 if (!startClass(AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME, 275 ErrorMsg)) 276 return false; 277 278 genScriptClassConstructor(); 279 280 // Reflect export variable 281 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 282 E = mRSContext->export_vars_end(); 283 I != E; I++) 284 genExportVariable(*I); 285 286 // Reflect export for each functions (only available on ICS+) 287 if (mRSContext->getTargetAPI() >= SLANG_ICS_TARGET_API) { 288 for (RSContext::const_export_foreach_iterator 289 I = mRSContext->export_foreach_begin(), 290 E = mRSContext->export_foreach_end(); 291 I != E; I++) 292 genExportForEach(*I); 293 } 294 295 // Reflect export function 296 for (RSContext::const_export_func_iterator 297 I = mRSContext->export_funcs_begin(), 298 E = mRSContext->export_funcs_end(); 299 I != E; I++) 300 genExportFunction(*I); 301 302 endClass(); 303 304 return true; 305} 306 307void RSReflectionJava::genScriptClassConstructor() { 308 std::string className(RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName( 309 getInputFileName().c_str())); 310 // Provide a simple way to reference this object. 311 indent() << "private static final String " RS_RESOURCE_NAME " = \"" 312 << getResourceId() << "\";\n"; 313 314 // Generate a simple constructor with only a single parameter (the rest 315 // can be inferred from information we already have). 316 indent() << "// Constructor\n"; 317 startFunction(AM_Public, false, NULL, getClassName(), 1, "RenderScript", 318 "rs"); 319 320 if (getEmbedBitcodeInJava()) { 321 // Call new single argument Java-only constructor 322 indent() << "super(rs,\n"; 323 indent() << " " << RS_RESOURCE_NAME ",\n"; 324 indent() << " " << className << ".getBitCode32(),\n"; 325 // TODO(srhines): Replace the extra BitCode32 with Bitcode64 here! 326 // indent() << " " << className << ".getBitCode64());\n"; 327 indent() << " " << className << ".getBitCode32());\n"; 328 } else { 329 // Call alternate constructor with required parameters. 330 // Look up the proper raw bitcode resource id via the context. 331 indent() << "this(rs,\n"; 332 indent() << " rs.getApplicationContext().getResources(),\n"; 333 indent() << " rs.getApplicationContext().getResources()." 334 "getIdentifier(\n"; 335 indent() << " " RS_RESOURCE_NAME ", \"raw\",\n"; 336 indent() << " rs.getApplicationContext().getPackageName()));\n"; 337 endFunction(); 338 339 // Alternate constructor (legacy) with 3 original parameters. 340 startFunction(AM_Public, false, NULL, getClassName(), 3, "RenderScript", 341 "rs", "Resources", "resources", "int", "id"); 342 // Call constructor of super class 343 indent() << "super(rs, resources, id);\n"; 344 } 345 346 // If an exported variable has initial value, reflect it 347 348 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 349 E = mRSContext->export_vars_end(); 350 I != E; I++) { 351 const RSExportVar *EV = *I; 352 if (!EV->getInit().isUninit()) { 353 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit()); 354 } else if (EV->getArraySize()) { 355 // Always create an initial zero-init array object. 356 indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = new " 357 << GetTypeName(EV->getType(), false) << "[" << EV->getArraySize() 358 << "];\n"; 359 size_t NumInits = EV->getNumInits(); 360 const RSExportConstantArrayType *ECAT = 361 static_cast<const RSExportConstantArrayType *>(EV->getType()); 362 const RSExportType *ET = ECAT->getElementType(); 363 for (size_t i = 0; i < NumInits; i++) { 364 std::stringstream Name; 365 Name << EV->getName() << "[" << i << "]"; 366 genInitExportVariable(ET, Name.str(), EV->getInitArray(i)); 367 } 368 } 369 if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) { 370 genTypeInstance(EV->getType()); 371 } 372 genFieldPackerInstance(EV->getType()); 373 } 374 375 for (RSContext::const_export_foreach_iterator 376 I = mRSContext->export_foreach_begin(), 377 E = mRSContext->export_foreach_end(); 378 I != E; I++) { 379 const RSExportForEach *EF = *I; 380 381 const RSExportType *IET = EF->getInType(); 382 if (IET) { 383 genTypeInstanceFromPointer(IET); 384 } 385 const RSExportType *OET = EF->getOutType(); 386 if (OET) { 387 genTypeInstanceFromPointer(OET); 388 } 389 } 390 391 endFunction(); 392 393 for (std::set<std::string>::iterator I = mTypesToCheck.begin(), 394 E = mTypesToCheck.end(); 395 I != E; I++) { 396 indent() << "private Element " RS_ELEM_PREFIX << *I << ";\n"; 397 } 398 399 for (std::set<std::string>::iterator I = mFieldPackerTypes.begin(), 400 E = mFieldPackerTypes.end(); 401 I != E; I++) { 402 indent() << "private FieldPacker " RS_FP_PREFIX << *I << ";\n"; 403 } 404} 405 406void RSReflectionJava::genInitBoolExportVariable(const std::string &VarName, 407 const clang::APValue &Val) { 408 slangAssert(!Val.isUninit() && "Not a valid initializer"); 409 slangAssert((Val.getKind() == clang::APValue::Int) && 410 "Bool type has wrong initial APValue"); 411 412 indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "; 413 414 out() << ((Val.getInt().getSExtValue() == 0) ? "false" : "true") << ";\n"; 415} 416 417void 418RSReflectionJava::genInitPrimitiveExportVariable(const std::string &VarName, 419 const clang::APValue &Val) { 420 slangAssert(!Val.isUninit() && "Not a valid initializer"); 421 422 indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "; 423 out() << RSReflectionBase::genInitValue(Val) << ";\n"; 424} 425 426void RSReflectionJava::genInitExportVariable(const RSExportType *ET, 427 const std::string &VarName, 428 const clang::APValue &Val) { 429 slangAssert(!Val.isUninit() && "Not a valid initializer"); 430 431 switch (ET->getClass()) { 432 case RSExportType::ExportClassPrimitive: { 433 const RSExportPrimitiveType *EPT = 434 static_cast<const RSExportPrimitiveType *>(ET); 435 if (EPT->getType() == DataTypeBoolean) { 436 genInitBoolExportVariable(VarName, Val); 437 } else { 438 genInitPrimitiveExportVariable(VarName, Val); 439 } 440 break; 441 } 442 case RSExportType::ExportClassPointer: { 443 if (!Val.isInt() || Val.getInt().getSExtValue() != 0) 444 std::cout << "Initializer which is non-NULL to pointer type variable " 445 "will be ignored\n"; 446 break; 447 } 448 case RSExportType::ExportClassVector: { 449 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET); 450 switch (Val.getKind()) { 451 case clang::APValue::Int: 452 case clang::APValue::Float: { 453 for (unsigned i = 0; i < EVT->getNumElement(); i++) { 454 std::string Name = VarName + "." + GetVectorAccessor(i); 455 genInitPrimitiveExportVariable(Name, Val); 456 } 457 break; 458 } 459 case clang::APValue::Vector: { 460 std::stringstream VecName; 461 VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix 462 << EVT->getNumElement(); 463 indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new " << VecName.str() 464 << "();\n"; 465 466 unsigned NumElements = std::min( 467 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength()); 468 for (unsigned i = 0; i < NumElements; i++) { 469 const clang::APValue &ElementVal = Val.getVectorElt(i); 470 std::string Name = VarName + "." + GetVectorAccessor(i); 471 genInitPrimitiveExportVariable(Name, ElementVal); 472 } 473 break; 474 } 475 case clang::APValue::MemberPointer: 476 case clang::APValue::Uninitialized: 477 case clang::APValue::ComplexInt: 478 case clang::APValue::ComplexFloat: 479 case clang::APValue::LValue: 480 case clang::APValue::Array: 481 case clang::APValue::Struct: 482 case clang::APValue::Union: 483 case clang::APValue::AddrLabelDiff: { 484 slangAssert(false && "Unexpected type of value of initializer."); 485 } 486 } 487 break; 488 } 489 // TODO(zonr): Resolving initializer of a record (and matrix) type variable 490 // is complex. It cannot obtain by just simply evaluating the initializer 491 // expression. 492 case RSExportType::ExportClassMatrix: 493 case RSExportType::ExportClassConstantArray: 494 case RSExportType::ExportClassRecord: { 495#if 0 496 unsigned InitIndex = 0; 497 const RSExportRecordType *ERT = 498 static_cast<const RSExportRecordType*>(ET); 499 500 slangAssert((Val.getKind() == clang::APValue::Vector) && 501 "Unexpected type of initializer for record type variable"); 502 503 indent() << RS_EXPORT_VAR_PREFIX << VarName 504 << " = new " << ERT->getElementName() 505 << "." RS_TYPE_ITEM_CLASS_NAME"();\n"; 506 507 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 508 E = ERT->fields_end(); 509 I != E; 510 I++) { 511 const RSExportRecordType::Field *F = *I; 512 std::string FieldName = VarName + "." + F->getName(); 513 514 if (InitIndex > Val.getVectorLength()) 515 break; 516 517 genInitPrimitiveExportVariable( 518 FieldName, 519 Val.getVectorElt(InitIndex++)); 520 } 521#endif 522 slangAssert(false && "Unsupported initializer for record/matrix/constant " 523 "array type variable currently"); 524 break; 525 } 526 default: { slangAssert(false && "Unknown class of type"); } 527 } 528} 529 530void RSReflectionJava::genExportVariable(const RSExportVar *EV) { 531 const RSExportType *ET = EV->getType(); 532 533 indent() << "private final static int " RS_EXPORT_VAR_INDEX_PREFIX 534 << EV->getName() << " = " << getNextExportVarSlot() << ";\n"; 535 536 switch (ET->getClass()) { 537 case RSExportType::ExportClassPrimitive: { 538 genPrimitiveTypeExportVariable(EV); 539 break; 540 } 541 case RSExportType::ExportClassPointer: { 542 genPointerTypeExportVariable(EV); 543 break; 544 } 545 case RSExportType::ExportClassVector: { 546 genVectorTypeExportVariable(EV); 547 break; 548 } 549 case RSExportType::ExportClassMatrix: { 550 genMatrixTypeExportVariable(EV); 551 break; 552 } 553 case RSExportType::ExportClassConstantArray: { 554 genConstantArrayTypeExportVariable(EV); 555 break; 556 } 557 case RSExportType::ExportClassRecord: { 558 genRecordTypeExportVariable(EV); 559 break; 560 } 561 default: { slangAssert(false && "Unknown class of type"); } 562 } 563} 564 565void RSReflectionJava::genExportFunction(const RSExportFunc *EF) { 566 indent() << "private final static int " RS_EXPORT_FUNC_INDEX_PREFIX 567 << EF->getName() << " = " << getNextExportFuncSlot() << ";\n"; 568 569 // invoke_*() 570 ArgTy Args; 571 572 if (EF->hasParam()) { 573 for (RSExportFunc::const_param_iterator I = EF->params_begin(), 574 E = EF->params_end(); 575 I != E; I++) { 576 Args.push_back( 577 std::make_pair(GetTypeName((*I)->getType()), (*I)->getName())); 578 } 579 } 580 581 startFunction(AM_Public, false, "void", 582 "invoke_" + EF->getName(/*Mangle=*/false), 583 // We are using un-mangled name since Java 584 // supports method overloading. 585 Args); 586 587 if (!EF->hasParam()) { 588 indent() << "invoke(" RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() 589 << ");\n"; 590 } else { 591 const RSExportRecordType *ERT = EF->getParamPacketType(); 592 std::string FieldPackerName = EF->getName() + "_fp"; 593 594 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) 595 genPackVarOfType(ERT, NULL, FieldPackerName.c_str()); 596 597 indent() << "invoke(" RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", " 598 << FieldPackerName << ");\n"; 599 } 600 601 endFunction(); 602} 603 604void RSReflectionJava::genExportForEach(const RSExportForEach *EF) { 605 if (EF->isDummyRoot()) { 606 // Skip reflection for dummy root() kernels. Note that we have to 607 // advance the next slot number for ForEach, however. 608 indent() << "//private final static int " RS_EXPORT_FOREACH_INDEX_PREFIX 609 << EF->getName() << " = " << getNextExportForEachSlot() << ";\n"; 610 return; 611 } 612 613 indent() << "private final static int " RS_EXPORT_FOREACH_INDEX_PREFIX 614 << EF->getName() << " = " << getNextExportForEachSlot() << ";\n"; 615 616 // forEach_*() 617 ArgTy Args; 618 619 slangAssert(EF->getNumParameters() > 0 || EF->hasReturn()); 620 621 if (EF->hasIn()) 622 Args.push_back(std::make_pair("Allocation", "ain")); 623 if (EF->hasOut() || EF->hasReturn()) 624 Args.push_back(std::make_pair("Allocation", "aout")); 625 626 const RSExportRecordType *ERT = EF->getParamPacketType(); 627 if (ERT) { 628 for (RSExportForEach::const_param_iterator I = EF->params_begin(), 629 E = EF->params_end(); 630 I != E; I++) { 631 Args.push_back( 632 std::make_pair(GetTypeName((*I)->getType()), (*I)->getName())); 633 } 634 } 635 636 const RSExportType *IET = EF->getInType(); 637 const RSExportType *OET = EF->getOutType(); 638 639 if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) { 640 int signature = 0; 641 startFunction(AM_Public, false, "Script.KernelID", 642 "getKernelID_" + EF->getName(), 0); 643 644 if (IET) 645 signature |= 1; 646 if (OET) 647 signature |= 2; 648 649 // TODO: add element checking 650 indent() << "return createKernelID(" << RS_EXPORT_FOREACH_INDEX_PREFIX 651 << EF->getName() << ", " << signature << ", null, null);\n"; 652 653 endFunction(); 654 } 655 656 if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) { 657 startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args); 658 659 indent() << "forEach_" << EF->getName(); 660 out() << "("; 661 662 if (EF->hasIn()) { 663 out() << "ain, "; 664 } 665 666 if (EF->hasOut() || EF->hasReturn()) { 667 out() << "aout, "; 668 } 669 670 if (EF->hasUsrData()) { 671 out() << Args.back().second << ", "; 672 } 673 674 // No clipped bounds to pass in. 675 out() << "null);\n"; 676 677 endFunction(); 678 679 // Add the clipped kernel parameters to the Args list. 680 Args.push_back(std::make_pair("Script.LaunchOptions", "sc")); 681 } 682 683 startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args); 684 685 if (IET) { 686 genTypeCheck(IET, "ain"); 687 } 688 if (OET) { 689 genTypeCheck(OET, "aout"); 690 } 691 692 if (EF->hasIn() && (EF->hasOut() || EF->hasReturn())) { 693 indent() << "// Verify dimensions\n"; 694 indent() << "Type tIn = ain.getType();\n"; 695 indent() << "Type tOut = aout.getType();\n"; 696 indent() << "if ((tIn.getCount() != tOut.getCount()) ||\n"; 697 indent() << " (tIn.getX() != tOut.getX()) ||\n"; 698 indent() << " (tIn.getY() != tOut.getY()) ||\n"; 699 indent() << " (tIn.getZ() != tOut.getZ()) ||\n"; 700 indent() << " (tIn.hasFaces() != tOut.hasFaces()) ||\n"; 701 indent() << " (tIn.hasMipmaps() != tOut.hasMipmaps())) {\n"; 702 indent() << " throw new RSRuntimeException(\"Dimension mismatch " 703 << "between input and output parameters!\");\n"; 704 indent() << "}\n"; 705 } 706 707 std::string FieldPackerName = EF->getName() + "_fp"; 708 if (ERT) { 709 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) { 710 genPackVarOfType(ERT, NULL, FieldPackerName.c_str()); 711 } 712 } 713 indent() << "forEach(" RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName(); 714 715 if (EF->hasIn()) 716 out() << ", ain"; 717 else 718 out() << ", null"; 719 720 if (EF->hasOut() || EF->hasReturn()) 721 out() << ", aout"; 722 else 723 out() << ", null"; 724 725 if (EF->hasUsrData()) 726 out() << ", " << FieldPackerName; 727 else 728 out() << ", null"; 729 730 if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) { 731 out() << ", sc);\n"; 732 } else { 733 out() << ");\n"; 734 } 735 736 endFunction(); 737} 738 739void RSReflectionJava::genTypeInstanceFromPointer(const RSExportType *ET) { 740 if (ET->getClass() == RSExportType::ExportClassPointer) { 741 // For pointer parameters to original forEach kernels. 742 const RSExportPointerType *EPT = 743 static_cast<const RSExportPointerType *>(ET); 744 genTypeInstance(EPT->getPointeeType()); 745 } else { 746 // For handling pass-by-value kernel parameters. 747 genTypeInstance(ET); 748 } 749} 750 751void RSReflectionJava::genTypeInstance(const RSExportType *ET) { 752 switch (ET->getClass()) { 753 case RSExportType::ExportClassPrimitive: 754 case RSExportType::ExportClassVector: 755 case RSExportType::ExportClassConstantArray: { 756 std::string TypeName = ET->getElementName(); 757 if (addTypeNameForElement(TypeName)) { 758 indent() << RS_ELEM_PREFIX << TypeName << " = Element." << TypeName 759 << "(rs);\n"; 760 } 761 break; 762 } 763 764 case RSExportType::ExportClassRecord: { 765 std::string ClassName = ET->getElementName(); 766 if (addTypeNameForElement(ClassName)) { 767 indent() << RS_ELEM_PREFIX << ClassName << " = " << ClassName 768 << ".createElement(rs);\n"; 769 } 770 break; 771 } 772 773 default: 774 break; 775 } 776} 777 778void RSReflectionJava::genFieldPackerInstance(const RSExportType *ET) { 779 switch (ET->getClass()) { 780 case RSExportType::ExportClassPrimitive: 781 case RSExportType::ExportClassVector: 782 case RSExportType::ExportClassConstantArray: 783 case RSExportType::ExportClassRecord: { 784 std::string TypeName = ET->getElementName(); 785 addTypeNameForFieldPacker(TypeName); 786 break; 787 } 788 789 default: 790 break; 791 } 792} 793 794void RSReflectionJava::genTypeCheck(const RSExportType *ET, 795 const char *VarName) { 796 indent() << "// check " << VarName << "\n"; 797 798 if (ET->getClass() == RSExportType::ExportClassPointer) { 799 const RSExportPointerType *EPT = 800 static_cast<const RSExportPointerType *>(ET); 801 ET = EPT->getPointeeType(); 802 } 803 804 std::string TypeName; 805 806 switch (ET->getClass()) { 807 case RSExportType::ExportClassPrimitive: 808 case RSExportType::ExportClassVector: 809 case RSExportType::ExportClassRecord: { 810 TypeName = ET->getElementName(); 811 break; 812 } 813 814 default: 815 break; 816 } 817 818 if (!TypeName.empty()) { 819 indent() << "if (!" << VarName 820 << ".getType().getElement().isCompatible(" RS_ELEM_PREFIX 821 << TypeName << ")) {\n"; 822 indent() << " throw new RSRuntimeException(\"Type mismatch with " 823 << TypeName << "!\");\n"; 824 indent() << "}\n"; 825 } 826} 827 828void RSReflectionJava::genPrimitiveTypeExportVariable(const RSExportVar *EV) { 829 slangAssert( 830 (EV->getType()->getClass() == RSExportType::ExportClassPrimitive) && 831 "Variable should be type of primitive here"); 832 833 const RSExportPrimitiveType *EPT = 834 static_cast<const RSExportPrimitiveType *>(EV->getType()); 835 std::string TypeName = GetTypeName(EPT); 836 std::string VarName = EV->getName(); 837 838 genPrivateExportVariable(TypeName, EV->getName()); 839 840 if (EV->isConst()) { 841 indent() << "public final static " << TypeName 842 << " " RS_EXPORT_VAR_CONST_PREFIX << VarName << " = "; 843 const clang::APValue &Val = EV->getInit(); 844 out() << RSReflectionBase::genInitValue(Val, EPT->getType() == 845 DataTypeBoolean) << ";\n"; 846 } else { 847 // set_*() 848 // This must remain synchronized, since multiple Dalvik threads may 849 // be calling setters. 850 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1, 851 TypeName.c_str(), "v"); 852 if ((EPT->getSize() < 4) || EV->isUnsigned()) { 853 // We create/cache a per-type FieldPacker. This allows us to reuse the 854 // validation logic (for catching negative inputs from Dalvik, as well 855 // as inputs that are too large to be represented in the unsigned type). 856 // Sub-integer types are also handled specially here, so that we don't 857 // overwrite bytes accidentally. 858 std::string ElemName = EPT->getElementName(); 859 std::string FPName; 860 FPName = RS_FP_PREFIX + ElemName; 861 indent() << "if (" << FPName << "!= null) {\n"; 862 incIndentLevel(); 863 indent() << FPName << ".reset();\n"; 864 decIndentLevel(); 865 indent() << "} else {\n"; 866 incIndentLevel(); 867 indent() << FPName << " = new FieldPacker(" << EPT->getSize() << ");\n"; 868 decIndentLevel(); 869 indent() << "}\n"; 870 871 genPackVarOfType(EPT, "v", FPName.c_str()); 872 indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", " 873 << FPName << ");\n"; 874 } else { 875 indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", v);\n"; 876 } 877 878 // Dalvik update comes last, since the input may be invalid (and hence 879 // throw an exception). 880 indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 881 882 endFunction(); 883 } 884 885 genGetExportVariable(TypeName, VarName); 886 genGetFieldID(VarName); 887} 888 889void RSReflectionJava::genPointerTypeExportVariable(const RSExportVar *EV) { 890 const RSExportType *ET = EV->getType(); 891 const RSExportType *PointeeType; 892 893 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) && 894 "Variable should be type of pointer here"); 895 896 PointeeType = static_cast<const RSExportPointerType *>(ET)->getPointeeType(); 897 std::string TypeName = GetTypeName(ET); 898 std::string VarName = EV->getName(); 899 900 genPrivateExportVariable(TypeName, VarName); 901 902 // bind_*() 903 startFunction(AM_Public, false, "void", "bind_" + VarName, 1, 904 TypeName.c_str(), "v"); 905 906 indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 907 indent() << "if (v == null) bindAllocation(null, " RS_EXPORT_VAR_INDEX_PREFIX 908 << VarName << ");\n"; 909 910 if (PointeeType->getClass() == RSExportType::ExportClassRecord) 911 indent() 912 << "else bindAllocation(v.getAllocation(), " RS_EXPORT_VAR_INDEX_PREFIX 913 << VarName << ");\n"; 914 else 915 indent() << "else bindAllocation(v, " RS_EXPORT_VAR_INDEX_PREFIX << VarName 916 << ");\n"; 917 918 endFunction(); 919 920 genGetExportVariable(TypeName, VarName); 921} 922 923void RSReflectionJava::genVectorTypeExportVariable(const RSExportVar *EV) { 924 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) && 925 "Variable should be type of vector here"); 926 927 std::string TypeName = GetTypeName(EV->getType()); 928 std::string VarName = EV->getName(); 929 930 genPrivateExportVariable(TypeName, VarName); 931 genSetExportVariable(TypeName, EV); 932 genGetExportVariable(TypeName, VarName); 933 genGetFieldID(VarName); 934} 935 936void RSReflectionJava::genMatrixTypeExportVariable(const RSExportVar *EV) { 937 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) && 938 "Variable should be type of matrix here"); 939 940 const RSExportType *ET = EV->getType(); 941 std::string TypeName = GetTypeName(ET); 942 std::string VarName = EV->getName(); 943 944 genPrivateExportVariable(TypeName, VarName); 945 946 // set_*() 947 if (!EV->isConst()) { 948 const char *FieldPackerName = "fp"; 949 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1, 950 TypeName.c_str(), "v"); 951 indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 952 953 if (genCreateFieldPacker(ET, FieldPackerName)) 954 genPackVarOfType(ET, "v", FieldPackerName); 955 indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", " 956 << FieldPackerName << ");\n"; 957 958 endFunction(); 959 } 960 961 genGetExportVariable(TypeName, VarName); 962 genGetFieldID(VarName); 963} 964 965void 966RSReflectionJava::genConstantArrayTypeExportVariable(const RSExportVar *EV) { 967 slangAssert( 968 (EV->getType()->getClass() == RSExportType::ExportClassConstantArray) && 969 "Variable should be type of constant array here"); 970 971 std::string TypeName = GetTypeName(EV->getType()); 972 std::string VarName = EV->getName(); 973 974 genPrivateExportVariable(TypeName, VarName); 975 genSetExportVariable(TypeName, EV); 976 genGetExportVariable(TypeName, VarName); 977 genGetFieldID(VarName); 978} 979 980void RSReflectionJava::genRecordTypeExportVariable(const RSExportVar *EV) { 981 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassRecord) && 982 "Variable should be type of struct here"); 983 984 std::string TypeName = GetTypeName(EV->getType()); 985 std::string VarName = EV->getName(); 986 987 genPrivateExportVariable(TypeName, VarName); 988 genSetExportVariable(TypeName, EV); 989 genGetExportVariable(TypeName, VarName); 990 genGetFieldID(VarName); 991} 992 993void RSReflectionJava::genPrivateExportVariable(const std::string &TypeName, 994 const std::string &VarName) { 995 indent() << "private " << TypeName << " " RS_EXPORT_VAR_PREFIX << VarName 996 << ";\n"; 997} 998 999void RSReflectionJava::genSetExportVariable(const std::string &TypeName, 1000 const RSExportVar *EV) { 1001 if (!EV->isConst()) { 1002 const char *FieldPackerName = "fp"; 1003 std::string VarName = EV->getName(); 1004 const RSExportType *ET = EV->getType(); 1005 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1, 1006 TypeName.c_str(), "v"); 1007 indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 1008 1009 if (genCreateFieldPacker(ET, FieldPackerName)) 1010 genPackVarOfType(ET, "v", FieldPackerName); 1011 1012 if (mRSContext->getTargetAPI() < SLANG_JB_TARGET_API) { 1013 // Legacy apps must use the old setVar() without Element/dim components. 1014 indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", " 1015 << FieldPackerName << ");\n"; 1016 } else { 1017 // We only have support for one-dimensional array reflection today, 1018 // but the entry point (i.e. setVar()) takes an array of dimensions. 1019 indent() << "int []__dimArr = new int[1];\n"; 1020 indent() << "__dimArr[0] = " << ET->getSize() << ";\n"; 1021 indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", " 1022 << FieldPackerName << ", " RS_ELEM_PREFIX << ET->getElementName() 1023 << ", __dimArr);\n"; 1024 } 1025 1026 endFunction(); 1027 } 1028} 1029 1030void RSReflectionJava::genGetExportVariable(const std::string &TypeName, 1031 const std::string &VarName) { 1032 startFunction(AM_Public, false, TypeName.c_str(), "get_" + VarName, 0); 1033 1034 indent() << "return " RS_EXPORT_VAR_PREFIX << VarName << ";\n"; 1035 1036 endFunction(); 1037} 1038 1039void RSReflectionJava::genGetFieldID(const std::string &VarName) { 1040 // We only generate getFieldID_*() for non-Pointer (bind) types. 1041 if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) { 1042 startFunction(AM_Public, false, "Script.FieldID", "getFieldID_" + VarName, 1043 0); 1044 1045 indent() << "return createFieldID(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName 1046 << ", null);\n"; 1047 1048 endFunction(); 1049 } 1050} 1051 1052/******************* Methods to generate script class /end *******************/ 1053 1054bool RSReflectionJava::genCreateFieldPacker(const RSExportType *ET, 1055 const char *FieldPackerName) { 1056 size_t AllocSize = ET->getAllocSize(); 1057 if (AllocSize > 0) 1058 indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(" 1059 << AllocSize << ");\n"; 1060 else 1061 return false; 1062 return true; 1063} 1064 1065void RSReflectionJava::genPackVarOfType(const RSExportType *ET, 1066 const char *VarName, 1067 const char *FieldPackerName) { 1068 switch (ET->getClass()) { 1069 case RSExportType::ExportClassPrimitive: 1070 case RSExportType::ExportClassVector: { 1071 indent() << FieldPackerName << "." 1072 << GetPackerAPIName(static_cast<const RSExportPrimitiveType *>(ET)) 1073 << "(" << VarName << ");\n"; 1074 break; 1075 } 1076 case RSExportType::ExportClassPointer: { 1077 // Must reflect as type Allocation in Java 1078 const RSExportType *PointeeType = 1079 static_cast<const RSExportPointerType *>(ET)->getPointeeType(); 1080 1081 if (PointeeType->getClass() != RSExportType::ExportClassRecord) 1082 indent() << FieldPackerName << ".addI32(" << VarName << ".getPtr());\n"; 1083 else 1084 indent() << FieldPackerName << ".addI32(" << VarName 1085 << ".getAllocation().getPtr());\n"; 1086 break; 1087 } 1088 case RSExportType::ExportClassMatrix: { 1089 indent() << FieldPackerName << ".addMatrix(" << VarName << ");\n"; 1090 break; 1091 } 1092 case RSExportType::ExportClassConstantArray: { 1093 const RSExportConstantArrayType *ECAT = 1094 static_cast<const RSExportConstantArrayType *>(ET); 1095 1096 // TODO(zonr): more elegant way. Currently, we obtain the unique index 1097 // variable (this method involves recursive call which means 1098 // we may have more than one level loop, therefore we can't 1099 // always use the same index variable name here) name given 1100 // in the for-loop from counting the '.' in @VarName. 1101 unsigned Level = 0; 1102 size_t LastDotPos = 0; 1103 std::string ElementVarName(VarName); 1104 1105 while (LastDotPos != std::string::npos) { 1106 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1); 1107 Level++; 1108 } 1109 std::string IndexVarName("ct"); 1110 IndexVarName.append(llvm::utostr_32(Level)); 1111 1112 indent() << "for (int " << IndexVarName << " = 0; " << IndexVarName << " < " 1113 << ECAT->getSize() << "; " << IndexVarName << "++)"; 1114 startBlock(); 1115 1116 ElementVarName.append("[" + IndexVarName + "]"); 1117 genPackVarOfType(ECAT->getElementType(), ElementVarName.c_str(), 1118 FieldPackerName); 1119 1120 endBlock(); 1121 break; 1122 } 1123 case RSExportType::ExportClassRecord: { 1124 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET); 1125 // Relative pos from now on in field packer 1126 unsigned Pos = 0; 1127 1128 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 1129 E = ERT->fields_end(); 1130 I != E; I++) { 1131 const RSExportRecordType::Field *F = *I; 1132 std::string FieldName; 1133 size_t FieldOffset = F->getOffsetInParent(); 1134 const RSExportType *T = F->getType(); 1135 size_t FieldStoreSize = T->getStoreSize(); 1136 size_t FieldAllocSize = T->getAllocSize(); 1137 1138 if (VarName != NULL) 1139 FieldName = VarName + ("." + F->getName()); 1140 else 1141 FieldName = F->getName(); 1142 1143 if (FieldOffset > Pos) 1144 indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos) 1145 << ");\n"; 1146 1147 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName); 1148 1149 // There is padding in the field type 1150 if (FieldAllocSize > FieldStoreSize) 1151 indent() << FieldPackerName << ".skip(" 1152 << (FieldAllocSize - FieldStoreSize) << ");\n"; 1153 1154 Pos = FieldOffset + FieldAllocSize; 1155 } 1156 1157 // There maybe some padding after the struct 1158 if (ERT->getAllocSize() > Pos) 1159 indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos 1160 << ");\n"; 1161 break; 1162 } 1163 default: { slangAssert(false && "Unknown class of type"); } 1164 } 1165} 1166 1167void RSReflectionJava::genAllocateVarOfType(const RSExportType *T, 1168 const std::string &VarName) { 1169 switch (T->getClass()) { 1170 case RSExportType::ExportClassPrimitive: { 1171 // Primitive type like int in Java has its own storage once it's declared. 1172 // 1173 // FIXME: Should we allocate storage for RS object? 1174 // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType()) 1175 // indent() << VarName << " = new " << GetTypeName(T) << "();\n"; 1176 break; 1177 } 1178 case RSExportType::ExportClassPointer: { 1179 // Pointer type is an instance of Allocation or a TypeClass whose value is 1180 // expected to be assigned by programmer later in Java program. Therefore 1181 // we don't reflect things like [VarName] = new Allocation(); 1182 indent() << VarName << " = null;\n"; 1183 break; 1184 } 1185 case RSExportType::ExportClassConstantArray: { 1186 const RSExportConstantArrayType *ECAT = 1187 static_cast<const RSExportConstantArrayType *>(T); 1188 const RSExportType *ElementType = ECAT->getElementType(); 1189 1190 indent() << VarName << " = new " << GetTypeName(ElementType) << "[" 1191 << ECAT->getSize() << "];\n"; 1192 1193 // Primitive type element doesn't need allocation code. 1194 if (ElementType->getClass() != RSExportType::ExportClassPrimitive) { 1195 indent() << "for (int $ct = 0; $ct < " << ECAT->getSize() << "; " 1196 "$ct++)"; 1197 startBlock(); 1198 1199 std::string ElementVarName(VarName); 1200 ElementVarName.append("[$ct]"); 1201 genAllocateVarOfType(ElementType, ElementVarName); 1202 1203 endBlock(); 1204 } 1205 break; 1206 } 1207 case RSExportType::ExportClassVector: 1208 case RSExportType::ExportClassMatrix: 1209 case RSExportType::ExportClassRecord: { 1210 indent() << VarName << " = new " << GetTypeName(T) << "();\n"; 1211 break; 1212 } 1213 } 1214} 1215 1216void RSReflectionJava::genNewItemBufferIfNull(const char *Index) { 1217 indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME 1218 " == null) " RS_TYPE_ITEM_BUFFER_NAME " = " 1219 "new " RS_TYPE_ITEM_CLASS_NAME 1220 "[getType().getX() /* count */];\n"; 1221 if (Index != NULL) 1222 indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME "[" << Index 1223 << "] == null) " RS_TYPE_ITEM_BUFFER_NAME "[" << Index 1224 << "] = " 1225 "new " RS_TYPE_ITEM_CLASS_NAME "();\n"; 1226} 1227 1228void RSReflectionJava::genNewItemBufferPackerIfNull() { 1229 indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME 1230 " == null) " RS_TYPE_ITEM_BUFFER_PACKER_NAME " = " 1231 "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME 1232 ".sizeof * getType().getX()/* count */" 1233 ");\n"; 1234} 1235 1236/********************** Methods to generate type class **********************/ 1237bool RSReflectionJava::genTypeClass(const RSExportRecordType *ERT, 1238 std::string &ErrorMsg) { 1239 std::string ClassName = ERT->getElementName(); 1240 std::string superClassName = getRSPackageName(); 1241 superClassName += RS_TYPE_CLASS_SUPER_CLASS_NAME; 1242 1243 if (!startClass(AM_Public, false, ClassName, superClassName.c_str(), 1244 ErrorMsg)) 1245 return false; 1246 1247 mGeneratedFileNames->push_back(ClassName); 1248 1249 genTypeItemClass(ERT); 1250 1251 // Declare item buffer and item buffer packer 1252 indent() << "private " RS_TYPE_ITEM_CLASS_NAME " " RS_TYPE_ITEM_BUFFER_NAME 1253 "[]" 1254 ";\n"; 1255 indent() << "private FieldPacker " RS_TYPE_ITEM_BUFFER_PACKER_NAME ";\n"; 1256 indent() << "private static " 1257 "java.lang.ref.WeakReference<Element> " RS_TYPE_ELEMENT_REF_NAME 1258 " = new java.lang.ref.WeakReference<Element>(null);\n"; 1259 1260 genTypeClassConstructor(ERT); 1261 genTypeClassCopyToArrayLocal(ERT); 1262 genTypeClassCopyToArray(ERT); 1263 genTypeClassItemSetter(ERT); 1264 genTypeClassItemGetter(ERT); 1265 genTypeClassComponentSetter(ERT); 1266 genTypeClassComponentGetter(ERT); 1267 genTypeClassCopyAll(ERT); 1268 if (!mRSContext->isCompatLib()) { 1269 // Skip the resize method if we are targeting a compatibility library. 1270 genTypeClassResize(); 1271 } 1272 1273 endClass(); 1274 1275 resetFieldIndex(); 1276 clearFieldIndexMap(); 1277 1278 return true; 1279} 1280 1281void RSReflectionJava::genTypeItemClass(const RSExportRecordType *ERT) { 1282 indent() << "static public class " RS_TYPE_ITEM_CLASS_NAME; 1283 startBlock(); 1284 1285 indent() << "public static final int sizeof = " << ERT->getAllocSize() 1286 << ";\n"; 1287 1288 // Member elements 1289 out() << "\n"; 1290 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1291 FE = ERT->fields_end(); 1292 FI != FE; FI++) { 1293 indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName() 1294 << ";\n"; 1295 } 1296 1297 // Constructor 1298 out() << "\n"; 1299 indent() << RS_TYPE_ITEM_CLASS_NAME "()"; 1300 startBlock(); 1301 1302 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1303 FE = ERT->fields_end(); 1304 FI != FE; FI++) { 1305 const RSExportRecordType::Field *F = *FI; 1306 genAllocateVarOfType(F->getType(), F->getName()); 1307 } 1308 1309 // end Constructor 1310 endBlock(); 1311 1312 // end Item class 1313 endBlock(); 1314} 1315 1316void RSReflectionJava::genTypeClassConstructor(const RSExportRecordType *ERT) { 1317 const char *RenderScriptVar = "rs"; 1318 1319 startFunction(AM_Public, true, "Element", "createElement", 1, "RenderScript", 1320 RenderScriptVar); 1321 1322 // TODO(all): Fix weak-refs + multi-context issue. 1323 // indent() << "Element e = " << RS_TYPE_ELEMENT_REF_NAME 1324 // << ".get();\n"; 1325 // indent() << "if (e != null) return e;\n"; 1326 genBuildElement("eb", ERT, RenderScriptVar, /* IsInline = */ true); 1327 indent() << "return eb.create();\n"; 1328 // indent() << "e = eb.create();\n"; 1329 // indent() << RS_TYPE_ELEMENT_REF_NAME 1330 // << " = new java.lang.ref.WeakReference<Element>(e);\n"; 1331 // indent() << "return e;\n"; 1332 endFunction(); 1333 1334 // private with element 1335 startFunction(AM_Private, false, NULL, getClassName(), 1, "RenderScript", 1336 RenderScriptVar); 1337 indent() << RS_TYPE_ITEM_BUFFER_NAME " = null;\n"; 1338 indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = null;\n"; 1339 indent() << "mElement = createElement(" << RenderScriptVar << ");\n"; 1340 endFunction(); 1341 1342 // 1D without usage 1343 startFunction(AM_Public, false, NULL, getClassName(), 2, "RenderScript", 1344 RenderScriptVar, "int", "count"); 1345 1346 indent() << RS_TYPE_ITEM_BUFFER_NAME " = null;\n"; 1347 indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = null;\n"; 1348 indent() << "mElement = createElement(" << RenderScriptVar << ");\n"; 1349 // Call init() in super class 1350 indent() << "init(" << RenderScriptVar << ", count);\n"; 1351 endFunction(); 1352 1353 // 1D with usage 1354 startFunction(AM_Public, false, NULL, getClassName(), 3, "RenderScript", 1355 RenderScriptVar, "int", "count", "int", "usages"); 1356 1357 indent() << RS_TYPE_ITEM_BUFFER_NAME " = null;\n"; 1358 indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = null;\n"; 1359 indent() << "mElement = createElement(" << RenderScriptVar << ");\n"; 1360 // Call init() in super class 1361 indent() << "init(" << RenderScriptVar << ", count, usages);\n"; 1362 endFunction(); 1363 1364 // create1D with usage 1365 startFunction(AM_Public, true, getClassName().c_str(), "create1D", 3, 1366 "RenderScript", RenderScriptVar, "int", "dimX", "int", 1367 "usages"); 1368 indent() << getClassName() << " obj = new " << getClassName() << "(" 1369 << RenderScriptVar << ");\n"; 1370 indent() << "obj.mAllocation = Allocation.createSized(" 1371 "rs, obj.mElement, dimX, usages);\n"; 1372 indent() << "return obj;\n"; 1373 endFunction(); 1374 1375 // create1D without usage 1376 startFunction(AM_Public, true, getClassName().c_str(), "create1D", 2, 1377 "RenderScript", RenderScriptVar, "int", "dimX"); 1378 indent() << "return create1D(" << RenderScriptVar 1379 << ", dimX, Allocation.USAGE_SCRIPT);\n"; 1380 endFunction(); 1381 1382 // create2D without usage 1383 startFunction(AM_Public, true, getClassName().c_str(), "create2D", 3, 1384 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY"); 1385 indent() << "return create2D(" << RenderScriptVar 1386 << ", dimX, dimY, Allocation.USAGE_SCRIPT);\n"; 1387 endFunction(); 1388 1389 // create2D with usage 1390 startFunction(AM_Public, true, getClassName().c_str(), "create2D", 4, 1391 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY", 1392 "int", "usages"); 1393 1394 indent() << getClassName() << " obj = new " << getClassName() << "(" 1395 << RenderScriptVar << ");\n"; 1396 indent() << "Type.Builder b = new Type.Builder(rs, obj.mElement);\n"; 1397 indent() << "b.setX(dimX);\n"; 1398 indent() << "b.setY(dimY);\n"; 1399 indent() << "Type t = b.create();\n"; 1400 indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n"; 1401 indent() << "return obj;\n"; 1402 endFunction(); 1403 1404 // createTypeBuilder 1405 startFunction(AM_Public, true, "Type.Builder", "createTypeBuilder", 1, 1406 "RenderScript", RenderScriptVar); 1407 indent() << "Element e = createElement(" << RenderScriptVar << ");\n"; 1408 indent() << "return new Type.Builder(rs, e);\n"; 1409 endFunction(); 1410 1411 // createCustom with usage 1412 startFunction(AM_Public, true, getClassName().c_str(), "createCustom", 3, 1413 "RenderScript", RenderScriptVar, "Type.Builder", "tb", "int", 1414 "usages"); 1415 indent() << getClassName() << " obj = new " << getClassName() << "(" 1416 << RenderScriptVar << ");\n"; 1417 indent() << "Type t = tb.create();\n"; 1418 indent() << "if (t.getElement() != obj.mElement) {\n"; 1419 indent() << " throw new RSIllegalArgumentException(" 1420 "\"Type.Builder did not match expected element type.\");\n"; 1421 indent() << "}\n"; 1422 indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n"; 1423 indent() << "return obj;\n"; 1424 endFunction(); 1425} 1426 1427void RSReflectionJava::genTypeClassCopyToArray(const RSExportRecordType *ERT) { 1428 startFunction(AM_Private, false, "void", "copyToArray", 2, 1429 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index"); 1430 1431 genNewItemBufferPackerIfNull(); 1432 indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME 1433 ".reset(index * " RS_TYPE_ITEM_CLASS_NAME ".sizeof);\n"; 1434 1435 indent() << "copyToArrayLocal(i, " RS_TYPE_ITEM_BUFFER_PACKER_NAME ");\n"; 1436 1437 endFunction(); 1438} 1439 1440void 1441RSReflectionJava::genTypeClassCopyToArrayLocal(const RSExportRecordType *ERT) { 1442 startFunction(AM_Private, false, "void", "copyToArrayLocal", 2, 1443 RS_TYPE_ITEM_CLASS_NAME, "i", "FieldPacker", "fp"); 1444 1445 genPackVarOfType(ERT, "i", "fp"); 1446 1447 endFunction(); 1448} 1449 1450void RSReflectionJava::genTypeClassItemSetter(const RSExportRecordType *ERT) { 1451 startFunction(AM_PublicSynchronized, false, "void", "set", 3, 1452 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index", "boolean", 1453 "copyNow"); 1454 genNewItemBufferIfNull(NULL); 1455 indent() << RS_TYPE_ITEM_BUFFER_NAME "[index] = i;\n"; 1456 1457 indent() << "if (copyNow) "; 1458 startBlock(); 1459 1460 indent() << "copyToArray(i, index);\n"; 1461 indent() << "FieldPacker fp = new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME 1462 ".sizeof);\n"; 1463 indent() << "copyToArrayLocal(i, fp);\n"; 1464 indent() << "mAllocation.setFromFieldPacker(index, fp);\n"; 1465 1466 // End of if (copyNow) 1467 endBlock(); 1468 1469 endFunction(); 1470} 1471 1472void RSReflectionJava::genTypeClassItemGetter(const RSExportRecordType *ERT) { 1473 startFunction(AM_PublicSynchronized, false, RS_TYPE_ITEM_CLASS_NAME, "get", 1, 1474 "int", "index"); 1475 indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME " == null) return null;\n"; 1476 indent() << "return " RS_TYPE_ITEM_BUFFER_NAME "[index];\n"; 1477 endFunction(); 1478} 1479 1480void 1481RSReflectionJava::genTypeClassComponentSetter(const RSExportRecordType *ERT) { 1482 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1483 FE = ERT->fields_end(); 1484 FI != FE; FI++) { 1485 const RSExportRecordType::Field *F = *FI; 1486 size_t FieldOffset = F->getOffsetInParent(); 1487 size_t FieldStoreSize = F->getType()->getStoreSize(); 1488 unsigned FieldIndex = getFieldIndex(F); 1489 1490 startFunction(AM_PublicSynchronized, false, "void", "set_" + F->getName(), 1491 3, "int", "index", GetTypeName(F->getType()).c_str(), "v", 1492 "boolean", "copyNow"); 1493 genNewItemBufferPackerIfNull(); 1494 genNewItemBufferIfNull("index"); 1495 indent() << RS_TYPE_ITEM_BUFFER_NAME "[index]." << F->getName() 1496 << " = v;\n"; 1497 1498 indent() << "if (copyNow) "; 1499 startBlock(); 1500 1501 if (FieldOffset > 0) 1502 indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME 1503 ".reset(index * " RS_TYPE_ITEM_CLASS_NAME ".sizeof + " << FieldOffset 1504 << ");\n"; 1505 else 1506 indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME 1507 ".reset(index * " RS_TYPE_ITEM_CLASS_NAME ".sizeof);\n"; 1508 genPackVarOfType(F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME); 1509 1510 indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");\n"; 1511 genPackVarOfType(F->getType(), "v", "fp"); 1512 indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex 1513 << ", fp);\n"; 1514 1515 // End of if (copyNow) 1516 endBlock(); 1517 1518 endFunction(); 1519 } 1520} 1521 1522void 1523RSReflectionJava::genTypeClassComponentGetter(const RSExportRecordType *ERT) { 1524 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1525 FE = ERT->fields_end(); 1526 FI != FE; FI++) { 1527 const RSExportRecordType::Field *F = *FI; 1528 startFunction(AM_PublicSynchronized, false, 1529 GetTypeName(F->getType()).c_str(), "get_" + F->getName(), 1, 1530 "int", "index"); 1531 indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME " == null) return " 1532 << GetTypeNullValue(F->getType()) << ";\n"; 1533 indent() << "return " RS_TYPE_ITEM_BUFFER_NAME "[index]." << F->getName() 1534 << ";\n"; 1535 endFunction(); 1536 } 1537} 1538 1539void RSReflectionJava::genTypeClassCopyAll(const RSExportRecordType *ERT) { 1540 startFunction(AM_PublicSynchronized, false, "void", "copyAll", 0); 1541 1542 indent() << "for (int ct = 0; ct < " RS_TYPE_ITEM_BUFFER_NAME ".length; ct++)" 1543 " copyToArray(" RS_TYPE_ITEM_BUFFER_NAME "[ct], ct);\n"; 1544 indent() 1545 << "mAllocation.setFromFieldPacker(0, " RS_TYPE_ITEM_BUFFER_PACKER_NAME 1546 ");\n"; 1547 1548 endFunction(); 1549} 1550 1551void RSReflectionJava::genTypeClassResize() { 1552 startFunction(AM_PublicSynchronized, false, "void", "resize", 1, "int", 1553 "newSize"); 1554 1555 indent() << "if (mItemArray != null) "; 1556 startBlock(); 1557 indent() << "int oldSize = mItemArray.length;\n"; 1558 indent() << "int copySize = Math.min(oldSize, newSize);\n"; 1559 indent() << "if (newSize == oldSize) return;\n"; 1560 indent() << "Item ni[] = new Item[newSize];\n"; 1561 indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);\n"; 1562 indent() << "mItemArray = ni;\n"; 1563 endBlock(); 1564 indent() << "mAllocation.resize(newSize);\n"; 1565 1566 indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME 1567 " != null) " RS_TYPE_ITEM_BUFFER_PACKER_NAME " = " 1568 "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME 1569 ".sizeof * getType().getX()/* count */" 1570 ");\n"; 1571 1572 endFunction(); 1573} 1574 1575/******************** Methods to generate type class /end ********************/ 1576 1577/********** Methods to create Element in Java of given record type ***********/ 1578void RSReflectionJava::genBuildElement(const char *ElementBuilderName, 1579 const RSExportRecordType *ERT, 1580 const char *RenderScriptVar, 1581 bool IsInline) { 1582 indent() << "Element.Builder " << ElementBuilderName << " = " 1583 "new Element.Builder(" 1584 << RenderScriptVar << ");\n"; 1585 1586 // eb.add(...) 1587 genAddElementToElementBuilder(ERT, "", ElementBuilderName, RenderScriptVar, 1588 /* ArraySize = */ 0); 1589 1590 if (!IsInline) 1591 indent() << "return " << ElementBuilderName << ".create();" << std::endl; 1592} 1593 1594#define EB_ADD(x) \ 1595 do { \ 1596 indent() << ElementBuilderName << ".add(" << x << ", \"" << VarName \ 1597 << "\""; \ 1598 if (ArraySize > 0) \ 1599 out() << ", " << ArraySize; \ 1600 out() << ");\n"; \ 1601 incFieldIndex(); \ 1602 } while (false) 1603 1604void RSReflectionJava::genAddElementToElementBuilder( 1605 const RSExportType *ET, const std::string &VarName, 1606 const char *ElementBuilderName, const char *RenderScriptVar, 1607 unsigned ArraySize) { 1608 std::string ElementConstruct = GetBuiltinElementConstruct(ET); 1609 1610 if (ElementConstruct != "") { 1611 EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")"); 1612 } else { 1613 if ((ET->getClass() == RSExportType::ExportClassPrimitive) || 1614 (ET->getClass() == RSExportType::ExportClassVector)) { 1615 const RSExportPrimitiveType *EPT = 1616 static_cast<const RSExportPrimitiveType *>(ET); 1617 const char *DataTypeName = 1618 RSExportPrimitiveType::getRSReflectionType(EPT)->rs_type; 1619 int Size = 1620 (ET->getClass() == RSExportType::ExportClassVector) 1621 ? static_cast<const RSExportVectorType *>(ET)->getNumElement() 1622 : 1; 1623 1624 if (EPT->getClass() == RSExportType::ExportClassPrimitive) { 1625 // Element.createUser() 1626 EB_ADD("Element.createUser(" << RenderScriptVar << ", Element.DataType." 1627 << DataTypeName << ")"); 1628 } else { 1629 slangAssert((ET->getClass() == RSExportType::ExportClassVector) && 1630 "Unexpected type."); 1631 EB_ADD("Element.createVector(" << RenderScriptVar 1632 << ", Element.DataType." << DataTypeName 1633 << ", " << Size << ")"); 1634 } 1635#ifndef NDEBUG 1636 } else if (ET->getClass() == RSExportType::ExportClassPointer) { 1637 // Pointer type variable should be resolved in 1638 // GetBuiltinElementConstruct() 1639 slangAssert(false && "??"); 1640 } else if (ET->getClass() == RSExportType::ExportClassMatrix) { 1641 // Matrix type variable should be resolved 1642 // in GetBuiltinElementConstruct() 1643 slangAssert(false && "??"); 1644#endif 1645 } else if (ET->getClass() == RSExportType::ExportClassConstantArray) { 1646 const RSExportConstantArrayType *ECAT = 1647 static_cast<const RSExportConstantArrayType *>(ET); 1648 1649 const RSExportType *ElementType = ECAT->getElementType(); 1650 if (ElementType->getClass() != RSExportType::ExportClassRecord) { 1651 genAddElementToElementBuilder(ECAT->getElementType(), VarName, 1652 ElementBuilderName, RenderScriptVar, 1653 ECAT->getSize()); 1654 } else { 1655 std::string NewElementBuilderName(ElementBuilderName); 1656 NewElementBuilderName.append(1, '_'); 1657 1658 genBuildElement(NewElementBuilderName.c_str(), 1659 static_cast<const RSExportRecordType *>(ElementType), 1660 RenderScriptVar, 1661 /* IsInline = */ true); 1662 ArraySize = ECAT->getSize(); 1663 EB_ADD(NewElementBuilderName << ".create()"); 1664 } 1665 } else if (ET->getClass() == RSExportType::ExportClassRecord) { 1666 // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType. 1667 // 1668 // TODO(zonr): Generalize these two function such that there's no 1669 // duplicated codes. 1670 const RSExportRecordType *ERT = 1671 static_cast<const RSExportRecordType *>(ET); 1672 int Pos = 0; // relative pos from now on 1673 1674 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 1675 E = ERT->fields_end(); 1676 I != E; I++) { 1677 const RSExportRecordType::Field *F = *I; 1678 std::string FieldName; 1679 int FieldOffset = F->getOffsetInParent(); 1680 const RSExportType *T = F->getType(); 1681 int FieldStoreSize = T->getStoreSize(); 1682 int FieldAllocSize = T->getAllocSize(); 1683 1684 if (!VarName.empty()) 1685 FieldName = VarName + "." + F->getName(); 1686 else 1687 FieldName = F->getName(); 1688 1689 // Alignment 1690 genAddPaddingToElementBuilder((FieldOffset - Pos), ElementBuilderName, 1691 RenderScriptVar); 1692 1693 // eb.add(...) 1694 addFieldIndexMapping(F); 1695 if (F->getType()->getClass() != RSExportType::ExportClassRecord) { 1696 genAddElementToElementBuilder(F->getType(), FieldName, 1697 ElementBuilderName, RenderScriptVar, 0); 1698 } else { 1699 std::string NewElementBuilderName(ElementBuilderName); 1700 NewElementBuilderName.append(1, '_'); 1701 1702 genBuildElement(NewElementBuilderName.c_str(), 1703 static_cast<const RSExportRecordType *>(F->getType()), 1704 RenderScriptVar, 1705 /* IsInline = */ true); 1706 1707 const std::string &VarName = FieldName; // Hack for EB_ADD macro 1708 EB_ADD(NewElementBuilderName << ".create()"); 1709 } 1710 1711 if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) { 1712 // There is padding within the field type. This is only necessary 1713 // for HC-targeted APIs. 1714 genAddPaddingToElementBuilder(FieldAllocSize - FieldStoreSize, 1715 ElementBuilderName, RenderScriptVar); 1716 } 1717 1718 Pos = FieldOffset + FieldAllocSize; 1719 } 1720 1721 // There maybe some padding after the struct 1722 size_t RecordAllocSize = ERT->getAllocSize(); 1723 1724 genAddPaddingToElementBuilder(RecordAllocSize - Pos, ElementBuilderName, 1725 RenderScriptVar); 1726 } else { 1727 slangAssert(false && "Unknown class of type"); 1728 } 1729 } 1730} 1731 1732void 1733RSReflectionJava::genAddPaddingToElementBuilder(int PaddingSize, 1734 const char *ElementBuilderName, 1735 const char *RenderScriptVar) { 1736 unsigned ArraySize = 0; // Hack the EB_ADD macro 1737 while (PaddingSize > 0) { 1738 const std::string &VarName = createPaddingField(); 1739 if (PaddingSize >= 4) { 1740 EB_ADD("Element.U32(" << RenderScriptVar << ")"); 1741 PaddingSize -= 4; 1742 } else if (PaddingSize >= 2) { 1743 EB_ADD("Element.U16(" << RenderScriptVar << ")"); 1744 PaddingSize -= 2; 1745 } else if (PaddingSize >= 1) { 1746 EB_ADD("Element.U8(" << RenderScriptVar << ")"); 1747 PaddingSize -= 1; 1748 } 1749 } 1750} 1751 1752#undef EB_ADD 1753/******** Methods to create Element in Java of given record type /end ********/ 1754 1755bool RSReflectionJava::reflect(const std::string &OutputPathBase, 1756 const std::string &OutputPackageName, 1757 const std::string &RSPackageName, 1758 const std::string &InputFileName, 1759 const std::string &OutputBCFileName, 1760 bool EmbedBitcodeInJava) { 1761 std::string ResourceId = ""; 1762 std::string PaddingPrefix = ""; 1763 1764 if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) { 1765 PaddingPrefix = "#padding_"; 1766 } else { 1767 PaddingPrefix = "#rs_padding_"; 1768 } 1769 1770 if (!GetClassNameFromFileName(OutputBCFileName, ResourceId)) 1771 return false; 1772 1773 if (ResourceId.empty()) 1774 ResourceId = "<Resource ID>"; 1775 1776 slangAssert(!OutputPackageName.empty() && OutputPackageName != "-"); 1777 1778 mVerbose = true; 1779 mOutputPathBase = OutputPathBase; 1780 mInputFileName = InputFileName; 1781 mPackageName = OutputPackageName; 1782 mRSPackageName = RSPackageName; 1783 mResourceId = ResourceId; 1784 mPaddingPrefix = PaddingPrefix; 1785 mLicenseNote = ApacheLicenseNote; 1786 mEmbedBitcodeInJava = EmbedBitcodeInJava; 1787 1788 clear(); 1789 resetFieldIndex(); 1790 clearFieldIndexMap(); 1791 1792 std::string ErrorMsg, ScriptClassName; 1793 // class ScriptC_<ScriptName> 1794 if (!GetClassNameFromFileName(InputFileName, ScriptClassName)) 1795 return false; 1796 1797 if (ScriptClassName.empty()) 1798 ScriptClassName = "<Input Script Name>"; 1799 1800 ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX); 1801 1802 if (mRSContext->getLicenseNote() != NULL) { 1803 setLicenseNote(*(mRSContext->getLicenseNote())); 1804 } 1805 1806 if (!genScriptClass(ScriptClassName, ErrorMsg)) { 1807 std::cerr << "Failed to generate class " << ScriptClassName << " (" 1808 << ErrorMsg << ")\n"; 1809 return false; 1810 } 1811 1812 mGeneratedFileNames->push_back(ScriptClassName); 1813 1814 // class ScriptField_<TypeName> 1815 for (RSContext::const_export_type_iterator 1816 TI = mRSContext->export_types_begin(), 1817 TE = mRSContext->export_types_end(); 1818 TI != TE; TI++) { 1819 const RSExportType *ET = TI->getValue(); 1820 1821 if (ET->getClass() == RSExportType::ExportClassRecord) { 1822 const RSExportRecordType *ERT = 1823 static_cast<const RSExportRecordType *>(ET); 1824 1825 if (!ERT->isArtificial() && !genTypeClass(ERT, ErrorMsg)) { 1826 std::cerr << "Failed to generate type class for struct '" 1827 << ERT->getName() << "' (" << ErrorMsg << ")\n"; 1828 return false; 1829 } 1830 } 1831 } 1832 1833 return true; 1834} 1835 1836/************************** RSReflectionJava::Context 1837 * **************************/ 1838const char *const RSReflectionJava::ApacheLicenseNote = 1839 "/*\n" 1840 " * Copyright (C) 2011-2013 The Android Open Source Project\n" 1841 " *\n" 1842 " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" 1843 " * you may not use this file except in compliance with the License.\n" 1844 " * You may obtain a copy of the License at\n" 1845 " *\n" 1846 " * http://www.apache.org/licenses/LICENSE-2.0\n" 1847 " *\n" 1848 " * Unless required by applicable law or agreed to in writing, software\n" 1849 " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" 1850 " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or " 1851 "implied.\n" 1852 " * See the License for the specific language governing permissions and\n" 1853 " * limitations under the License.\n" 1854 " */\n" 1855 "\n"; 1856 1857bool RSReflectionJava::openClassFile(const std::string &ClassName, 1858 std::string &ErrorMsg) { 1859 mOF.clear(); 1860 std::string Path = RSSlangReflectUtils::ComputePackagedPath( 1861 mOutputPathBase.c_str(), mPackageName.c_str()); 1862 1863 if (!SlangUtils::CreateDirectoryWithParents(Path, &ErrorMsg)) 1864 return false; 1865 1866 std::string ClassFile = Path + OS_PATH_SEPARATOR_STR + ClassName + ".java"; 1867 1868 mOF.open(ClassFile.c_str()); 1869 if (!mOF.good()) { 1870 ErrorMsg = "failed to open file '" + ClassFile + "' for write"; 1871 return false; 1872 } 1873 return true; 1874} 1875 1876const char *RSReflectionJava::AccessModifierStr(AccessModifier AM) { 1877 switch (AM) { 1878 case AM_Public: 1879 return "public"; 1880 break; 1881 case AM_Protected: 1882 return "protected"; 1883 break; 1884 case AM_Private: 1885 return "private"; 1886 break; 1887 case AM_PublicSynchronized: 1888 return "public synchronized"; 1889 break; 1890 default: 1891 return ""; 1892 break; 1893 } 1894} 1895 1896bool RSReflectionJava::startClass(AccessModifier AM, bool IsStatic, 1897 const std::string &ClassName, 1898 const char *SuperClassName, 1899 std::string &ErrorMsg) { 1900 if (mVerbose) 1901 std::cout << "Generating " << ClassName << ".java ...\n"; 1902 1903 // Open file for class 1904 if (!openClassFile(ClassName, ErrorMsg)) 1905 return false; 1906 1907 // License 1908 out() << mLicenseNote; 1909 1910 // Notice of generated file 1911 out() << "/*\n"; 1912 out() << " * This file is auto-generated. DO NOT MODIFY!\n"; 1913 out() << " * The source Renderscript file: " << SanitizeString(mInputFileName) 1914 << "\n"; 1915 out() << " */\n"; 1916 1917 // Package 1918 if (!mPackageName.empty()) 1919 out() << "package " << mPackageName << ";\n"; 1920 out() << "\n"; 1921 1922 // Imports 1923 out() << "import " << mRSPackageName << ".*;\n"; 1924 if (getEmbedBitcodeInJava()) { 1925 out() << "import " << mPackageName << "." 1926 << RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName( 1927 mInputFileName.c_str()) << ";\n"; 1928 } else { 1929 out() << "import android.content.res.Resources;\n"; 1930 } 1931 out() << "\n"; 1932 1933 // All reflected classes should be annotated as hidden, so that they won't 1934 // be exposed in SDK. 1935 out() << "/**\n"; 1936 out() << " * @hide\n"; 1937 out() << " */\n"; 1938 1939 out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class " 1940 << ClassName; 1941 if (SuperClassName != NULL) 1942 out() << " extends " << SuperClassName; 1943 1944 startBlock(); 1945 1946 mClassName = ClassName; 1947 1948 return true; 1949} 1950 1951void RSReflectionJava::endClass() { 1952 endBlock(); 1953 mOF.close(); 1954 clear(); 1955} 1956 1957void RSReflectionJava::startBlock(bool ShouldIndent) { 1958 if (ShouldIndent) 1959 indent() << "{\n"; 1960 else 1961 out() << " {\n"; 1962 incIndentLevel(); 1963} 1964 1965void RSReflectionJava::endBlock() { 1966 decIndentLevel(); 1967 indent() << "}\n\n"; 1968} 1969 1970void RSReflectionJava::startTypeClass(const std::string &ClassName) { 1971 indent() << "public static class " << ClassName; 1972 startBlock(); 1973} 1974 1975void RSReflectionJava::endTypeClass() { endBlock(); } 1976 1977void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic, 1978 const char *ReturnType, 1979 const std::string &FunctionName, int Argc, 1980 ...) { 1981 ArgTy Args; 1982 va_list vl; 1983 va_start(vl, Argc); 1984 1985 for (int i = 0; i < Argc; i++) { 1986 const char *ArgType = va_arg(vl, const char *); 1987 const char *ArgName = va_arg(vl, const char *); 1988 1989 Args.push_back(std::make_pair(ArgType, ArgName)); 1990 } 1991 va_end(vl); 1992 1993 startFunction(AM, IsStatic, ReturnType, FunctionName, Args); 1994} 1995 1996void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic, 1997 const char *ReturnType, 1998 const std::string &FunctionName, 1999 const ArgTy &Args) { 2000 indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ") 2001 << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "("; 2002 2003 bool FirstArg = true; 2004 for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) { 2005 if (!FirstArg) 2006 out() << ", "; 2007 else 2008 FirstArg = false; 2009 2010 out() << I->first << " " << I->second; 2011 } 2012 2013 out() << ")"; 2014 startBlock(); 2015} 2016 2017void RSReflectionJava::endFunction() { endBlock(); } 2018 2019bool RSReflectionJava::addTypeNameForElement(const std::string &TypeName) { 2020 if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) { 2021 mTypesToCheck.insert(TypeName); 2022 return true; 2023 } else { 2024 return false; 2025 } 2026} 2027 2028bool RSReflectionJava::addTypeNameForFieldPacker(const std::string &TypeName) { 2029 if (mFieldPackerTypes.find(TypeName) == mFieldPackerTypes.end()) { 2030 mFieldPackerTypes.insert(TypeName); 2031 return true; 2032 } else { 2033 return false; 2034 } 2035} 2036 2037} // namespace slang 2038