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