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