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