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