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