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