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 java.util.HashMap; 20 import android.content.res.Resources; 21 import android.graphics.Bitmap; 22 import android.graphics.BitmapFactory; 23 import android.view.Surface; 24 import android.util.Log; 25 import android.graphics.Canvas; 26 import android.os.Trace; 27 28 /** 29 * <p> This class provides the primary method through which data is passed to 30 * and from RenderScript kernels. An Allocation provides the backing store for 31 * a given {@link android.renderscript.Type}. </p> 32 * 33 * <p>An Allocation also contains a set of usage flags that denote how the 34 * Allocation could be used. For example, an Allocation may have usage flags 35 * specifying that it can be used from a script as well as input to a {@link 36 * android.renderscript.Sampler}. A developer must synchronize across these 37 * different usages using {@link android.renderscript.Allocation#syncAll} in 38 * order to ensure that different users of the Allocation have a consistent view 39 * of memory. For example, in the case where an Allocation is used as the output 40 * of one kernel and as Sampler input in a later kernel, a developer must call 41 * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the 42 * second kernel to ensure correctness. 43 * 44 * <p>An Allocation can be populated with the {@link #copyFrom} routines. For 45 * more complex Element types, the {@link #copyFromUnchecked} methods can be 46 * used to copy from byte arrays or similar constructs.</p> 47 * 48 * <div class="special reference"> 49 * <h3>Developer Guides</h3> 50 * <p>For more information about creating an application that uses RenderScript, read the 51 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p> 52 * </div> 53 **/ 54 public class Allocation extends BaseObj { 55 Type mType; 56 Bitmap mBitmap; 57 int mUsage; 58 Allocation mAdaptedAllocation; 59 int mSize; 60 61 boolean mConstrainedLOD; 62 boolean mConstrainedFace; 63 boolean mConstrainedY; 64 boolean mConstrainedZ; 65 boolean mReadAllowed = true; 66 boolean mWriteAllowed = true; 67 int mSelectedY; 68 int mSelectedZ; 69 int mSelectedLOD; 70 Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X; 71 72 int mCurrentDimX; 73 int mCurrentDimY; 74 int mCurrentDimZ; 75 int mCurrentCount; 76 static HashMap<Long, Allocation> mAllocationMap = 77 new HashMap<Long, Allocation>(); 78 OnBufferAvailableListener mBufferNotifier; 79 validateObjectIsPrimitiveArray(Object d, boolean checkType)80 private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) { 81 final Class c = d.getClass(); 82 if (!c.isArray()) { 83 throw new RSIllegalArgumentException("Object passed is not an array of primitives."); 84 } 85 final Class cmp = c.getComponentType(); 86 if (!cmp.isPrimitive()) { 87 throw new RSIllegalArgumentException("Object passed is not an Array of primitives."); 88 } 89 90 if (cmp == Long.TYPE) { 91 if (checkType) { 92 validateIsInt64(); 93 return mType.mElement.mType; 94 } 95 return Element.DataType.SIGNED_64; 96 } 97 98 if (cmp == Integer.TYPE) { 99 if (checkType) { 100 validateIsInt32(); 101 return mType.mElement.mType; 102 } 103 return Element.DataType.SIGNED_32; 104 } 105 106 if (cmp == Short.TYPE) { 107 if (checkType) { 108 validateIsInt16(); 109 return mType.mElement.mType; 110 } 111 return Element.DataType.SIGNED_16; 112 } 113 114 if (cmp == Byte.TYPE) { 115 if (checkType) { 116 validateIsInt8(); 117 return mType.mElement.mType; 118 } 119 return Element.DataType.SIGNED_8; 120 } 121 122 if (cmp == Float.TYPE) { 123 if (checkType) { 124 validateIsFloat32(); 125 } 126 return Element.DataType.FLOAT_32; 127 } 128 129 if (cmp == Double.TYPE) { 130 if (checkType) { 131 validateIsFloat64(); 132 } 133 return Element.DataType.FLOAT_64; 134 } 135 return null; 136 } 137 138 139 /** 140 * The usage of the Allocation. These signal to RenderScript where to place 141 * the Allocation in memory. 142 * 143 */ 144 145 /** 146 * The Allocation will be bound to and accessed by scripts. 147 */ 148 public static final int USAGE_SCRIPT = 0x0001; 149 150 /** 151 * The Allocation will be used as a texture source by one or more graphics 152 * programs. 153 * 154 */ 155 public static final int USAGE_GRAPHICS_TEXTURE = 0x0002; 156 157 /** 158 * The Allocation will be used as a graphics mesh. 159 * 160 * This was deprecated in API level 16. 161 * 162 */ 163 public static final int USAGE_GRAPHICS_VERTEX = 0x0004; 164 165 166 /** 167 * The Allocation will be used as the source of shader constants by one or 168 * more programs. 169 * 170 * This was deprecated in API level 16. 171 * 172 */ 173 public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008; 174 175 /** 176 * The Allocation will be used as a target for offscreen rendering 177 * 178 * This was deprecated in API level 16. 179 * 180 */ 181 public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010; 182 183 /** 184 * The Allocation will be used as a {@link android.view.Surface} 185 * consumer. This usage will cause the Allocation to be created 186 * as read-only. 187 * 188 */ 189 public static final int USAGE_IO_INPUT = 0x0020; 190 191 /** 192 * The Allocation will be used as a {@link android.view.Surface} 193 * producer. The dimensions and format of the {@link 194 * android.view.Surface} will be forced to those of the 195 * Allocation. 196 * 197 */ 198 public static final int USAGE_IO_OUTPUT = 0x0040; 199 200 /** 201 * The Allocation's backing store will be inherited from another object 202 * (usually a {@link android.graphics.Bitmap}); copying to or from the 203 * original source Bitmap will cause a synchronization rather than a full 204 * copy. {@link #syncAll} may also be used to synchronize the Allocation 205 * and the source Bitmap. 206 * 207 * <p>This is set by default for allocations created with {@link 208 * #createFromBitmap} in API version 18 and higher.</p> 209 * 210 */ 211 public static final int USAGE_SHARED = 0x0080; 212 213 /** 214 * Controls mipmap behavior when using the bitmap creation and update 215 * functions. 216 */ 217 public enum MipmapControl { 218 /** 219 * No mipmaps will be generated and the type generated from the incoming 220 * bitmap will not contain additional LODs. 221 */ 222 MIPMAP_NONE(0), 223 224 /** 225 * A full mipmap chain will be created in script memory. The Type of 226 * the Allocation will contain a full mipmap chain. On upload, the full 227 * chain will be transferred. 228 */ 229 MIPMAP_FULL(1), 230 231 /** 232 * The Type of the Allocation will be the same as MIPMAP_NONE. It will 233 * not contain mipmaps. On upload, the allocation data will contain a 234 * full mipmap chain generated from the top level in script memory. 235 */ 236 MIPMAP_ON_SYNC_TO_TEXTURE(2); 237 238 int mID; MipmapControl(int id)239 MipmapControl(int id) { 240 mID = id; 241 } 242 } 243 244 getIDSafe()245 private long getIDSafe() { 246 if (mAdaptedAllocation != null) { 247 return mAdaptedAllocation.getID(mRS); 248 } 249 return getID(mRS); 250 } 251 252 253 /** 254 * Get the {@link android.renderscript.Element} of the {@link 255 * android.renderscript.Type} of the Allocation. 256 * 257 * @return Element 258 * 259 */ getElement()260 public Element getElement() { 261 return mType.getElement(); 262 } 263 264 /** 265 * Get the usage flags of the Allocation. 266 * 267 * @return usage this Allocation's set of the USAGE_* flags OR'd together 268 * 269 */ getUsage()270 public int getUsage() { 271 return mUsage; 272 } 273 274 /** 275 * Get the size of the Allocation in bytes. 276 * 277 * @return size of the Allocation in bytes. 278 * 279 */ getBytesSize()280 public int getBytesSize() { 281 if (mType.mDimYuv != 0) { 282 return (int)Math.ceil(mType.getCount() * mType.getElement().getBytesSize() * 1.5); 283 } 284 return mType.getCount() * mType.getElement().getBytesSize(); 285 } 286 updateCacheInfo(Type t)287 private void updateCacheInfo(Type t) { 288 mCurrentDimX = t.getX(); 289 mCurrentDimY = t.getY(); 290 mCurrentDimZ = t.getZ(); 291 mCurrentCount = mCurrentDimX; 292 if (mCurrentDimY > 1) { 293 mCurrentCount *= mCurrentDimY; 294 } 295 if (mCurrentDimZ > 1) { 296 mCurrentCount *= mCurrentDimZ; 297 } 298 } 299 setBitmap(Bitmap b)300 private void setBitmap(Bitmap b) { 301 mBitmap = b; 302 } 303 Allocation(long id, RenderScript rs, Type t, int usage)304 Allocation(long id, RenderScript rs, Type t, int usage) { 305 super(id, rs); 306 if ((usage & ~(USAGE_SCRIPT | 307 USAGE_GRAPHICS_TEXTURE | 308 USAGE_GRAPHICS_VERTEX | 309 USAGE_GRAPHICS_CONSTANTS | 310 USAGE_GRAPHICS_RENDER_TARGET | 311 USAGE_IO_INPUT | 312 USAGE_IO_OUTPUT | 313 USAGE_SHARED)) != 0) { 314 throw new RSIllegalArgumentException("Unknown usage specified."); 315 } 316 317 if ((usage & USAGE_IO_INPUT) != 0) { 318 mWriteAllowed = false; 319 320 if ((usage & ~(USAGE_IO_INPUT | 321 USAGE_GRAPHICS_TEXTURE | 322 USAGE_SCRIPT)) != 0) { 323 throw new RSIllegalArgumentException("Invalid usage combination."); 324 } 325 } 326 327 mType = t; 328 mUsage = usage; 329 330 if (t != null) { 331 // TODO: A3D doesn't have Type info during creation, so we can't 332 // calculate the size ahead of time. We can possibly add a method 333 // to update the size in the future if it seems reasonable. 334 mSize = mType.getCount() * mType.getElement().getBytesSize(); 335 updateCacheInfo(t); 336 } 337 try { 338 RenderScript.registerNativeAllocation.invoke(RenderScript.sRuntime, mSize); 339 } catch (Exception e) { 340 Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e); 341 throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e); 342 } 343 } 344 finalize()345 protected void finalize() throws Throwable { 346 RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize); 347 super.finalize(); 348 } 349 validateIsInt64()350 private void validateIsInt64() { 351 if ((mType.mElement.mType == Element.DataType.SIGNED_64) || 352 (mType.mElement.mType == Element.DataType.UNSIGNED_64)) { 353 return; 354 } 355 throw new RSIllegalArgumentException( 356 "64 bit integer source does not match allocation type " + mType.mElement.mType); 357 } 358 validateIsInt32()359 private void validateIsInt32() { 360 if ((mType.mElement.mType == Element.DataType.SIGNED_32) || 361 (mType.mElement.mType == Element.DataType.UNSIGNED_32)) { 362 return; 363 } 364 throw new RSIllegalArgumentException( 365 "32 bit integer source does not match allocation type " + mType.mElement.mType); 366 } 367 validateIsInt16()368 private void validateIsInt16() { 369 if ((mType.mElement.mType == Element.DataType.SIGNED_16) || 370 (mType.mElement.mType == Element.DataType.UNSIGNED_16)) { 371 return; 372 } 373 throw new RSIllegalArgumentException( 374 "16 bit integer source does not match allocation type " + mType.mElement.mType); 375 } 376 validateIsInt8()377 private void validateIsInt8() { 378 if ((mType.mElement.mType == Element.DataType.SIGNED_8) || 379 (mType.mElement.mType == Element.DataType.UNSIGNED_8)) { 380 return; 381 } 382 throw new RSIllegalArgumentException( 383 "8 bit integer source does not match allocation type " + mType.mElement.mType); 384 } 385 validateIsFloat32()386 private void validateIsFloat32() { 387 if (mType.mElement.mType == Element.DataType.FLOAT_32) { 388 return; 389 } 390 throw new RSIllegalArgumentException( 391 "32 bit float source does not match allocation type " + mType.mElement.mType); 392 } 393 validateIsFloat64()394 private void validateIsFloat64() { 395 if (mType.mElement.mType == Element.DataType.FLOAT_64) { 396 return; 397 } 398 throw new RSIllegalArgumentException( 399 "64 bit float source does not match allocation type " + mType.mElement.mType); 400 } 401 validateIsObject()402 private void validateIsObject() { 403 if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) || 404 (mType.mElement.mType == Element.DataType.RS_TYPE) || 405 (mType.mElement.mType == Element.DataType.RS_ALLOCATION) || 406 (mType.mElement.mType == Element.DataType.RS_SAMPLER) || 407 (mType.mElement.mType == Element.DataType.RS_SCRIPT) || 408 (mType.mElement.mType == Element.DataType.RS_MESH) || 409 (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) || 410 (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) || 411 (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) || 412 (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) { 413 return; 414 } 415 throw new RSIllegalArgumentException( 416 "Object source does not match allocation type " + mType.mElement.mType); 417 } 418 419 @Override updateFromNative()420 void updateFromNative() { 421 super.updateFromNative(); 422 long typeID = mRS.nAllocationGetType(getID(mRS)); 423 if(typeID != 0) { 424 mType = new Type(typeID, mRS); 425 mType.updateFromNative(); 426 updateCacheInfo(mType); 427 } 428 } 429 430 /** 431 * Get the {@link android.renderscript.Type} of the Allocation. 432 * 433 * @return Type 434 * 435 */ getType()436 public Type getType() { 437 return mType; 438 } 439 440 /** 441 * Propagate changes from one usage of the Allocation to the 442 * other usages of the Allocation. 443 * 444 */ syncAll(int srcLocation)445 public void syncAll(int srcLocation) { 446 Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll"); 447 switch (srcLocation) { 448 case USAGE_GRAPHICS_TEXTURE: 449 case USAGE_SCRIPT: 450 if ((mUsage & USAGE_SHARED) != 0) { 451 copyFrom(mBitmap); 452 } 453 break; 454 case USAGE_GRAPHICS_CONSTANTS: 455 case USAGE_GRAPHICS_VERTEX: 456 break; 457 case USAGE_SHARED: 458 if ((mUsage & USAGE_SHARED) != 0) { 459 copyTo(mBitmap); 460 } 461 break; 462 default: 463 throw new RSIllegalArgumentException("Source must be exactly one usage type."); 464 } 465 mRS.validate(); 466 mRS.nAllocationSyncAll(getIDSafe(), srcLocation); 467 Trace.traceEnd(RenderScript.TRACE_TAG); 468 } 469 470 /** 471 * Send a buffer to the output stream. The contents of the Allocation will 472 * be undefined after this operation. This operation is only valid if {@link 473 * #USAGE_IO_OUTPUT} is set on the Allocation. 474 * 475 * 476 */ ioSend()477 public void ioSend() { 478 Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend"); 479 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 480 throw new RSIllegalArgumentException( 481 "Can only send buffer if IO_OUTPUT usage specified."); 482 } 483 mRS.validate(); 484 mRS.nAllocationIoSend(getID(mRS)); 485 Trace.traceEnd(RenderScript.TRACE_TAG); 486 } 487 488 /** 489 * Receive the latest input into the Allocation. This operation 490 * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation. 491 * 492 */ ioReceive()493 public void ioReceive() { 494 Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive"); 495 if ((mUsage & USAGE_IO_INPUT) == 0) { 496 throw new RSIllegalArgumentException( 497 "Can only receive if IO_INPUT usage specified."); 498 } 499 mRS.validate(); 500 mRS.nAllocationIoReceive(getID(mRS)); 501 Trace.traceEnd(RenderScript.TRACE_TAG); 502 } 503 504 /** 505 * Copy an array of RS objects to the Allocation. 506 * 507 * @param d Source array. 508 */ copyFrom(BaseObj[] d)509 public void copyFrom(BaseObj[] d) { 510 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 511 mRS.validate(); 512 validateIsObject(); 513 if (d.length != mCurrentCount) { 514 throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + 515 mCurrentCount + ", array length = " + d.length); 516 } 517 518 if (RenderScript.sPointerSize == 8) { 519 long i[] = new long[d.length * 4]; 520 for (int ct=0; ct < d.length; ct++) { 521 i[ct * 4] = d[ct].getID(mRS); 522 } 523 copy1DRangeFromUnchecked(0, mCurrentCount, i); 524 } else { 525 int i[] = new int[d.length]; 526 for (int ct=0; ct < d.length; ct++) { 527 i[ct] = (int)d[ct].getID(mRS); 528 } 529 copy1DRangeFromUnchecked(0, mCurrentCount, i); 530 } 531 Trace.traceEnd(RenderScript.TRACE_TAG); 532 } 533 validateBitmapFormat(Bitmap b)534 private void validateBitmapFormat(Bitmap b) { 535 Bitmap.Config bc = b.getConfig(); 536 if (bc == null) { 537 throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation"); 538 } 539 switch (bc) { 540 case ALPHA_8: 541 if (mType.getElement().mKind != Element.DataKind.PIXEL_A) { 542 throw new RSIllegalArgumentException("Allocation kind is " + 543 mType.getElement().mKind + ", type " + 544 mType.getElement().mType + 545 " of " + mType.getElement().getBytesSize() + 546 " bytes, passed bitmap was " + bc); 547 } 548 break; 549 case ARGB_8888: 550 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 551 (mType.getElement().getBytesSize() != 4)) { 552 throw new RSIllegalArgumentException("Allocation kind is " + 553 mType.getElement().mKind + ", type " + 554 mType.getElement().mType + 555 " of " + mType.getElement().getBytesSize() + 556 " bytes, passed bitmap was " + bc); 557 } 558 break; 559 case RGB_565: 560 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) || 561 (mType.getElement().getBytesSize() != 2)) { 562 throw new RSIllegalArgumentException("Allocation kind is " + 563 mType.getElement().mKind + ", type " + 564 mType.getElement().mType + 565 " of " + mType.getElement().getBytesSize() + 566 " bytes, passed bitmap was " + bc); 567 } 568 break; 569 case ARGB_4444: 570 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 571 (mType.getElement().getBytesSize() != 2)) { 572 throw new RSIllegalArgumentException("Allocation kind is " + 573 mType.getElement().mKind + ", type " + 574 mType.getElement().mType + 575 " of " + mType.getElement().getBytesSize() + 576 " bytes, passed bitmap was " + bc); 577 } 578 break; 579 580 } 581 } 582 validateBitmapSize(Bitmap b)583 private void validateBitmapSize(Bitmap b) { 584 if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) { 585 throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); 586 } 587 } 588 copyFromUnchecked(Object array, Element.DataType dt, int arrayLen)589 private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) { 590 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked"); 591 mRS.validate(); 592 if (mCurrentDimZ > 0) { 593 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen); 594 } else if (mCurrentDimY > 0) { 595 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen); 596 } else { 597 copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen); 598 } 599 Trace.traceEnd(RenderScript.TRACE_TAG); 600 } 601 602 /** 603 * Copy into this Allocation from an array. This method does not guarantee 604 * that the Allocation is compatible with the input buffer; it copies memory 605 * without reinterpretation. 606 * 607 * @param array The source data array 608 */ copyFromUnchecked(Object array)609 public void copyFromUnchecked(Object array) { 610 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked"); 611 copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false), 612 java.lang.reflect.Array.getLength(array)); 613 Trace.traceEnd(RenderScript.TRACE_TAG); 614 } 615 616 /** 617 * Copy into this Allocation from an array. This method does not guarantee 618 * that the Allocation is compatible with the input buffer; it copies memory 619 * without reinterpretation. 620 * 621 * @param d the source data array 622 */ copyFromUnchecked(int[] d)623 public void copyFromUnchecked(int[] d) { 624 copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length); 625 } 626 627 /** 628 * Copy into this Allocation from an array. This method does not guarantee 629 * that the Allocation is compatible with the input buffer; it copies memory 630 * without reinterpretation. 631 * 632 * @param d the source data array 633 */ copyFromUnchecked(short[] d)634 public void copyFromUnchecked(short[] d) { 635 copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length); 636 } 637 638 /** 639 * Copy into this Allocation from an array. This method does not guarantee 640 * that the Allocation is compatible with the input buffer; it copies memory 641 * without reinterpretation. 642 * 643 * @param d the source data array 644 */ copyFromUnchecked(byte[] d)645 public void copyFromUnchecked(byte[] d) { 646 copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length); 647 } 648 649 /** 650 * Copy into this Allocation from an array. This method does not guarantee 651 * that the Allocation is compatible with the input buffer; it copies memory 652 * without reinterpretation. 653 * 654 * @param d the source data array 655 */ copyFromUnchecked(float[] d)656 public void copyFromUnchecked(float[] d) { 657 copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length); 658 } 659 660 661 /** 662 * Copy into this Allocation from an array. This variant is type checked 663 * and will generate exceptions if the Allocation's {@link 664 * android.renderscript.Element} does not match the array's 665 * primitive type. 666 * 667 * @param array The source data array 668 */ copyFrom(Object array)669 public void copyFrom(Object array) { 670 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 671 copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true), 672 java.lang.reflect.Array.getLength(array)); 673 Trace.traceEnd(RenderScript.TRACE_TAG); 674 } 675 676 /** 677 * Copy into this Allocation from an array. This variant is type checked 678 * and will generate exceptions if the Allocation's {@link 679 * android.renderscript.Element} is not a 32 bit integer type. 680 * 681 * @param d the source data array 682 */ copyFrom(int[] d)683 public void copyFrom(int[] d) { 684 validateIsInt32(); 685 copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length); 686 } 687 688 /** 689 * Copy into this Allocation from an array. This variant is type checked 690 * and will generate exceptions if the Allocation's {@link 691 * android.renderscript.Element} is not a 16 bit integer type. 692 * 693 * @param d the source data array 694 */ copyFrom(short[] d)695 public void copyFrom(short[] d) { 696 validateIsInt16(); 697 copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length); 698 } 699 700 /** 701 * Copy into this Allocation from an array. This variant is type checked 702 * and will generate exceptions if the Allocation's {@link 703 * android.renderscript.Element} is not an 8 bit integer type. 704 * 705 * @param d the source data array 706 */ copyFrom(byte[] d)707 public void copyFrom(byte[] d) { 708 validateIsInt8(); 709 copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length); 710 } 711 712 /** 713 * Copy into this Allocation from an array. This variant is type checked 714 * and will generate exceptions if the Allocation's {@link 715 * android.renderscript.Element} is not a 32 bit float type. 716 * 717 * @param d the source data array 718 */ copyFrom(float[] d)719 public void copyFrom(float[] d) { 720 validateIsFloat32(); 721 copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length); 722 } 723 724 /** 725 * Copy into an Allocation from a {@link android.graphics.Bitmap}. The 726 * height, width, and format of the bitmap must match the existing 727 * allocation. 728 * 729 * <p>If the {@link android.graphics.Bitmap} is the same as the {@link 730 * android.graphics.Bitmap} used to create the Allocation with {@link 731 * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation, 732 * this will synchronize the Allocation with the latest data from the {@link 733 * android.graphics.Bitmap}, potentially avoiding the actual copy.</p> 734 * 735 * @param b the source bitmap 736 */ copyFrom(Bitmap b)737 public void copyFrom(Bitmap b) { 738 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 739 mRS.validate(); 740 if (b.getConfig() == null) { 741 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 742 Canvas c = new Canvas(newBitmap); 743 c.drawBitmap(b, 0, 0, null); 744 copyFrom(newBitmap); 745 return; 746 } 747 validateBitmapSize(b); 748 validateBitmapFormat(b); 749 mRS.nAllocationCopyFromBitmap(getID(mRS), b); 750 Trace.traceEnd(RenderScript.TRACE_TAG); 751 } 752 753 /** 754 * Copy an Allocation from an Allocation. The types of both allocations 755 * must be identical. 756 * 757 * @param a the source allocation 758 */ copyFrom(Allocation a)759 public void copyFrom(Allocation a) { 760 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 761 mRS.validate(); 762 if (!mType.equals(a.getType())) { 763 throw new RSIllegalArgumentException("Types of allocations must match."); 764 } 765 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0); 766 Trace.traceEnd(RenderScript.TRACE_TAG); 767 } 768 769 /** 770 * This is only intended to be used by auto-generated code reflected from 771 * the RenderScript script files and should not be used by developers. 772 * 773 * @param xoff 774 * @param fp 775 */ setFromFieldPacker(int xoff, FieldPacker fp)776 public void setFromFieldPacker(int xoff, FieldPacker fp) { 777 mRS.validate(); 778 int eSize = mType.mElement.getBytesSize(); 779 final byte[] data = fp.getData(); 780 int data_length = fp.getPos(); 781 782 int count = data_length / eSize; 783 if ((eSize * count) != data_length) { 784 throw new RSIllegalArgumentException("Field packer length " + data_length + 785 " not divisible by element size " + eSize + "."); 786 } 787 copy1DRangeFromUnchecked(xoff, count, data); 788 } 789 790 /** 791 * This is only intended to be used by auto-generated code reflected from 792 * the RenderScript script files. 793 * 794 * @param xoff 795 * @param component_number 796 * @param fp 797 */ setFromFieldPacker(int xoff, int component_number, FieldPacker fp)798 public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) { 799 mRS.validate(); 800 if (component_number >= mType.mElement.mElements.length) { 801 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 802 } 803 if(xoff < 0) { 804 throw new RSIllegalArgumentException("Offset must be >= 0."); 805 } 806 807 final byte[] data = fp.getData(); 808 int data_length = fp.getPos(); 809 int eSize = mType.mElement.mElements[component_number].getBytesSize(); 810 eSize *= mType.mElement.mArraySizes[component_number]; 811 812 if (data_length != eSize) { 813 throw new RSIllegalArgumentException("Field packer sizelength " + data_length + 814 " does not match component size " + eSize + "."); 815 } 816 817 mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD, 818 component_number, data, data_length); 819 } 820 data1DChecks(int off, int count, int len, int dataSize)821 private void data1DChecks(int off, int count, int len, int dataSize) { 822 mRS.validate(); 823 if(off < 0) { 824 throw new RSIllegalArgumentException("Offset must be >= 0."); 825 } 826 if(count < 1) { 827 throw new RSIllegalArgumentException("Count must be >= 1."); 828 } 829 if((off + count) > mCurrentCount) { 830 throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount + 831 ", got " + count + " at offset " + off + "."); 832 } 833 if(len < dataSize) { 834 throw new RSIllegalArgumentException("Array too small for allocation type."); 835 } 836 } 837 838 /** 839 * Generate a mipmap chain. This is only valid if the Type of the Allocation 840 * includes mipmaps. 841 * 842 * <p>This function will generate a complete set of mipmaps from the top 843 * level LOD and place them into the script memory space.</p> 844 * 845 * <p>If the Allocation is also using other memory spaces, a call to {@link 846 * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p> 847 */ generateMipmaps()848 public void generateMipmaps() { 849 mRS.nAllocationGenerateMipmaps(getID(mRS)); 850 } 851 copy1DRangeFromUnchecked(int off, int count, Object array, Element.DataType dt, int arrayLen)852 private void copy1DRangeFromUnchecked(int off, int count, Object array, 853 Element.DataType dt, int arrayLen) { 854 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked"); 855 final int dataSize = mType.mElement.getBytesSize() * count; 856 data1DChecks(off, count, arrayLen * dt.mSize, dataSize); 857 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt); 858 Trace.traceEnd(RenderScript.TRACE_TAG); 859 } 860 861 /** 862 * Copy an array into part of this Allocation. This method does not 863 * guarantee that the Allocation is compatible with the input buffer. 864 * 865 * @param off The offset of the first element to be copied. 866 * @param count The number of elements to be copied. 867 * @param array The source data array 868 */ copy1DRangeFromUnchecked(int off, int count, Object array)869 public void copy1DRangeFromUnchecked(int off, int count, Object array) { 870 copy1DRangeFromUnchecked(off, count, array, 871 validateObjectIsPrimitiveArray(array, false), 872 java.lang.reflect.Array.getLength(array)); 873 } 874 875 /** 876 * Copy an array into part of this Allocation. This method does not 877 * guarantee that the Allocation is compatible with the input buffer. 878 * 879 * @param off The offset of the first element to be copied. 880 * @param count The number of elements to be copied. 881 * @param d the source data array 882 */ copy1DRangeFromUnchecked(int off, int count, int[] d)883 public void copy1DRangeFromUnchecked(int off, int count, int[] d) { 884 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length); 885 } 886 887 /** 888 * Copy an array into part of this Allocation. This method does not 889 * guarantee that the Allocation is compatible with the input buffer. 890 * 891 * @param off The offset of the first element to be copied. 892 * @param count The number of elements to be copied. 893 * @param d the source data array 894 */ copy1DRangeFromUnchecked(int off, int count, short[] d)895 public void copy1DRangeFromUnchecked(int off, int count, short[] d) { 896 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length); 897 } 898 899 /** 900 * Copy an array into part of this Allocation. This method does not 901 * guarantee that the Allocation is compatible with the input buffer. 902 * 903 * @param off The offset of the first element to be copied. 904 * @param count The number of elements to be copied. 905 * @param d the source data array 906 */ copy1DRangeFromUnchecked(int off, int count, byte[] d)907 public void copy1DRangeFromUnchecked(int off, int count, byte[] d) { 908 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length); 909 } 910 911 /** 912 * Copy an array into part of this Allocation. This method does not 913 * guarantee that the Allocation is compatible with the input buffer. 914 * 915 * @param off The offset of the first element to be copied. 916 * @param count The number of elements to be copied. 917 * @param d the source data array 918 */ copy1DRangeFromUnchecked(int off, int count, float[] d)919 public void copy1DRangeFromUnchecked(int off, int count, float[] d) { 920 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length); 921 } 922 923 924 /** 925 * Copy an array into part of this Allocation. This variant is type checked 926 * and will generate exceptions if the Allocation type does not 927 * match the component type of the array passed in. 928 * 929 * @param off The offset of the first element to be copied. 930 * @param count The number of elements to be copied. 931 * @param array The source data array. 932 */ copy1DRangeFrom(int off, int count, Object array)933 public void copy1DRangeFrom(int off, int count, Object array) { 934 copy1DRangeFromUnchecked(off, count, array, 935 validateObjectIsPrimitiveArray(array, true), 936 java.lang.reflect.Array.getLength(array)); 937 } 938 939 /** 940 * Copy an array into part of this Allocation. This variant is type checked 941 * and will generate exceptions if the Allocation type is not a 32 bit 942 * integer type. 943 * 944 * @param off The offset of the first element to be copied. 945 * @param count The number of elements to be copied. 946 * @param d the source data array 947 */ copy1DRangeFrom(int off, int count, int[] d)948 public void copy1DRangeFrom(int off, int count, int[] d) { 949 validateIsInt32(); 950 copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length); 951 } 952 953 /** 954 * Copy an array into part of this Allocation. This variant is type checked 955 * and will generate exceptions if the Allocation type is not a 16 bit 956 * integer type. 957 * 958 * @param off The offset of the first element to be copied. 959 * @param count The number of elements to be copied. 960 * @param d the source data array 961 */ copy1DRangeFrom(int off, int count, short[] d)962 public void copy1DRangeFrom(int off, int count, short[] d) { 963 validateIsInt16(); 964 copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length); 965 } 966 967 /** 968 * Copy an array into part of this Allocation. This variant is type checked 969 * and will generate exceptions if the Allocation type is not an 8 bit 970 * integer type. 971 * 972 * @param off The offset of the first element to be copied. 973 * @param count The number of elements to be copied. 974 * @param d the source data array 975 */ copy1DRangeFrom(int off, int count, byte[] d)976 public void copy1DRangeFrom(int off, int count, byte[] d) { 977 validateIsInt8(); 978 copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length); 979 } 980 981 /** 982 * Copy an array into part of this Allocation. This variant is type checked 983 * and will generate exceptions if the Allocation type is not a 32 bit float 984 * type. 985 * 986 * @param off The offset of the first element to be copied. 987 * @param count The number of elements to be copied. 988 * @param d the source data array. 989 */ copy1DRangeFrom(int off, int count, float[] d)990 public void copy1DRangeFrom(int off, int count, float[] d) { 991 validateIsFloat32(); 992 copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length); 993 } 994 995 /** 996 * Copy part of an Allocation into this Allocation. 997 * 998 * @param off The offset of the first element to be copied. 999 * @param count The number of elements to be copied. 1000 * @param data the source data allocation. 1001 * @param dataOff off The offset of the first element in data to 1002 * be copied. 1003 */ copy1DRangeFrom(int off, int count, Allocation data, int dataOff)1004 public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) { 1005 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom"); 1006 mRS.nAllocationData2D(getIDSafe(), off, 0, 1007 mSelectedLOD, mSelectedFace.mID, 1008 count, 1, data.getID(mRS), dataOff, 0, 1009 data.mSelectedLOD, data.mSelectedFace.mID); 1010 } 1011 validate2DRange(int xoff, int yoff, int w, int h)1012 private void validate2DRange(int xoff, int yoff, int w, int h) { 1013 if (mAdaptedAllocation != null) { 1014 1015 } else { 1016 1017 if (xoff < 0 || yoff < 0) { 1018 throw new RSIllegalArgumentException("Offset cannot be negative."); 1019 } 1020 if (h < 0 || w < 0) { 1021 throw new RSIllegalArgumentException("Height or width cannot be negative."); 1022 } 1023 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 1024 throw new RSIllegalArgumentException("Updated region larger than allocation."); 1025 } 1026 } 1027 } 1028 copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array, Element.DataType dt, int arrayLen)1029 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array, 1030 Element.DataType dt, int arrayLen) { 1031 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked"); 1032 mRS.validate(); 1033 validate2DRange(xoff, yoff, w, h); 1034 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h, 1035 array, arrayLen * dt.mSize, dt); 1036 Trace.traceEnd(RenderScript.TRACE_TAG); 1037 } 1038 1039 /** 1040 * Copy from an array into a rectangular region in this Allocation. The 1041 * array is assumed to be tightly packed. 1042 * 1043 * @param xoff X offset of the region to update in this Allocation 1044 * @param yoff Y offset of the region to update in this Allocation 1045 * @param w Width of the region to update 1046 * @param h Height of the region to update 1047 * @param array Data to be placed into the Allocation 1048 */ copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array)1049 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) { 1050 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1051 copy2DRangeFromUnchecked(xoff, yoff, w, h, array, 1052 validateObjectIsPrimitiveArray(array, true), 1053 java.lang.reflect.Array.getLength(array)); 1054 Trace.traceEnd(RenderScript.TRACE_TAG); 1055 } 1056 1057 /** 1058 * Copy from an array into a rectangular region in this Allocation. The 1059 * array is assumed to be tightly packed. 1060 * 1061 * @param xoff X offset of the region to update in this Allocation 1062 * @param yoff Y offset of the region to update in this Allocation 1063 * @param w Width of the region to update 1064 * @param h Height of the region to update 1065 * @param data to be placed into the Allocation 1066 */ copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data)1067 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { 1068 validateIsInt8(); 1069 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1070 Element.DataType.SIGNED_8, data.length); 1071 } 1072 1073 /** 1074 * Copy from an array into a rectangular region in this Allocation. The 1075 * array is assumed to be tightly packed. 1076 * 1077 * @param xoff X offset of the region to update in this Allocation 1078 * @param yoff Y offset of the region to update in this Allocation 1079 * @param w Width of the region to update 1080 * @param h Height of the region to update 1081 * @param data to be placed into the Allocation 1082 */ copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data)1083 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) { 1084 validateIsInt16(); 1085 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1086 Element.DataType.SIGNED_16, data.length); 1087 } 1088 1089 /** 1090 * Copy from an array into a rectangular region in this Allocation. The 1091 * array is assumed to be tightly packed. 1092 * 1093 * @param xoff X offset of the region to update in this Allocation 1094 * @param yoff Y offset of the region to update in this Allocation 1095 * @param w Width of the region to update 1096 * @param h Height of the region to update 1097 * @param data to be placed into the Allocation 1098 */ copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data)1099 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) { 1100 validateIsInt32(); 1101 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1102 Element.DataType.SIGNED_32, data.length); 1103 } 1104 1105 /** 1106 * Copy from an array into a rectangular region in this Allocation. The 1107 * array is assumed to be tightly packed. 1108 * 1109 * @param xoff X offset of the region to update in this Allocation 1110 * @param yoff Y offset of the region to update in this Allocation 1111 * @param w Width of the region to update 1112 * @param h Height of the region to update 1113 * @param data to be placed into the Allocation 1114 */ copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data)1115 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) { 1116 validateIsFloat32(); 1117 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1118 Element.DataType.FLOAT_32, data.length); 1119 } 1120 1121 /** 1122 * Copy a rectangular region from an Allocation into a rectangular region in 1123 * this Allocation. 1124 * 1125 * @param xoff X offset of the region in this Allocation 1126 * @param yoff Y offset of the region in this Allocation 1127 * @param w Width of the region to update. 1128 * @param h Height of the region to update. 1129 * @param data source Allocation. 1130 * @param dataXoff X offset in source Allocation 1131 * @param dataYoff Y offset in source Allocation 1132 */ copy2DRangeFrom(int xoff, int yoff, int w, int h, Allocation data, int dataXoff, int dataYoff)1133 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, 1134 Allocation data, int dataXoff, int dataYoff) { 1135 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1136 mRS.validate(); 1137 validate2DRange(xoff, yoff, w, h); 1138 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, 1139 mSelectedLOD, mSelectedFace.mID, 1140 w, h, data.getID(mRS), dataXoff, dataYoff, 1141 data.mSelectedLOD, data.mSelectedFace.mID); 1142 Trace.traceEnd(RenderScript.TRACE_TAG); 1143 } 1144 1145 /** 1146 * Copy a {@link android.graphics.Bitmap} into an Allocation. The height 1147 * and width of the update will use the height and width of the {@link 1148 * android.graphics.Bitmap}. 1149 * 1150 * @param xoff X offset of the region to update in this Allocation 1151 * @param yoff Y offset of the region to update in this Allocation 1152 * @param data the Bitmap to be copied 1153 */ copy2DRangeFrom(int xoff, int yoff, Bitmap data)1154 public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) { 1155 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1156 mRS.validate(); 1157 if (data.getConfig() == null) { 1158 Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888); 1159 Canvas c = new Canvas(newBitmap); 1160 c.drawBitmap(data, 0, 0, null); 1161 copy2DRangeFrom(xoff, yoff, newBitmap); 1162 return; 1163 } 1164 validateBitmapFormat(data); 1165 validate2DRange(xoff, yoff, data.getWidth(), data.getHeight()); 1166 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data); 1167 Trace.traceEnd(RenderScript.TRACE_TAG); 1168 } 1169 validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d)1170 private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) { 1171 if (mAdaptedAllocation != null) { 1172 1173 } else { 1174 1175 if (xoff < 0 || yoff < 0 || zoff < 0) { 1176 throw new RSIllegalArgumentException("Offset cannot be negative."); 1177 } 1178 if (h < 0 || w < 0 || d < 0) { 1179 throw new RSIllegalArgumentException("Height or width cannot be negative."); 1180 } 1181 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) { 1182 throw new RSIllegalArgumentException("Updated region larger than allocation."); 1183 } 1184 } 1185 } 1186 1187 /** 1188 * @hide 1189 * 1190 */ copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, Object array, Element.DataType dt, int arrayLen)1191 private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, 1192 Object array, Element.DataType dt, int arrayLen) { 1193 Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked"); 1194 mRS.validate(); 1195 validate3DRange(xoff, yoff, zoff, w, h, d); 1196 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d, 1197 array, arrayLen * dt.mSize, dt); 1198 Trace.traceEnd(RenderScript.TRACE_TAG); 1199 } 1200 1201 /** 1202 * @hide 1203 * Copy a rectangular region from the array into the allocation. 1204 * The array is assumed to be tightly packed. 1205 * 1206 * @param xoff X offset of the region to update in this Allocation 1207 * @param yoff Y offset of the region to update in this Allocation 1208 * @param zoff Z offset of the region to update in this Allocation 1209 * @param w Width of the region to update 1210 * @param h Height of the region to update 1211 * @param d Depth of the region to update 1212 * @param data to be placed into the allocation 1213 */ copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array)1214 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) { 1215 Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom"); 1216 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array, 1217 validateObjectIsPrimitiveArray(array, true), 1218 java.lang.reflect.Array.getLength(array)); 1219 Trace.traceEnd(RenderScript.TRACE_TAG); 1220 } 1221 1222 /** 1223 * @hide 1224 * Copy a rectangular region into the allocation from another 1225 * allocation. 1226 * 1227 * @param xoff X offset of the region to update in this Allocation 1228 * @param yoff Y offset of the region to update in this Allocation 1229 * @param zoff Z offset of the region to update in this Allocation 1230 * @param w Width of the region to update. 1231 * @param h Height of the region to update. 1232 * @param d Depth of the region to update. 1233 * @param data source allocation. 1234 * @param dataXoff X offset of the region in the source Allocation 1235 * @param dataYoff Y offset of the region in the source Allocation 1236 * @param dataZoff Z offset of the region in the source Allocation 1237 */ copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Allocation data, int dataXoff, int dataYoff, int dataZoff)1238 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, 1239 Allocation data, int dataXoff, int dataYoff, int dataZoff) { 1240 mRS.validate(); 1241 validate3DRange(xoff, yoff, zoff, w, h, d); 1242 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1243 w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff, 1244 data.mSelectedLOD); 1245 } 1246 1247 1248 /** 1249 * Copy from the Allocation into a {@link android.graphics.Bitmap}. The 1250 * bitmap must match the dimensions of the Allocation. 1251 * 1252 * @param b The bitmap to be set from the Allocation. 1253 */ copyTo(Bitmap b)1254 public void copyTo(Bitmap b) { 1255 Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); 1256 mRS.validate(); 1257 validateBitmapFormat(b); 1258 validateBitmapSize(b); 1259 mRS.nAllocationCopyToBitmap(getID(mRS), b); 1260 Trace.traceEnd(RenderScript.TRACE_TAG); 1261 } 1262 copyTo(Object array, Element.DataType dt, int arrayLen)1263 private void copyTo(Object array, Element.DataType dt, int arrayLen) { 1264 Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); 1265 if (dt.mSize * arrayLen < mSize) { 1266 throw new RSIllegalArgumentException( 1267 "Size of output array cannot be smaller than size of allocation."); 1268 } 1269 mRS.validate(); 1270 mRS.nAllocationRead(getID(mRS), array, dt); 1271 Trace.traceEnd(RenderScript.TRACE_TAG); 1272 } 1273 1274 /** 1275 * Copy from the Allocation into an array. The array must be at 1276 * least as large as the Allocation. The 1277 * {@link android.renderscript.Element} must match the component 1278 * type of the array passed in. 1279 * 1280 * @param array The array to be set from the Allocation. 1281 */ copyTo(Object array)1282 public void copyTo(Object array) { 1283 copyTo(array, validateObjectIsPrimitiveArray(array, true), 1284 java.lang.reflect.Array.getLength(array)); 1285 } 1286 1287 /** 1288 * Copy from the Allocation into a byte array. The array must be at least 1289 * as large as the Allocation. The allocation must be of an 8 bit integer 1290 * {@link android.renderscript.Element} type. 1291 * 1292 * @param d The array to be set from the Allocation. 1293 */ copyTo(byte[] d)1294 public void copyTo(byte[] d) { 1295 validateIsInt8(); 1296 copyTo(d, Element.DataType.SIGNED_8, d.length); 1297 } 1298 1299 /** 1300 * Copy from the Allocation into a short array. The array must be at least 1301 * as large as the Allocation. The allocation must be of an 16 bit integer 1302 * {@link android.renderscript.Element} type. 1303 * 1304 * @param d The array to be set from the Allocation. 1305 */ copyTo(short[] d)1306 public void copyTo(short[] d) { 1307 validateIsInt16(); 1308 copyTo(d, Element.DataType.SIGNED_16, d.length); 1309 } 1310 1311 /** 1312 * Copy from the Allocation into a int array. The array must be at least as 1313 * large as the Allocation. The allocation must be of an 32 bit integer 1314 * {@link android.renderscript.Element} type. 1315 * 1316 * @param d The array to be set from the Allocation. 1317 */ copyTo(int[] d)1318 public void copyTo(int[] d) { 1319 validateIsInt32(); 1320 copyTo(d, Element.DataType.SIGNED_32, d.length); 1321 } 1322 1323 /** 1324 * Copy from the Allocation into a float array. The array must be at least 1325 * as large as the Allocation. The allocation must be of an 32 bit float 1326 * {@link android.renderscript.Element} type. 1327 * 1328 * @param d The array to be set from the Allocation. 1329 */ copyTo(float[] d)1330 public void copyTo(float[] d) { 1331 validateIsFloat32(); 1332 copyTo(d, Element.DataType.FLOAT_32, d.length); 1333 } 1334 1335 /** 1336 * Resize a 1D allocation. The contents of the allocation are preserved. 1337 * If new elements are allocated objects are created with null contents and 1338 * the new region is otherwise undefined. 1339 * 1340 * <p>If the new region is smaller the references of any objects outside the 1341 * new region will be released.</p> 1342 * 1343 * <p>A new type will be created with the new dimension.</p> 1344 * 1345 * @param dimX The new size of the allocation. 1346 * 1347 * @deprecated RenderScript objects should be immutable once created. The 1348 * replacement is to create a new allocation and copy the contents. This 1349 * function will throw an exception if API 21 or higher is used. 1350 */ resize(int dimX)1351 public synchronized void resize(int dimX) { 1352 if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 21) { 1353 throw new RSRuntimeException("Resize is not allowed in API 21+."); 1354 } 1355 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 1356 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 1357 } 1358 mRS.nAllocationResize1D(getID(mRS), dimX); 1359 mRS.finish(); // Necessary because resize is fifoed and update is async. 1360 1361 long typeID = mRS.nAllocationGetType(getID(mRS)); 1362 mType = new Type(typeID, mRS); 1363 mType.updateFromNative(); 1364 updateCacheInfo(mType); 1365 } 1366 1367 1368 // creation 1369 1370 static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 1371 static { 1372 mBitmapOptions.inScaled = false; 1373 } 1374 1375 /** 1376 * Creates a new Allocation with the given {@link 1377 * android.renderscript.Type}, mipmap flag, and usage flags. 1378 * 1379 * @param type RenderScript type describing data layout 1380 * @param mips specifies desired mipmap behaviour for the 1381 * allocation 1382 * @param usage bit field specifying how the Allocation is 1383 * utilized 1384 */ createTyped(RenderScript rs, Type type, MipmapControl mips, int usage)1385 static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) { 1386 Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped"); 1387 rs.validate(); 1388 if (type.getID(rs) == 0) { 1389 throw new RSInvalidStateException("Bad Type"); 1390 } 1391 long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0); 1392 if (id == 0) { 1393 throw new RSRuntimeException("Allocation creation failed."); 1394 } 1395 Trace.traceEnd(RenderScript.TRACE_TAG); 1396 return new Allocation(id, rs, type, usage); 1397 } 1398 1399 /** 1400 * Creates an Allocation with the size specified by the type and no mipmaps 1401 * generated by default 1402 * 1403 * @param rs Context to which the allocation will belong. 1404 * @param type renderscript type describing data layout 1405 * @param usage bit field specifying how the allocation is 1406 * utilized 1407 * 1408 * @return allocation 1409 */ createTyped(RenderScript rs, Type type, int usage)1410 static public Allocation createTyped(RenderScript rs, Type type, int usage) { 1411 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage); 1412 } 1413 1414 /** 1415 * Creates an Allocation for use by scripts with a given {@link 1416 * android.renderscript.Type} and no mipmaps 1417 * 1418 * @param rs Context to which the Allocation will belong. 1419 * @param type RenderScript Type describing data layout 1420 * 1421 * @return allocation 1422 */ createTyped(RenderScript rs, Type type)1423 static public Allocation createTyped(RenderScript rs, Type type) { 1424 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT); 1425 } 1426 1427 /** 1428 * Creates an Allocation with a specified number of given elements 1429 * 1430 * @param rs Context to which the Allocation will belong. 1431 * @param e Element to use in the Allocation 1432 * @param count the number of Elements in the Allocation 1433 * @param usage bit field specifying how the Allocation is 1434 * utilized 1435 * 1436 * @return allocation 1437 */ createSized(RenderScript rs, Element e, int count, int usage)1438 static public Allocation createSized(RenderScript rs, Element e, 1439 int count, int usage) { 1440 Trace.traceBegin(RenderScript.TRACE_TAG, "createSized"); 1441 rs.validate(); 1442 Type.Builder b = new Type.Builder(rs, e); 1443 b.setX(count); 1444 Type t = b.create(); 1445 1446 long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0); 1447 if (id == 0) { 1448 throw new RSRuntimeException("Allocation creation failed."); 1449 } 1450 Trace.traceEnd(RenderScript.TRACE_TAG); 1451 return new Allocation(id, rs, t, usage); 1452 } 1453 1454 /** 1455 * Creates an Allocation with a specified number of given elements 1456 * 1457 * @param rs Context to which the Allocation will belong. 1458 * @param e Element to use in the Allocation 1459 * @param count the number of Elements in the Allocation 1460 * 1461 * @return allocation 1462 */ createSized(RenderScript rs, Element e, int count)1463 static public Allocation createSized(RenderScript rs, Element e, int count) { 1464 return createSized(rs, e, count, USAGE_SCRIPT); 1465 } 1466 elementFromBitmap(RenderScript rs, Bitmap b)1467 static Element elementFromBitmap(RenderScript rs, Bitmap b) { 1468 final Bitmap.Config bc = b.getConfig(); 1469 if (bc == Bitmap.Config.ALPHA_8) { 1470 return Element.A_8(rs); 1471 } 1472 if (bc == Bitmap.Config.ARGB_4444) { 1473 return Element.RGBA_4444(rs); 1474 } 1475 if (bc == Bitmap.Config.ARGB_8888) { 1476 return Element.RGBA_8888(rs); 1477 } 1478 if (bc == Bitmap.Config.RGB_565) { 1479 return Element.RGB_565(rs); 1480 } 1481 throw new RSInvalidStateException("Bad bitmap type: " + bc); 1482 } 1483 typeFromBitmap(RenderScript rs, Bitmap b, MipmapControl mip)1484 static Type typeFromBitmap(RenderScript rs, Bitmap b, 1485 MipmapControl mip) { 1486 Element e = elementFromBitmap(rs, b); 1487 Type.Builder tb = new Type.Builder(rs, e); 1488 tb.setX(b.getWidth()); 1489 tb.setY(b.getHeight()); 1490 tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); 1491 return tb.create(); 1492 } 1493 1494 /** 1495 * Creates an Allocation from a {@link android.graphics.Bitmap}. 1496 * 1497 * @param rs Context to which the allocation will belong. 1498 * @param b Bitmap source for the allocation data 1499 * @param mips specifies desired mipmap behaviour for the 1500 * allocation 1501 * @param usage bit field specifying how the allocation is 1502 * utilized 1503 * 1504 * @return Allocation containing bitmap data 1505 * 1506 */ createFromBitmap(RenderScript rs, Bitmap b, MipmapControl mips, int usage)1507 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 1508 MipmapControl mips, 1509 int usage) { 1510 Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap"); 1511 rs.validate(); 1512 1513 // WAR undocumented color formats 1514 if (b.getConfig() == null) { 1515 if ((usage & USAGE_SHARED) != 0) { 1516 throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config."); 1517 } 1518 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 1519 Canvas c = new Canvas(newBitmap); 1520 c.drawBitmap(b, 0, 0, null); 1521 return createFromBitmap(rs, newBitmap, mips, usage); 1522 } 1523 1524 Type t = typeFromBitmap(rs, b, mips); 1525 1526 // enable optimized bitmap path only with no mipmap and script-only usage 1527 if (mips == MipmapControl.MIPMAP_NONE && 1528 t.getElement().isCompatible(Element.RGBA_8888(rs)) && 1529 usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) { 1530 long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage); 1531 if (id == 0) { 1532 throw new RSRuntimeException("Load failed."); 1533 } 1534 1535 // keep a reference to the Bitmap around to prevent GC 1536 Allocation alloc = new Allocation(id, rs, t, usage); 1537 alloc.setBitmap(b); 1538 return alloc; 1539 } 1540 1541 1542 long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1543 if (id == 0) { 1544 throw new RSRuntimeException("Load failed."); 1545 } 1546 Trace.traceEnd(RenderScript.TRACE_TAG); 1547 return new Allocation(id, rs, t, usage); 1548 } 1549 1550 /** 1551 * Returns the handle to a raw buffer that is being managed by the screen 1552 * compositor. This operation is only valid for Allocations with {@link 1553 * #USAGE_IO_INPUT}. 1554 * 1555 * @return Surface object associated with allocation 1556 * 1557 */ getSurface()1558 public Surface getSurface() { 1559 if ((mUsage & USAGE_IO_INPUT) == 0) { 1560 throw new RSInvalidStateException("Allocation is not a surface texture."); 1561 } 1562 return mRS.nAllocationGetSurface(getID(mRS)); 1563 } 1564 1565 /** 1566 * Associate a {@link android.view.Surface} with this Allocation. This 1567 * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}. 1568 * 1569 * @param sur Surface to associate with allocation 1570 */ setSurface(Surface sur)1571 public void setSurface(Surface sur) { 1572 mRS.validate(); 1573 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 1574 throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT."); 1575 } 1576 1577 mRS.nAllocationSetSurface(getID(mRS), sur); 1578 } 1579 1580 /** 1581 * Creates an Allocation from a {@link android.graphics.Bitmap}. 1582 * 1583 * <p>With target API version 18 or greater, this Allocation will be created 1584 * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link 1585 * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this 1586 * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p> 1587 * 1588 * @param rs Context to which the allocation will belong. 1589 * @param b bitmap source for the allocation data 1590 * 1591 * @return Allocation containing bitmap data 1592 * 1593 */ createFromBitmap(RenderScript rs, Bitmap b)1594 static public Allocation createFromBitmap(RenderScript rs, Bitmap b) { 1595 if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) { 1596 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1597 USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 1598 } 1599 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1600 USAGE_GRAPHICS_TEXTURE); 1601 } 1602 1603 /** 1604 * Creates a cubemap Allocation from a {@link android.graphics.Bitmap} 1605 * containing the horizontal list of cube faces. Each face must be a square, 1606 * have the same size as all other faces, and have a width that is a power 1607 * of 2. 1608 * 1609 * @param rs Context to which the allocation will belong. 1610 * @param b Bitmap with cubemap faces layed out in the following 1611 * format: right, left, top, bottom, front, back 1612 * @param mips specifies desired mipmap behaviour for the cubemap 1613 * @param usage bit field specifying how the cubemap is utilized 1614 * 1615 * @return allocation containing cubemap data 1616 * 1617 */ createCubemapFromBitmap(RenderScript rs, Bitmap b, MipmapControl mips, int usage)1618 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 1619 MipmapControl mips, 1620 int usage) { 1621 rs.validate(); 1622 1623 int height = b.getHeight(); 1624 int width = b.getWidth(); 1625 1626 if (width % 6 != 0) { 1627 throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); 1628 } 1629 if (width / 6 != height) { 1630 throw new RSIllegalArgumentException("Only square cube map faces supported"); 1631 } 1632 boolean isPow2 = (height & (height - 1)) == 0; 1633 if (!isPow2) { 1634 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 1635 } 1636 1637 Element e = elementFromBitmap(rs, b); 1638 Type.Builder tb = new Type.Builder(rs, e); 1639 tb.setX(height); 1640 tb.setY(height); 1641 tb.setFaces(true); 1642 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 1643 Type t = tb.create(); 1644 1645 long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1646 if(id == 0) { 1647 throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); 1648 } 1649 return new Allocation(id, rs, t, usage); 1650 } 1651 1652 /** 1653 * Creates a non-mipmapped cubemap Allocation for use as a graphics texture 1654 * from a {@link android.graphics.Bitmap} containing the horizontal list of 1655 * cube faces. Each face must be a square, have the same size as all other 1656 * faces, and have a width that is a power of 2. 1657 * 1658 * @param rs Context to which the allocation will belong. 1659 * @param b bitmap with cubemap faces layed out in the following 1660 * format: right, left, top, bottom, front, back 1661 * 1662 * @return allocation containing cubemap data 1663 * 1664 */ createCubemapFromBitmap(RenderScript rs, Bitmap b)1665 static public Allocation createCubemapFromBitmap(RenderScript rs, 1666 Bitmap b) { 1667 return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1668 USAGE_GRAPHICS_TEXTURE); 1669 } 1670 1671 /** 1672 * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap} 1673 * objects containing the cube faces. Each face must be a square, have the 1674 * same size as all other faces, and have a width that is a power of 2. 1675 * 1676 * @param rs Context to which the allocation will belong. 1677 * @param xpos cubemap face in the positive x direction 1678 * @param xneg cubemap face in the negative x direction 1679 * @param ypos cubemap face in the positive y direction 1680 * @param yneg cubemap face in the negative y direction 1681 * @param zpos cubemap face in the positive z direction 1682 * @param zneg cubemap face in the negative z direction 1683 * @param mips specifies desired mipmap behaviour for the cubemap 1684 * @param usage bit field specifying how the cubemap is utilized 1685 * 1686 * @return allocation containing cubemap data 1687 * 1688 */ createCubemapFromCubeFaces(RenderScript rs, Bitmap xpos, Bitmap xneg, Bitmap ypos, Bitmap yneg, Bitmap zpos, Bitmap zneg, MipmapControl mips, int usage)1689 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 1690 Bitmap xpos, 1691 Bitmap xneg, 1692 Bitmap ypos, 1693 Bitmap yneg, 1694 Bitmap zpos, 1695 Bitmap zneg, 1696 MipmapControl mips, 1697 int usage) { 1698 int height = xpos.getHeight(); 1699 if (xpos.getWidth() != height || 1700 xneg.getWidth() != height || xneg.getHeight() != height || 1701 ypos.getWidth() != height || ypos.getHeight() != height || 1702 yneg.getWidth() != height || yneg.getHeight() != height || 1703 zpos.getWidth() != height || zpos.getHeight() != height || 1704 zneg.getWidth() != height || zneg.getHeight() != height) { 1705 throw new RSIllegalArgumentException("Only square cube map faces supported"); 1706 } 1707 boolean isPow2 = (height & (height - 1)) == 0; 1708 if (!isPow2) { 1709 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 1710 } 1711 1712 Element e = elementFromBitmap(rs, xpos); 1713 Type.Builder tb = new Type.Builder(rs, e); 1714 tb.setX(height); 1715 tb.setY(height); 1716 tb.setFaces(true); 1717 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 1718 Type t = tb.create(); 1719 Allocation cubemap = Allocation.createTyped(rs, t, mips, usage); 1720 1721 AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap); 1722 adapter.setFace(Type.CubemapFace.POSITIVE_X); 1723 adapter.copyFrom(xpos); 1724 adapter.setFace(Type.CubemapFace.NEGATIVE_X); 1725 adapter.copyFrom(xneg); 1726 adapter.setFace(Type.CubemapFace.POSITIVE_Y); 1727 adapter.copyFrom(ypos); 1728 adapter.setFace(Type.CubemapFace.NEGATIVE_Y); 1729 adapter.copyFrom(yneg); 1730 adapter.setFace(Type.CubemapFace.POSITIVE_Z); 1731 adapter.copyFrom(zpos); 1732 adapter.setFace(Type.CubemapFace.NEGATIVE_Z); 1733 adapter.copyFrom(zneg); 1734 1735 return cubemap; 1736 } 1737 1738 /** 1739 * Creates a non-mipmapped cubemap Allocation for use as a sampler input 1740 * from 6 {@link android.graphics.Bitmap} objects containing the cube 1741 * faces. Each face must be a square, have the same size as all other faces, 1742 * and have a width that is a power of 2. 1743 * 1744 * @param rs Context to which the allocation will belong. 1745 * @param xpos cubemap face in the positive x direction 1746 * @param xneg cubemap face in the negative x direction 1747 * @param ypos cubemap face in the positive y direction 1748 * @param yneg cubemap face in the negative y direction 1749 * @param zpos cubemap face in the positive z direction 1750 * @param zneg cubemap face in the negative z direction 1751 * 1752 * @return allocation containing cubemap data 1753 * 1754 */ createCubemapFromCubeFaces(RenderScript rs, Bitmap xpos, Bitmap xneg, Bitmap ypos, Bitmap yneg, Bitmap zpos, Bitmap zneg)1755 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 1756 Bitmap xpos, 1757 Bitmap xneg, 1758 Bitmap ypos, 1759 Bitmap yneg, 1760 Bitmap zpos, 1761 Bitmap zneg) { 1762 return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg, 1763 zpos, zneg, MipmapControl.MIPMAP_NONE, 1764 USAGE_GRAPHICS_TEXTURE); 1765 } 1766 1767 /** 1768 * Creates an Allocation from the Bitmap referenced 1769 * by resource ID. 1770 * 1771 * @param rs Context to which the allocation will belong. 1772 * @param res application resources 1773 * @param id resource id to load the data from 1774 * @param mips specifies desired mipmap behaviour for the 1775 * allocation 1776 * @param usage bit field specifying how the allocation is 1777 * utilized 1778 * 1779 * @return Allocation containing resource data 1780 * 1781 */ createFromBitmapResource(RenderScript rs, Resources res, int id, MipmapControl mips, int usage)1782 static public Allocation createFromBitmapResource(RenderScript rs, 1783 Resources res, 1784 int id, 1785 MipmapControl mips, 1786 int usage) { 1787 1788 rs.validate(); 1789 if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) { 1790 throw new RSIllegalArgumentException("Unsupported usage specified."); 1791 } 1792 Bitmap b = BitmapFactory.decodeResource(res, id); 1793 Allocation alloc = createFromBitmap(rs, b, mips, usage); 1794 b.recycle(); 1795 return alloc; 1796 } 1797 1798 /** 1799 * Creates a non-mipmapped Allocation to use as a graphics texture from the 1800 * {@link android.graphics.Bitmap} referenced by resource ID. 1801 * 1802 * <p>With target API version 18 or greater, this allocation will be created 1803 * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With 1804 * target API version 17 or lower, this allocation will be created with 1805 * {@link #USAGE_GRAPHICS_TEXTURE}.</p> 1806 * 1807 * @param rs Context to which the allocation will belong. 1808 * @param res application resources 1809 * @param id resource id to load the data from 1810 * 1811 * @return Allocation containing resource data 1812 * 1813 */ createFromBitmapResource(RenderScript rs, Resources res, int id)1814 static public Allocation createFromBitmapResource(RenderScript rs, 1815 Resources res, 1816 int id) { 1817 if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) { 1818 return createFromBitmapResource(rs, res, id, 1819 MipmapControl.MIPMAP_NONE, 1820 USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 1821 } 1822 return createFromBitmapResource(rs, res, id, 1823 MipmapControl.MIPMAP_NONE, 1824 USAGE_GRAPHICS_TEXTURE); 1825 } 1826 1827 /** 1828 * Creates an Allocation containing string data encoded in UTF-8 format. 1829 * 1830 * @param rs Context to which the allocation will belong. 1831 * @param str string to create the allocation from 1832 * @param usage bit field specifying how the allocaiton is 1833 * utilized 1834 * 1835 */ createFromString(RenderScript rs, String str, int usage)1836 static public Allocation createFromString(RenderScript rs, 1837 String str, 1838 int usage) { 1839 rs.validate(); 1840 byte[] allocArray = null; 1841 try { 1842 allocArray = str.getBytes("UTF-8"); 1843 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 1844 alloc.copyFrom(allocArray); 1845 return alloc; 1846 } 1847 catch (Exception e) { 1848 throw new RSRuntimeException("Could not convert string to utf-8."); 1849 } 1850 } 1851 1852 /** 1853 * Interface to handle notification when new buffers are available via 1854 * {@link #USAGE_IO_INPUT}. An application will receive one notification 1855 * when a buffer is available. Additional buffers will not trigger new 1856 * notifications until a buffer is processed. 1857 */ 1858 public interface OnBufferAvailableListener { onBufferAvailable(Allocation a)1859 public void onBufferAvailable(Allocation a); 1860 } 1861 1862 /** 1863 * Set a notification handler for {@link #USAGE_IO_INPUT}. 1864 * 1865 * @param callback instance of the OnBufferAvailableListener 1866 * class to be called when buffer arrive. 1867 */ setOnBufferAvailableListener(OnBufferAvailableListener callback)1868 public void setOnBufferAvailableListener(OnBufferAvailableListener callback) { 1869 synchronized(mAllocationMap) { 1870 mAllocationMap.put(new Long(getID(mRS)), this); 1871 mBufferNotifier = callback; 1872 } 1873 } 1874 sendBufferNotification(long id)1875 static void sendBufferNotification(long id) { 1876 synchronized(mAllocationMap) { 1877 Allocation a = mAllocationMap.get(new Long(id)); 1878 1879 if ((a != null) && (a.mBufferNotifier != null)) { 1880 a.mBufferNotifier.onBufferAvailable(a); 1881 } 1882 } 1883 } 1884 1885 } 1886