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