Allocation.java revision 21b4103e42cb0fa004cc4a978f49f63e7668ab0b
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 @Override 125 void updateFromNative() { 126 super.updateFromNative(); 127 int typeID = mRS.nAllocationGetType(getID()); 128 if(typeID != 0) { 129 mType = new Type(typeID, mRS); 130 mType.updateFromNative(); 131 } 132 } 133 134 public Type getType() { 135 return mType; 136 } 137 138 public void syncAll(int srcLocation) { 139 switch (srcLocation) { 140 case USAGE_SCRIPT: 141 case USAGE_GRAPHICS_CONSTANTS: 142 case USAGE_GRAPHICS_TEXTURE: 143 case USAGE_GRAPHICS_VERTEX: 144 break; 145 default: 146 throw new RSIllegalArgumentException("Source must be exactly one usage type."); 147 } 148 mRS.validate(); 149 mRS.nAllocationSyncAll(getID(), srcLocation); 150 } 151 152 public void copyFrom(BaseObj[] d) { 153 mRS.validate(); 154 if (d.length != mType.getCount()) { 155 throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + 156 mType.getCount() + ", array length = " + d.length); 157 } 158 int i[] = new int[d.length]; 159 for (int ct=0; ct < d.length; ct++) { 160 i[ct] = d[ct].getID(); 161 } 162 copy1DRangeFrom(0, mType.getCount(), i); 163 } 164 165 private void validateBitmapFormat(Bitmap b) { 166 Bitmap.Config bc = b.getConfig(); 167 switch (bc) { 168 case ALPHA_8: 169 if (mType.getElement().mKind != Element.DataKind.PIXEL_A) { 170 throw new RSIllegalArgumentException("Allocation kind is " + 171 mType.getElement().mKind + ", type " + 172 mType.getElement().mType + 173 " of " + mType.getElement().getSizeBytes() + 174 " bytes, passed bitmap was " + bc); 175 } 176 break; 177 case ARGB_8888: 178 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 179 (mType.getElement().getSizeBytes() != 4)) { 180 throw new RSIllegalArgumentException("Allocation kind is " + 181 mType.getElement().mKind + ", type " + 182 mType.getElement().mType + 183 " of " + mType.getElement().getSizeBytes() + 184 " bytes, passed bitmap was " + bc); 185 } 186 break; 187 case RGB_565: 188 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) || 189 (mType.getElement().getSizeBytes() != 2)) { 190 throw new RSIllegalArgumentException("Allocation kind is " + 191 mType.getElement().mKind + ", type " + 192 mType.getElement().mType + 193 " of " + mType.getElement().getSizeBytes() + 194 " bytes, passed bitmap was " + bc); 195 } 196 break; 197 case ARGB_4444: 198 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 199 (mType.getElement().getSizeBytes() != 2)) { 200 throw new RSIllegalArgumentException("Allocation kind is " + 201 mType.getElement().mKind + ", type " + 202 mType.getElement().mType + 203 " of " + mType.getElement().getSizeBytes() + 204 " bytes, passed bitmap was " + bc); 205 } 206 break; 207 208 } 209 } 210 211 private void validateBitmapSize(Bitmap b) { 212 if(mType.getX() != b.getWidth() || 213 mType.getY() != b.getHeight()) { 214 throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); 215 } 216 } 217 218 public void copyFrom(int[] d) { 219 mRS.validate(); 220 copy1DRangeFrom(0, mType.getCount(), d); 221 } 222 public void copyFrom(short[] d) { 223 mRS.validate(); 224 copy1DRangeFrom(0, mType.getCount(), d); 225 } 226 public void copyFrom(byte[] d) { 227 mRS.validate(); 228 copy1DRangeFrom(0, mType.getCount(), d); 229 } 230 public void copyFrom(float[] d) { 231 mRS.validate(); 232 copy1DRangeFrom(0, mType.getCount(), d); 233 } 234 public void copyFrom(Bitmap b) { 235 mRS.validate(); 236 validateBitmapSize(b); 237 validateBitmapFormat(b); 238 mRS.nAllocationCopyFromBitmap(getID(), b); 239 } 240 241 /** 242 * This is only intended to be used by auto-generate code reflected from the 243 * renderscript script files. 244 * 245 * @param xoff 246 * @param fp 247 */ 248 public void setFromFieldPacker(int xoff, FieldPacker fp) { 249 int eSize = mType.mElement.getSizeBytes(); 250 final byte[] data = fp.getData(); 251 252 int count = data.length / eSize; 253 if ((eSize * count) != data.length) { 254 throw new RSIllegalArgumentException("Field packer length " + data.length + 255 " not divisible by element size " + eSize + "."); 256 } 257 data1DChecks(xoff, count, data.length, data.length); 258 mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length); 259 } 260 261 262 /** 263 * This is only intended to be used by auto-generate code reflected from the 264 * renderscript script files. 265 * 266 * @param xoff 267 * @param component_number 268 * @param fp 269 */ 270 public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) { 271 if (component_number >= mType.mElement.mElements.length) { 272 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 273 } 274 if(xoff < 0) { 275 throw new RSIllegalArgumentException("Offset must be >= 0."); 276 } 277 278 final byte[] data = fp.getData(); 279 int eSize = mType.mElement.mElements[component_number].getSizeBytes(); 280 281 if (data.length != eSize) { 282 throw new RSIllegalArgumentException("Field packer sizelength " + data.length + 283 " does not match component size " + eSize + "."); 284 } 285 286 mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length); 287 } 288 289 private void data1DChecks(int off, int count, int len, int dataSize) { 290 mRS.validate(); 291 if(off < 0) { 292 throw new RSIllegalArgumentException("Offset must be >= 0."); 293 } 294 if(count < 1) { 295 throw new RSIllegalArgumentException("Count must be >= 1."); 296 } 297 if((off + count) > mType.getCount()) { 298 throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() + 299 ", got " + count + " at offset " + off + "."); 300 } 301 if((len) < dataSize) { 302 throw new RSIllegalArgumentException("Array too small for allocation type."); 303 } 304 } 305 306 /** 307 * Generate a mipmap chain. Requires the type of the allocation 308 * include mipmaps. 309 * 310 * This function will generate a complete set of mipmaps from 311 * the top level lod and place them into the script memoryspace. 312 * 313 * If the allocation is also using other memory spaces a 314 * followup sync will be required. 315 */ 316 public void generateMipmaps() { 317 mRS.nAllocationGenerateMipmaps(getID()); 318 } 319 320 public void copy1DRangeFrom(int off, int count, int[] d) { 321 int dataSize = mType.mElement.getSizeBytes() * count; 322 data1DChecks(off, count, d.length * 4, dataSize); 323 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 324 } 325 public void copy1DRangeFrom(int off, int count, short[] d) { 326 int dataSize = mType.mElement.getSizeBytes() * count; 327 data1DChecks(off, count, d.length * 2, dataSize); 328 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 329 } 330 public void copy1DRangeFrom(int off, int count, byte[] d) { 331 int dataSize = mType.mElement.getSizeBytes() * count; 332 data1DChecks(off, count, d.length, dataSize); 333 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 334 } 335 public void copy1DRangeFrom(int off, int count, float[] d) { 336 int dataSize = mType.mElement.getSizeBytes() * count; 337 data1DChecks(off, count, d.length * 4, dataSize); 338 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 339 } 340 341 private void validate2DRange(int xoff, int yoff, int w, int h) { 342 if (xoff < 0 || yoff < 0) { 343 throw new RSIllegalArgumentException("Offset cannot be negative."); 344 } 345 if (h < 0 || w < 0) { 346 throw new RSIllegalArgumentException("Height or width cannot be negative."); 347 } 348 if ((xoff + w) > mType.mDimX || 349 (yoff + h) > mType.mDimY) { 350 throw new RSIllegalArgumentException("Updated region larger than allocation."); 351 } 352 } 353 354 /** 355 * Copy a rectanglular region from the array into the 356 * allocation. The incoming array is assumed to be tightly 357 * packed. 358 * 359 * @param xoff X offset of the region to update 360 * @param yoff Y offset of the region to update 361 * @param w Width of the incoming region to update 362 * @param h Height of the incoming region to update 363 * @param data to be placed into the allocation 364 */ 365 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { 366 mRS.validate(); 367 validate2DRange(xoff, yoff, w, h); 368 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length); 369 } 370 371 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) { 372 mRS.validate(); 373 validate2DRange(xoff, yoff, w, h); 374 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2); 375 } 376 377 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) { 378 mRS.validate(); 379 validate2DRange(xoff, yoff, w, h); 380 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); 381 } 382 383 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) { 384 mRS.validate(); 385 validate2DRange(xoff, yoff, w, h); 386 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); 387 } 388 389 /** 390 * Copy a bitmap into an allocation. The height and width of 391 * the update will use the height and width of the incoming 392 * bitmap. 393 * 394 * @param xoff X offset of the region to update 395 * @param yoff Y offset of the region to update 396 * @param data the bitmap to be copied 397 */ 398 public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) { 399 mRS.validate(); 400 validateBitmapFormat(data); 401 validate2DRange(xoff, yoff, data.getWidth(), data.getHeight()); 402 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data); 403 } 404 405 406 public void copyTo(Bitmap b) { 407 mRS.validate(); 408 validateBitmapFormat(b); 409 validateBitmapSize(b); 410 mRS.nAllocationCopyToBitmap(getID(), b); 411 } 412 413 public void copyTo(byte[] d) { 414 mRS.validate(); 415 mRS.nAllocationRead(getID(), d); 416 } 417 418 public void copyTo(short[] d) { 419 mRS.validate(); 420 mRS.nAllocationRead(getID(), d); 421 } 422 423 public void copyTo(int[] d) { 424 mRS.validate(); 425 mRS.nAllocationRead(getID(), d); 426 } 427 428 public void copyTo(float[] d) { 429 mRS.validate(); 430 mRS.nAllocationRead(getID(), d); 431 } 432 433 /** 434 * Resize a 1D allocation. The contents of the allocation are 435 * preserved. If new elements are allocated objects are created 436 * with null contents and the new region is otherwise undefined. 437 * 438 * If the new region is smaller the references of any objects 439 * outside the new region will be released. 440 * 441 * A new type will be created with the new dimension. 442 * 443 * @param dimX The new size of the allocation. 444 */ 445 public synchronized void resize(int dimX) { 446 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 447 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 448 } 449 mRS.nAllocationResize1D(getID(), dimX); 450 mRS.finish(); // Necessary because resize is fifoed and update is async. 451 452 int typeID = mRS.nAllocationGetType(getID()); 453 mType = new Type(typeID, mRS); 454 mType.updateFromNative(); 455 } 456 457 /* 458 public void resize(int dimX, int dimY) { 459 if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) { 460 throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); 461 } 462 if (mType.getY() == 0) { 463 throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); 464 } 465 mRS.nAllocationResize2D(getID(), dimX, dimY); 466 } 467 */ 468 469 470 471 // creation 472 473 static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 474 static { 475 mBitmapOptions.inScaled = false; 476 } 477 478 /** 479 * 480 * @param type renderscript type describing data layout 481 * @param mips specifies desired mipmap behaviour for the 482 * allocation 483 * @param usage bit field specifying how the allocation is 484 * utilized 485 */ 486 static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) { 487 rs.validate(); 488 if (type.getID() == 0) { 489 throw new RSInvalidStateException("Bad Type"); 490 } 491 int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage); 492 if (id == 0) { 493 throw new RSRuntimeException("Allocation creation failed."); 494 } 495 return new Allocation(id, rs, type, usage); 496 } 497 498 /** 499 * Creates a renderscript allocation with the size specified by 500 * the type and no mipmaps generated by default 501 * 502 * @param rs Context to which the allocation will belong. 503 * @param type renderscript type describing data layout 504 * @param usage bit field specifying how the allocation is 505 * utilized 506 * 507 * @return allocation 508 */ 509 static public Allocation createTyped(RenderScript rs, Type type, int usage) { 510 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage); 511 } 512 513 /** 514 * Creates a renderscript allocation for use by the script with 515 * the size specified by the type and no mipmaps generated by 516 * default 517 * 518 * @param rs Context to which the allocation will belong. 519 * @param type renderscript type describing data layout 520 * 521 * @return allocation 522 */ 523 static public Allocation createTyped(RenderScript rs, Type type) { 524 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT); 525 } 526 527 /** 528 * Creates a renderscript allocation with a specified number of 529 * given elements 530 * 531 * @param rs Context to which the allocation will belong. 532 * @param e describes what each element of an allocation is 533 * @param count specifies the number of element in the allocation 534 * @param usage bit field specifying how the allocation is 535 * utilized 536 * 537 * @return allocation 538 */ 539 static public Allocation createSized(RenderScript rs, Element e, 540 int count, int usage) { 541 rs.validate(); 542 Type.Builder b = new Type.Builder(rs, e); 543 b.setX(count); 544 Type t = b.create(); 545 546 int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage); 547 if (id == 0) { 548 throw new RSRuntimeException("Allocation creation failed."); 549 } 550 return new Allocation(id, rs, t, usage); 551 } 552 553 /** 554 * Creates a renderscript allocation with a specified number of 555 * given elements 556 * 557 * @param rs Context to which the allocation will belong. 558 * @param e describes what each element of an allocation is 559 * @param count specifies the number of element in the allocation 560 * 561 * @return allocation 562 */ 563 static public Allocation createSized(RenderScript rs, Element e, int count) { 564 return createSized(rs, e, count, USAGE_SCRIPT); 565 } 566 567 static Element elementFromBitmap(RenderScript rs, Bitmap b) { 568 final Bitmap.Config bc = b.getConfig(); 569 if (bc == Bitmap.Config.ALPHA_8) { 570 return Element.A_8(rs); 571 } 572 if (bc == Bitmap.Config.ARGB_4444) { 573 return Element.RGBA_4444(rs); 574 } 575 if (bc == Bitmap.Config.ARGB_8888) { 576 return Element.RGBA_8888(rs); 577 } 578 if (bc == Bitmap.Config.RGB_565) { 579 return Element.RGB_565(rs); 580 } 581 throw new RSInvalidStateException("Bad bitmap type: " + bc); 582 } 583 584 static Type typeFromBitmap(RenderScript rs, Bitmap b, 585 MipmapControl mip) { 586 Element e = elementFromBitmap(rs, b); 587 Type.Builder tb = new Type.Builder(rs, e); 588 tb.setX(b.getWidth()); 589 tb.setY(b.getHeight()); 590 tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); 591 return tb.create(); 592 } 593 594 /** 595 * Creates a renderscript allocation from a bitmap 596 * 597 * @param rs Context to which the allocation will belong. 598 * @param b bitmap source for the allocation data 599 * @param mips specifies desired mipmap behaviour for the 600 * allocation 601 * @param usage bit field specifying how the allocation is 602 * utilized 603 * 604 * @return renderscript allocation containing bitmap data 605 * 606 */ 607 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 608 MipmapControl mips, 609 int usage) { 610 rs.validate(); 611 Type t = typeFromBitmap(rs, b, mips); 612 613 int id = rs.nAllocationCreateFromBitmap(t.getID(), mips.mID, b, usage); 614 if (id == 0) { 615 throw new RSRuntimeException("Load failed."); 616 } 617 return new Allocation(id, rs, t, usage); 618 } 619 620 /** 621 * Creates a non-mipmapped renderscript allocation to use as a 622 * graphics texture 623 * 624 * @param rs Context to which the allocation will belong. 625 * @param b bitmap source for the allocation data 626 * 627 * @return renderscript allocation containing bitmap data 628 * 629 */ 630 static public Allocation createFromBitmap(RenderScript rs, Bitmap b) { 631 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 632 USAGE_GRAPHICS_TEXTURE); 633 } 634 635 /** 636 * Creates a cubemap allocation from a bitmap containing the 637 * horizontal list of cube faces. Each individual face must be 638 * the same size and power of 2 639 * 640 * @param rs Context to which the allocation will belong. 641 * @param b bitmap with cubemap faces layed out in the following 642 * format: right, left, top, bottom, front, back 643 * @param mips specifies desired mipmap behaviour for the cubemap 644 * @param usage bit field specifying how the cubemap is utilized 645 * 646 * @return allocation containing cubemap data 647 * 648 */ 649 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 650 MipmapControl mips, 651 int usage) { 652 rs.validate(); 653 654 int height = b.getHeight(); 655 int width = b.getWidth(); 656 657 if (width % 6 != 0) { 658 throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); 659 } 660 if (width / 6 != height) { 661 throw new RSIllegalArgumentException("Only square cube map faces supported"); 662 } 663 boolean isPow2 = (height & (height - 1)) == 0; 664 if (!isPow2) { 665 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 666 } 667 668 Element e = elementFromBitmap(rs, b); 669 Type.Builder tb = new Type.Builder(rs, e); 670 tb.setX(height); 671 tb.setY(height); 672 tb.setFaces(true); 673 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 674 Type t = tb.create(); 675 676 int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage); 677 if(id == 0) { 678 throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); 679 } 680 return new Allocation(id, rs, t, usage); 681 } 682 683 /** 684 * Creates a non-mipmapped cubemap allocation for use as a 685 * graphics texture from a bitmap containing the horizontal list 686 * of cube faces. Each individual face must be the same size and 687 * power of 2 688 * 689 * @param rs Context to which the allocation will belong. 690 * @param b bitmap with cubemap faces layed out in the following 691 * format: right, left, top, bottom, front, back 692 * 693 * @return allocation containing cubemap data 694 * 695 */ 696 static public Allocation createCubemapFromBitmap(RenderScript rs, 697 Bitmap b) { 698 return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 699 USAGE_GRAPHICS_TEXTURE); 700 } 701 702 /** 703 * Creates a cubemap allocation from 6 bitmaps containing 704 * the cube faces. All the faces must be the same size and 705 * power of 2 706 * 707 * @param rs Context to which the allocation will belong. 708 * @param xpos cubemap face in the positive x direction 709 * @param xneg cubemap face in the negative x direction 710 * @param ypos cubemap face in the positive y direction 711 * @param yneg cubemap face in the negative y direction 712 * @param zpos cubemap face in the positive z direction 713 * @param zneg cubemap face in the negative z direction 714 * @param mips specifies desired mipmap behaviour for the cubemap 715 * @param usage bit field specifying how the cubemap is utilized 716 * 717 * @return allocation containing cubemap data 718 * 719 */ 720 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 721 Bitmap xpos, 722 Bitmap xneg, 723 Bitmap ypos, 724 Bitmap yneg, 725 Bitmap zpos, 726 Bitmap zneg, 727 MipmapControl mips, 728 int usage) { 729 int height = xpos.getHeight(); 730 if (xpos.getWidth() != height || 731 xneg.getWidth() != height || xneg.getHeight() != height || 732 ypos.getWidth() != height || ypos.getHeight() != height || 733 yneg.getWidth() != height || yneg.getHeight() != height || 734 zpos.getWidth() != height || zpos.getHeight() != height || 735 zneg.getWidth() != height || zneg.getHeight() != height) { 736 throw new RSIllegalArgumentException("Only square cube map faces supported"); 737 } 738 boolean isPow2 = (height & (height - 1)) == 0; 739 if (!isPow2) { 740 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 741 } 742 743 Element e = elementFromBitmap(rs, xpos); 744 Type.Builder tb = new Type.Builder(rs, e); 745 tb.setX(height); 746 tb.setY(height); 747 tb.setFaces(true); 748 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 749 Type t = tb.create(); 750 Allocation cubemap = Allocation.createTyped(rs, t, mips, usage); 751 752 AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap); 753 adapter.setFace(Type.CubemapFace.POSITVE_X); 754 adapter.copyFrom(xpos); 755 adapter.setFace(Type.CubemapFace.NEGATIVE_X); 756 adapter.copyFrom(xneg); 757 adapter.setFace(Type.CubemapFace.POSITVE_Y); 758 adapter.copyFrom(ypos); 759 adapter.setFace(Type.CubemapFace.NEGATIVE_Y); 760 adapter.copyFrom(yneg); 761 adapter.setFace(Type.CubemapFace.POSITVE_Z); 762 adapter.copyFrom(zpos); 763 adapter.setFace(Type.CubemapFace.NEGATIVE_Z); 764 adapter.copyFrom(zneg); 765 766 return cubemap; 767 } 768 769 /** 770 * Creates a non-mipmapped cubemap allocation for use as a 771 * graphics texture from 6 bitmaps containing 772 * the cube faces. All the faces must be the same size and 773 * power of 2 774 * 775 * @param rs Context to which the allocation will belong. 776 * @param xpos cubemap face in the positive x direction 777 * @param xneg cubemap face in the negative x direction 778 * @param ypos cubemap face in the positive y direction 779 * @param yneg cubemap face in the negative y direction 780 * @param zpos cubemap face in the positive z direction 781 * @param zneg cubemap face in the negative z direction 782 * 783 * @return allocation containing cubemap data 784 * 785 */ 786 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 787 Bitmap xpos, 788 Bitmap xneg, 789 Bitmap ypos, 790 Bitmap yneg, 791 Bitmap zpos, 792 Bitmap zneg) { 793 return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg, 794 zpos, zneg, MipmapControl.MIPMAP_NONE, 795 USAGE_GRAPHICS_TEXTURE); 796 } 797 798 /** 799 * Creates a renderscript allocation from the bitmap referenced 800 * by resource id 801 * 802 * @param rs Context to which the allocation will belong. 803 * @param res application resources 804 * @param id resource id to load the data from 805 * @param mips specifies desired mipmap behaviour for the 806 * allocation 807 * @param usage bit field specifying how the allocation is 808 * utilized 809 * 810 * @return renderscript allocation containing resource data 811 * 812 */ 813 static public Allocation createFromBitmapResource(RenderScript rs, 814 Resources res, 815 int id, 816 MipmapControl mips, 817 int usage) { 818 819 rs.validate(); 820 Bitmap b = BitmapFactory.decodeResource(res, id); 821 Allocation alloc = createFromBitmap(rs, b, mips, usage); 822 b.recycle(); 823 return alloc; 824 } 825 826 /** 827 * Creates a non-mipmapped renderscript allocation to use as a 828 * graphics texture from the bitmap referenced by resource id 829 * 830 * @param rs Context to which the allocation will belong. 831 * @param res application resources 832 * @param id resource id to load the data from 833 * 834 * @return renderscript allocation containing resource data 835 * 836 */ 837 static public Allocation createFromBitmapResource(RenderScript rs, 838 Resources res, 839 int id) { 840 return createFromBitmapResource(rs, res, id, 841 MipmapControl.MIPMAP_NONE, 842 USAGE_GRAPHICS_TEXTURE); 843 } 844 845 /** 846 * Creates a renderscript allocation containing string data 847 * encoded in UTF-8 format 848 * 849 * @param rs Context to which the allocation will belong. 850 * @param str string to create the allocation from 851 * @param usage bit field specifying how the allocaiton is 852 * utilized 853 * 854 */ 855 static public Allocation createFromString(RenderScript rs, 856 String str, 857 int usage) { 858 rs.validate(); 859 byte[] allocArray = null; 860 try { 861 allocArray = str.getBytes("UTF-8"); 862 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 863 alloc.copyFrom(allocArray); 864 return alloc; 865 } 866 catch (Exception e) { 867 throw new RSRuntimeException("Could not convert string to utf-8."); 868 } 869 } 870} 871 872 873