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