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