Allocation.java revision a4f4a00cdd01fe58862f7ee7d81a9fd445f9dbf7
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 zoff 800 * @param component_number 801 * @param fp 802 */ 803 /* 804 public void setFromFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) { 805 mRS.validate(); 806 if (component_number >= mType.mElement.mElements.length) { 807 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 808 } 809 if(xoff < 0) { 810 throw new RSIllegalArgumentException("Offset x must be >= 0."); 811 } 812 if(yoff < 0) { 813 throw new RSIllegalArgumentException("Offset y must be >= 0."); 814 } 815 if(zoff < 0) { 816 throw new RSIllegalArgumentException("Offset z must be >= 0."); 817 } 818 819 final byte[] data = fp.getData(); 820 int data_length = fp.getPos(); 821 int eSize = mType.mElement.mElements[component_number].getBytesSize(); 822 eSize *= mType.mElement.mArraySizes[component_number]; 823 824 if (data_length != eSize) { 825 throw new RSIllegalArgumentException("Field packer sizelength " + data_length + 826 " does not match component size " + eSize + "."); 827 } 828 829 mRS.nAllocationElementData(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 830 component_number, data, data_length); 831 } 832 */ 833 834 private void data1DChecks(int off, int count, int len, int dataSize, boolean usePadding) { 835 mRS.validate(); 836 if(off < 0) { 837 throw new RSIllegalArgumentException("Offset must be >= 0."); 838 } 839 if(count < 1) { 840 throw new RSIllegalArgumentException("Count must be >= 1."); 841 } 842 if((off + count) > mCurrentCount) { 843 throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount + 844 ", got " + count + " at offset " + off + "."); 845 } 846 if(usePadding) { 847 if(len < dataSize / 4 * 3) { 848 throw new RSIllegalArgumentException("Array too small for allocation type."); 849 } 850 } else { 851 if(len < dataSize) { 852 throw new RSIllegalArgumentException("Array too small for allocation type."); 853 } 854 } 855 } 856 857 /** 858 * Generate a mipmap chain. This is only valid if the Type of the Allocation 859 * includes mipmaps. 860 * 861 * <p>This function will generate a complete set of mipmaps from the top 862 * level LOD and place them into the script memory space.</p> 863 * 864 * <p>If the Allocation is also using other memory spaces, a call to {@link 865 * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p> 866 */ 867 public void generateMipmaps() { 868 mRS.nAllocationGenerateMipmaps(getID(mRS)); 869 } 870 871 private void copy1DRangeFromUnchecked(int off, int count, Object array, 872 Element.DataType dt, int arrayLen) { 873 final int dataSize = mType.mElement.getBytesSize() * count; 874 // AutoPadding for Vec3 Element 875 boolean usePadding = false; 876 if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { 877 usePadding = true; 878 } 879 data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding); 880 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt, 881 mType.mElement.mType.mSize, usePadding); 882 } 883 884 /** 885 * Copy an array into part of this Allocation. This method does not 886 * guarantee that the Allocation is compatible with the input buffer. 887 * 888 * @param off The offset of the first element to be copied. 889 * @param count The number of elements to be copied. 890 * @param array The source data array 891 */ 892 public void copy1DRangeFromUnchecked(int off, int count, Object array) { 893 copy1DRangeFromUnchecked(off, count, array, 894 validateObjectIsPrimitiveArray(array, false), 895 java.lang.reflect.Array.getLength(array)); 896 } 897 898 /** 899 * Copy an array into part of this Allocation. This method does not 900 * guarantee that the Allocation is compatible with the input buffer. 901 * 902 * @param off The offset of the first element to be copied. 903 * @param count The number of elements to be copied. 904 * @param d the source data array 905 */ 906 public void copy1DRangeFromUnchecked(int off, int count, int[] d) { 907 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length); 908 } 909 910 /** 911 * Copy an array into part of this Allocation. This method does not 912 * guarantee that the Allocation is compatible with the input buffer. 913 * 914 * @param off The offset of the first element to be copied. 915 * @param count The number of elements to be copied. 916 * @param d the source data array 917 */ 918 public void copy1DRangeFromUnchecked(int off, int count, short[] d) { 919 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length); 920 } 921 922 /** 923 * Copy an array into part of this Allocation. This method does not 924 * guarantee that the Allocation is compatible with the input buffer. 925 * 926 * @param off The offset of the first element to be copied. 927 * @param count The number of elements to be copied. 928 * @param d the source data array 929 */ 930 public void copy1DRangeFromUnchecked(int off, int count, byte[] d) { 931 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length); 932 } 933 934 /** 935 * Copy an array into part of this Allocation. This method does not 936 * guarantee that the Allocation is compatible with the input buffer. 937 * 938 * @param off The offset of the first element to be copied. 939 * @param count The number of elements to be copied. 940 * @param d the source data array 941 */ 942 public void copy1DRangeFromUnchecked(int off, int count, float[] d) { 943 copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length); 944 } 945 946 947 /** 948 * Copy an array into part of this Allocation. This variant is type checked 949 * and will generate exceptions if the Allocation type does not 950 * match the component type of the array passed in. 951 * 952 * @param off The offset of the first element to be copied. 953 * @param count The number of elements to be copied. 954 * @param array The source data array. 955 */ 956 public void copy1DRangeFrom(int off, int count, Object array) { 957 copy1DRangeFromUnchecked(off, count, array, 958 validateObjectIsPrimitiveArray(array, true), 959 java.lang.reflect.Array.getLength(array)); 960 } 961 962 /** 963 * Copy an array into part of this Allocation. This variant is type checked 964 * and will generate exceptions if the Allocation type is not a 32 bit 965 * integer type. 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 copy1DRangeFrom(int off, int count, int[] d) { 972 validateIsInt32(); 973 copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length); 974 } 975 976 /** 977 * Copy an array into part of this Allocation. This variant is type checked 978 * and will generate exceptions if the Allocation type is not a 16 bit 979 * integer type. 980 * 981 * @param off The offset of the first element to be copied. 982 * @param count The number of elements to be copied. 983 * @param d the source data array 984 */ 985 public void copy1DRangeFrom(int off, int count, short[] d) { 986 validateIsInt16(); 987 copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length); 988 } 989 990 /** 991 * Copy an array into part of this Allocation. This variant is type checked 992 * and will generate exceptions if the Allocation type is not an 8 bit 993 * integer type. 994 * 995 * @param off The offset of the first element to be copied. 996 * @param count The number of elements to be copied. 997 * @param d the source data array 998 */ 999 public void copy1DRangeFrom(int off, int count, byte[] d) { 1000 validateIsInt8(); 1001 copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length); 1002 } 1003 1004 /** 1005 * Copy an array into part of this Allocation. This variant is type checked 1006 * and will generate exceptions if the Allocation type is not a 32 bit float 1007 * type. 1008 * 1009 * @param off The offset of the first element to be copied. 1010 * @param count The number of elements to be copied. 1011 * @param d the source data array. 1012 */ 1013 public void copy1DRangeFrom(int off, int count, float[] d) { 1014 validateIsFloat32(); 1015 copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length); 1016 } 1017 1018 /** 1019 * Copy part of an Allocation into this Allocation. 1020 * 1021 * @param off The offset of the first element to be copied. 1022 * @param count The number of elements to be copied. 1023 * @param data the source data allocation. 1024 * @param dataOff off The offset of the first element in data to 1025 * be copied. 1026 */ 1027 public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) { 1028 mRS.nAllocationData2D(getIDSafe(), off, 0, 1029 mSelectedLOD, mSelectedFace.mID, 1030 count, 1, data.getID(mRS), dataOff, 0, 1031 data.mSelectedLOD, data.mSelectedFace.mID); 1032 } 1033 1034 private void validate2DRange(int xoff, int yoff, int w, int h) { 1035 if (mAdaptedAllocation != null) { 1036 1037 } else { 1038 1039 if (xoff < 0 || yoff < 0) { 1040 throw new RSIllegalArgumentException("Offset cannot be negative."); 1041 } 1042 if (h < 0 || w < 0) { 1043 throw new RSIllegalArgumentException("Height or width cannot be negative."); 1044 } 1045 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 1046 throw new RSIllegalArgumentException("Updated region larger than allocation."); 1047 } 1048 } 1049 } 1050 1051 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array, 1052 Element.DataType dt, int arrayLen) { 1053 mRS.validate(); 1054 validate2DRange(xoff, yoff, w, h); 1055 final int dataSize = mType.mElement.getBytesSize() * w * h; 1056 // AutoPadding for Vec3 Element 1057 boolean usePadding = false; 1058 int sizeBytes = arrayLen * dt.mSize; 1059 if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { 1060 if (dataSize / 4 * 3 > sizeBytes) { 1061 throw new RSIllegalArgumentException("Array too small for allocation type."); 1062 } 1063 usePadding = true; 1064 sizeBytes = dataSize; 1065 } else { 1066 if (dataSize > sizeBytes) { 1067 throw new RSIllegalArgumentException("Array too small for allocation type."); 1068 } 1069 } 1070 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h, 1071 array, sizeBytes, dt, 1072 mType.mElement.mType.mSize, usePadding); 1073 } 1074 1075 /** 1076 * Copy from an array into a rectangular region in this Allocation. The 1077 * array is assumed to be tightly packed. 1078 * 1079 * @param xoff X offset of the region to update in this Allocation 1080 * @param yoff Y offset of the region to update in this Allocation 1081 * @param w Width of the region to update 1082 * @param h Height of the region to update 1083 * @param array Data to be placed into the Allocation 1084 */ 1085 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) { 1086 copy2DRangeFromUnchecked(xoff, yoff, w, h, array, 1087 validateObjectIsPrimitiveArray(array, true), 1088 java.lang.reflect.Array.getLength(array)); 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 data to be placed into the Allocation 1100 */ 1101 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { 1102 validateIsInt8(); 1103 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1104 Element.DataType.SIGNED_8, data.length); 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, short[] data) { 1118 validateIsInt16(); 1119 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1120 Element.DataType.SIGNED_16, 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, int[] data) { 1134 validateIsInt32(); 1135 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1136 Element.DataType.SIGNED_32, 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, float[] data) { 1150 validateIsFloat32(); 1151 copy2DRangeFromUnchecked(xoff, yoff, w, h, data, 1152 Element.DataType.FLOAT_32, data.length); 1153 } 1154 1155 /** 1156 * Copy a rectangular region from an Allocation into a rectangular region in 1157 * this Allocation. 1158 * 1159 * @param xoff X offset of the region in this Allocation 1160 * @param yoff Y offset of the region in this Allocation 1161 * @param w Width of the region to update. 1162 * @param h Height of the region to update. 1163 * @param data source Allocation. 1164 * @param dataXoff X offset in source Allocation 1165 * @param dataYoff Y offset in source Allocation 1166 */ 1167 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, 1168 Allocation data, int dataXoff, int dataYoff) { 1169 mRS.validate(); 1170 validate2DRange(xoff, yoff, w, h); 1171 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, 1172 mSelectedLOD, mSelectedFace.mID, 1173 w, h, data.getID(mRS), dataXoff, dataYoff, 1174 data.mSelectedLOD, data.mSelectedFace.mID); 1175 } 1176 1177 /** 1178 * Copy a {@link android.graphics.Bitmap} into an Allocation. The height 1179 * and width of the update will use the height and width of the {@link 1180 * android.graphics.Bitmap}. 1181 * 1182 * @param xoff X offset of the region to update in this Allocation 1183 * @param yoff Y offset of the region to update in this Allocation 1184 * @param data the Bitmap to be copied 1185 */ 1186 public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) { 1187 mRS.validate(); 1188 if (data.getConfig() == null) { 1189 Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888); 1190 Canvas c = new Canvas(newBitmap); 1191 c.drawBitmap(data, 0, 0, null); 1192 copy2DRangeFrom(xoff, yoff, newBitmap); 1193 return; 1194 } 1195 validateBitmapFormat(data); 1196 validate2DRange(xoff, yoff, data.getWidth(), data.getHeight()); 1197 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data); 1198 } 1199 1200 private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) { 1201 if (mAdaptedAllocation != null) { 1202 1203 } else { 1204 1205 if (xoff < 0 || yoff < 0 || zoff < 0) { 1206 throw new RSIllegalArgumentException("Offset cannot be negative."); 1207 } 1208 if (h < 0 || w < 0 || d < 0) { 1209 throw new RSIllegalArgumentException("Height or width cannot be negative."); 1210 } 1211 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) { 1212 throw new RSIllegalArgumentException("Updated region larger than allocation."); 1213 } 1214 } 1215 } 1216 1217 /** 1218 * @hide 1219 * 1220 */ 1221 private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, 1222 Object array, Element.DataType dt, int arrayLen) { 1223 mRS.validate(); 1224 validate3DRange(xoff, yoff, zoff, w, h, d); 1225 final int dataSize = mType.mElement.getBytesSize() * w * h * d; 1226 // AutoPadding for Vec3 Element 1227 boolean usePadding = false; 1228 int sizeBytes = arrayLen * dt.mSize; 1229 if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { 1230 if (dataSize / 4 * 3 > sizeBytes) { 1231 throw new RSIllegalArgumentException("Array too small for allocation type."); 1232 } 1233 usePadding = true; 1234 sizeBytes = dataSize; 1235 } else { 1236 if (dataSize > sizeBytes) { 1237 throw new RSIllegalArgumentException("Array too small for allocation type."); 1238 } 1239 } 1240 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d, 1241 array, sizeBytes, dt, 1242 mType.mElement.mType.mSize, usePadding); 1243 } 1244 1245 /** 1246 * @hide 1247 * Copy a rectangular region from the array into the allocation. 1248 * The array is assumed to be tightly packed. 1249 * 1250 * @param xoff X offset of the region to update in this Allocation 1251 * @param yoff Y offset of the region to update in this Allocation 1252 * @param zoff Z offset of the region to update in this Allocation 1253 * @param w Width of the region to update 1254 * @param h Height of the region to update 1255 * @param d Depth of the region to update 1256 * @param data to be placed into the allocation 1257 */ 1258 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) { 1259 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array, 1260 validateObjectIsPrimitiveArray(array, true), 1261 java.lang.reflect.Array.getLength(array)); 1262 } 1263 1264 /** 1265 * @hide 1266 * Copy a rectangular region into the allocation from another 1267 * allocation. 1268 * 1269 * @param xoff X offset of the region to update in this Allocation 1270 * @param yoff Y offset of the region to update in this Allocation 1271 * @param zoff Z offset of the region to update in this Allocation 1272 * @param w Width of the region to update. 1273 * @param h Height of the region to update. 1274 * @param d Depth of the region to update. 1275 * @param data source allocation. 1276 * @param dataXoff X offset of the region in the source Allocation 1277 * @param dataYoff Y offset of the region in the source Allocation 1278 * @param dataZoff Z offset of the region in the source Allocation 1279 */ 1280 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, 1281 Allocation data, int dataXoff, int dataYoff, int dataZoff) { 1282 mRS.validate(); 1283 validate3DRange(xoff, yoff, zoff, w, h, d); 1284 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1285 w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff, 1286 data.mSelectedLOD); 1287 } 1288 1289 1290 /** 1291 * Copy from the Allocation into a {@link android.graphics.Bitmap}. The 1292 * bitmap must match the dimensions of the Allocation. 1293 * 1294 * @param b The bitmap to be set from the Allocation. 1295 */ 1296 public void copyTo(Bitmap b) { 1297 mRS.validate(); 1298 validateBitmapFormat(b); 1299 validateBitmapSize(b); 1300 mRS.nAllocationCopyToBitmap(getID(mRS), b); 1301 } 1302 1303 private void copyTo(Object array, Element.DataType dt, int arrayLen) { 1304 mRS.validate(); 1305 boolean usePadding = false; 1306 if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { 1307 usePadding = true; 1308 } 1309 if (usePadding) { 1310 if (dt.mSize * arrayLen < mSize / 4 * 3) { 1311 throw new RSIllegalArgumentException( 1312 "Size of output array cannot be smaller than size of allocation."); 1313 } 1314 } else { 1315 if (dt.mSize * arrayLen < mSize) { 1316 throw new RSIllegalArgumentException( 1317 "Size of output array cannot be smaller than size of allocation."); 1318 } 1319 } 1320 mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding); 1321 } 1322 1323 /** 1324 * Copy from the Allocation into an array. The array must be at 1325 * least as large as the Allocation. The 1326 * {@link android.renderscript.Element} must match the component 1327 * type of the array passed in. 1328 * 1329 * @param array The array to be set from the Allocation. 1330 */ 1331 public void copyTo(Object array) { 1332 copyTo(array, validateObjectIsPrimitiveArray(array, true), 1333 java.lang.reflect.Array.getLength(array)); 1334 } 1335 1336 /** 1337 * Copy from the Allocation into a byte array. The array must be at least 1338 * as large as the Allocation. The allocation must be of an 8 bit integer 1339 * {@link android.support.v8.renderscript.Element} type. 1340 * 1341 * @param d The array to be set from the Allocation. 1342 */ 1343 public void copyTo(byte[] d) { 1344 validateIsInt8(); 1345 copyTo(d, Element.DataType.SIGNED_8, d.length); 1346 } 1347 1348 /** 1349 * Copy from the Allocation into a short array. The array must be at least 1350 * as large as the Allocation. The allocation must be of an 16 bit integer 1351 * {@link android.support.v8.renderscript.Element} type. 1352 * 1353 * @param d The array to be set from the Allocation. 1354 */ 1355 public void copyTo(short[] d) { 1356 validateIsInt16(); 1357 copyTo(d, Element.DataType.SIGNED_16, d.length); 1358 } 1359 1360 /** 1361 * Copy from the Allocation into a int array. The array must be at least as 1362 * large as the Allocation. The allocation must be of an 32 bit integer 1363 * {@link android.support.v8.renderscript.Element} type. 1364 * 1365 * @param d The array to be set from the Allocation. 1366 */ 1367 public void copyTo(int[] d) { 1368 validateIsInt32(); 1369 copyTo(d, Element.DataType.SIGNED_32, d.length); 1370 } 1371 1372 /** 1373 * Copy from the Allocation into a float array. The array must be at least 1374 * as large as the Allocation. The allocation must be of an 32 bit float 1375 * {@link android.support.v8.renderscript.Element} type. 1376 * 1377 * @param d The array to be set from the Allocation. 1378 */ 1379 public void copyTo(float[] d) { 1380 validateIsFloat32(); 1381 copyTo(d, Element.DataType.FLOAT_32, d.length); 1382 } 1383 1384 /** 1385 * @hide 1386 * This is only intended to be used by auto-generated code reflected from 1387 * the RenderScript script files and should not be used by developers. 1388 * 1389 * @param xoff 1390 * @param yoff 1391 * @param zoff 1392 * @param component_number 1393 * @param array 1394 */ 1395 /* 1396 public void copyToFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) { 1397 mRS.validate(); 1398 if (component_number >= mType.mElement.mElements.length) { 1399 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 1400 } 1401 if(xoff < 0) { 1402 throw new RSIllegalArgumentException("Offset x must be >= 0."); 1403 } 1404 if(yoff < 0) { 1405 throw new RSIllegalArgumentException("Offset y must be >= 0."); 1406 } 1407 if(zoff < 0) { 1408 throw new RSIllegalArgumentException("Offset z must be >= 0."); 1409 } 1410 1411 final byte[] data = fp.getData(); 1412 int data_length = fp.getPos(); 1413 int eSize = mType.mElement.mElements[component_number].getBytesSize(); 1414 eSize *= mType.mElement.mArraySizes[component_number]; 1415 1416 if (data_length != eSize) { 1417 throw new RSIllegalArgumentException("Field packer sizelength " + data_length + 1418 " does not match component size " + eSize + "."); 1419 } 1420 1421 mRS.nAllocationElementRead(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1422 component_number, data, data_length); 1423 } 1424 */ 1425 1426 private void copy1DRangeToUnchecked(int off, int count, Object array, 1427 Element.DataType dt, int arrayLen) { 1428 final int dataSize = mType.mElement.getBytesSize() * count; 1429 // AutoPadding for Vec3 Element 1430 boolean usePadding = false; 1431 if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { 1432 usePadding = true; 1433 } 1434 data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding); 1435 mRS.nAllocationRead1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt, 1436 mType.mElement.mType.mSize, usePadding); 1437 } 1438 1439 /** 1440 * @hide 1441 * Copy part of this Allocation into an array. This method does not 1442 * guarantee that the Allocation is compatible with the input buffer. 1443 * 1444 * @param off The offset of the first element to be copied. 1445 * @param count The number of elements to be copied. 1446 * @param array The dest data array 1447 */ 1448 public void copy1DRangeToUnchecked(int off, int count, Object array) { 1449 copy1DRangeToUnchecked(off, count, array, 1450 validateObjectIsPrimitiveArray(array, false), 1451 java.lang.reflect.Array.getLength(array)); 1452 } 1453 1454 /** 1455 * @hide 1456 * Copy part of this Allocation into an array. This method does not 1457 * guarantee that the Allocation is compatible with the input buffer. 1458 * 1459 * @param off The offset of the first element to be copied. 1460 * @param count The number of elements to be copied. 1461 * @param d the source data array 1462 */ 1463 public void copy1DRangeToUnchecked(int off, int count, int[] d) { 1464 copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length); 1465 } 1466 1467 /** 1468 * @hide 1469 * Copy part of this Allocation into an array. This method does not 1470 * guarantee that the Allocation is compatible with the input buffer. 1471 * 1472 * @param off The offset of the first element to be copied. 1473 * @param count The number of elements to be copied. 1474 * @param d the source data array 1475 */ 1476 public void copy1DRangeToUnchecked(int off, int count, short[] d) { 1477 copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length); 1478 } 1479 1480 /** 1481 * @hide 1482 * Copy part of this Allocation into an array. This method does not 1483 * guarantee that the Allocation is compatible with the input buffer. 1484 * 1485 * @param off The offset of the first element to be copied. 1486 * @param count The number of elements to be copied. 1487 * @param d the source data array 1488 */ 1489 public void copy1DRangeToUnchecked(int off, int count, byte[] d) { 1490 copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length); 1491 } 1492 1493 /** 1494 * @hide 1495 * Copy part of this Allocation into an array. This method does not 1496 * guarantee that the Allocation is compatible with the input buffer. 1497 * 1498 * @param off The offset of the first element to be copied. 1499 * @param count The number of elements to be copied. 1500 * @param d the source data array 1501 */ 1502 public void copy1DRangeToUnchecked(int off, int count, float[] d) { 1503 copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length); 1504 } 1505 1506 1507 /** 1508 * @hide 1509 * Copy part of this Allocation into an array. This method does not 1510 * and will generate exceptions if the Allocation type does not 1511 * match the component type of the array passed in. 1512 * 1513 * @param off The offset of the first element to be copied. 1514 * @param count The number of elements to be copied. 1515 * @param array The source data array. 1516 */ 1517 public void copy1DRangeTo(int off, int count, Object array) { 1518 copy1DRangeToUnchecked(off, count, array, 1519 validateObjectIsPrimitiveArray(array, true), 1520 java.lang.reflect.Array.getLength(array)); 1521 } 1522 1523 /** 1524 * @hide 1525 * Copy part of this Allocation into an array. This method does not 1526 * and will generate exceptions if the Allocation type is not a 32 bit 1527 * integer type. 1528 * 1529 * @param off The offset of the first element to be copied. 1530 * @param count The number of elements to be copied. 1531 * @param d the source data array 1532 */ 1533 public void copy1DRangeTo(int off, int count, int[] d) { 1534 validateIsInt32(); 1535 copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length); 1536 } 1537 1538 /** 1539 * @hide 1540 * Copy part of this Allocation into an array. This method does not 1541 * and will generate exceptions if the Allocation type is not a 16 bit 1542 * integer type. 1543 * 1544 * @param off The offset of the first element to be copied. 1545 * @param count The number of elements to be copied. 1546 * @param d the source data array 1547 */ 1548 public void copy1DRangeTo(int off, int count, short[] d) { 1549 validateIsInt16(); 1550 copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length); 1551 } 1552 1553 /** 1554 * @hide 1555 * Copy part of this Allocation into an array. This method does not 1556 * and will generate exceptions if the Allocation type is not an 8 bit 1557 * integer type. 1558 * 1559 * @param off The offset of the first element to be copied. 1560 * @param count The number of elements to be copied. 1561 * @param d the source data array 1562 */ 1563 public void copy1DRangeTo(int off, int count, byte[] d) { 1564 validateIsInt8(); 1565 copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length); 1566 } 1567 1568 /** 1569 * @hide 1570 * Copy part of this Allocation into an array. This method does not 1571 * and will generate exceptions if the Allocation type is not a 32 bit float 1572 * type. 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 d the source data array. 1577 */ 1578 public void copy1DRangeTo(int off, int count, float[] d) { 1579 validateIsFloat32(); 1580 copy1DRangeToUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length); 1581 } 1582 1583 1584 void copy2DRangeToUnchecked(int xoff, int yoff, int w, int h, Object array, 1585 Element.DataType dt, int arrayLen) { 1586 mRS.validate(); 1587 validate2DRange(xoff, yoff, w, h); 1588 final int dataSize = mType.mElement.getBytesSize() * w * h; 1589 // AutoPadding for Vec3 Element 1590 boolean usePadding = false; 1591 int sizeBytes = arrayLen * dt.mSize; 1592 if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { 1593 if (dataSize / 4 * 3 > sizeBytes) { 1594 throw new RSIllegalArgumentException("Array too small for allocation type."); 1595 } 1596 usePadding = true; 1597 sizeBytes = dataSize; 1598 } else { 1599 if (dataSize > sizeBytes) { 1600 throw new RSIllegalArgumentException("Array too small for allocation type."); 1601 } 1602 } 1603 mRS.nAllocationRead2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h, 1604 array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding); 1605 } 1606 1607 /** 1608 * @hide 1609 * Copy from a rectangular region in this Allocation into an array. 1610 * 1611 * @param xoff X offset of the region to copy in this Allocation 1612 * @param yoff Y offset of the region to copy in this Allocation 1613 * @param w Width of the region to copy 1614 * @param h Height of the region to copy 1615 * @param array Dest Array to be copied into 1616 */ 1617 public void copy2DRangeTo(int xoff, int yoff, int w, int h, Object array) { 1618 copy2DRangeToUnchecked(xoff, yoff, w, h, array, 1619 validateObjectIsPrimitiveArray(array, true), 1620 java.lang.reflect.Array.getLength(array)); 1621 } 1622 1623 /** 1624 * @hide 1625 * Copy from a rectangular region in this Allocation into an array. 1626 * 1627 * @param xoff X offset of the region to copy in this Allocation 1628 * @param yoff Y offset of the region to copy in this Allocation 1629 * @param w Width of the region to copy 1630 * @param h Height of the region to copy 1631 * @param array Dest Array to be copied into 1632 */ 1633 public void copy2DRangeTo(int xoff, int yoff, int w, int h, byte[] data) { 1634 validateIsInt8(); 1635 copy2DRangeToUnchecked(xoff, yoff, w, h, data, 1636 Element.DataType.SIGNED_8, data.length); 1637 } 1638 1639 /** 1640 * @hide 1641 * Copy from a rectangular region in this Allocation into an array. 1642 * 1643 * @param xoff X offset of the region to copy in this Allocation 1644 * @param yoff Y offset of the region to copy in this Allocation 1645 * @param w Width of the region to copy 1646 * @param h Height of the region to copy 1647 * @param array Dest Array to be copied into 1648 */ 1649 public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) { 1650 validateIsInt16(); 1651 copy2DRangeToUnchecked(xoff, yoff, w, h, data, 1652 Element.DataType.SIGNED_16, data.length); 1653 } 1654 1655 /** 1656 * @hide 1657 * Copy from a rectangular region in this Allocation into an array. 1658 * 1659 * @param xoff X offset of the region to copy in this Allocation 1660 * @param yoff Y offset of the region to copy in this Allocation 1661 * @param w Width of the region to copy 1662 * @param h Height of the region to copy 1663 * @param array Dest Array to be copied into 1664 */ 1665 public void copy2DRangeTo(int xoff, int yoff, int w, int h, int[] data) { 1666 validateIsInt32(); 1667 copy2DRangeToUnchecked(xoff, yoff, w, h, data, 1668 Element.DataType.SIGNED_32, data.length); 1669 } 1670 1671 /** 1672 * @hide 1673 * Copy from a rectangular region in this Allocation into an array. 1674 * 1675 * @param xoff X offset of the region to copy in this Allocation 1676 * @param yoff Y offset of the region to copy in this Allocation 1677 * @param w Width of the region to copy 1678 * @param h Height of the region to copy 1679 * @param array Dest Array to be copied into 1680 */ 1681 public void copy2DRangeTo(int xoff, int yoff, int w, int h, float[] data) { 1682 validateIsFloat32(); 1683 copy2DRangeToUnchecked(xoff, yoff, w, h, data, 1684 Element.DataType.FLOAT_32, data.length); 1685 } 1686 1687 1688 /** 1689 * @hide 1690 * 1691 */ 1692 /* 1693 private void copy3DRangeToUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, 1694 Object array, Element.DataType dt, int arrayLen) { 1695 mRS.validate(); 1696 validate3DRange(xoff, yoff, zoff, w, h, d); 1697 final int dataSize = mType.mElement.getBytesSize() * w * h * d; 1698 // AutoPadding for Vec3 Element 1699 boolean usePadding = false; 1700 int sizeBytes = arrayLen * dt.mSize; 1701 if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) { 1702 if (dataSize / 4 * 3 > sizeBytes) { 1703 throw new RSIllegalArgumentException("Array too small for allocation type."); 1704 } 1705 usePadding = true; 1706 sizeBytes = dataSize; 1707 } else { 1708 if (dataSize > sizeBytes) { 1709 throw new RSIllegalArgumentException("Array too small for allocation type."); 1710 } 1711 } 1712 mRS.nAllocationRead3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d, 1713 array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding); 1714 } 1715 */ 1716 1717 /** 1718 * @hide 1719 * Copy from a rectangular region in this Allocation into an array. 1720 * 1721 * @param xoff X offset of the region to copy in this Allocation 1722 * @param yoff Y offset of the region to copy in this Allocation 1723 * @param zoff Z offset of the region to copy in this Allocation 1724 * @param w Width of the region to copy 1725 * @param h Height of the region to copy 1726 * @param d Depth of the region to copy 1727 * @param array Dest Array to be copied into 1728 */ 1729 /* 1730 public void copy3DRangeTo(int xoff, int yoff, int zoff, int w, int h, int d, Object array) { 1731 copy3DRangeToUnchecked(xoff, yoff, zoff, w, h, d, array, 1732 validateObjectIsPrimitiveArray(array, true), 1733 java.lang.reflect.Array.getLength(array)); 1734 } 1735 */ 1736 1737 // creation 1738 1739 static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 1740 static { 1741 mBitmapOptions.inScaled = false; 1742 } 1743 1744 /** 1745 * Creates a new Allocation with the given {@link 1746 * android.support.v8.renderscript.Type}, mipmap flag, and usage flags. 1747 * 1748 * @param type RenderScript type describing data layout 1749 * @param mips specifies desired mipmap behaviour for the 1750 * allocation 1751 * @param usage bit field specifying how the Allocation is 1752 * utilized 1753 */ 1754 static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) { 1755 rs.validate(); 1756 if (type.getID(rs) == 0) { 1757 throw new RSInvalidStateException("Bad Type"); 1758 } 1759 1760 if(!rs.usingIO() && (usage & (USAGE_IO_INPUT | USAGE_IO_INPUT)) != 0) { 1761 throw new RSRuntimeException("USAGE_IO not supported, Allocation creation failed."); 1762 } 1763 1764 long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0); 1765 if (id == 0) { 1766 throw new RSRuntimeException("Allocation creation failed."); 1767 } 1768 return new Allocation(id, rs, type, usage); 1769 } 1770 1771 /** 1772 * Creates an Allocation with the size specified by the type and no mipmaps 1773 * generated by default 1774 * 1775 * @param rs Context to which the allocation will belong. 1776 * @param type renderscript type describing data layout 1777 * @param usage bit field specifying how the allocation is 1778 * utilized 1779 * 1780 * @return allocation 1781 */ 1782 static public Allocation createTyped(RenderScript rs, Type type, int usage) { 1783 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage); 1784 } 1785 1786 /** 1787 * Creates an Allocation for use by scripts with a given {@link 1788 * android.support.v8.renderscript.Type} and no mipmaps 1789 * 1790 * @param rs Context to which the Allocation will belong. 1791 * @param type RenderScript Type describing data layout 1792 * 1793 * @return allocation 1794 */ 1795 static public Allocation createTyped(RenderScript rs, Type type) { 1796 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT); 1797 } 1798 1799 /** 1800 * Creates an Allocation with a specified number of given elements 1801 * 1802 * @param rs Context to which the Allocation will belong. 1803 * @param e Element to use in the Allocation 1804 * @param count the number of Elements in the Allocation 1805 * @param usage bit field specifying how the Allocation is 1806 * utilized 1807 * 1808 * @return allocation 1809 */ 1810 static public Allocation createSized(RenderScript rs, Element e, 1811 int count, int usage) { 1812 rs.validate(); 1813 Type.Builder b = new Type.Builder(rs, e); 1814 b.setX(count); 1815 Type t = b.create(); 1816 1817 long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0); 1818 if (id == 0) { 1819 throw new RSRuntimeException("Allocation creation failed."); 1820 } 1821 return new Allocation(id, rs, t, usage); 1822 } 1823 1824 /** 1825 * Creates an Allocation with a specified number of given elements 1826 * 1827 * @param rs Context to which the Allocation will belong. 1828 * @param e Element to use in the Allocation 1829 * @param count the number of Elements in the Allocation 1830 * 1831 * @return allocation 1832 */ 1833 static public Allocation createSized(RenderScript rs, Element e, int count) { 1834 return createSized(rs, e, count, USAGE_SCRIPT); 1835 } 1836 1837 static Element elementFromBitmap(RenderScript rs, Bitmap b) { 1838 final Bitmap.Config bc = b.getConfig(); 1839 if (bc == Bitmap.Config.ALPHA_8) { 1840 return Element.A_8(rs); 1841 } 1842 if (bc == Bitmap.Config.ARGB_4444) { 1843 return Element.RGBA_4444(rs); 1844 } 1845 if (bc == Bitmap.Config.ARGB_8888) { 1846 return Element.RGBA_8888(rs); 1847 } 1848 if (bc == Bitmap.Config.RGB_565) { 1849 return Element.RGB_565(rs); 1850 } 1851 throw new RSInvalidStateException("Bad bitmap type: " + bc); 1852 } 1853 1854 static Type typeFromBitmap(RenderScript rs, Bitmap b, 1855 MipmapControl mip) { 1856 Element e = elementFromBitmap(rs, b); 1857 Type.Builder tb = new Type.Builder(rs, e); 1858 tb.setX(b.getWidth()); 1859 tb.setY(b.getHeight()); 1860 tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); 1861 return tb.create(); 1862 } 1863 1864 /** 1865 * Creates an Allocation from a {@link android.graphics.Bitmap}. 1866 * 1867 * @param rs Context to which the allocation will belong. 1868 * @param b Bitmap source for the allocation data 1869 * @param mips specifies desired mipmap behaviour for the 1870 * allocation 1871 * @param usage bit field specifying how the allocation is 1872 * utilized 1873 * 1874 * @return Allocation containing bitmap data 1875 * 1876 */ 1877 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 1878 MipmapControl mips, 1879 int usage) { 1880 rs.validate(); 1881 1882 // WAR undocumented color formats 1883 if (b.getConfig() == null) { 1884 if ((usage & USAGE_SHARED) != 0) { 1885 throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config."); 1886 } 1887 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 1888 Canvas c = new Canvas(newBitmap); 1889 c.drawBitmap(b, 0, 0, null); 1890 return createFromBitmap(rs, newBitmap, mips, usage); 1891 } 1892 1893 Type t = typeFromBitmap(rs, b, mips); 1894 1895 // enable optimized bitmap path only with no mipmap and script-only usage 1896 if (mips == MipmapControl.MIPMAP_NONE && 1897 t.getElement().isCompatible(Element.RGBA_8888(rs)) && 1898 usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) { 1899 long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage); 1900 if (id == 0) { 1901 throw new RSRuntimeException("Load failed."); 1902 } 1903 1904 // keep a reference to the Bitmap around to prevent GC 1905 Allocation alloc = new Allocation(id, rs, t, usage); 1906 alloc.setBitmap(b); 1907 return alloc; 1908 } 1909 1910 1911 long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1912 if (id == 0) { 1913 throw new RSRuntimeException("Load failed."); 1914 } 1915 return new Allocation(id, rs, t, usage); 1916 } 1917 1918 /** 1919 * Associate a {@link android.view.Surface} with this Allocation. This 1920 * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}. 1921 * 1922 * @param sur Surface to associate with allocation 1923 */ 1924 public void setSurface(Surface sur) { 1925 mRS.validate(); 1926 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 1927 throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT."); 1928 } 1929 1930 mRS.nAllocationSetSurface(getID(mRS), sur); 1931 } 1932 1933 /** 1934 * Creates an Allocation from a {@link android.graphics.Bitmap}. 1935 * 1936 * <p>This Allocation will be created with {@link #USAGE_SHARED}, and 1937 * {@link #USAGE_SCRIPT}.</p> 1938 * 1939 * @param rs Context to which the allocation will belong. 1940 * @param b bitmap source for the allocation data 1941 * 1942 * @return Allocation containing bitmap data 1943 * 1944 */ 1945 static public Allocation createFromBitmap(RenderScript rs, Bitmap b) { 1946 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1947 USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 1948 } 1949 1950 /** 1951 * Creates a cubemap Allocation from a {@link android.graphics.Bitmap} 1952 * containing the horizontal list of cube faces. Each face must be a square, 1953 * have the same size as all other faces, and have a width that is a power 1954 * of 2. 1955 * 1956 * @param rs Context to which the allocation will belong. 1957 * @param b Bitmap with cubemap faces layed out in the following 1958 * format: right, left, top, bottom, front, back 1959 * @param mips specifies desired mipmap behaviour for the cubemap 1960 * @param usage bit field specifying how the cubemap is utilized 1961 * 1962 * @return allocation containing cubemap data 1963 * 1964 */ 1965 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 1966 MipmapControl mips, 1967 int usage) { 1968 rs.validate(); 1969 1970 int height = b.getHeight(); 1971 int width = b.getWidth(); 1972 1973 if (width % 6 != 0) { 1974 throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); 1975 } 1976 if (width / 6 != height) { 1977 throw new RSIllegalArgumentException("Only square cube map faces supported"); 1978 } 1979 boolean isPow2 = (height & (height - 1)) == 0; 1980 if (!isPow2) { 1981 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 1982 } 1983 1984 Element e = elementFromBitmap(rs, b); 1985 Type.Builder tb = new Type.Builder(rs, e); 1986 tb.setX(height); 1987 tb.setY(height); 1988 tb.setFaces(true); 1989 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 1990 Type t = tb.create(); 1991 1992 long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1993 if(id == 0) { 1994 throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); 1995 } 1996 return new Allocation(id, rs, t, usage); 1997 } 1998 1999 /** 2000 * Creates a non-mipmapped cubemap Allocation for use as a graphics texture 2001 * from a {@link android.graphics.Bitmap} containing the horizontal list of 2002 * cube faces. Each face must be a square, have the same size as all other 2003 * faces, and have a width that is a power of 2. 2004 * 2005 * @param rs Context to which the allocation will belong. 2006 * @param b bitmap with cubemap faces layed out in the following 2007 * format: right, left, top, bottom, front, back 2008 * 2009 * @return allocation containing cubemap data 2010 * 2011 */ 2012 static public Allocation createCubemapFromBitmap(RenderScript rs, 2013 Bitmap b) { 2014 return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 2015 USAGE_GRAPHICS_TEXTURE); 2016 } 2017 2018 /** 2019 * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap} 2020 * objects containing the cube faces. Each face must be a square, have the 2021 * same size as all other faces, and have a width that is a power of 2. 2022 * 2023 * @param rs Context to which the allocation will belong. 2024 * @param xpos cubemap face in the positive x direction 2025 * @param xneg cubemap face in the negative x direction 2026 * @param ypos cubemap face in the positive y direction 2027 * @param yneg cubemap face in the negative y direction 2028 * @param zpos cubemap face in the positive z direction 2029 * @param zneg cubemap face in the negative z direction 2030 * @param mips specifies desired mipmap behaviour for the cubemap 2031 * @param usage bit field specifying how the cubemap is utilized 2032 * 2033 * @return allocation containing cubemap data 2034 * 2035 */ 2036 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 2037 Bitmap xpos, 2038 Bitmap xneg, 2039 Bitmap ypos, 2040 Bitmap yneg, 2041 Bitmap zpos, 2042 Bitmap zneg, 2043 MipmapControl mips, 2044 int usage) { 2045 /* 2046 int height = xpos.getHeight(); 2047 if (xpos.getWidth() != height || 2048 xneg.getWidth() != height || xneg.getHeight() != height || 2049 ypos.getWidth() != height || ypos.getHeight() != height || 2050 yneg.getWidth() != height || yneg.getHeight() != height || 2051 zpos.getWidth() != height || zpos.getHeight() != height || 2052 zneg.getWidth() != height || zneg.getHeight() != height) { 2053 throw new RSIllegalArgumentException("Only square cube map faces supported"); 2054 } 2055 boolean isPow2 = (height & (height - 1)) == 0; 2056 if (!isPow2) { 2057 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 2058 } 2059 2060 Element e = elementFromBitmap(rs, xpos); 2061 Type.Builder tb = new Type.Builder(rs, e); 2062 tb.setX(height); 2063 tb.setY(height); 2064 tb.setFaces(true); 2065 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 2066 Type t = tb.create(); 2067 Allocation cubemap = Allocation.createTyped(rs, t, mips, usage); 2068 2069 AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap); 2070 adapter.setFace(Type.CubemapFace.POSITIVE_X); 2071 adapter.copyFrom(xpos); 2072 adapter.setFace(Type.CubemapFace.NEGATIVE_X); 2073 adapter.copyFrom(xneg); 2074 adapter.setFace(Type.CubemapFace.POSITIVE_Y); 2075 adapter.copyFrom(ypos); 2076 adapter.setFace(Type.CubemapFace.NEGATIVE_Y); 2077 adapter.copyFrom(yneg); 2078 adapter.setFace(Type.CubemapFace.POSITIVE_Z); 2079 adapter.copyFrom(zpos); 2080 adapter.setFace(Type.CubemapFace.NEGATIVE_Z); 2081 adapter.copyFrom(zneg); 2082 2083 return cubemap; 2084 */ 2085 return null; 2086 } 2087 2088 /** 2089 * Creates a non-mipmapped cubemap Allocation for use as a sampler input 2090 * from 6 {@link android.graphics.Bitmap} objects containing the cube 2091 * faces. Each face must be a square, have the same size as all other faces, 2092 * and have a width that is a power of 2. 2093 * 2094 * @param rs Context to which the allocation will belong. 2095 * @param xpos cubemap face in the positive x direction 2096 * @param xneg cubemap face in the negative x direction 2097 * @param ypos cubemap face in the positive y direction 2098 * @param yneg cubemap face in the negative y direction 2099 * @param zpos cubemap face in the positive z direction 2100 * @param zneg cubemap face in the negative z direction 2101 * 2102 * @return allocation containing cubemap data 2103 * 2104 */ 2105 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 2106 Bitmap xpos, 2107 Bitmap xneg, 2108 Bitmap ypos, 2109 Bitmap yneg, 2110 Bitmap zpos, 2111 Bitmap zneg) { 2112 return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg, 2113 zpos, zneg, MipmapControl.MIPMAP_NONE, 2114 USAGE_GRAPHICS_TEXTURE); 2115 } 2116 2117 /** 2118 * Creates an Allocation from the Bitmap referenced 2119 * by resource ID. 2120 * 2121 * @param rs Context to which the allocation will belong. 2122 * @param res application resources 2123 * @param id resource id to load the data from 2124 * @param mips specifies desired mipmap behaviour for the 2125 * allocation 2126 * @param usage bit field specifying how the allocation is 2127 * utilized 2128 * 2129 * @return Allocation containing resource data 2130 * 2131 */ 2132 static public Allocation createFromBitmapResource(RenderScript rs, 2133 Resources res, 2134 int id, 2135 MipmapControl mips, 2136 int usage) { 2137 2138 rs.validate(); 2139 if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) { 2140 throw new RSIllegalArgumentException("Unsupported usage specified."); 2141 } 2142 Bitmap b = BitmapFactory.decodeResource(res, id); 2143 Allocation alloc = createFromBitmap(rs, b, mips, usage); 2144 b.recycle(); 2145 return alloc; 2146 } 2147 2148 /** 2149 * Creates a non-mipmapped Allocation to use as a graphics texture from the 2150 * {@link android.graphics.Bitmap} referenced by resource ID. 2151 * 2152 * <p>This allocation will be created with {@link #USAGE_SCRIPT} and 2153 * {@link #USAGE_GRAPHICS_TEXTURE}.</p> 2154 * 2155 * @param rs Context to which the allocation will belong. 2156 * @param res application resources 2157 * @param id resource id to load the data from 2158 * 2159 * @return Allocation containing resource data 2160 * 2161 */ 2162 static public Allocation createFromBitmapResource(RenderScript rs, 2163 Resources res, 2164 int id) { 2165 return createFromBitmapResource(rs, res, id, 2166 MipmapControl.MIPMAP_NONE, 2167 USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 2168 } 2169 2170 /** 2171 * Creates an Allocation containing string data encoded in UTF-8 format. 2172 * 2173 * @param rs Context to which the allocation will belong. 2174 * @param str string to create the allocation from 2175 * @param usage bit field specifying how the allocaiton is 2176 * utilized 2177 * 2178 */ 2179 static public Allocation createFromString(RenderScript rs, 2180 String str, 2181 int usage) { 2182 rs.validate(); 2183 byte[] allocArray = null; 2184 try { 2185 allocArray = str.getBytes("UTF-8"); 2186 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 2187 alloc.copyFrom(allocArray); 2188 return alloc; 2189 } 2190 catch (Exception e) { 2191 throw new RSRuntimeException("Could not convert string to utf-8."); 2192 } 2193 } 2194 2195 /** 2196 * Frees any native resources associated with this object. The 2197 * primary use is to force immediate cleanup of resources when it is 2198 * believed the GC will not respond quickly enough. 2199 * For USAGE_IO_OUTPUT, destroy() implies setSurface(null). 2200 */ 2201 @Override 2202 public void destroy() { 2203 if (mIncCompatAllocation != 0) { 2204 boolean shouldDestroy = false; 2205 synchronized(this) { 2206 if (!mIncAllocDestroyed) { 2207 shouldDestroy = true; 2208 mIncAllocDestroyed = true; 2209 } 2210 } 2211 2212 if (shouldDestroy) { 2213 // must include nObjDestroy in the critical section 2214 ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock(); 2215 rlock.lock(); 2216 if(mRS.isAlive()) { 2217 mRS.nIncObjDestroy(mIncCompatAllocation); 2218 } 2219 rlock.unlock(); 2220 mIncCompatAllocation = 0; 2221 } 2222 } 2223 if ((mUsage & (USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) { 2224 setSurface(null); 2225 } 2226 super.destroy(); 2227 } 2228 2229} 2230 2231