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