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