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