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