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 17 package androidx.renderscript; 18 19 import android.util.SparseArray; 20 21 /** 22 * The parent class for all executable scripts. This should not be used by 23 * applications. 24 **/ 25 public class Script extends BaseObj { 26 /** 27 * Determine if Incremental Intrinsic Support is needed 28 * 29 */ 30 private boolean mUseIncSupp; setIncSupp(boolean useInc)31 protected void setIncSupp(boolean useInc) { 32 mUseIncSupp = useInc; 33 } isIncSupp()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 */ getDummyAlloc(Allocation ain)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; KernelID(long id, RenderScript rs, Script s, int slot, int sig)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 */ createKernelID(int slot, int sig, Element ein, Element eout)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; InvokeID(long id, RenderScript rs, Script s, int slot)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 */ createInvokeID(int slot)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; FieldID(long id, RenderScript rs, Script s, int slot)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 */ createFieldID(int slot, Element e)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 */ invoke(int slot)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 */ invoke(int slot, FieldPacker v)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 */ bindAllocation(Allocation va, int slot)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 setTimeZone(String timeZone)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 */ forEach(int slot, Allocation ain, Allocation aout, FieldPacker v)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 */ forEach(int slot, Allocation ain, Allocation aout, FieldPacker v, LaunchOptions sc)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 Script(long id, RenderScript rs)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 */ forEach(int slot, Allocation[] ains, Allocation aout, FieldPacker v)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 */ forEach(int slot, Allocation[] ains, Allocation aout, FieldPacker v, LaunchOptions sc)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. (General reduction) 387 * 388 * @hide 389 */ reduce(int slot, Allocation[] ains, Allocation aout, LaunchOptions sc)390 protected void reduce(int slot, Allocation[] ains, Allocation aout, LaunchOptions sc) { 391 mRS.validate(); 392 if (ains == null || ains.length < 1) { 393 throw new RSIllegalArgumentException( 394 "At least one input is required."); 395 } 396 if (aout == null) { 397 throw new RSIllegalArgumentException( 398 "aout is required to be non-null."); 399 } 400 for (Allocation ain : ains) { 401 mRS.validateObject(ain); 402 } 403 404 long[] in_ids = new long[ains.length]; 405 for (int index = 0; index < ains.length; ++index) { 406 in_ids[index] = ains[index].getID(mRS); 407 } 408 long out_id = aout.getID(mRS); 409 410 int[] limits = null; 411 if (sc != null) { 412 limits = new int[6]; 413 414 limits[0] = sc.xstart; 415 limits[1] = sc.xend; 416 limits[2] = sc.ystart; 417 limits[3] = sc.yend; 418 limits[4] = sc.zstart; 419 limits[5] = sc.zend; 420 } 421 422 mRS.nScriptReduce(getID(mRS), slot, in_ids, out_id, limits); 423 } 424 425 /** 426 * Only intended for use by generated reflected code. 427 * 428 * @param index 429 * @param v 430 */ setVar(int index, float v)431 public void setVar(int index, float v) { 432 mRS.nScriptSetVarF(getID(mRS), index, v, mUseIncSupp); 433 } 434 435 /** 436 * Only intended for use by generated reflected code. 437 * 438 * @param index 439 * @param v 440 */ setVar(int index, double v)441 public void setVar(int index, double v) { 442 mRS.nScriptSetVarD(getID(mRS), index, v, mUseIncSupp); 443 } 444 445 /** 446 * Only intended for use by generated reflected code. 447 * 448 * @param index 449 * @param v 450 */ setVar(int index, int v)451 public void setVar(int index, int v) { 452 mRS.nScriptSetVarI(getID(mRS), index, v, mUseIncSupp); 453 } 454 455 /** 456 * Only intended for use by generated reflected code. 457 * 458 * @param index 459 * @param v 460 */ setVar(int index, long v)461 public void setVar(int index, long v) { 462 mRS.nScriptSetVarJ(getID(mRS), index, v, mUseIncSupp); 463 } 464 465 /** 466 * Only intended for use by generated reflected code. 467 * 468 * @param index 469 * @param v 470 */ setVar(int index, boolean v)471 public void setVar(int index, boolean v) { 472 mRS.nScriptSetVarI(getID(mRS), index, v ? 1 : 0, mUseIncSupp); 473 } 474 475 /** 476 * Only intended for use by generated reflected code. 477 * 478 * @param index 479 * @param o 480 */ setVar(int index, BaseObj o)481 public void setVar(int index, BaseObj o) { 482 if (mUseIncSupp) { 483 long oInc = getDummyAlloc((Allocation)o); 484 mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : oInc, mUseIncSupp); 485 } else { 486 mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS), mUseIncSupp); 487 } 488 } 489 490 /** 491 * Only intended for use by generated reflected code. 492 * 493 * @param index 494 * @param v 495 */ setVar(int index, FieldPacker v)496 public void setVar(int index, FieldPacker v) { 497 mRS.nScriptSetVarV(getID(mRS), index, v.getData(), mUseIncSupp); 498 } 499 500 /** 501 * Only intended for use by generated reflected code. 502 * 503 * @param index 504 * @param v 505 * @param e 506 * @param dims 507 */ setVar(int index, FieldPacker v, Element e, int[] dims)508 public void setVar(int index, FieldPacker v, Element e, int[] dims) { 509 if (mUseIncSupp) { 510 long dElement = e.getDummyElement(mRS); 511 mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), dElement, dims, mUseIncSupp); 512 } else { 513 mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), e.getID(mRS), dims, mUseIncSupp); 514 } 515 } 516 517 /** 518 * Only intended for use by generated reflected code. 519 * 520 */ 521 public static class Builder { 522 RenderScript mRS; 523 Builder(RenderScript rs)524 Builder(RenderScript rs) { 525 mRS = rs; 526 } 527 } 528 529 530 /** 531 * Only intended for use by generated reflected code. 532 * 533 */ 534 public static class FieldBase { 535 protected Element mElement; 536 protected Allocation mAllocation; 537 init(RenderScript rs, int dimx)538 protected void init(RenderScript rs, int dimx) { 539 mAllocation = Allocation.createSized(rs, mElement, dimx, Allocation.USAGE_SCRIPT); 540 } 541 init(RenderScript rs, int dimx, int usages)542 protected void init(RenderScript rs, int dimx, int usages) { 543 mAllocation = Allocation.createSized(rs, mElement, dimx, Allocation.USAGE_SCRIPT | usages); 544 } 545 FieldBase()546 protected FieldBase() { 547 } 548 getElement()549 public Element getElement() { 550 return mElement; 551 } 552 getType()553 public Type getType() { 554 return mAllocation.getType(); 555 } 556 getAllocation()557 public Allocation getAllocation() { 558 return mAllocation; 559 } 560 561 //@Override updateAllocation()562 public void updateAllocation() { 563 } 564 } 565 566 567 /** 568 * Class for specifying the specifics about how a kernel will be 569 * launched. 570 * 571 * This class can specify a potential range of cells on which to 572 * run a kernel. If no set is called for a dimension then this 573 * class will have no impact on that dimension when the kernel 574 * is executed. 575 * 576 * The forEach kernel launch will operate over the intersection of 577 * the dimensions. 578 * 579 * Example: 580 * LaunchOptions with setX(5, 15) 581 * Allocation with dimension X=10, Y=10 582 * The resulting forEach run would execute over: 583 * x = 5 to 9 (inclusive) and 584 * y = 0 to 9 (inclusive). 585 * 586 */ 587 public static final class LaunchOptions { 588 private int xstart = 0; 589 private int ystart = 0; 590 private int xend = 0; 591 private int yend = 0; 592 private int zstart = 0; 593 private int zend = 0; 594 private int strategy; 595 596 /** 597 * Set the X range. xstartArg is the lowest coordinate of the range, 598 * and xendArg-1 is the highest coordinate of the range. 599 * 600 * @param xstartArg Must be >= 0 601 * @param xendArg Must be > xstartArg 602 * 603 * @return LaunchOptions 604 */ setX(int xstartArg, int xendArg)605 public LaunchOptions setX(int xstartArg, int xendArg) { 606 if (xstartArg < 0 || xendArg <= xstartArg) { 607 throw new RSIllegalArgumentException("Invalid dimensions"); 608 } 609 xstart = xstartArg; 610 xend = xendArg; 611 return this; 612 } 613 614 /** 615 * Set the Y range. ystartArg is the lowest coordinate of the range, 616 * and yendArg-1 is the highest coordinate of the range. 617 * 618 * @param ystartArg Must be >= 0 619 * @param yendArg Must be > ystartArg 620 * 621 * @return LaunchOptions 622 */ setY(int ystartArg, int yendArg)623 public LaunchOptions setY(int ystartArg, int yendArg) { 624 if (ystartArg < 0 || yendArg <= ystartArg) { 625 throw new RSIllegalArgumentException("Invalid dimensions"); 626 } 627 ystart = ystartArg; 628 yend = yendArg; 629 return this; 630 } 631 632 /** 633 * Set the Z range. zstartArg is the lowest coordinate of the range, 634 * and zendArg-1 is the highest coordinate of the range. 635 * 636 * @param zstartArg Must be >= 0 637 * @param zendArg Must be > zstartArg 638 * 639 * @return LaunchOptions 640 */ setZ(int zstartArg, int zendArg)641 public LaunchOptions setZ(int zstartArg, int zendArg) { 642 if (zstartArg < 0 || zendArg <= zstartArg) { 643 throw new RSIllegalArgumentException("Invalid dimensions"); 644 } 645 zstart = zstartArg; 646 zend = zendArg; 647 return this; 648 } 649 650 651 /** 652 * Returns the current X start 653 * 654 * @return int current value 655 */ getXStart()656 public int getXStart() { 657 return xstart; 658 } 659 /** 660 * Returns the current X end 661 * 662 * @return int current value 663 */ getXEnd()664 public int getXEnd() { 665 return xend; 666 } 667 /** 668 * Returns the current Y start 669 * 670 * @return int current value 671 */ getYStart()672 public int getYStart() { 673 return ystart; 674 } 675 /** 676 * Returns the current Y end 677 * 678 * @return int current value 679 */ getYEnd()680 public int getYEnd() { 681 return yend; 682 } 683 /** 684 * Returns the current Z start 685 * 686 * @return int current value 687 */ getZStart()688 public int getZStart() { 689 return zstart; 690 } 691 /** 692 * Returns the current Z end 693 * 694 * @return int current value 695 */ getZEnd()696 public int getZEnd() { 697 return zend; 698 } 699 700 } 701 } 702