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