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