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