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