Allocation.java revision e6eaaf6a8e491404c33aab5cd70444d2637df1bc
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 17package android.renderscript; 18 19import java.io.IOException; 20import java.io.InputStream; 21import java.util.HashMap; 22import android.content.res.Resources; 23import android.content.res.AssetManager; 24import android.graphics.Bitmap; 25import android.graphics.BitmapFactory; 26import android.view.Surface; 27import android.util.Log; 28import android.util.TypedValue; 29import android.graphics.Canvas; 30import android.os.Trace; 31 32/** 33 * <p> This class provides the primary method through which data is passed to 34 * and from RenderScript kernels. An Allocation provides the backing store for 35 * a given {@link android.renderscript.Type}. </p> 36 * 37 * <p>An Allocation also contains a set of usage flags that denote how the 38 * Allocation could be used. For example, an Allocation may have usage flags 39 * specifying that it can be used from a script as well as input to a {@link 40 * android.renderscript.Sampler}. A developer must synchronize across these 41 * different usages using {@link android.renderscript.Allocation#syncAll} in 42 * order to ensure that different users of the Allocation have a consistent view 43 * of memory. For example, in the case where an Allocation is used as the output 44 * of one kernel and as Sampler input in a later kernel, a developer must call 45 * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the 46 * second kernel to ensure correctness. 47 * 48 * <p>An Allocation can be populated with the {@link #copyFrom} routines. For 49 * more complex Element types, the {@link #copyFromUnchecked} methods can be 50 * used to copy from byte arrays or similar constructs.</p> 51 * 52 * <div class="special reference"> 53 * <h3>Developer Guides</h3> 54 * <p>For more information about creating an application that uses RenderScript, read the 55 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p> 56 * </div> 57 **/ 58public class Allocation extends BaseObj { 59 Type mType; 60 Bitmap mBitmap; 61 int mUsage; 62 Allocation mAdaptedAllocation; 63 int mSize; 64 65 boolean mConstrainedLOD; 66 boolean mConstrainedFace; 67 boolean mConstrainedY; 68 boolean mConstrainedZ; 69 boolean mReadAllowed = true; 70 boolean mWriteAllowed = true; 71 int mSelectedY; 72 int mSelectedZ; 73 int mSelectedLOD; 74 Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X; 75 76 int mCurrentDimX; 77 int mCurrentDimY; 78 int mCurrentDimZ; 79 int mCurrentCount; 80 static HashMap<Long, Allocation> mAllocationMap = 81 new HashMap<Long, Allocation>(); 82 OnBufferAvailableListener mBufferNotifier; 83 84 /** 85 * The usage of the Allocation. These signal to RenderScript where to place 86 * the Allocation in memory. 87 * 88 */ 89 90 /** 91 * The Allocation will be bound to and accessed by scripts. 92 */ 93 public static final int USAGE_SCRIPT = 0x0001; 94 95 /** 96 * The Allocation will be used as a texture source by one or more graphics 97 * programs. 98 * 99 */ 100 public static final int USAGE_GRAPHICS_TEXTURE = 0x0002; 101 102 /** 103 * The Allocation will be used as a graphics mesh. 104 * 105 * This was deprecated in API level 16. 106 * 107 */ 108 public static final int USAGE_GRAPHICS_VERTEX = 0x0004; 109 110 111 /** 112 * The Allocation will be used as the source of shader constants by one or 113 * more programs. 114 * 115 * This was deprecated in API level 16. 116 * 117 */ 118 public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008; 119 120 /** 121 * The Allocation will be used as a target for offscreen rendering 122 * 123 * This was deprecated in API level 16. 124 * 125 */ 126 public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010; 127 128 /** 129 * The Allocation will be used as a {@link android.view.Surface} 130 * consumer. This usage will cause the Allocation to be created 131 * as read-only. 132 * 133 */ 134 public static final int USAGE_IO_INPUT = 0x0020; 135 136 /** 137 * The Allocation will be used as a {@link android.view.Surface} 138 * producer. The dimensions and format of the {@link 139 * android.view.Surface} will be forced to those of the 140 * Allocation. 141 * 142 */ 143 public static final int USAGE_IO_OUTPUT = 0x0040; 144 145 /** 146 * The Allocation's backing store will be inherited from another object 147 * (usually a {@link android.graphics.Bitmap}); copying to or from the 148 * original source Bitmap will cause a synchronization rather than a full 149 * copy. {@link #syncAll} may also be used to synchronize the Allocation 150 * and the source Bitmap. 151 * 152 * <p>This is set by default for allocations created with {@link 153 * #createFromBitmap} in API version 18 and higher.</p> 154 * 155 */ 156 public static final int USAGE_SHARED = 0x0080; 157 158 /** 159 * Controls mipmap behavior when using the bitmap creation and update 160 * functions. 161 */ 162 public enum MipmapControl { 163 /** 164 * No mipmaps will be generated and the type generated from the incoming 165 * bitmap will not contain additional LODs. 166 */ 167 MIPMAP_NONE(0), 168 169 /** 170 * A full mipmap chain will be created in script memory. The Type of 171 * the Allocation will contain a full mipmap chain. On upload, the full 172 * chain will be transferred. 173 */ 174 MIPMAP_FULL(1), 175 176 /** 177 * The Type of the Allocation will be the same as MIPMAP_NONE. It will 178 * not contain mipmaps. On upload, the allocation data will contain a 179 * full mipmap chain generated from the top level in script memory. 180 */ 181 MIPMAP_ON_SYNC_TO_TEXTURE(2); 182 183 int mID; 184 MipmapControl(int id) { 185 mID = id; 186 } 187 } 188 189 190 private long getIDSafe() { 191 if (mAdaptedAllocation != null) { 192 return mAdaptedAllocation.getID(mRS); 193 } 194 return getID(mRS); 195 } 196 197 198 /** 199 * Get the {@link android.renderscript.Element} of the {@link 200 * android.renderscript.Type} of the Allocation. 201 * 202 * @return Element 203 * 204 */ 205 public Element getElement() { 206 return mType.getElement(); 207 } 208 209 /** 210 * Get the usage flags of the Allocation. 211 * 212 * @return usage this Allocation's set of the USAGE_* flags OR'd together 213 * 214 */ 215 public int getUsage() { 216 return mUsage; 217 } 218 219 /** 220 * Get the size of the Allocation in bytes. 221 * 222 * @return size of the Allocation in bytes. 223 * 224 */ 225 public int getBytesSize() { 226 if (mType.mDimYuv != 0) { 227 return (int)Math.ceil(mType.getCount() * mType.getElement().getBytesSize() * 1.5); 228 } 229 return mType.getCount() * mType.getElement().getBytesSize(); 230 } 231 232 private void updateCacheInfo(Type t) { 233 mCurrentDimX = t.getX(); 234 mCurrentDimY = t.getY(); 235 mCurrentDimZ = t.getZ(); 236 mCurrentCount = mCurrentDimX; 237 if (mCurrentDimY > 1) { 238 mCurrentCount *= mCurrentDimY; 239 } 240 if (mCurrentDimZ > 1) { 241 mCurrentCount *= mCurrentDimZ; 242 } 243 } 244 245 private void setBitmap(Bitmap b) { 246 mBitmap = b; 247 } 248 249 Allocation(long id, RenderScript rs, Type t, int usage) { 250 super(id, rs); 251 if ((usage & ~(USAGE_SCRIPT | 252 USAGE_GRAPHICS_TEXTURE | 253 USAGE_GRAPHICS_VERTEX | 254 USAGE_GRAPHICS_CONSTANTS | 255 USAGE_GRAPHICS_RENDER_TARGET | 256 USAGE_IO_INPUT | 257 USAGE_IO_OUTPUT | 258 USAGE_SHARED)) != 0) { 259 throw new RSIllegalArgumentException("Unknown usage specified."); 260 } 261 262 if ((usage & USAGE_IO_INPUT) != 0) { 263 mWriteAllowed = false; 264 265 if ((usage & ~(USAGE_IO_INPUT | 266 USAGE_GRAPHICS_TEXTURE | 267 USAGE_SCRIPT)) != 0) { 268 throw new RSIllegalArgumentException("Invalid usage combination."); 269 } 270 } 271 272 mType = t; 273 mUsage = usage; 274 275 if (t != null) { 276 // TODO: A3D doesn't have Type info during creation, so we can't 277 // calculate the size ahead of time. We can possibly add a method 278 // to update the size in the future if it seems reasonable. 279 mSize = mType.getCount() * mType.getElement().getBytesSize(); 280 updateCacheInfo(t); 281 } 282 try { 283 RenderScript.registerNativeAllocation.invoke(RenderScript.sRuntime, mSize); 284 } catch (Exception e) { 285 Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e); 286 throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e); 287 } 288 } 289 290 protected void finalize() throws Throwable { 291 RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize); 292 super.finalize(); 293 } 294 295 private void validateIsInt32() { 296 if ((mType.mElement.mType == Element.DataType.SIGNED_32) || 297 (mType.mElement.mType == Element.DataType.UNSIGNED_32)) { 298 return; 299 } 300 throw new RSIllegalArgumentException( 301 "32 bit integer source does not match allocation type " + mType.mElement.mType); 302 } 303 304 private void validateIsInt16() { 305 if ((mType.mElement.mType == Element.DataType.SIGNED_16) || 306 (mType.mElement.mType == Element.DataType.UNSIGNED_16)) { 307 return; 308 } 309 throw new RSIllegalArgumentException( 310 "16 bit integer source does not match allocation type " + mType.mElement.mType); 311 } 312 313 private void validateIsInt8() { 314 if ((mType.mElement.mType == Element.DataType.SIGNED_8) || 315 (mType.mElement.mType == Element.DataType.UNSIGNED_8)) { 316 return; 317 } 318 throw new RSIllegalArgumentException( 319 "8 bit integer source does not match allocation type " + mType.mElement.mType); 320 } 321 322 private void validateIsFloat32() { 323 if (mType.mElement.mType == Element.DataType.FLOAT_32) { 324 return; 325 } 326 throw new RSIllegalArgumentException( 327 "32 bit float source does not match allocation type " + mType.mElement.mType); 328 } 329 330 private void validateIsObject() { 331 if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) || 332 (mType.mElement.mType == Element.DataType.RS_TYPE) || 333 (mType.mElement.mType == Element.DataType.RS_ALLOCATION) || 334 (mType.mElement.mType == Element.DataType.RS_SAMPLER) || 335 (mType.mElement.mType == Element.DataType.RS_SCRIPT) || 336 (mType.mElement.mType == Element.DataType.RS_MESH) || 337 (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) || 338 (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) || 339 (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) || 340 (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) { 341 return; 342 } 343 throw new RSIllegalArgumentException( 344 "Object source does not match allocation type " + mType.mElement.mType); 345 } 346 347 @Override 348 void updateFromNative() { 349 super.updateFromNative(); 350 long typeID = mRS.nAllocationGetType(getID(mRS)); 351 if(typeID != 0) { 352 mType = new Type(typeID, mRS); 353 mType.updateFromNative(); 354 updateCacheInfo(mType); 355 } 356 } 357 358 /** 359 * Get the {@link android.renderscript.Type} of the Allocation. 360 * 361 * @return Type 362 * 363 */ 364 public Type getType() { 365 return mType; 366 } 367 368 /** 369 * Propagate changes from one usage of the Allocation to the 370 * other usages of the Allocation. 371 * 372 */ 373 public void syncAll(int srcLocation) { 374 Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll"); 375 switch (srcLocation) { 376 case USAGE_GRAPHICS_TEXTURE: 377 case USAGE_SCRIPT: 378 if ((mUsage & USAGE_SHARED) != 0) { 379 copyFrom(mBitmap); 380 } 381 break; 382 case USAGE_GRAPHICS_CONSTANTS: 383 case USAGE_GRAPHICS_VERTEX: 384 break; 385 case USAGE_SHARED: 386 if ((mUsage & USAGE_SHARED) != 0) { 387 copyTo(mBitmap); 388 } 389 break; 390 default: 391 throw new RSIllegalArgumentException("Source must be exactly one usage type."); 392 } 393 mRS.validate(); 394 mRS.nAllocationSyncAll(getIDSafe(), srcLocation); 395 Trace.traceEnd(RenderScript.TRACE_TAG); 396 } 397 398 /** 399 * Send a buffer to the output stream. The contents of the Allocation will 400 * be undefined after this operation. This operation is only valid if {@link 401 * #USAGE_IO_OUTPUT} is set on the Allocation. 402 * 403 * 404 */ 405 public void ioSend() { 406 Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend"); 407 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 408 throw new RSIllegalArgumentException( 409 "Can only send buffer if IO_OUTPUT usage specified."); 410 } 411 mRS.validate(); 412 mRS.nAllocationIoSend(getID(mRS)); 413 Trace.traceEnd(RenderScript.TRACE_TAG); 414 } 415 416 /** 417 * Receive the latest input into the Allocation. This operation 418 * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation. 419 * 420 */ 421 public void ioReceive() { 422 Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive"); 423 if ((mUsage & USAGE_IO_INPUT) == 0) { 424 throw new RSIllegalArgumentException( 425 "Can only receive if IO_INPUT usage specified."); 426 } 427 mRS.validate(); 428 mRS.nAllocationIoReceive(getID(mRS)); 429 Trace.traceEnd(RenderScript.TRACE_TAG); 430 } 431 432 /** 433 * Copy an array of RS objects to the Allocation. 434 * 435 * @param d Source array. 436 */ 437 public void copyFrom(BaseObj[] d) { 438 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 439 mRS.validate(); 440 validateIsObject(); 441 if (d.length != mCurrentCount) { 442 throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + 443 mCurrentCount + ", array length = " + d.length); 444 } 445 // FIXME: requires 64-bit path 446 447 int i[] = new int[d.length]; 448 for (int ct=0; ct < d.length; ct++) { 449 i[ct] = (int)d[ct].getID(mRS); 450 } 451 copy1DRangeFromUnchecked(0, mCurrentCount, i); 452 Trace.traceEnd(RenderScript.TRACE_TAG); 453 } 454 455 private void validateBitmapFormat(Bitmap b) { 456 Bitmap.Config bc = b.getConfig(); 457 if (bc == null) { 458 throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation"); 459 } 460 switch (bc) { 461 case ALPHA_8: 462 if (mType.getElement().mKind != Element.DataKind.PIXEL_A) { 463 throw new RSIllegalArgumentException("Allocation kind is " + 464 mType.getElement().mKind + ", type " + 465 mType.getElement().mType + 466 " of " + mType.getElement().getBytesSize() + 467 " bytes, passed bitmap was " + bc); 468 } 469 break; 470 case ARGB_8888: 471 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 472 (mType.getElement().getBytesSize() != 4)) { 473 throw new RSIllegalArgumentException("Allocation kind is " + 474 mType.getElement().mKind + ", type " + 475 mType.getElement().mType + 476 " of " + mType.getElement().getBytesSize() + 477 " bytes, passed bitmap was " + bc); 478 } 479 break; 480 case RGB_565: 481 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) || 482 (mType.getElement().getBytesSize() != 2)) { 483 throw new RSIllegalArgumentException("Allocation kind is " + 484 mType.getElement().mKind + ", type " + 485 mType.getElement().mType + 486 " of " + mType.getElement().getBytesSize() + 487 " bytes, passed bitmap was " + bc); 488 } 489 break; 490 case ARGB_4444: 491 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 492 (mType.getElement().getBytesSize() != 2)) { 493 throw new RSIllegalArgumentException("Allocation kind is " + 494 mType.getElement().mKind + ", type " + 495 mType.getElement().mType + 496 " of " + mType.getElement().getBytesSize() + 497 " bytes, passed bitmap was " + bc); 498 } 499 break; 500 501 } 502 } 503 504 private void validateBitmapSize(Bitmap b) { 505 if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) { 506 throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); 507 } 508 } 509 510 /** 511 * Copy into this Allocation from an array. This method does not guarantee 512 * that the Allocation is compatible with the input buffer; it copies memory 513 * without reinterpretation. 514 * 515 * @param d the source data array 516 */ 517 public void copyFromUnchecked(int[] d) { 518 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked"); 519 mRS.validate(); 520 if (mCurrentDimZ > 0) { 521 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 522 } else if (mCurrentDimY > 0) { 523 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 524 } else { 525 copy1DRangeFromUnchecked(0, mCurrentCount, d); 526 } 527 Trace.traceEnd(RenderScript.TRACE_TAG); 528 } 529 530 /** 531 * Copy into this Allocation from an array. This method does not guarantee 532 * that the Allocation is compatible with the input buffer; it copies memory 533 * without reinterpretation. 534 * 535 * @param d the source data array 536 */ 537 public void copyFromUnchecked(short[] d) { 538 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked"); 539 mRS.validate(); 540 if (mCurrentDimZ > 0) { 541 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 542 } else if (mCurrentDimY > 0) { 543 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 544 } else { 545 copy1DRangeFromUnchecked(0, mCurrentCount, d); 546 } 547 Trace.traceEnd(RenderScript.TRACE_TAG); 548 } 549 550 /** 551 * Copy into this Allocation from an array. This method does not guarantee 552 * that the Allocation is compatible with the input buffer; it copies memory 553 * without reinterpretation. 554 * 555 * @param d the source data array 556 */ 557 public void copyFromUnchecked(byte[] d) { 558 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked"); 559 mRS.validate(); 560 if (mCurrentDimZ > 0) { 561 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 562 } else if (mCurrentDimY > 0) { 563 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 564 } else { 565 copy1DRangeFromUnchecked(0, mCurrentCount, d); 566 } 567 Trace.traceEnd(RenderScript.TRACE_TAG); 568 } 569 570 /** 571 * Copy into this Allocation from an array. This method does not guarantee 572 * that the Allocation is compatible with the input buffer; it copies memory 573 * without reinterpretation. 574 * 575 * @param d the source data array 576 */ 577 public void copyFromUnchecked(float[] d) { 578 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked"); 579 mRS.validate(); 580 if (mCurrentDimZ > 0) { 581 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 582 } else if (mCurrentDimY > 0) { 583 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d); 584 } else { 585 copy1DRangeFromUnchecked(0, mCurrentCount, d); 586 } 587 Trace.traceEnd(RenderScript.TRACE_TAG); 588 } 589 590 591 /** 592 * Copy into this Allocation from an array. This variant is type checked 593 * and will generate exceptions if the Allocation's {@link 594 * android.renderscript.Element} is not a 32 bit integer type. 595 * 596 * @param d the source data array 597 */ 598 public void copyFrom(int[] d) { 599 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 600 mRS.validate(); 601 if (mCurrentDimZ > 0) { 602 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 603 } else if (mCurrentDimY > 0) { 604 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 605 } else { 606 copy1DRangeFrom(0, mCurrentCount, d); 607 } 608 Trace.traceEnd(RenderScript.TRACE_TAG); 609 } 610 611 /** 612 * Copy into this Allocation from an array. This variant is type checked 613 * and will generate exceptions if the Allocation's {@link 614 * android.renderscript.Element} is not a 16 bit integer type. 615 * 616 * @param d the source data array 617 */ 618 public void copyFrom(short[] d) { 619 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 620 mRS.validate(); 621 if (mCurrentDimZ > 0) { 622 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 623 } else if (mCurrentDimY > 0) { 624 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 625 } else { 626 copy1DRangeFrom(0, mCurrentCount, d); 627 } 628 Trace.traceEnd(RenderScript.TRACE_TAG); 629 } 630 631 /** 632 * Copy into this Allocation from an array. This variant is type checked 633 * and will generate exceptions if the Allocation's {@link 634 * android.renderscript.Element} is not an 8 bit integer type. 635 * 636 * @param d the source data array 637 */ 638 public void copyFrom(byte[] d) { 639 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 640 mRS.validate(); 641 if (mCurrentDimZ > 0) { 642 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 643 } else if (mCurrentDimY > 0) { 644 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 645 } else { 646 copy1DRangeFrom(0, mCurrentCount, d); 647 } 648 Trace.traceEnd(RenderScript.TRACE_TAG); 649 } 650 651 /** 652 * Copy into this Allocation from an array. This variant is type checked 653 * and will generate exceptions if the Allocation's {@link 654 * android.renderscript.Element} is not a 32 bit float type. 655 * 656 * @param d the source data array 657 */ 658 public void copyFrom(float[] d) { 659 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 660 mRS.validate(); 661 if (mCurrentDimZ > 0) { 662 copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d); 663 } else if (mCurrentDimY > 0) { 664 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d); 665 } else { 666 copy1DRangeFrom(0, mCurrentCount, d); 667 } 668 Trace.traceEnd(RenderScript.TRACE_TAG); 669 } 670 671 /** 672 * Copy into an Allocation from a {@link android.graphics.Bitmap}. The 673 * height, width, and format of the bitmap must match the existing 674 * allocation. 675 * 676 * <p>If the {@link android.graphics.Bitmap} is the same as the {@link 677 * android.graphics.Bitmap} used to create the Allocation with {@link 678 * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation, 679 * this will synchronize the Allocation with the latest data from the {@link 680 * android.graphics.Bitmap}, potentially avoiding the actual copy.</p> 681 * 682 * @param b the source bitmap 683 */ 684 public void copyFrom(Bitmap b) { 685 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 686 mRS.validate(); 687 if (b.getConfig() == null) { 688 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 689 Canvas c = new Canvas(newBitmap); 690 c.drawBitmap(b, 0, 0, null); 691 copyFrom(newBitmap); 692 return; 693 } 694 validateBitmapSize(b); 695 validateBitmapFormat(b); 696 mRS.nAllocationCopyFromBitmap(getID(mRS), b); 697 Trace.traceEnd(RenderScript.TRACE_TAG); 698 } 699 700 /** 701 * Copy an Allocation from an Allocation. The types of both allocations 702 * must be identical. 703 * 704 * @param a the source allocation 705 */ 706 public void copyFrom(Allocation a) { 707 Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom"); 708 mRS.validate(); 709 if (!mType.equals(a.getType())) { 710 throw new RSIllegalArgumentException("Types of allocations must match."); 711 } 712 copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0); 713 Trace.traceEnd(RenderScript.TRACE_TAG); 714 } 715 716 /** 717 * This is only intended to be used by auto-generated code reflected from 718 * the RenderScript script files and should not be used by developers. 719 * 720 * @param xoff 721 * @param fp 722 */ 723 public void setFromFieldPacker(int xoff, FieldPacker fp) { 724 mRS.validate(); 725 int eSize = mType.mElement.getBytesSize(); 726 final byte[] data = fp.getData(); 727 728 int count = data.length / eSize; 729 if ((eSize * count) != data.length) { 730 throw new RSIllegalArgumentException("Field packer length " + data.length + 731 " not divisible by element size " + eSize + "."); 732 } 733 copy1DRangeFromUnchecked(xoff, count, data); 734 } 735 736 /** 737 * This is only intended to be used by auto-generated code reflected from 738 * the RenderScript script files. 739 * 740 * @param xoff 741 * @param component_number 742 * @param fp 743 */ 744 public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) { 745 mRS.validate(); 746 if (component_number >= mType.mElement.mElements.length) { 747 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 748 } 749 if(xoff < 0) { 750 throw new RSIllegalArgumentException("Offset must be >= 0."); 751 } 752 753 final byte[] data = fp.getData(); 754 int eSize = mType.mElement.mElements[component_number].getBytesSize(); 755 eSize *= mType.mElement.mArraySizes[component_number]; 756 757 if (data.length != eSize) { 758 throw new RSIllegalArgumentException("Field packer sizelength " + data.length + 759 " does not match component size " + eSize + "."); 760 } 761 762 mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD, 763 component_number, data, data.length); 764 } 765 766 private void data1DChecks(int off, int count, int len, int dataSize) { 767 mRS.validate(); 768 if(off < 0) { 769 throw new RSIllegalArgumentException("Offset must be >= 0."); 770 } 771 if(count < 1) { 772 throw new RSIllegalArgumentException("Count must be >= 1."); 773 } 774 if((off + count) > mCurrentCount) { 775 throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount + 776 ", got " + count + " at offset " + off + "."); 777 } 778 if(len < dataSize) { 779 throw new RSIllegalArgumentException("Array too small for allocation type."); 780 } 781 } 782 783 /** 784 * Generate a mipmap chain. This is only valid if the Type of the Allocation 785 * includes mipmaps. 786 * 787 * <p>This function will generate a complete set of mipmaps from the top 788 * level LOD and place them into the script memory space.</p> 789 * 790 * <p>If the Allocation is also using other memory spaces, a call to {@link 791 * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p> 792 */ 793 public void generateMipmaps() { 794 mRS.nAllocationGenerateMipmaps(getID(mRS)); 795 } 796 797 /** 798 * Copy an array into part of this Allocation. This method does not 799 * guarantee that the Allocation is compatible with the input buffer. 800 * 801 * @param off The offset of the first element to be copied. 802 * @param count The number of elements to be copied. 803 * @param d the source data array 804 */ 805 public void copy1DRangeFromUnchecked(int off, int count, int[] d) { 806 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked"); 807 int dataSize = mType.mElement.getBytesSize() * count; 808 data1DChecks(off, count, d.length * 4, dataSize); 809 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.SIGNED_32); 810 Trace.traceEnd(RenderScript.TRACE_TAG); 811 } 812 813 /** 814 * Copy an array into part of this Allocation. This method does not 815 * guarantee that the Allocation is compatible with the input buffer. 816 * 817 * @param off The offset of the first element to be copied. 818 * @param count The number of elements to be copied. 819 * @param d the source data array 820 */ 821 public void copy1DRangeFromUnchecked(int off, int count, short[] d) { 822 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked"); 823 int dataSize = mType.mElement.getBytesSize() * count; 824 data1DChecks(off, count, d.length * 2, dataSize); 825 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.SIGNED_16); 826 Trace.traceEnd(RenderScript.TRACE_TAG); 827 } 828 829 /** 830 * Copy an array into part of this Allocation. This method does not 831 * guarantee that the Allocation is compatible with the input buffer. 832 * 833 * @param off The offset of the first element to be copied. 834 * @param count The number of elements to be copied. 835 * @param d the source data array 836 */ 837 public void copy1DRangeFromUnchecked(int off, int count, byte[] d) { 838 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked"); 839 int dataSize = mType.mElement.getBytesSize() * count; 840 data1DChecks(off, count, d.length, dataSize); 841 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.SIGNED_8); 842 Trace.traceEnd(RenderScript.TRACE_TAG); 843 } 844 845 /** 846 * Copy an array into part of this Allocation. This method does not 847 * guarantee that the Allocation is compatible with the input buffer. 848 * 849 * @param off The offset of the first element to be copied. 850 * @param count The number of elements to be copied. 851 * @param d the source data array 852 */ 853 public void copy1DRangeFromUnchecked(int off, int count, float[] d) { 854 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked"); 855 int dataSize = mType.mElement.getBytesSize() * count; 856 data1DChecks(off, count, d.length * 4, dataSize); 857 mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.FLOAT_32); 858 Trace.traceEnd(RenderScript.TRACE_TAG); 859 } 860 861 /** 862 * Copy an array into part of this Allocation. This variant is type checked 863 * and will generate exceptions if the Allocation type is not a 32 bit 864 * integer type. 865 * 866 * @param off The offset of the first element to be copied. 867 * @param count The number of elements to be copied. 868 * @param d the source data array 869 */ 870 public void copy1DRangeFrom(int off, int count, int[] d) { 871 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom"); 872 validateIsInt32(); 873 copy1DRangeFromUnchecked(off, count, d); 874 Trace.traceEnd(RenderScript.TRACE_TAG); 875 } 876 877 /** 878 * Copy an array into part of this Allocation. This variant is type checked 879 * and will generate exceptions if the Allocation type is not a 16 bit 880 * integer type. 881 * 882 * @param off The offset of the first element to be copied. 883 * @param count The number of elements to be copied. 884 * @param d the source data array 885 */ 886 public void copy1DRangeFrom(int off, int count, short[] d) { 887 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom"); 888 validateIsInt16(); 889 copy1DRangeFromUnchecked(off, count, d); 890 Trace.traceEnd(RenderScript.TRACE_TAG); 891 } 892 893 /** 894 * Copy an array into part of this Allocation. This variant is type checked 895 * and will generate exceptions if the Allocation type is not an 8 bit 896 * integer type. 897 * 898 * @param off The offset of the first element to be copied. 899 * @param count The number of elements to be copied. 900 * @param d the source data array 901 */ 902 public void copy1DRangeFrom(int off, int count, byte[] d) { 903 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom"); 904 validateIsInt8(); 905 copy1DRangeFromUnchecked(off, count, d); 906 Trace.traceEnd(RenderScript.TRACE_TAG); 907 } 908 909 /** 910 * Copy an array into part of this Allocation. This variant is type checked 911 * and will generate exceptions if the Allocation type is not a 32 bit float 912 * type. 913 * 914 * @param off The offset of the first element to be copied. 915 * @param count The number of elements to be copied. 916 * @param d the source data array. 917 */ 918 public void copy1DRangeFrom(int off, int count, float[] d) { 919 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom"); 920 validateIsFloat32(); 921 copy1DRangeFromUnchecked(off, count, d); 922 Trace.traceEnd(RenderScript.TRACE_TAG); 923 } 924 /** 925 * Copy part of an Allocation into this Allocation. 926 * 927 * @param off The offset of the first element to be copied. 928 * @param count The number of elements to be copied. 929 * @param data the source data allocation. 930 * @param dataOff off The offset of the first element in data to 931 * be copied. 932 */ 933 public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) { 934 Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom"); 935 mRS.nAllocationData2D(getIDSafe(), off, 0, 936 mSelectedLOD, mSelectedFace.mID, 937 count, 1, data.getID(mRS), dataOff, 0, 938 data.mSelectedLOD, data.mSelectedFace.mID); 939 } 940 941 private void validate2DRange(int xoff, int yoff, int w, int h) { 942 if (mAdaptedAllocation != null) { 943 944 } else { 945 946 if (xoff < 0 || yoff < 0) { 947 throw new RSIllegalArgumentException("Offset cannot be negative."); 948 } 949 if (h < 0 || w < 0) { 950 throw new RSIllegalArgumentException("Height or width cannot be negative."); 951 } 952 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 953 throw new RSIllegalArgumentException("Updated region larger than allocation."); 954 } 955 } 956 } 957 958 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, byte[] data) { 959 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked"); 960 mRS.validate(); 961 validate2DRange(xoff, yoff, w, h); 962 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 963 w, h, data, data.length, Element.DataType.SIGNED_8); 964 Trace.traceEnd(RenderScript.TRACE_TAG); 965 } 966 967 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, short[] data) { 968 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked"); 969 mRS.validate(); 970 validate2DRange(xoff, yoff, w, h); 971 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 972 w, h, data, data.length * 2, Element.DataType.SIGNED_16); 973 Trace.traceEnd(RenderScript.TRACE_TAG); 974 } 975 976 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, int[] data) { 977 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked"); 978 mRS.validate(); 979 validate2DRange(xoff, yoff, w, h); 980 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 981 w, h, data, data.length * 4, Element.DataType.SIGNED_32); 982 Trace.traceEnd(RenderScript.TRACE_TAG); 983 } 984 985 void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, float[] data) { 986 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked"); 987 mRS.validate(); 988 validate2DRange(xoff, yoff, w, h); 989 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, 990 w, h, data, data.length * 4, Element.DataType.FLOAT_32); 991 Trace.traceEnd(RenderScript.TRACE_TAG); 992 } 993 994 /** 995 * Copy from an array into a rectangular region in this Allocation. The 996 * array is assumed to be tightly packed. 997 * 998 * @param xoff X offset of the region to update in this Allocation 999 * @param yoff Y offset of the region to update in this Allocation 1000 * @param w Width of the region to update 1001 * @param h Height of the region to update 1002 * @param data to be placed into the Allocation 1003 */ 1004 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { 1005 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1006 validateIsInt8(); 1007 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 1008 Trace.traceEnd(RenderScript.TRACE_TAG); 1009 } 1010 1011 /** 1012 * Copy from an array into a rectangular region in this Allocation. The 1013 * array is assumed to be tightly packed. 1014 * 1015 * @param xoff X offset of the region to update in this Allocation 1016 * @param yoff Y offset of the region to update in this Allocation 1017 * @param w Width of the region to update 1018 * @param h Height of the region to update 1019 * @param data to be placed into the Allocation 1020 */ 1021 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) { 1022 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1023 validateIsInt16(); 1024 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 1025 Trace.traceEnd(RenderScript.TRACE_TAG); 1026 } 1027 1028 /** 1029 * Copy from an array into a rectangular region in this Allocation. The 1030 * array is assumed to be tightly packed. 1031 * 1032 * @param xoff X offset of the region to update in this Allocation 1033 * @param yoff Y offset of the region to update in this Allocation 1034 * @param w Width of the region to update 1035 * @param h Height of the region to update 1036 * @param data to be placed into the Allocation 1037 */ 1038 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) { 1039 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1040 validateIsInt32(); 1041 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 1042 Trace.traceEnd(RenderScript.TRACE_TAG); 1043 } 1044 1045 /** 1046 * Copy from an array into a rectangular region in this Allocation. The 1047 * array is assumed to be tightly packed. 1048 * 1049 * @param xoff X offset of the region to update in this Allocation 1050 * @param yoff Y offset of the region to update in this Allocation 1051 * @param w Width of the region to update 1052 * @param h Height of the region to update 1053 * @param data to be placed into the Allocation 1054 */ 1055 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) { 1056 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1057 validateIsFloat32(); 1058 copy2DRangeFromUnchecked(xoff, yoff, w, h, data); 1059 Trace.traceEnd(RenderScript.TRACE_TAG); 1060 } 1061 1062 /** 1063 * Copy a rectangular region from an Allocation into a rectangular region in 1064 * this Allocation. 1065 * 1066 * @param xoff X offset of the region in this Allocation 1067 * @param yoff Y offset of the region in this Allocation 1068 * @param w Width of the region to update. 1069 * @param h Height of the region to update. 1070 * @param data source Allocation. 1071 * @param dataXoff X offset in source Allocation 1072 * @param dataYoff Y offset in source Allocation 1073 */ 1074 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, 1075 Allocation data, int dataXoff, int dataYoff) { 1076 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1077 mRS.validate(); 1078 validate2DRange(xoff, yoff, w, h); 1079 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, 1080 mSelectedLOD, mSelectedFace.mID, 1081 w, h, data.getID(mRS), dataXoff, dataYoff, 1082 data.mSelectedLOD, data.mSelectedFace.mID); 1083 Trace.traceEnd(RenderScript.TRACE_TAG); 1084 } 1085 1086 /** 1087 * Copy a {@link android.graphics.Bitmap} into an Allocation. The height 1088 * and width of the update will use the height and width of the {@link 1089 * android.graphics.Bitmap}. 1090 * 1091 * @param xoff X offset of the region to update in this Allocation 1092 * @param yoff Y offset of the region to update in this Allocation 1093 * @param data the Bitmap to be copied 1094 */ 1095 public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) { 1096 Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom"); 1097 mRS.validate(); 1098 if (data.getConfig() == null) { 1099 Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888); 1100 Canvas c = new Canvas(newBitmap); 1101 c.drawBitmap(data, 0, 0, null); 1102 copy2DRangeFrom(xoff, yoff, newBitmap); 1103 return; 1104 } 1105 validateBitmapFormat(data); 1106 validate2DRange(xoff, yoff, data.getWidth(), data.getHeight()); 1107 mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data); 1108 Trace.traceEnd(RenderScript.TRACE_TAG); 1109 } 1110 1111 private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) { 1112 if (mAdaptedAllocation != null) { 1113 1114 } else { 1115 1116 if (xoff < 0 || yoff < 0 || zoff < 0) { 1117 throw new RSIllegalArgumentException("Offset cannot be negative."); 1118 } 1119 if (h < 0 || w < 0 || d < 0) { 1120 throw new RSIllegalArgumentException("Height or width cannot be negative."); 1121 } 1122 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) { 1123 throw new RSIllegalArgumentException("Updated region larger than allocation."); 1124 } 1125 } 1126 } 1127 1128 /** 1129 * @hide 1130 * 1131 */ 1132 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) { 1133 mRS.validate(); 1134 validate3DRange(xoff, yoff, zoff, w, h, d); 1135 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1136 w, h, d, data, data.length, Element.DataType.SIGNED_8); 1137 } 1138 1139 /** 1140 * @hide 1141 * 1142 */ 1143 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) { 1144 mRS.validate(); 1145 validate3DRange(xoff, yoff, zoff, w, h, d); 1146 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1147 w, h, d, data, data.length * 2, Element.DataType.SIGNED_16); 1148 } 1149 1150 /** 1151 * @hide 1152 * 1153 */ 1154 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) { 1155 mRS.validate(); 1156 validate3DRange(xoff, yoff, zoff, w, h, d); 1157 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1158 w, h, d, data, data.length * 4, Element.DataType.SIGNED_32); 1159 } 1160 1161 /** 1162 * @hide 1163 * 1164 */ 1165 void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) { 1166 mRS.validate(); 1167 validate3DRange(xoff, yoff, zoff, w, h, d); 1168 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1169 w, h, d, data, data.length * 4, Element.DataType.FLOAT_32); 1170 } 1171 1172 1173 /** 1174 * @hide 1175 * Copy a rectangular region from the array into the allocation. 1176 * The array is assumed to be tightly packed. 1177 * 1178 * @param xoff X offset of the region to update in this Allocation 1179 * @param yoff Y offset of the region to update in this Allocation 1180 * @param zoff Z offset of the region to update in this Allocation 1181 * @param w Width of the region to update 1182 * @param h Height of the region to update 1183 * @param d Depth of the region to update 1184 * @param data to be placed into the allocation 1185 */ 1186 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) { 1187 validateIsInt8(); 1188 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1189 } 1190 1191 /** 1192 * @hide 1193 * 1194 */ 1195 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) { 1196 validateIsInt16(); 1197 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1198 } 1199 1200 /** 1201 * @hide 1202 * 1203 */ 1204 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) { 1205 validateIsInt32(); 1206 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1207 } 1208 1209 /** 1210 * @hide 1211 * 1212 */ 1213 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) { 1214 validateIsFloat32(); 1215 copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data); 1216 } 1217 1218 /** 1219 * @hide 1220 * Copy a rectangular region into the allocation from another 1221 * allocation. 1222 * 1223 * @param xoff X offset of the region to update in this Allocation 1224 * @param yoff Y offset of the region to update in this Allocation 1225 * @param zoff Z offset of the region to update in this Allocation 1226 * @param w Width of the region to update. 1227 * @param h Height of the region to update. 1228 * @param d Depth of the region to update. 1229 * @param data source allocation. 1230 * @param dataXoff X offset of the region in the source Allocation 1231 * @param dataYoff Y offset of the region in the source Allocation 1232 * @param dataZoff Z offset of the region in the source Allocation 1233 */ 1234 public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, 1235 Allocation data, int dataXoff, int dataYoff, int dataZoff) { 1236 mRS.validate(); 1237 validate3DRange(xoff, yoff, zoff, w, h, d); 1238 mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, 1239 w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff, 1240 data.mSelectedLOD); 1241 } 1242 1243 1244 /** 1245 * Copy from the Allocation into a {@link android.graphics.Bitmap}. The 1246 * bitmap must match the dimensions of the Allocation. 1247 * 1248 * @param b The bitmap to be set from the Allocation. 1249 */ 1250 public void copyTo(Bitmap b) { 1251 Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); 1252 mRS.validate(); 1253 validateBitmapFormat(b); 1254 validateBitmapSize(b); 1255 mRS.nAllocationCopyToBitmap(getID(mRS), b); 1256 Trace.traceEnd(RenderScript.TRACE_TAG); 1257 } 1258 1259 /** 1260 * Copy from the Allocation into a byte array. The array must be at least 1261 * as large as the Allocation. The allocation must be of an 8 bit integer 1262 * {@link android.renderscript.Element} type. 1263 * 1264 * @param d The array to be set from the Allocation. 1265 */ 1266 public void copyTo(byte[] d) { 1267 Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); 1268 validateIsInt8(); 1269 mRS.validate(); 1270 mRS.nAllocationRead(getID(mRS), d, Element.DataType.SIGNED_8); 1271 Trace.traceEnd(RenderScript.TRACE_TAG); 1272 } 1273 1274 /** 1275 * Copy from the Allocation into a short array. The array must be at least 1276 * as large as the Allocation. The allocation must be of an 16 bit integer 1277 * {@link android.renderscript.Element} type. 1278 * 1279 * @param d The array to be set from the Allocation. 1280 */ 1281 public void copyTo(short[] d) { 1282 Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); 1283 validateIsInt16(); 1284 mRS.validate(); 1285 mRS.nAllocationRead(getID(mRS), d, Element.DataType.SIGNED_16); 1286 Trace.traceEnd(RenderScript.TRACE_TAG); 1287 } 1288 1289 /** 1290 * Copy from the Allocation into a int array. The array must be at least as 1291 * large as the Allocation. The allocation must be of an 32 bit integer 1292 * {@link android.renderscript.Element} type. 1293 * 1294 * @param d The array to be set from the Allocation. 1295 */ 1296 public void copyTo(int[] d) { 1297 Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); 1298 validateIsInt32(); 1299 mRS.validate(); 1300 mRS.nAllocationRead(getID(mRS), d, Element.DataType.SIGNED_32); 1301 Trace.traceEnd(RenderScript.TRACE_TAG); 1302 } 1303 1304 /** 1305 * Copy from the Allocation into a float array. The array must be at least 1306 * as large as the Allocation. The allocation must be of an 32 bit float 1307 * {@link android.renderscript.Element} type. 1308 * 1309 * @param d The array to be set from the Allocation. 1310 */ 1311 public void copyTo(float[] d) { 1312 Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo"); 1313 validateIsFloat32(); 1314 mRS.validate(); 1315 mRS.nAllocationRead(getID(mRS), d, Element.DataType.FLOAT_32); 1316 Trace.traceEnd(RenderScript.TRACE_TAG); 1317 } 1318 1319 /** 1320 * Resize a 1D allocation. The contents of the allocation are preserved. 1321 * If new elements are allocated objects are created with null contents and 1322 * the new region is otherwise undefined. 1323 * 1324 * <p>If the new region is smaller the references of any objects outside the 1325 * new region will be released.</p> 1326 * 1327 * <p>A new type will be created with the new dimension.</p> 1328 * 1329 * @param dimX The new size of the allocation. 1330 * 1331 * @deprecated RenderScript objects should be immutable once created. The 1332 * replacement is to create a new allocation and copy the contents. 1333 */ 1334 public synchronized void resize(int dimX) { 1335 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 1336 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 1337 } 1338 mRS.nAllocationResize1D(getID(mRS), dimX); 1339 mRS.finish(); // Necessary because resize is fifoed and update is async. 1340 1341 long typeID = mRS.nAllocationGetType(getID(mRS)); 1342 mType = new Type(typeID, mRS); 1343 mType.updateFromNative(); 1344 updateCacheInfo(mType); 1345 } 1346 1347 1348 // creation 1349 1350 static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 1351 static { 1352 mBitmapOptions.inScaled = false; 1353 } 1354 1355 /** 1356 * Creates a new Allocation with the given {@link 1357 * android.renderscript.Type}, mipmap flag, and usage flags. 1358 * 1359 * @param type RenderScript type describing data layout 1360 * @param mips specifies desired mipmap behaviour for the 1361 * allocation 1362 * @param usage bit field specifying how the Allocation is 1363 * utilized 1364 */ 1365 static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) { 1366 Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped"); 1367 rs.validate(); 1368 if (type.getID(rs) == 0) { 1369 throw new RSInvalidStateException("Bad Type"); 1370 } 1371 long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0); 1372 if (id == 0) { 1373 throw new RSRuntimeException("Allocation creation failed."); 1374 } 1375 Trace.traceEnd(RenderScript.TRACE_TAG); 1376 return new Allocation(id, rs, type, usage); 1377 } 1378 1379 /** 1380 * Creates an Allocation with the size specified by the type and no mipmaps 1381 * generated by default 1382 * 1383 * @param rs Context to which the allocation will belong. 1384 * @param type renderscript type describing data layout 1385 * @param usage bit field specifying how the allocation is 1386 * utilized 1387 * 1388 * @return allocation 1389 */ 1390 static public Allocation createTyped(RenderScript rs, Type type, int usage) { 1391 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage); 1392 } 1393 1394 /** 1395 * Creates an Allocation for use by scripts with a given {@link 1396 * android.renderscript.Type} and no mipmaps 1397 * 1398 * @param rs Context to which the Allocation will belong. 1399 * @param type RenderScript Type describing data layout 1400 * 1401 * @return allocation 1402 */ 1403 static public Allocation createTyped(RenderScript rs, Type type) { 1404 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT); 1405 } 1406 1407 /** 1408 * Creates an Allocation with a specified number of given elements 1409 * 1410 * @param rs Context to which the Allocation will belong. 1411 * @param e Element to use in the Allocation 1412 * @param count the number of Elements in the Allocation 1413 * @param usage bit field specifying how the Allocation is 1414 * utilized 1415 * 1416 * @return allocation 1417 */ 1418 static public Allocation createSized(RenderScript rs, Element e, 1419 int count, int usage) { 1420 Trace.traceBegin(RenderScript.TRACE_TAG, "createSized"); 1421 rs.validate(); 1422 Type.Builder b = new Type.Builder(rs, e); 1423 b.setX(count); 1424 Type t = b.create(); 1425 1426 long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0); 1427 if (id == 0) { 1428 throw new RSRuntimeException("Allocation creation failed."); 1429 } 1430 Trace.traceEnd(RenderScript.TRACE_TAG); 1431 return new Allocation(id, rs, t, usage); 1432 } 1433 1434 /** 1435 * Creates an Allocation with a specified number of given elements 1436 * 1437 * @param rs Context to which the Allocation will belong. 1438 * @param e Element to use in the Allocation 1439 * @param count the number of Elements in the Allocation 1440 * 1441 * @return allocation 1442 */ 1443 static public Allocation createSized(RenderScript rs, Element e, int count) { 1444 return createSized(rs, e, count, USAGE_SCRIPT); 1445 } 1446 1447 static Element elementFromBitmap(RenderScript rs, Bitmap b) { 1448 final Bitmap.Config bc = b.getConfig(); 1449 if (bc == Bitmap.Config.ALPHA_8) { 1450 return Element.A_8(rs); 1451 } 1452 if (bc == Bitmap.Config.ARGB_4444) { 1453 return Element.RGBA_4444(rs); 1454 } 1455 if (bc == Bitmap.Config.ARGB_8888) { 1456 return Element.RGBA_8888(rs); 1457 } 1458 if (bc == Bitmap.Config.RGB_565) { 1459 return Element.RGB_565(rs); 1460 } 1461 throw new RSInvalidStateException("Bad bitmap type: " + bc); 1462 } 1463 1464 static Type typeFromBitmap(RenderScript rs, Bitmap b, 1465 MipmapControl mip) { 1466 Element e = elementFromBitmap(rs, b); 1467 Type.Builder tb = new Type.Builder(rs, e); 1468 tb.setX(b.getWidth()); 1469 tb.setY(b.getHeight()); 1470 tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); 1471 return tb.create(); 1472 } 1473 1474 /** 1475 * Creates an Allocation from a {@link android.graphics.Bitmap}. 1476 * 1477 * @param rs Context to which the allocation will belong. 1478 * @param b Bitmap source for the allocation data 1479 * @param mips specifies desired mipmap behaviour for the 1480 * allocation 1481 * @param usage bit field specifying how the allocation is 1482 * utilized 1483 * 1484 * @return Allocation containing bitmap data 1485 * 1486 */ 1487 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 1488 MipmapControl mips, 1489 int usage) { 1490 Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap"); 1491 rs.validate(); 1492 1493 // WAR undocumented color formats 1494 if (b.getConfig() == null) { 1495 if ((usage & USAGE_SHARED) != 0) { 1496 throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config."); 1497 } 1498 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 1499 Canvas c = new Canvas(newBitmap); 1500 c.drawBitmap(b, 0, 0, null); 1501 return createFromBitmap(rs, newBitmap, mips, usage); 1502 } 1503 1504 Type t = typeFromBitmap(rs, b, mips); 1505 1506 // enable optimized bitmap path only with no mipmap and script-only usage 1507 if (mips == MipmapControl.MIPMAP_NONE && 1508 t.getElement().isCompatible(Element.RGBA_8888(rs)) && 1509 usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) { 1510 long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage); 1511 if (id == 0) { 1512 throw new RSRuntimeException("Load failed."); 1513 } 1514 1515 // keep a reference to the Bitmap around to prevent GC 1516 Allocation alloc = new Allocation(id, rs, t, usage); 1517 alloc.setBitmap(b); 1518 return alloc; 1519 } 1520 1521 1522 long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1523 if (id == 0) { 1524 throw new RSRuntimeException("Load failed."); 1525 } 1526 Trace.traceEnd(RenderScript.TRACE_TAG); 1527 return new Allocation(id, rs, t, usage); 1528 } 1529 1530 /** 1531 * Returns the handle to a raw buffer that is being managed by the screen 1532 * compositor. This operation is only valid for Allocations with {@link 1533 * #USAGE_IO_INPUT}. 1534 * 1535 * @return Surface object associated with allocation 1536 * 1537 */ 1538 public Surface getSurface() { 1539 if ((mUsage & USAGE_IO_INPUT) == 0) { 1540 throw new RSInvalidStateException("Allocation is not a surface texture."); 1541 } 1542 return mRS.nAllocationGetSurface(getID(mRS)); 1543 } 1544 1545 /** 1546 * Associate a {@link android.view.Surface} with this Allocation. This 1547 * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}. 1548 * 1549 * @param sur Surface to associate with allocation 1550 */ 1551 public void setSurface(Surface sur) { 1552 mRS.validate(); 1553 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 1554 throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT."); 1555 } 1556 1557 mRS.nAllocationSetSurface(getID(mRS), sur); 1558 } 1559 1560 /** 1561 * Creates an Allocation from a {@link android.graphics.Bitmap}. 1562 * 1563 * <p>With target API version 18 or greater, this Allocation will be created 1564 * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link 1565 * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this 1566 * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p> 1567 * 1568 * @param rs Context to which the allocation will belong. 1569 * @param b bitmap source for the allocation data 1570 * 1571 * @return Allocation containing bitmap data 1572 * 1573 */ 1574 static public Allocation createFromBitmap(RenderScript rs, Bitmap b) { 1575 if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) { 1576 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1577 USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 1578 } 1579 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1580 USAGE_GRAPHICS_TEXTURE); 1581 } 1582 1583 /** 1584 * Creates a cubemap Allocation from a {@link android.graphics.Bitmap} 1585 * containing the horizontal list of cube faces. Each face must be a square, 1586 * have the same size as all other faces, and have a width that is a power 1587 * of 2. 1588 * 1589 * @param rs Context to which the allocation will belong. 1590 * @param b Bitmap with cubemap faces layed out in the following 1591 * format: right, left, top, bottom, front, back 1592 * @param mips specifies desired mipmap behaviour for the cubemap 1593 * @param usage bit field specifying how the cubemap is utilized 1594 * 1595 * @return allocation containing cubemap data 1596 * 1597 */ 1598 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 1599 MipmapControl mips, 1600 int usage) { 1601 rs.validate(); 1602 1603 int height = b.getHeight(); 1604 int width = b.getWidth(); 1605 1606 if (width % 6 != 0) { 1607 throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); 1608 } 1609 if (width / 6 != height) { 1610 throw new RSIllegalArgumentException("Only square cube map faces supported"); 1611 } 1612 boolean isPow2 = (height & (height - 1)) == 0; 1613 if (!isPow2) { 1614 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 1615 } 1616 1617 Element e = elementFromBitmap(rs, b); 1618 Type.Builder tb = new Type.Builder(rs, e); 1619 tb.setX(height); 1620 tb.setY(height); 1621 tb.setFaces(true); 1622 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 1623 Type t = tb.create(); 1624 1625 long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage); 1626 if(id == 0) { 1627 throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); 1628 } 1629 return new Allocation(id, rs, t, usage); 1630 } 1631 1632 /** 1633 * Creates a non-mipmapped cubemap Allocation for use as a graphics texture 1634 * from a {@link android.graphics.Bitmap} containing the horizontal list of 1635 * cube faces. Each face must be a square, have the same size as all other 1636 * faces, and have a width that is a power of 2. 1637 * 1638 * @param rs Context to which the allocation will belong. 1639 * @param b bitmap with cubemap faces layed out in the following 1640 * format: right, left, top, bottom, front, back 1641 * 1642 * @return allocation containing cubemap data 1643 * 1644 */ 1645 static public Allocation createCubemapFromBitmap(RenderScript rs, 1646 Bitmap b) { 1647 return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 1648 USAGE_GRAPHICS_TEXTURE); 1649 } 1650 1651 /** 1652 * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap} 1653 * objects containing the cube faces. Each face must be a square, have the 1654 * same size as all other faces, and have a width that is a power of 2. 1655 * 1656 * @param rs Context to which the allocation will belong. 1657 * @param xpos cubemap face in the positive x direction 1658 * @param xneg cubemap face in the negative x direction 1659 * @param ypos cubemap face in the positive y direction 1660 * @param yneg cubemap face in the negative y direction 1661 * @param zpos cubemap face in the positive z direction 1662 * @param zneg cubemap face in the negative z direction 1663 * @param mips specifies desired mipmap behaviour for the cubemap 1664 * @param usage bit field specifying how the cubemap is utilized 1665 * 1666 * @return allocation containing cubemap data 1667 * 1668 */ 1669 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 1670 Bitmap xpos, 1671 Bitmap xneg, 1672 Bitmap ypos, 1673 Bitmap yneg, 1674 Bitmap zpos, 1675 Bitmap zneg, 1676 MipmapControl mips, 1677 int usage) { 1678 int height = xpos.getHeight(); 1679 if (xpos.getWidth() != height || 1680 xneg.getWidth() != height || xneg.getHeight() != height || 1681 ypos.getWidth() != height || ypos.getHeight() != height || 1682 yneg.getWidth() != height || yneg.getHeight() != height || 1683 zpos.getWidth() != height || zpos.getHeight() != height || 1684 zneg.getWidth() != height || zneg.getHeight() != height) { 1685 throw new RSIllegalArgumentException("Only square cube map faces supported"); 1686 } 1687 boolean isPow2 = (height & (height - 1)) == 0; 1688 if (!isPow2) { 1689 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 1690 } 1691 1692 Element e = elementFromBitmap(rs, xpos); 1693 Type.Builder tb = new Type.Builder(rs, e); 1694 tb.setX(height); 1695 tb.setY(height); 1696 tb.setFaces(true); 1697 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 1698 Type t = tb.create(); 1699 Allocation cubemap = Allocation.createTyped(rs, t, mips, usage); 1700 1701 AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap); 1702 adapter.setFace(Type.CubemapFace.POSITIVE_X); 1703 adapter.copyFrom(xpos); 1704 adapter.setFace(Type.CubemapFace.NEGATIVE_X); 1705 adapter.copyFrom(xneg); 1706 adapter.setFace(Type.CubemapFace.POSITIVE_Y); 1707 adapter.copyFrom(ypos); 1708 adapter.setFace(Type.CubemapFace.NEGATIVE_Y); 1709 adapter.copyFrom(yneg); 1710 adapter.setFace(Type.CubemapFace.POSITIVE_Z); 1711 adapter.copyFrom(zpos); 1712 adapter.setFace(Type.CubemapFace.NEGATIVE_Z); 1713 adapter.copyFrom(zneg); 1714 1715 return cubemap; 1716 } 1717 1718 /** 1719 * Creates a non-mipmapped cubemap Allocation for use as a sampler input 1720 * from 6 {@link android.graphics.Bitmap} objects containing the cube 1721 * faces. Each face must be a square, have the same size as all other faces, 1722 * and have a width that is a power of 2. 1723 * 1724 * @param rs Context to which the allocation will belong. 1725 * @param xpos cubemap face in the positive x direction 1726 * @param xneg cubemap face in the negative x direction 1727 * @param ypos cubemap face in the positive y direction 1728 * @param yneg cubemap face in the negative y direction 1729 * @param zpos cubemap face in the positive z direction 1730 * @param zneg cubemap face in the negative z direction 1731 * 1732 * @return allocation containing cubemap data 1733 * 1734 */ 1735 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 1736 Bitmap xpos, 1737 Bitmap xneg, 1738 Bitmap ypos, 1739 Bitmap yneg, 1740 Bitmap zpos, 1741 Bitmap zneg) { 1742 return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg, 1743 zpos, zneg, MipmapControl.MIPMAP_NONE, 1744 USAGE_GRAPHICS_TEXTURE); 1745 } 1746 1747 /** 1748 * Creates an Allocation from the Bitmap referenced 1749 * by resource ID. 1750 * 1751 * @param rs Context to which the allocation will belong. 1752 * @param res application resources 1753 * @param id resource id to load the data from 1754 * @param mips specifies desired mipmap behaviour for the 1755 * allocation 1756 * @param usage bit field specifying how the allocation is 1757 * utilized 1758 * 1759 * @return Allocation containing resource data 1760 * 1761 */ 1762 static public Allocation createFromBitmapResource(RenderScript rs, 1763 Resources res, 1764 int id, 1765 MipmapControl mips, 1766 int usage) { 1767 1768 rs.validate(); 1769 if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) { 1770 throw new RSIllegalArgumentException("Unsupported usage specified."); 1771 } 1772 Bitmap b = BitmapFactory.decodeResource(res, id); 1773 Allocation alloc = createFromBitmap(rs, b, mips, usage); 1774 b.recycle(); 1775 return alloc; 1776 } 1777 1778 /** 1779 * Creates a non-mipmapped Allocation to use as a graphics texture from the 1780 * {@link android.graphics.Bitmap} referenced by resource ID. 1781 * 1782 * <p>With target API version 18 or greater, this allocation will be created 1783 * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With 1784 * target API version 17 or lower, this allocation will be created with 1785 * {@link #USAGE_GRAPHICS_TEXTURE}.</p> 1786 * 1787 * @param rs Context to which the allocation will belong. 1788 * @param res application resources 1789 * @param id resource id to load the data from 1790 * 1791 * @return Allocation containing resource data 1792 * 1793 */ 1794 static public Allocation createFromBitmapResource(RenderScript rs, 1795 Resources res, 1796 int id) { 1797 if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) { 1798 return createFromBitmapResource(rs, res, id, 1799 MipmapControl.MIPMAP_NONE, 1800 USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE); 1801 } 1802 return createFromBitmapResource(rs, res, id, 1803 MipmapControl.MIPMAP_NONE, 1804 USAGE_GRAPHICS_TEXTURE); 1805 } 1806 1807 /** 1808 * Creates an Allocation containing string data encoded in UTF-8 format. 1809 * 1810 * @param rs Context to which the allocation will belong. 1811 * @param str string to create the allocation from 1812 * @param usage bit field specifying how the allocaiton is 1813 * utilized 1814 * 1815 */ 1816 static public Allocation createFromString(RenderScript rs, 1817 String str, 1818 int usage) { 1819 rs.validate(); 1820 byte[] allocArray = null; 1821 try { 1822 allocArray = str.getBytes("UTF-8"); 1823 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 1824 alloc.copyFrom(allocArray); 1825 return alloc; 1826 } 1827 catch (Exception e) { 1828 throw new RSRuntimeException("Could not convert string to utf-8."); 1829 } 1830 } 1831 1832 /** 1833 * Interface to handle notification when new buffers are available via 1834 * {@link #USAGE_IO_INPUT}. An application will receive one notification 1835 * when a buffer is available. Additional buffers will not trigger new 1836 * notifications until a buffer is processed. 1837 */ 1838 public interface OnBufferAvailableListener { 1839 public void onBufferAvailable(Allocation a); 1840 } 1841 1842 /** 1843 * Set a notification handler for {@link #USAGE_IO_INPUT}. 1844 * 1845 * @param callback instance of the OnBufferAvailableListener 1846 * class to be called when buffer arrive. 1847 */ 1848 public void setOnBufferAvailableListener(OnBufferAvailableListener callback) { 1849 synchronized(mAllocationMap) { 1850 mAllocationMap.put(new Long(getID(mRS)), this); 1851 mBufferNotifier = callback; 1852 } 1853 } 1854 1855 static void sendBufferNotification(int id) { 1856 synchronized(mAllocationMap) { 1857 Allocation a = mAllocationMap.get(new Long(id)); 1858 1859 if ((a != null) && (a.mBufferNotifier != null)) { 1860 a.mBufferNotifier.onBufferAvailable(a); 1861 } 1862 } 1863 } 1864 1865} 1866 1867