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