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