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