Allocation.java revision d6b8a035337e096f8d313b70f2178f4ec54ba2e4
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 if (t != null) { 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 // don't need to account for USAGE_SHARED Allocations 359 if ((mUsage & USAGE_SHARED) == 0) { 360 int numBytes = mType.getCount() * mType.getElement().getBytesSize(); 361 mRS.addAllocSizeForGC(numBytes); 362 mGCSize = numBytes; 363 } 364 } 365 366 /** 367 * Get the type of the Allocation. 368 * 369 * @return Type 370 * 371 */ 372 public Type getType() { 373 return mType; 374 } 375 376 /** 377 * Propagate changes from one usage of the allocation to the 378 * remaining usages of the allocation. 379 * 380 */ 381 public void syncAll(int srcLocation) { 382 switch (srcLocation) { 383 case USAGE_GRAPHICS_TEXTURE: 384 case USAGE_SCRIPT: 385 if ((mUsage & USAGE_SHARED) != 0) { 386 copyFrom(mBitmap); 387 } 388 break; 389 case USAGE_GRAPHICS_CONSTANTS: 390 case USAGE_GRAPHICS_VERTEX: 391 break; 392 case USAGE_SHARED: 393 if ((mUsage & USAGE_SHARED) != 0) { 394 copyTo(mBitmap); 395 } 396 break; 397 default: 398 throw new RSIllegalArgumentException("Source must be exactly one usage type."); 399 } 400 mRS.validate(); 401 mRS.nAllocationSyncAll(getIDSafe(), srcLocation); 402 } 403 404 /** 405 * Send a buffer to the output stream. The contents of the 406 * Allocation will be undefined after this operation. 407 * 408 */ 409 public void ioSend() { 410 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 411 throw new RSIllegalArgumentException( 412 "Can only send buffer if IO_OUTPUT usage specified."); 413 } 414 mRS.validate(); 415 mRS.nAllocationIoSend(getID(mRS)); 416 } 417 418 /** 419 * Delete once code is updated. 420 * @hide 421 */ 422 public void ioSendOutput() { 423 ioSend(); 424 } 425 426 /** 427 * Receive the latest input into the Allocation. 428 * 429 */ 430 public void ioReceive() { 431 if ((mUsage & USAGE_IO_INPUT) == 0) { 432 throw new RSIllegalArgumentException( 433 "Can only receive if IO_INPUT usage specified."); 434 } 435 mRS.validate(); 436 mRS.nAllocationIoReceive(getID(mRS)); 437 } 438 439 /** 440 * Copy an array of RS objects to the allocation. 441 * 442 * @param d Source array. 443 */ 444 public void copyFrom(BaseObj[] d) { 445 mRS.validate(); 446 validateIsObject(); 447 if (d.length != mCurrentCount) { 448 throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + 449 mCurrentCount + ", array length = " + d.length); 450 } 451 int i[] = new int[d.length]; 452 for (int ct=0; ct < d.length; ct++) { 453 i[ct] = d[ct].getID(mRS); 454 } 455 copy1DRangeFromUnchecked(0, mCurrentCount, i); 456 } 457 458 private void validateBitmapFormat(Bitmap b) { 459 Bitmap.Config bc = b.getConfig(); 460 if (bc == null) { 461 throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation"); 462 } 463 switch (bc) { 464 case ALPHA_8: 465 if (mType.getElement().mKind != Element.DataKind.PIXEL_A) { 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 ARGB_8888: 474 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 475 (mType.getElement().getBytesSize() != 4)) { 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 RGB_565: 484 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) || 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 case ARGB_4444: 494 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 495 (mType.getElement().getBytesSize() != 2)) { 496 throw new RSIllegalArgumentException("Allocation kind is " + 497 mType.getElement().mKind + ", type " + 498 mType.getElement().mType + 499 " of " + mType.getElement().getBytesSize() + 500 " bytes, passed bitmap was " + bc); 501 } 502 break; 503 504 } 505 } 506 507 private void validateBitmapSize(Bitmap b) { 508 if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) { 509 throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); 510 } 511 } 512 513 /** 514 * Copy an allocation from an array. This variant is not type 515 * checked which allows an application to fill in structured 516 * data from an array. 517 * 518 * @param d the source data array 519 */ 520 public void copyFromUnchecked(int[] d) { 521 mRS.validate(); 522 if (mCurrentDimZ > 0) { 523 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 524 } else if (mCurrentDimY > 0) { 525 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 526 } else { 527 copy1DRangeFromUnchecked(0, mCurrentCount, d); 528 } 529 } 530 /** 531 * Copy an allocation from an array. This variant is not type 532 * checked which allows an application to fill in structured 533 * data from an array. 534 * 535 * @param d the source data array 536 */ 537 public void copyFromUnchecked(short[] d) { 538 mRS.validate(); 539 if (mCurrentDimZ > 0) { 540 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 541 } else if (mCurrentDimY > 0) { 542 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 543 } else { 544 copy1DRangeFromUnchecked(0, mCurrentCount, d); 545 } 546 } 547 /** 548 * Copy an allocation from an array. This variant is not type 549 * checked which allows an application to fill in structured 550 * data from an array. 551 * 552 * @param d the source data array 553 */ 554 public void copyFromUnchecked(byte[] d) { 555 mRS.validate(); 556 if (mCurrentDimZ > 0) { 557 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 558 } else if (mCurrentDimY > 0) { 559 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 560 } else { 561 copy1DRangeFromUnchecked(0, mCurrentCount, d); 562 } 563 } 564 /** 565 * Copy an allocation from an array. This variant is not type 566 * checked which allows an application to fill in structured 567 * data from an array. 568 * 569 * @param d the source data array 570 */ 571 public void copyFromUnchecked(float[] d) { 572 mRS.validate(); 573 if (mCurrentDimZ > 0) { 574 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 575 } else if (mCurrentDimY > 0) { 576 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 577 } else { 578 copy1DRangeFromUnchecked(0, mCurrentCount, d); 579 } 580 } 581 582 /** 583 * Copy an allocation from an array. This variant is type 584 * checked and will generate exceptions if the Allocation type 585 * is not a 32 bit integer type. 586 * 587 * @param d the source data array 588 */ 589 public void copyFrom(int[] d) { 590 mRS.validate(); 591 if (mCurrentDimZ > 0) { 592 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 593 } else if (mCurrentDimY > 0) { 594 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 595 } else { 596 copy1DRangeFrom(0, mCurrentCount, d); 597 } 598 } 599 600 /** 601 * Copy an allocation from an array. This variant is type 602 * checked and will generate exceptions if the Allocation type 603 * is not a 16 bit integer type. 604 * 605 * @param d the source data array 606 */ 607 public void copyFrom(short[] d) { 608 mRS.validate(); 609 if (mCurrentDimZ > 0) { 610 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 611 } else if (mCurrentDimY > 0) { 612 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 613 } else { 614 copy1DRangeFrom(0, mCurrentCount, d); 615 } 616 } 617 618 /** 619 * Copy an allocation from an array. This variant is type 620 * checked and will generate exceptions if the Allocation type 621 * is not a 8 bit integer type. 622 * 623 * @param d the source data array 624 */ 625 public void copyFrom(byte[] d) { 626 mRS.validate(); 627 if (mCurrentDimZ > 0) { 628 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 629 } else if (mCurrentDimY > 0) { 630 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 631 } else { 632 copy1DRangeFrom(0, mCurrentCount, d); 633 } 634 } 635 636 /** 637 * Copy an allocation from an array. This variant is type 638 * checked and will generate exceptions if the Allocation type 639 * is not a 32 bit float type. 640 * 641 * @param d the source data array 642 */ 643 public void copyFrom(float[] d) { 644 mRS.validate(); 645 if (mCurrentDimZ > 0) { 646 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 647 } else if (mCurrentDimY > 0) { 648 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 649 } else { 650 copy1DRangeFrom(0, mCurrentCount, d); 651 } 652 } 653 654 /** 655 * Copy an allocation from a bitmap. The height, width, and 656 * format of the bitmap must match the existing allocation. 657 * 658 * @param b the source bitmap 659 */ 660 public void copyFrom(Bitmap b) { 661 mRS.validate(); 662 if (b.getConfig() == null) { 663 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 664 Canvas c = new Canvas(newBitmap); 665 c.drawBitmap(b, 0, 0, null); 666 copyFrom(newBitmap); 667 return; 668 } 669 validateBitmapSize(b); 670 validateBitmapFormat(b); 671 mRS.nAllocationCopyFromBitmap(getID(mRS), b); 672 } 673 674 /** 675 * Copy an allocation from an allocation. The types of both allocations 676 * must be identical. 677 * 678 * @param a the source allocation 679 */ 680 public void copyFrom(Allocation a) { 681 mRS.validate(); 682 if (!mType.equals(a.getType())) { 683 throw new RSIllegalArgumentException("Types of allocations must match."); 684 } 685 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0); 686 } 687 688 689 /** 690 * This is only intended to be used by auto-generate code reflected from the 691 * renderscript script files. 692 * 693 * @param xoff 694 * @param fp 695 */ 696 public void setFromFieldPacker(int xoff, FieldPacker fp) { 697 mRS.validate(); 698 int eSize = mType.mElement.getBytesSize(); 699 final byte[] data = fp.getData(); 700 701 int count = data.length / eSize; 702 if ((eSize * count) != data.length) { 703 throw new RSIllegalArgumentException("Field packer length " + data.length + 704 " not divisible by element size " + eSize + "."); 705 } 706 copy1DRangeFromUnchecked(xoff, count, data); 707 } 708 709 /** 710 * This is only intended to be used by auto-generate code reflected from the 711 * renderscript script files. 712 * 713 * @param xoff 714 * @param component_number 715 * @param fp 716 */ 717 public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) { 718 mRS.validate(); 719 if (component_number >= mType.mElement.mElements.length) { 720 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 721 } 722 if(xoff < 0) { 723 throw new RSIllegalArgumentException("Offset must be >= 0."); 724 } 725 726 final byte[] data = fp.getData(); 727 int eSize = mType.mElement.mElements[component_number].getBytesSize(); 728 eSize *= mType.mElement.mArraySizes[component_number]; 729 730 if (data.length != eSize) { 731 throw new RSIllegalArgumentException("Field packer sizelength " + data.length + 732 " does not match component size " + eSize + "."); 733 } 734 735 mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD, 736 component_number, data, data.length); 737 } 738 739 private void data1DChecks(int off, int count, int len, int dataSize) { 740 mRS.validate(); 741 if(off < 0) { 742 throw new RSIllegalArgumentException("Offset must be >= 0."); 743 } 744 if(count < 1) { 745 throw new RSIllegalArgumentException("Count must be >= 1."); 746 } 747 if((off + count) > mCurrentCount) { 748 throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount + 749 ", got " + count + " at offset " + off + "."); 750 } 751 if(len < dataSize) { 752 throw new RSIllegalArgumentException("Array too small for allocation type."); 753 } 754 } 755 756 /** 757 * Generate a mipmap chain. Requires the type of the allocation 758 * include mipmaps. 759 * 760 * This function will generate a complete set of mipmaps from 761 * the top level lod and place them into the script memoryspace. 762 * 763 * If the allocation is also using other memory spaces a 764 * followup sync will be required. 765 */ 766 public void generateMipmaps() { 767 mRS.nAllocationGenerateMipmaps(getID(mRS)); 768 } 769 770 /** 771 * Copy part of an allocation from an array. This variant is 772 * not type checked which allows an application to fill in 773 * structured data from an array. 774 * 775 * @param off The offset of the first element to be copied. 776 * @param count The number of elements to be copied. 777 * @param d the source data array 778 */ 779 public void copy1DRangeFromUnchecked(int off, int count, int[] d) { 780 int dataSize = mType.mElement.getBytesSize() * count; 781 data1DChecks(off, count, d.length * 4, dataSize); 782 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); 783 } 784 /** 785 * Copy part of an allocation from an array. This variant is 786 * not type checked which allows an application to fill in 787 * structured data from an array. 788 * 789 * @param off The offset of the first element to be copied. 790 * @param count The number of elements to be copied. 791 * @param d the source data array 792 */ 793 public void copy1DRangeFromUnchecked(int off, int count, short[] d) { 794 int dataSize = mType.mElement.getBytesSize() * count; 795 data1DChecks(off, count, d.length * 2, dataSize); 796 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); 797 } 798 /** 799 * Copy part of an allocation from an array. This variant is 800 * not type checked which allows an application to fill in 801 * structured data from an array. 802 * 803 * @param off The offset of the first element to be copied. 804 * @param count The number of elements to be copied. 805 * @param d the source data array 806 */ 807 public void copy1DRangeFromUnchecked(int off, int count, byte[] d) { 808 int dataSize = mType.mElement.getBytesSize() * count; 809 data1DChecks(off, count, d.length, dataSize); 810 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); 811 } 812 /** 813 * Copy part of an allocation from an array. This variant is 814 * not type checked which allows an application to fill in 815 * structured data from an array. 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 copy1DRangeFromUnchecked(int off, int count, float[] d) { 822 int dataSize = mType.mElement.getBytesSize() * count; 823 data1DChecks(off, count, d.length * 4, dataSize); 824 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); 825 } 826 827 /** 828 * Copy part of an allocation from an array. This variant is 829 * type checked and will generate exceptions if the Allocation 830 * type is not a 32 bit integer type. 831 * 832 * @param off The offset of the first element to be copied. 833 * @param count The number of elements to be copied. 834 * @param d the source data array 835 */ 836 public void copy1DRangeFrom(int off, int count, int[] d) { 837 validateIsInt32(); 838 copy1DRangeFromUnchecked(off, count, d); 839 } 840 841 /** 842 * Copy part of an allocation from an array. This variant is 843 * type checked and will generate exceptions if the Allocation 844 * type is not a 16 bit integer type. 845 * 846 * @param off The offset of the first element to be copied. 847 * @param count The number of elements to be copied. 848 * @param d the source data array 849 */ 850 public void copy1DRangeFrom(int off, int count, short[] d) { 851 validateIsInt16(); 852 copy1DRangeFromUnchecked(off, count, d); 853 } 854 855 /** 856 * Copy part of an allocation from an array. This variant is 857 * type checked and will generate exceptions if the Allocation 858 * type is not a 8 bit integer type. 859 * 860 * @param off The offset of the first element to be copied. 861 * @param count The number of elements to be copied. 862 * @param d the source data array 863 */ 864 public void copy1DRangeFrom(int off, int count, byte[] d) { 865 validateIsInt8(); 866 copy1DRangeFromUnchecked(off, count, d); 867 } 868 869 /** 870 * Copy part of an allocation from an array. This variant is 871 * type checked and will generate exceptions if the Allocation 872 * type is not a 32 bit float type. 873 * 874 * @param off The offset of the first element to be copied. 875 * @param count The number of elements to be copied. 876 * @param d the source data array. 877 */ 878 public void copy1DRangeFrom(int off, int count, float[] d) { 879 validateIsFloat32(); 880 copy1DRangeFromUnchecked(off, count, d); 881 } 882 883 /** 884 * Copy part of an allocation from another allocation. 885 * 886 * @param off The offset of the first element to be copied. 887 * @param count The number of elements to be copied. 888 * @param data the source data allocation. 889 * @param dataOff off The offset of the first element in data to 890 * be copied. 891 */ 892 public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) { 893 mRS.nAllocationData2D(getIDSafe(), off, 0, 894 mSelectedLOD, mSelectedFace.mID, 895 count, 1, data.getID(mRS), dataOff, 0, 896 data.mSelectedLOD, data.mSelectedFace.mID); 897 } 898 899 private void validate2DRange(int xoff, int yoff, int w, int h) { 900 if (mAdaptedAllocation != null) { 901 902 } else { 903 904 if (xoff < 0 || yoff < 0) { 905 throw new RSIllegalArgumentException("Offset cannot be negative."); 906 } 907 if (h < 0 || w < 0) { 908 throw new RSIllegalArgumentException("Height or width cannot be negative."); 909 } 910 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 911 throw new RSIllegalArgumentException("Updated region larger than allocation."); 912 } 913 } 914 } 915 916 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, byte[] data) { 917 mRS.validate(); 918 validate2DRange(xoff, yoff, w, h); 919 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 920 w, h, data, data.length); 921 } 922 923 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, short[] data) { 924 mRS.validate(); 925 validate2DRange(xoff, yoff, w, h); 926 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 927 w, h, data, data.length * 2); 928 } 929 930 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, int[] data) { 931 mRS.validate(); 932 validate2DRange(xoff, yoff, w, h); 933 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 934 w, h, data, data.length * 4); 935 } 936 937 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, float[] data) { 938 mRS.validate(); 939 validate2DRange(xoff, yoff, w, h); 940 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 941 w, h, data, data.length * 4); 942 } 943 944 945 /** 946 * Copy a rectangular region from the array into the allocation. 947 * The incoming array is assumed to be tightly packed. 948 * 949 * @param xoff X offset of the region to update 950 * @param yoff Y offset of the region to update 951 * @param w Width of the incoming region to update 952 * @param h Height of the incoming region to update 953 * @param data to be placed into the allocation 954 */ 955 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { 956 validateIsInt8(); 957 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 958 } 959 960 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) { 961 validateIsInt16(); 962 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 963 } 964 965 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) { 966 validateIsInt32(); 967 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 968 } 969 970 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) { 971 validateIsFloat32(); 972 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 973 } 974 975 /** 976 * Copy a rectangular region into the allocation from another 977 * allocation. 978 * 979 * @param xoff X offset of the region to update. 980 * @param yoff Y offset of the region to update. 981 * @param w Width of the incoming region to update. 982 * @param h Height of the incoming region to update. 983 * @param data source allocation. 984 * @param dataXoff X offset in data of the region to update. 985 * @param dataYoff Y offset in data of the region to update. 986 */ 987 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, 988 Allocation data, int dataXoff, int dataYoff) { 989 mRS.validate(); 990 validate2DRange(xoff, yoff, w, h); 991 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, 992 mSelectedLOD, mSelectedFace.mID, 993 w, h, data.getID(mRS), dataXoff, dataYoff, 994 data.mSelectedLOD, data.mSelectedFace.mID); 995 } 996 997 /** 998 * Copy a bitmap into an allocation. The height and width of 999 * the update will use the height and width of the incoming 1000 * bitmap. 1001 * 1002 * @param xoff X offset of the region to update 1003 * @param yoff Y offset of the region to update 1004 * @param data the bitmap to be copied 1005 */ 1006 public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) { 1007 mRS.validate(); 1008 if (data.getConfig() == null) { 1009 Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888); 1010 Canvas c = new Canvas(newBitmap); 1011 c.drawBitmap(data, 0, 0, null); 1012 copy2DRangeFrom(xoff, yoff, newBitmap); 1013 return; 1014 } 1015 validateBitmapFormat(data); 1016 validate2DRange(xoff, yoff, data.getWidth(), data.getHeight()); 1017 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data); 1018 } 1019 1020 private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) { 1021 if (mAdaptedAllocation != null) { 1022 1023 } else { 1024 1025 if (xoff < 0 || yoff < 0 || zoff < 0) { 1026 throw new RSIllegalArgumentException("Offset cannot be negative."); 1027 } 1028 if (h < 0 || w < 0 || d < 0) { 1029 throw new RSIllegalArgumentException("Height or width cannot be negative."); 1030 } 1031 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) { 1032 throw new RSIllegalArgumentException("Updated region larger than allocation."); 1033 } 1034 } 1035 } 1036 1037 /** 1038 * @hide 1039 * 1040 */ 1041 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) { 1042 mRS.validate(); 1043 validate3DRange(xoff, yoff, zoff, w, h, d); 1044 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1045 w, h, d, data, data.length); 1046 } 1047 1048 /** 1049 * @hide 1050 * 1051 */ 1052 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) { 1053 mRS.validate(); 1054 validate3DRange(xoff, yoff, zoff, w, h, d); 1055 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1056 w, h, d, data, data.length * 2); 1057 } 1058 1059 /** 1060 * @hide 1061 * 1062 */ 1063 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) { 1064 mRS.validate(); 1065 validate3DRange(xoff, yoff, zoff, w, h, d); 1066 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1067 w, h, d, data, data.length * 4); 1068 } 1069 1070 /** 1071 * @hide 1072 * 1073 */ 1074 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) { 1075 mRS.validate(); 1076 validate3DRange(xoff, yoff, zoff, w, h, d); 1077 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1078 w, h, d, data, data.length * 4); 1079 } 1080 1081 1082 /** 1083 * @hide 1084 * Copy a rectangular region from the array into the allocation. 1085 * The incoming array is assumed to be tightly packed. 1086 * 1087 * @param xoff X offset of the region to update 1088 * @param yoff Y offset of the region to update 1089 * @param zoff Z offset of the region to update 1090 * @param w Width of the incoming region to update 1091 * @param h Height of the incoming region to update 1092 * @param d Depth of the incoming region to update 1093 * @param data to be placed into the allocation 1094 */ 1095 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) { 1096 validateIsInt8(); 1097 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1098 } 1099 1100 /** 1101 * @hide 1102 * 1103 */ 1104 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) { 1105 validateIsInt16(); 1106 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1107 } 1108 1109 /** 1110 * @hide 1111 * 1112 */ 1113 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) { 1114 validateIsInt32(); 1115 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1116 } 1117 1118 /** 1119 * @hide 1120 * 1121 */ 1122 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) { 1123 validateIsFloat32(); 1124 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1125 } 1126 1127 /** 1128 * @hide 1129 * Copy a rectangular region into the allocation from another 1130 * allocation. 1131 * 1132 * @param xoff X offset of the region to update. 1133 * @param yoff Y offset of the region to update. 1134 * @param w Width of the incoming region to update. 1135 * @param h Height of the incoming region to update. 1136 * @param d Depth of the incoming region to update. 1137 * @param data source allocation. 1138 * @param dataXoff X offset in data of the region to update. 1139 * @param dataYoff Y offset in data of the region to update. 1140 * @param dataZoff Z offset in data of the region to update 1141 */ 1142 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, 1143 Allocation data, int dataXoff, int dataYoff, int dataZoff) { 1144 mRS.validate(); 1145 validate3DRange(xoff, yoff, zoff, w, h, d); 1146 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1147 w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff, 1148 data.mSelectedLOD); 1149 } 1150 1151 1152 /** 1153 * Copy from the Allocation into a Bitmap. The bitmap must 1154 * match the dimensions of the Allocation. 1155 * 1156 * @param b The bitmap to be set from the Allocation. 1157 */ 1158 public void copyTo(Bitmap b) { 1159 mRS.validate(); 1160 validateBitmapFormat(b); 1161 validateBitmapSize(b); 1162 mRS.nAllocationCopyToBitmap(getID(mRS), b); 1163 } 1164 1165 /** 1166 * Copy from the Allocation into a byte array. The array must 1167 * be at least as large as the Allocation. The allocation must 1168 * be of an 8 bit elemental type. 1169 * 1170 * @param d The array to be set from the Allocation. 1171 */ 1172 public void copyTo(byte[] d) { 1173 validateIsInt8(); 1174 mRS.validate(); 1175 mRS.nAllocationRead(getID(mRS), d); 1176 } 1177 1178 /** 1179 * Copy from the Allocation into a short array. The array must 1180 * be at least as large as the Allocation. The allocation must 1181 * be of an 16 bit elemental type. 1182 * 1183 * @param d The array to be set from the Allocation. 1184 */ 1185 public void copyTo(short[] d) { 1186 validateIsInt16(); 1187 mRS.validate(); 1188 mRS.nAllocationRead(getID(mRS), d); 1189 } 1190 1191 /** 1192 * Copy from the Allocation into a int array. The array must be 1193 * at least as large as the Allocation. The allocation must be 1194 * of an 32 bit elemental type. 1195 * 1196 * @param d The array to be set from the Allocation. 1197 */ 1198 public void copyTo(int[] d) { 1199 validateIsInt32(); 1200 mRS.validate(); 1201 mRS.nAllocationRead(getID(mRS), d); 1202 } 1203 1204 /** 1205 * Copy from the Allocation into a float array. The array must 1206 * be at least as large as the Allocation. The allocation must 1207 * be of an 32 bit float elemental type. 1208 * 1209 * @param d The array to be set from the Allocation. 1210 */ 1211 public void copyTo(float[] d) { 1212 validateIsFloat32(); 1213 mRS.validate(); 1214 mRS.nAllocationRead(getID(mRS), d); 1215 } 1216 1217 /** 1218 * Resize a 1D allocation. The contents of the allocation are 1219 * preserved. If new elements are allocated objects are created 1220 * with null contents and the new region is otherwise undefined. 1221 * 1222 * If the new region is smaller the references of any objects 1223 * outside the new region will be released. 1224 * 1225 * A new type will be created with the new dimension. 1226 * 1227 * @param dimX The new size of the allocation. 1228 * 1229 * @deprecated Renderscript objects should be immutable once 1230 * created. The replacement is to create a new allocation and copy the 1231 * contents. 1232 */ 1233 public synchronized void resize(int dimX) { 1234 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 1235 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 1236 } 1237 mRS.nAllocationResize1D(getID(mRS), dimX); 1238 mRS.finish(); // Necessary because resize is fifoed and update is async. 1239 1240 int typeID = mRS.nAllocationGetType(getID(mRS)); 1241 mType = new Type(typeID, mRS); 1242 mType.updateFromNative(); 1243 updateCacheInfo(mType); 1244 } 1245 1246 1247 // creation 1248 1249 static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 1250 static { 1251 mBitmapOptions.inScaled = false; 1252 } 1253 1254 /** 1255 * 1256 * @param type renderscript type describing data layout 1257 * @param mips specifies desired mipmap behaviour for the 1258 * allocation 1259 * @param usage bit field specifying how the allocation is 1260 * utilized 1261 */ 1262 static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) { 1263 rs.validate(); 1264 if (type.getID(rs) == 0) { 1265 throw new RSInvalidStateException("Bad Type"); 1266 } 1267 1268 int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0); 1269 if (id == 0) { 1270 throw new RSRuntimeException("Allocation creation failed."); 1271 } 1272 return new Allocation(id, rs, type, usage); 1273 } 1274 1275 /** 1276 * Creates a renderscript allocation with the size specified by 1277 * the type and no mipmaps generated by default 1278 * 1279 * @param rs Context to which the allocation will belong. 1280 * @param type renderscript type describing data layout 1281 * @param usage bit field specifying how the allocation is 1282 * utilized 1283 * 1284 * @return allocation 1285 */ 1286 static public Allocation createTyped(RenderScript rs, Type type, int usage) { 1287 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage); 1288 } 1289 1290 /** 1291 * Creates a renderscript allocation for use by the script with 1292 * the size specified by the type and no mipmaps generated by 1293 * default 1294 * 1295 * @param rs Context to which the allocation will belong. 1296 * @param type renderscript type describing data layout 1297 * 1298 * @return allocation 1299 */ 1300 static public Allocation createTyped(RenderScript rs, Type type) { 1301 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT); 1302 } 1303 1304 /** 1305 * Creates a renderscript allocation with a specified number of 1306 * given elements 1307 * 1308 * @param rs Context to which the allocation will belong. 1309 * @param e describes what each element of an allocation is 1310 * @param count specifies the number of element in the allocation 1311 * @param usage bit field specifying how the allocation is 1312 * utilized 1313 * 1314 * @return allocation 1315 */ 1316 static public Allocation createSized(RenderScript rs, Element e, 1317 int count, int usage) { 1318 rs.validate(); 1319 Type.Builder b = new Type.Builder(rs, e); 1320 b.setX(count); 1321 Type t = b.create(); 1322 1323 int id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0); 1324 if (id == 0) { 1325 throw new RSRuntimeException("Allocation creation failed."); 1326 } 1327 return new Allocation(id, rs, t, usage); 1328 } 1329 1330 /** 1331 * Creates a renderscript allocation with a specified number of 1332 * given elements 1333 * 1334 * @param rs Context to which the allocation will belong. 1335 * @param e describes what each element of an allocation is 1336 * @param count specifies the number of element in the allocation 1337 * 1338 * @return allocation 1339 */ 1340 static public Allocation createSized(RenderScript rs, Element e, int count) { 1341 return createSized(rs, e, count, USAGE_SCRIPT); 1342 } 1343 1344 static Element elementFromBitmap(RenderScript rs, Bitmap b) { 1345 final Bitmap.Config bc = b.getConfig(); 1346 if (bc == Bitmap.Config.ALPHA_8) { 1347 return Element.A_8(rs); 1348 } 1349 if (bc == Bitmap.Config.ARGB_4444) { 1350 return Element.RGBA_4444(rs); 1351 } 1352 if (bc == Bitmap.Config.ARGB_8888) { 1353 return Element.RGBA_8888(rs); 1354 } 1355 if (bc == Bitmap.Config.RGB_565) { 1356 return Element.RGB_565(rs); 1357 } 1358 throw new RSInvalidStateException("Bad bitmap type: " + bc); 1359 } 1360 1361 static Type typeFromBitmap(RenderScript rs, Bitmap b, 1362 MipmapControl mip) { 1363 Element e = elementFromBitmap(rs, b); 1364 Type.Builder tb = new Type.Builder(rs, e); 1365 tb.setX(b.getWidth()); 1366 tb.setY(b.getHeight()); 1367 tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); 1368 return tb.create(); 1369 } 1370 1371 /** 1372 * Creates a renderscript allocation from a bitmap 1373 * 1374 * @param rs Context to which the allocation will belong. 1375 * @param b bitmap source for the allocation data 1376 * @param mips specifies desired mipmap behaviour for the 1377 * allocation 1378 * @param usage bit field specifying how the allocation is 1379 * utilized 1380 * 1381 * @return renderscript allocation containing bitmap data 1382 * 1383 */ 1384 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 1385 MipmapControl mips, 1386 int usage) { 1387 rs.validate(); 1388 1389 // WAR undocumented color formats 1390 if (b.getConfig() == null) { 1391 if ((usage & USAGE_SHARED) != 0) { 1392 throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config."); 1393 } 1394 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 1395 Canvas c = new Canvas(newBitmap); 1396 c.drawBitmap(b, 0, 0, null); 1397 return createFromBitmap(rs, newBitmap, mips, usage); 1398 } 1399 1400 Type t = typeFromBitmap(rs, b, mips); 1401 1402 // enable optimized bitmap path only with no mipmap and script-only usage 1403 if (mips == MipmapControl.MIPMAP_NONE && 1404 t.getElement().isCompatible(Element.RGBA_8888(rs)) && 1405 usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) { 1406 int id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage); 1407 if (id == 0) { 1408 throw new RSRuntimeException("Load failed."); 1409 } 1410 1411 // keep a reference to the Bitmap around to prevent GC 1412 Allocation alloc = new Allocation(id, rs, t, usage); 1413 alloc.setBitmap(b); 1414 return alloc; 1415 } 1416 1417 int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1418 if (id == 0) { 1419 throw new RSRuntimeException("Load failed."); 1420 } 1421 return new Allocation(id, rs, t, usage); 1422 } 1423 1424 /** 1425 * For allocations used with io operations, returns the handle 1426 * onto a raw buffer that is being managed by the screen 1427 * compositor. 1428 * 1429 * @return Surface object associated with allocation 1430 * 1431 */ 1432 public Surface getSurface() { 1433 if ((mUsage & USAGE_IO_INPUT) == 0) { 1434 throw new RSInvalidStateException("Allocation is not a surface texture."); 1435 } 1436 return mRS.nAllocationGetSurface(getID(mRS)); 1437 } 1438 1439 /** 1440 * @hide 1441 */ 1442 public void setSurfaceTexture(SurfaceTexture st) { 1443 setSurface(new Surface(st)); 1444 } 1445 1446 /** 1447 * Associate a surface for io output with this allocation 1448 * 1449 * @param sur Surface to associate with allocation 1450 */ 1451 public void setSurface(Surface sur) { 1452 mRS.validate(); 1453 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 1454 throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT."); 1455 } 1456 1457 mRS.nAllocationSetSurface(getID(mRS), sur); 1458 } 1459 1460 /** 1461 * Creates a RenderScript allocation from a bitmap. 1462 * 1463 * With target API version 18 or greater, this allocation will be 1464 * created with USAGE_SHARED. With target API version 17 or lower, 1465 * this allocation will be created with USAGE_GRAPHICS_TEXTURE. 1466 * 1467 * @param rs Context to which the allocation will belong. 1468 * @param b bitmap source for the allocation data 1469 * 1470 * @return renderscript allocation containing bitmap data 1471 * 1472 */ 1473 static public Allocation createFromBitmap(RenderScript rs, Bitmap b) { 1474 if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) { 1475 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1476 USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 1477 } 1478 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1479 USAGE_GRAPHICS_TEXTURE); 1480 } 1481 1482 /** 1483 * Creates a cubemap allocation from a bitmap containing the 1484 * horizontal list of cube faces. Each individual face must be 1485 * the same size and power of 2 1486 * 1487 * @param rs Context to which the allocation will belong. 1488 * @param b bitmap with cubemap faces layed out in the following 1489 * format: right, left, top, bottom, front, back 1490 * @param mips specifies desired mipmap behaviour for the cubemap 1491 * @param usage bit field specifying how the cubemap is utilized 1492 * 1493 * @return allocation containing cubemap data 1494 * 1495 */ 1496 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 1497 MipmapControl mips, 1498 int usage) { 1499 rs.validate(); 1500 1501 int height = b.getHeight(); 1502 int width = b.getWidth(); 1503 1504 if (width % 6 != 0) { 1505 throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); 1506 } 1507 if (width / 6 != height) { 1508 throw new RSIllegalArgumentException("Only square cube map faces supported"); 1509 } 1510 boolean isPow2 = (height & (height - 1)) == 0; 1511 if (!isPow2) { 1512 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 1513 } 1514 1515 Element e = elementFromBitmap(rs, b); 1516 Type.Builder tb = new Type.Builder(rs, e); 1517 tb.setX(height); 1518 tb.setY(height); 1519 tb.setFaces(true); 1520 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 1521 Type t = tb.create(); 1522 1523 int id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1524 if(id == 0) { 1525 throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); 1526 } 1527 return new Allocation(id, rs, t, usage); 1528 } 1529 1530 /** 1531 * Creates a non-mipmapped cubemap allocation for use as a 1532 * graphics texture from a bitmap containing the horizontal list 1533 * of cube faces. Each individual face must be the same size and 1534 * power of 2 1535 * 1536 * @param rs Context to which the allocation will belong. 1537 * @param b bitmap with cubemap faces layed out in the following 1538 * format: right, left, top, bottom, front, back 1539 * 1540 * @return allocation containing cubemap data 1541 * 1542 */ 1543 static public Allocation createCubemapFromBitmap(RenderScript rs, 1544 Bitmap b) { 1545 return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1546 USAGE_GRAPHICS_TEXTURE); 1547 } 1548 1549 /** 1550 * Creates a cubemap allocation from 6 bitmaps containing 1551 * the cube faces. All the faces must be the same size and 1552 * power of 2 1553 * 1554 * @param rs Context to which the allocation will belong. 1555 * @param xpos cubemap face in the positive x direction 1556 * @param xneg cubemap face in the negative x direction 1557 * @param ypos cubemap face in the positive y direction 1558 * @param yneg cubemap face in the negative y direction 1559 * @param zpos cubemap face in the positive z direction 1560 * @param zneg cubemap face in the negative z direction 1561 * @param mips specifies desired mipmap behaviour for the cubemap 1562 * @param usage bit field specifying how the cubemap is utilized 1563 * 1564 * @return allocation containing cubemap data 1565 * 1566 */ 1567 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 1568 Bitmap xpos, 1569 Bitmap xneg, 1570 Bitmap ypos, 1571 Bitmap yneg, 1572 Bitmap zpos, 1573 Bitmap zneg, 1574 MipmapControl mips, 1575 int usage) { 1576 int height = xpos.getHeight(); 1577 if (xpos.getWidth() != height || 1578 xneg.getWidth() != height || xneg.getHeight() != height || 1579 ypos.getWidth() != height || ypos.getHeight() != height || 1580 yneg.getWidth() != height || yneg.getHeight() != height || 1581 zpos.getWidth() != height || zpos.getHeight() != height || 1582 zneg.getWidth() != height || zneg.getHeight() != height) { 1583 throw new RSIllegalArgumentException("Only square cube map faces supported"); 1584 } 1585 boolean isPow2 = (height & (height - 1)) == 0; 1586 if (!isPow2) { 1587 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 1588 } 1589 1590 Element e = elementFromBitmap(rs, xpos); 1591 Type.Builder tb = new Type.Builder(rs, e); 1592 tb.setX(height); 1593 tb.setY(height); 1594 tb.setFaces(true); 1595 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 1596 Type t = tb.create(); 1597 Allocation cubemap = Allocation.createTyped(rs, t, mips, usage); 1598 1599 AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap); 1600 adapter.setFace(Type.CubemapFace.POSITIVE_X); 1601 adapter.copyFrom(xpos); 1602 adapter.setFace(Type.CubemapFace.NEGATIVE_X); 1603 adapter.copyFrom(xneg); 1604 adapter.setFace(Type.CubemapFace.POSITIVE_Y); 1605 adapter.copyFrom(ypos); 1606 adapter.setFace(Type.CubemapFace.NEGATIVE_Y); 1607 adapter.copyFrom(yneg); 1608 adapter.setFace(Type.CubemapFace.POSITIVE_Z); 1609 adapter.copyFrom(zpos); 1610 adapter.setFace(Type.CubemapFace.NEGATIVE_Z); 1611 adapter.copyFrom(zneg); 1612 1613 return cubemap; 1614 } 1615 1616 /** 1617 * Creates a non-mipmapped cubemap allocation for use as a 1618 * graphics texture from 6 bitmaps containing 1619 * the cube faces. All the faces must be the same size and 1620 * power of 2 1621 * 1622 * @param rs Context to which the allocation will belong. 1623 * @param xpos cubemap face in the positive x direction 1624 * @param xneg cubemap face in the negative x direction 1625 * @param ypos cubemap face in the positive y direction 1626 * @param yneg cubemap face in the negative y direction 1627 * @param zpos cubemap face in the positive z direction 1628 * @param zneg cubemap face in the negative z direction 1629 * 1630 * @return allocation containing cubemap data 1631 * 1632 */ 1633 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 1634 Bitmap xpos, 1635 Bitmap xneg, 1636 Bitmap ypos, 1637 Bitmap yneg, 1638 Bitmap zpos, 1639 Bitmap zneg) { 1640 return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg, 1641 zpos, zneg, MipmapControl.MIPMAP_NONE, 1642 USAGE_GRAPHICS_TEXTURE); 1643 } 1644 1645 /** 1646 * Creates a renderscript allocation from the bitmap referenced 1647 * by resource id 1648 * 1649 * @param rs Context to which the allocation will belong. 1650 * @param res application resources 1651 * @param id resource id to load the data from 1652 * @param mips specifies desired mipmap behaviour for the 1653 * allocation 1654 * @param usage bit field specifying how the allocation is 1655 * utilized 1656 * 1657 * @return renderscript allocation containing resource data 1658 * 1659 */ 1660 static public Allocation createFromBitmapResource(RenderScript rs, 1661 Resources res, 1662 int id, 1663 MipmapControl mips, 1664 int usage) { 1665 1666 rs.validate(); 1667 Bitmap b = BitmapFactory.decodeResource(res, id); 1668 Allocation alloc = createFromBitmap(rs, b, mips, usage); 1669 b.recycle(); 1670 return alloc; 1671 } 1672 1673 /** 1674 * Creates a non-mipmapped renderscript allocation to use as a 1675 * graphics texture from the bitmap referenced by resource id 1676 * 1677 * With target API version 18 or greater, this allocation will be 1678 * created with USAGE_SHARED. With target API version 17 or lower, 1679 * this allocation will be created with USAGE_GRAPHICS_TEXTURE. 1680 * 1681 * @param rs Context to which the allocation will belong. 1682 * @param res application resources 1683 * @param id resource id to load the data from 1684 * 1685 * @return renderscript allocation containing resource data 1686 * 1687 */ 1688 static public Allocation createFromBitmapResource(RenderScript rs, 1689 Resources res, 1690 int id) { 1691 if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) { 1692 return createFromBitmapResource(rs, res, id, 1693 MipmapControl.MIPMAP_NONE, 1694 USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 1695 } 1696 return createFromBitmapResource(rs, res, id, 1697 MipmapControl.MIPMAP_NONE, 1698 USAGE_GRAPHICS_TEXTURE); 1699 } 1700 1701 /** 1702 * Creates a renderscript allocation containing string data 1703 * encoded in UTF-8 format 1704 * 1705 * @param rs Context to which the allocation will belong. 1706 * @param str string to create the allocation from 1707 * @param usage bit field specifying how the allocaiton is 1708 * utilized 1709 * 1710 */ 1711 static public Allocation createFromString(RenderScript rs, 1712 String str, 1713 int usage) { 1714 rs.validate(); 1715 byte[] allocArray = null; 1716 try { 1717 allocArray = str.getBytes("UTF-8"); 1718 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 1719 alloc.copyFrom(allocArray); 1720 return alloc; 1721 } 1722 catch (Exception e) { 1723 throw new RSRuntimeException("Could not convert string to utf-8."); 1724 } 1725 } 1726 1727 /** 1728 * Interface to handle notification when new buffers are 1729 * available via USAGE_IO_INPUT. An application will receive 1730 * one notification when a buffer is available. Additional 1731 * buffers will not trigger new notifications until a buffer is 1732 * processed. 1733 */ 1734 public interface IoInputNotifier { 1735 public void onBufferAvailable(Allocation a); 1736 } 1737 1738 /** 1739 * Set a notification handler for USAGE_IO_INPUT 1740 * 1741 * @param callback instance of the IoInputNotifier class to be called 1742 * when buffer arrive. 1743 */ 1744 public void setIoInputNotificationHandler(IoInputNotifier callback) { 1745 synchronized(mAllocationMap) { 1746 mAllocationMap.put(new Integer(getID(mRS)), this); 1747 mBufferNotifier = callback; 1748 } 1749 } 1750 1751 static void sendBufferNotification(int id) { 1752 synchronized(mAllocationMap) { 1753 Allocation a = mAllocationMap.get(new Integer(id)); 1754 1755 if ((a != null) && (a.mBufferNotifier != null)) { 1756 a.mBufferNotifier.onBufferAvailable(a); 1757 } 1758 } 1759 } 1760 1761} 1762 1763 1764