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