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