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