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