1/* 2 * Copyright (C) 2008-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 17package android.renderscript; 18 19import android.util.SparseArray; 20 21/** 22 * The parent class for all executable scripts. This should not be used by 23 * applications. 24 **/ 25public class Script extends BaseObj { 26 27 /** 28 * KernelID is an identifier for a Script + root function pair. It is used 29 * as an identifier for ScriptGroup creation. 30 * 31 * This class should not be directly created. Instead use the method in the 32 * reflected or intrinsic code "getKernelID_funcname()". 33 * 34 */ 35 public static final class KernelID extends BaseObj { 36 Script mScript; 37 int mSlot; 38 int mSig; 39 KernelID(long id, RenderScript rs, Script s, int slot, int sig) { 40 super(id, rs); 41 mScript = s; 42 mSlot = slot; 43 mSig = sig; 44 guard.open("destroy"); 45 } 46 } 47 48 private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>(); 49 /** 50 * Only to be used by generated reflected classes. 51 */ 52 protected KernelID createKernelID(int slot, int sig, Element ein, 53 Element eout) { 54 KernelID k = mKIDs.get(slot); 55 if (k != null) { 56 return k; 57 } 58 59 long id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig); 60 if (id == 0) { 61 throw new RSDriverException("Failed to create KernelID"); 62 } 63 64 k = new KernelID(id, mRS, this, slot, sig); 65 mKIDs.put(slot, k); 66 return k; 67 } 68 69 /** 70 * InvokeID is an identifier for an invoke function. It is used 71 * as an identifier for ScriptGroup creation. 72 * 73 * This class should not be directly created. Instead use the method in the 74 * reflected or intrinsic code "getInvokeID_funcname()". 75 * 76 */ 77 public static final class InvokeID extends BaseObj { 78 Script mScript; 79 int mSlot; 80 InvokeID(long id, RenderScript rs, Script s, int slot) { 81 super(id, rs); 82 mScript = s; 83 mSlot = slot; 84 } 85 } 86 87 private final SparseArray<InvokeID> mIIDs = new SparseArray<InvokeID>(); 88 /** 89 * Only to be used by generated reflected classes. 90 */ 91 protected InvokeID createInvokeID(int slot) { 92 InvokeID i = mIIDs.get(slot); 93 if (i != null) { 94 return i; 95 } 96 97 long id = mRS.nScriptInvokeIDCreate(getID(mRS), slot); 98 if (id == 0) { 99 throw new RSDriverException("Failed to create KernelID"); 100 } 101 102 i = new InvokeID(id, mRS, this, slot); 103 mIIDs.put(slot, i); 104 return i; 105 } 106 107 /** 108 * FieldID is an identifier for a Script + exported field pair. It is used 109 * as an identifier for ScriptGroup creation. 110 * 111 * This class should not be directly created. Instead use the method in the 112 * reflected or intrinsic code "getFieldID_funcname()". 113 * 114 */ 115 public static final class FieldID extends BaseObj { 116 Script mScript; 117 int mSlot; 118 FieldID(long id, RenderScript rs, Script s, int slot) { 119 super(id, rs); 120 mScript = s; 121 mSlot = slot; 122 guard.open("destroy"); 123 } 124 } 125 126 private final SparseArray<FieldID> mFIDs = new SparseArray(); 127 /** 128 * Only to be used by generated reflected classes. 129 */ 130 protected FieldID createFieldID(int slot, Element e) { 131 FieldID f = mFIDs.get(slot); 132 if (f != null) { 133 return f; 134 } 135 136 long id = mRS.nScriptFieldIDCreate(getID(mRS), slot); 137 if (id == 0) { 138 throw new RSDriverException("Failed to create FieldID"); 139 } 140 141 f = new FieldID(id, mRS, this, slot); 142 mFIDs.put(slot, f); 143 return f; 144 } 145 146 147 /** 148 * Only intended for use by generated reflected code. 149 * 150 */ 151 protected void invoke(int slot) { 152 mRS.nScriptInvoke(getID(mRS), slot); 153 } 154 155 /** 156 * Only intended for use by generated reflected code. 157 * 158 */ 159 protected void invoke(int slot, FieldPacker v) { 160 if (v != null) { 161 mRS.nScriptInvokeV(getID(mRS), slot, v.getData()); 162 } else { 163 mRS.nScriptInvoke(getID(mRS), slot); 164 } 165 } 166 167 /** 168 * Only intended for use by generated reflected code. 169 * 170 */ 171 protected void forEach(int slot, Allocation ain, Allocation aout, 172 FieldPacker v) { 173 forEach(slot, ain, aout, v, null); 174 } 175 176 /** 177 * Only intended for use by generated reflected code. 178 * 179 */ 180 protected void forEach(int slot, Allocation ain, Allocation aout, 181 FieldPacker v, LaunchOptions sc) { 182 // TODO: Is this necessary if nScriptForEach calls validate as well? 183 mRS.validate(); 184 mRS.validateObject(ain); 185 mRS.validateObject(aout); 186 187 if (ain == null && aout == null && sc == null) { 188 throw new RSIllegalArgumentException( 189 "At least one of input allocation, output allocation, or LaunchOptions is required to be non-null."); 190 } 191 192 long[] in_ids = null; 193 if (ain != null) { 194 in_ids = mInIdsBuffer; 195 in_ids[0] = ain.getID(mRS); 196 } 197 198 long out_id = 0; 199 if (aout != null) { 200 out_id = aout.getID(mRS); 201 } 202 203 byte[] params = null; 204 if (v != null) { 205 params = v.getData(); 206 } 207 208 int[] limits = null; 209 if (sc != null) { 210 limits = new int[6]; 211 212 limits[0] = sc.xstart; 213 limits[1] = sc.xend; 214 limits[2] = sc.ystart; 215 limits[3] = sc.yend; 216 limits[4] = sc.zstart; 217 limits[5] = sc.zend; 218 } 219 220 mRS.nScriptForEach(getID(mRS), slot, in_ids, out_id, params, limits); 221 } 222 223 /** 224 * Only intended for use by generated reflected code. 225 */ 226 protected void forEach(int slot, Allocation[] ains, Allocation aout, 227 FieldPacker v) { 228 229 // FieldPacker is kept here to support regular params in the future. 230 forEach(slot, ains, aout, v, null); 231 } 232 233 /** 234 * Only intended for use by generated reflected code. 235 */ 236 protected void forEach(int slot, Allocation[] ains, Allocation aout, 237 FieldPacker v, LaunchOptions sc) { 238 // TODO: Is this necessary if nScriptForEach calls validate as well? 239 // FieldPacker is kept here to support regular params in the future. 240 mRS.validate(); 241 if (ains != null) { 242 for (Allocation ain : ains) { 243 mRS.validateObject(ain); 244 } 245 } 246 mRS.validateObject(aout); 247 248 if (ains == null && aout == null) { 249 throw new RSIllegalArgumentException( 250 "At least one of ain or aout is required to be non-null."); 251 } 252 253 long[] in_ids; 254 if (ains != null) { 255 in_ids = new long[ains.length]; 256 for (int index = 0; index < ains.length; ++index) { 257 in_ids[index] = ains[index].getID(mRS); 258 } 259 } else { 260 in_ids = null; 261 } 262 263 long out_id = 0; 264 if (aout != null) { 265 out_id = aout.getID(mRS); 266 } 267 268 byte[] params = null; 269 if (v != null) { 270 params = v.getData(); 271 } 272 273 int[] limits = null; 274 if (sc != null) { 275 limits = new int[6]; 276 277 limits[0] = sc.xstart; 278 limits[1] = sc.xend; 279 limits[2] = sc.ystart; 280 limits[3] = sc.yend; 281 limits[4] = sc.zstart; 282 limits[5] = sc.zend; 283 } 284 285 mRS.nScriptForEach(getID(mRS), slot, in_ids, out_id, params, limits); 286 } 287 288 /** 289 * Only intended for use by generated reflected code. (General reduction) 290 * 291 */ 292 protected void reduce(int slot, Allocation[] ains, Allocation aout, LaunchOptions sc) { 293 mRS.validate(); 294 if (ains == null || ains.length < 1) { 295 throw new RSIllegalArgumentException( 296 "At least one input is required."); 297 } 298 if (aout == null) { 299 throw new RSIllegalArgumentException( 300 "aout is required to be non-null."); 301 } 302 for (Allocation ain : ains) { 303 mRS.validateObject(ain); 304 } 305 306 long[] in_ids = new long[ains.length]; 307 for (int index = 0; index < ains.length; ++index) { 308 in_ids[index] = ains[index].getID(mRS); 309 } 310 long out_id = aout.getID(mRS); 311 312 int[] limits = null; 313 if (sc != null) { 314 limits = new int[6]; 315 316 limits[0] = sc.xstart; 317 limits[1] = sc.xend; 318 limits[2] = sc.ystart; 319 limits[3] = sc.yend; 320 limits[4] = sc.zstart; 321 limits[5] = sc.zend; 322 } 323 324 mRS.nScriptReduce(getID(mRS), slot, in_ids, out_id, limits); 325 } 326 327 long[] mInIdsBuffer; 328 329 Script(long id, RenderScript rs) { 330 super(id, rs); 331 332 mInIdsBuffer = new long[1]; 333 334 /* The constructors for the derived classes (including ScriptIntrinsic 335 * derived classes and ScriptC derived classes generated by Slang 336 * reflection) seem to be simple enough, so we just put the guard.open() 337 * call here, rather than in the end of the constructor for the derived 338 * class. This, of course, assumes the derived constructor would not 339 * throw any exception after calling this constructor. 340 * 341 * If new derived classes are added with more complicated constructors 342 * that throw exceptions, this call has to be (duplicated and) moved 343 * to the end of each derived class constructor. 344 */ 345 guard.open("destroy"); 346 } 347 348 /** 349 * Only intended for use by generated reflected code. 350 * 351 */ 352 public void bindAllocation(Allocation va, int slot) { 353 mRS.validate(); 354 mRS.validateObject(va); 355 if (va != null) { 356 357 android.content.Context context = mRS.getApplicationContext(); 358 359 if (context.getApplicationInfo().targetSdkVersion >= 20) { 360 final Type t = va.mType; 361 if (t.hasMipmaps() || t.hasFaces() || (t.getY() != 0) || 362 (t.getZ() != 0)) { 363 364 throw new RSIllegalArgumentException( 365 "API 20+ only allows simple 1D allocations to be " + 366 "used with bind."); 367 } 368 } 369 mRS.nScriptBindAllocation(getID(mRS), va.getID(mRS), slot); 370 } else { 371 mRS.nScriptBindAllocation(getID(mRS), 0, slot); 372 } 373 } 374 375 /** 376 * Only intended for use by generated reflected code. 377 * 378 */ 379 public void setVar(int index, float v) { 380 mRS.nScriptSetVarF(getID(mRS), index, v); 381 } 382 public float getVarF(int index) { 383 return mRS.nScriptGetVarF(getID(mRS), index); 384 } 385 386 /** 387 * Only intended for use by generated reflected code. 388 * 389 */ 390 public void setVar(int index, double v) { 391 mRS.nScriptSetVarD(getID(mRS), index, v); 392 } 393 public double getVarD(int index) { 394 return mRS.nScriptGetVarD(getID(mRS), index); 395 } 396 397 /** 398 * Only intended for use by generated reflected code. 399 * 400 */ 401 public void setVar(int index, int v) { 402 mRS.nScriptSetVarI(getID(mRS), index, v); 403 } 404 public int getVarI(int index) { 405 return mRS.nScriptGetVarI(getID(mRS), index); 406 } 407 408 409 /** 410 * Only intended for use by generated reflected code. 411 * 412 */ 413 public void setVar(int index, long v) { 414 mRS.nScriptSetVarJ(getID(mRS), index, v); 415 } 416 public long getVarJ(int index) { 417 return mRS.nScriptGetVarJ(getID(mRS), index); 418 } 419 420 421 /** 422 * Only intended for use by generated reflected code. 423 * 424 */ 425 public void setVar(int index, boolean v) { 426 mRS.nScriptSetVarI(getID(mRS), index, v ? 1 : 0); 427 } 428 public boolean getVarB(int index) { 429 return mRS.nScriptGetVarI(getID(mRS), index) > 0 ? true : false; 430 } 431 432 /** 433 * Only intended for use by generated reflected code. 434 * 435 */ 436 public void setVar(int index, BaseObj o) { 437 mRS.validate(); 438 mRS.validateObject(o); 439 mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS)); 440 } 441 442 /** 443 * Only intended for use by generated reflected code. 444 * 445 */ 446 public void setVar(int index, FieldPacker v) { 447 mRS.nScriptSetVarV(getID(mRS), index, v.getData()); 448 } 449 450 /** 451 * Only intended for use by generated reflected code. 452 * 453 */ 454 public void setVar(int index, FieldPacker v, Element e, int[] dims) { 455 mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), e.getID(mRS), dims); 456 } 457 458 /** 459 * Only intended for use by generated reflected code. 460 * 461 */ 462 public void getVarV(int index, FieldPacker v) { 463 mRS.nScriptGetVarV(getID(mRS), index, v.getData()); 464 } 465 466 public void setTimeZone(String timeZone) { 467 mRS.validate(); 468 try { 469 mRS.nScriptSetTimeZone(getID(mRS), timeZone.getBytes("UTF-8")); 470 } catch (java.io.UnsupportedEncodingException e) { 471 throw new RuntimeException(e); 472 } 473 } 474 475 /** 476 * Only intended for use by generated reflected code. 477 * 478 */ 479 public static class Builder { 480 RenderScript mRS; 481 482 Builder(RenderScript rs) { 483 mRS = rs; 484 } 485 } 486 487 488 /** 489 * Only intended for use by generated reflected code. 490 * 491 */ 492 public static class FieldBase { 493 protected Element mElement; 494 protected Allocation mAllocation; 495 496 protected void init(RenderScript rs, int dimx) { 497 mAllocation = Allocation.createSized(rs, mElement, dimx, 498 Allocation.USAGE_SCRIPT); 499 } 500 501 protected void init(RenderScript rs, int dimx, int usages) { 502 mAllocation = 503 Allocation.createSized(rs, mElement, dimx, 504 Allocation.USAGE_SCRIPT | usages); 505 } 506 507 protected FieldBase() { 508 } 509 510 public Element getElement() { 511 return mElement; 512 } 513 514 public Type getType() { 515 return mAllocation.getType(); 516 } 517 518 public Allocation getAllocation() { 519 return mAllocation; 520 } 521 522 //@Override 523 public void updateAllocation() { 524 } 525 } 526 527 528 /** 529 * Class for specifying the specifics about how a kernel will be 530 * launched. 531 * 532 * This class can specify a potential range of cells on which to 533 * run a kernel. If no set is called for a dimension then this 534 * class will have no impact on that dimension when the kernel 535 * is executed. 536 * 537 * The forEach kernel launch will operate over the intersection of 538 * the dimensions. 539 * 540 * Example: 541 * LaunchOptions with setX(5, 15) 542 * Allocation with dimension X=10, Y=10 543 * The resulting forEach run would execute over: 544 * x = 5 to 9 (inclusive) and 545 * y = 0 to 9 (inclusive). 546 * 547 * 548 */ 549 public static final class LaunchOptions { 550 private int xstart = 0; 551 private int ystart = 0; 552 private int xend = 0; 553 private int yend = 0; 554 private int zstart = 0; 555 private int zend = 0; 556 private int strategy; 557 558 /** 559 * Set the X range. xstartArg is the lowest coordinate of the range, 560 * and xendArg-1 is the highest coordinate of the range. 561 * 562 * @param xstartArg Must be >= 0 563 * @param xendArg Must be > xstartArg 564 * 565 * @return LaunchOptions 566 */ 567 public LaunchOptions setX(int xstartArg, int xendArg) { 568 if (xstartArg < 0 || xendArg <= xstartArg) { 569 throw new RSIllegalArgumentException("Invalid dimensions"); 570 } 571 xstart = xstartArg; 572 xend = xendArg; 573 return this; 574 } 575 576 /** 577 * Set the Y range. ystartArg is the lowest coordinate of the range, 578 * and yendArg-1 is the highest coordinate of the range. 579 * 580 * @param ystartArg Must be >= 0 581 * @param yendArg Must be > ystartArg 582 * 583 * @return LaunchOptions 584 */ 585 public LaunchOptions setY(int ystartArg, int yendArg) { 586 if (ystartArg < 0 || yendArg <= ystartArg) { 587 throw new RSIllegalArgumentException("Invalid dimensions"); 588 } 589 ystart = ystartArg; 590 yend = yendArg; 591 return this; 592 } 593 594 /** 595 * Set the Z range. zstartArg is the lowest coordinate of the range, 596 * and zendArg-1 is the highest coordinate of the range. 597 * 598 * @param zstartArg Must be >= 0 599 * @param zendArg Must be > zstartArg 600 * 601 * @return LaunchOptions 602 */ 603 public LaunchOptions setZ(int zstartArg, int zendArg) { 604 if (zstartArg < 0 || zendArg <= zstartArg) { 605 throw new RSIllegalArgumentException("Invalid dimensions"); 606 } 607 zstart = zstartArg; 608 zend = zendArg; 609 return this; 610 } 611 612 613 /** 614 * Returns the current X start 615 * 616 * @return int current value 617 */ 618 public int getXStart() { 619 return xstart; 620 } 621 /** 622 * Returns the current X end 623 * 624 * @return int current value 625 */ 626 public int getXEnd() { 627 return xend; 628 } 629 /** 630 * Returns the current Y start 631 * 632 * @return int current value 633 */ 634 public int getYStart() { 635 return ystart; 636 } 637 /** 638 * Returns the current Y end 639 * 640 * @return int current value 641 */ 642 public int getYEnd() { 643 return yend; 644 } 645 /** 646 * Returns the current Z start 647 * 648 * @return int current value 649 */ 650 public int getZStart() { 651 return zstart; 652 } 653 /** 654 * Returns the current Z end 655 * 656 * @return int current value 657 */ 658 public int getZEnd() { 659 return zend; 660 } 661 662 } 663} 664