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