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