Allocation.java revision f7086090cfc8d97b5bd3b4d7801a27af11f7c207
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.renderscript; 18 19import java.io.IOException; 20import java.io.InputStream; 21import android.content.res.Resources; 22import android.content.res.AssetManager; 23import android.graphics.Bitmap; 24import android.graphics.BitmapFactory; 25import android.util.Log; 26import android.util.TypedValue; 27 28/** 29 * Memory allocation class for renderscript. An allocation combines a Type with 30 * memory to provide storage for user data and objects. 31 * 32 * Allocations may exist in one or more memory spaces. Currently those are 33 * Script: accessable by RS scripts. 34 * Graphics Texture: accessable as a graphics texture. 35 * Graphics Vertex: accessable as graphical vertex data. 36 * Graphics Constants: Accessable as constants in user shaders 37 * 38 * By default java side updates are always applied to the script accessable 39 * memory. If this is not present they are then applied to the various HW 40 * memory types. A syncAll call is necessary after the script data is update to 41 * keep the other memory spaces in sync. 42 * 43 **/ 44public class Allocation extends BaseObj { 45 Type mType; 46 Bitmap mBitmap; 47 int mUsage; 48 49 /** 50 * The usage of the allocation. These signal to renderscript 51 * where to place the allocation in memory. 52 * 53 * SCRIPT The allocation will be bound to and accessed by 54 * scripts. 55 */ 56 public static final int USAGE_SCRIPT = 0x0001; 57 58 /** 59 * GRAPHICS_TEXTURE The allcation will be used as a texture 60 * source by one or more graphcics programs. 61 * 62 */ 63 public static final int USAGE_GRAPHICS_TEXTURE = 0x0002; 64 65 /** 66 * GRAPHICS_VERTEX The allocation will be used as a graphics 67 * mesh. 68 * 69 */ 70 public static final int USAGE_GRAPHICS_VERTEX = 0x0004; 71 72 73 /** 74 * GRAPHICS_CONSTANTS The allocation will be used as the source 75 * of shader constants by one or more programs. 76 * 77 */ 78 public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008; 79 80 81 /** 82 * Controls mipmap behavior when using the bitmap creation and 83 * update functions. 84 */ 85 public enum MipmapControl { 86 /** 87 * No mipmaps will be generated and the type generated from the 88 * incoming bitmap will not contain additional LODs. 89 */ 90 MIPMAP_NONE(0), 91 92 /** 93 * A Full mipmap chain will be created in script memory. The 94 * type of the allocation will contain a full mipmap chain. On 95 * upload to graphics the full chain will be transfered. 96 */ 97 MIPMAP_FULL(1), 98 99 /** 100 * The type of the allocation will be the same as MIPMAP_NONE. 101 * It will not contain mipmaps. On upload to graphics the 102 * graphics copy of the allocation data will contain a full 103 * mipmap chain generated from the top level in script memory. 104 */ 105 MIPMAP_ON_SYNC_TO_TEXTURE(2); 106 107 int mID; 108 MipmapControl(int id) { 109 mID = id; 110 } 111 } 112 113 Allocation(int id, RenderScript rs, Type t, int usage) { 114 super(id, rs); 115 if ((usage & ~(USAGE_SCRIPT | 116 USAGE_GRAPHICS_TEXTURE | 117 USAGE_GRAPHICS_VERTEX | 118 USAGE_GRAPHICS_CONSTANTS)) != 0) { 119 throw new RSIllegalArgumentException("Unknown usage specified."); 120 } 121 mType = t; 122 } 123 124 @Override 125 void updateFromNative() { 126 super.updateFromNative(); 127 int typeID = mRS.nAllocationGetType(getID()); 128 if(typeID != 0) { 129 mType = new Type(typeID, mRS); 130 mType.updateFromNative(); 131 } 132 } 133 134 public Type getType() { 135 return mType; 136 } 137 138 public void syncAll(int srcLocation) { 139 switch (srcLocation) { 140 case USAGE_SCRIPT: 141 case USAGE_GRAPHICS_CONSTANTS: 142 case USAGE_GRAPHICS_TEXTURE: 143 case USAGE_GRAPHICS_VERTEX: 144 break; 145 default: 146 throw new RSIllegalArgumentException("Source must be exactly one usage type."); 147 } 148 mRS.validate(); 149 mRS.nAllocationSyncAll(getID(), srcLocation); 150 } 151 152 public void copyFrom(BaseObj[] d) { 153 mRS.validate(); 154 if (d.length != mType.getCount()) { 155 throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + 156 mType.getCount() + ", array length = " + d.length); 157 } 158 int i[] = new int[d.length]; 159 for (int ct=0; ct < d.length; ct++) { 160 i[ct] = d[ct].getID(); 161 } 162 copy1DRangeFrom(0, mType.getCount(), i); 163 } 164 165 private void validateBitmap(Bitmap b) { 166 mRS.validate(); 167 if(mType.getX() != b.getWidth() || 168 mType.getY() != b.getHeight()) { 169 throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); 170 } 171 Bitmap.Config bc = b.getConfig(); 172 switch (bc) { 173 case ALPHA_8: 174 if (mType.getElement().mKind != Element.DataKind.PIXEL_A) { 175 throw new RSIllegalArgumentException("Allocation kind is " + 176 mType.getElement().mKind + ", type " + 177 mType.getElement().mType + 178 " of " + mType.getElement().getSizeBytes() + 179 " bytes, passed bitmap was " + bc); 180 } 181 break; 182 case ARGB_8888: 183 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 184 (mType.getElement().getSizeBytes() != 4)) { 185 throw new RSIllegalArgumentException("Allocation kind is " + 186 mType.getElement().mKind + ", type " + 187 mType.getElement().mType + 188 " of " + mType.getElement().getSizeBytes() + 189 " bytes, passed bitmap was " + bc); 190 } 191 break; 192 case RGB_565: 193 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) || 194 (mType.getElement().getSizeBytes() != 2)) { 195 throw new RSIllegalArgumentException("Allocation kind is " + 196 mType.getElement().mKind + ", type " + 197 mType.getElement().mType + 198 " of " + mType.getElement().getSizeBytes() + 199 " bytes, passed bitmap was " + bc); 200 } 201 break; 202 case ARGB_4444: 203 if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || 204 (mType.getElement().getSizeBytes() != 2)) { 205 throw new RSIllegalArgumentException("Allocation kind is " + 206 mType.getElement().mKind + ", type " + 207 mType.getElement().mType + 208 " of " + mType.getElement().getSizeBytes() + 209 " bytes, passed bitmap was " + bc); 210 } 211 break; 212 213 } 214 } 215 216 public void copyFrom(int[] d) { 217 mRS.validate(); 218 copy1DRangeFrom(0, mType.getCount(), d); 219 } 220 public void copyFrom(short[] d) { 221 mRS.validate(); 222 copy1DRangeFrom(0, mType.getCount(), d); 223 } 224 public void copyFrom(byte[] d) { 225 mRS.validate(); 226 copy1DRangeFrom(0, mType.getCount(), d); 227 } 228 public void copyFrom(float[] d) { 229 mRS.validate(); 230 copy1DRangeFrom(0, mType.getCount(), d); 231 } 232 public void copyFrom(Bitmap b) { 233 validateBitmap(b); 234 mRS.nAllocationCopyFromBitmap(getID(), b); 235 } 236 237 /** 238 * @hide 239 * 240 * This is only intended to be used by auto-generate code reflected from the 241 * renderscript script files. 242 * 243 * @param xoff 244 * @param fp 245 */ 246 public void setOneElement(int xoff, FieldPacker fp) { 247 int eSize = mType.mElement.getSizeBytes(); 248 final byte[] data = fp.getData(); 249 250 int count = data.length / eSize; 251 if ((eSize * count) != data.length) { 252 throw new RSIllegalArgumentException("Field packer length " + data.length + 253 " not divisible by element size " + eSize + "."); 254 } 255 data1DChecks(xoff, count, data.length, data.length); 256 mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length); 257 } 258 259 260 /** 261 * @hide 262 * 263 * This is only intended to be used by auto-generate code reflected from the 264 * renderscript script files. 265 * 266 * @param xoff 267 * @param component_number 268 * @param fp 269 */ 270 public void setOneComponent(int xoff, int component_number, FieldPacker fp) { 271 if (component_number >= mType.mElement.mElements.length) { 272 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 273 } 274 if(xoff < 0) { 275 throw new RSIllegalArgumentException("Offset must be >= 0."); 276 } 277 278 final byte[] data = fp.getData(); 279 int eSize = mType.mElement.mElements[component_number].getSizeBytes(); 280 281 if (data.length != eSize) { 282 throw new RSIllegalArgumentException("Field packer sizelength " + data.length + 283 " does not match component size " + eSize + "."); 284 } 285 286 mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length); 287 } 288 289 private void data1DChecks(int off, int count, int len, int dataSize) { 290 mRS.validate(); 291 if(off < 0) { 292 throw new RSIllegalArgumentException("Offset must be >= 0."); 293 } 294 if(count < 1) { 295 throw new RSIllegalArgumentException("Count must be >= 1."); 296 } 297 if((off + count) > mType.getCount()) { 298 throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() + 299 ", got " + count + " at offset " + off + "."); 300 } 301 if((len) < dataSize) { 302 throw new RSIllegalArgumentException("Array too small for allocation type."); 303 } 304 } 305 306 /** 307 * Generate a mipmap chain. Requires the type of the allocation 308 * include mipmaps. 309 * 310 * This function will generate a complete set of mipmaps from 311 * the top level lod and place them into the script memoryspace. 312 * 313 * If the allocation is also using other memory spaces a 314 * followup sync will be required. 315 */ 316 public void generateMipmaps() { 317 mRS.nAllocationGenerateMipmaps(getID()); 318 } 319 320 public void copy1DRangeFrom(int off, int count, int[] d) { 321 int dataSize = mType.mElement.getSizeBytes() * count; 322 data1DChecks(off, count, d.length * 4, dataSize); 323 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 324 } 325 public void copy1DRangeFrom(int off, int count, short[] d) { 326 int dataSize = mType.mElement.getSizeBytes() * count; 327 data1DChecks(off, count, d.length * 2, dataSize); 328 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 329 } 330 public void copy1DRangeFrom(int off, int count, byte[] d) { 331 int dataSize = mType.mElement.getSizeBytes() * count; 332 data1DChecks(off, count, d.length, dataSize); 333 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 334 } 335 public void copy1DRangeFrom(int off, int count, float[] d) { 336 int dataSize = mType.mElement.getSizeBytes() * count; 337 data1DChecks(off, count, d.length * 4, dataSize); 338 mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); 339 } 340 341 342 /** 343 * Copy a rectanglular region from the array into the 344 * allocation. The incoming array is assumed to be tightly 345 * packed. 346 * 347 * @param xoff X offset of the region to update 348 * @param yoff Y offset of the region to update 349 * @param w Width of the incoming region to update 350 * @param h Height of the incoming region to update 351 * @param data to be placed into the allocation 352 */ 353 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { 354 mRS.validate(); 355 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length); 356 } 357 358 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) { 359 mRS.validate(); 360 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2); 361 } 362 363 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) { 364 mRS.validate(); 365 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); 366 } 367 368 public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) { 369 mRS.validate(); 370 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); 371 } 372 373 /** 374 * Copy a bitmap into an allocation. The height and width of 375 * the update will use the height and width of the incoming 376 * bitmap. 377 * 378 * @param xoff X offset of the region to update 379 * @param yoff Y offset of the region to update 380 * @param data the bitmap to be copied 381 */ 382 public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) { 383 mRS.validate(); 384 mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data); 385 } 386 387 388 public void copyTo(Bitmap b) { 389 validateBitmap(b); 390 mRS.nAllocationCopyToBitmap(getID(), b); 391 } 392 393 public void copyTo(byte[] d) { 394 mRS.validate(); 395 mRS.nAllocationRead(getID(), d); 396 } 397 398 public void copyTo(short[] d) { 399 mRS.validate(); 400 mRS.nAllocationRead(getID(), d); 401 } 402 403 public void copyTo(int[] d) { 404 mRS.validate(); 405 mRS.nAllocationRead(getID(), d); 406 } 407 408 public void copyTo(float[] d) { 409 mRS.validate(); 410 mRS.nAllocationRead(getID(), d); 411 } 412 413 /** 414 * Resize a 1D allocation. The contents of the allocation are 415 * preserved. If new elements are allocated objects are created 416 * with null contents and the new region is otherwise undefined. 417 * 418 * If the new region is smaller the references of any objects 419 * outside the new region will be released. 420 * 421 * A new type will be created with the new dimension. 422 * 423 * @param dimX The new size of the allocation. 424 */ 425 public synchronized void resize(int dimX) { 426 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 427 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 428 } 429 mRS.nAllocationResize1D(getID(), dimX); 430 mRS.finish(); // Necessary because resize is fifoed and update is async. 431 432 int typeID = mRS.nAllocationGetType(getID()); 433 mType = new Type(typeID, mRS); 434 mType.updateFromNative(); 435 } 436 437 /* 438 public void resize(int dimX, int dimY) { 439 if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) { 440 throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); 441 } 442 if (mType.getY() == 0) { 443 throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); 444 } 445 mRS.nAllocationResize2D(getID(), dimX, dimY); 446 } 447 */ 448 449 450 451 // creation 452 453 static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 454 static { 455 mBitmapOptions.inScaled = false; 456 } 457 458 static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mc, int usage) { 459 rs.validate(); 460 if (type.getID() == 0) { 461 throw new RSInvalidStateException("Bad Type"); 462 } 463 int id = rs.nAllocationCreateTyped(type.getID(), mc.mID, usage); 464 if (id == 0) { 465 throw new RSRuntimeException("Allocation creation failed."); 466 } 467 return new Allocation(id, rs, type, usage); 468 } 469 470 static public Allocation createTyped(RenderScript rs, Type type, int usage) { 471 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage); 472 } 473 474 static public Allocation createTyped(RenderScript rs, Type type) { 475 return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT); 476 } 477 478 static public Allocation createSized(RenderScript rs, Element e, 479 int count, int usage) { 480 rs.validate(); 481 Type.Builder b = new Type.Builder(rs, e); 482 b.setX(count); 483 Type t = b.create(); 484 485 int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage); 486 if (id == 0) { 487 throw new RSRuntimeException("Allocation creation failed."); 488 } 489 return new Allocation(id, rs, t, usage); 490 } 491 492 static public Allocation createSized(RenderScript rs, Element e, int count) { 493 return createSized(rs, e, count, USAGE_SCRIPT); 494 } 495 496 static Element elementFromBitmap(RenderScript rs, Bitmap b) { 497 final Bitmap.Config bc = b.getConfig(); 498 if (bc == Bitmap.Config.ALPHA_8) { 499 return Element.A_8(rs); 500 } 501 if (bc == Bitmap.Config.ARGB_4444) { 502 return Element.RGBA_4444(rs); 503 } 504 if (bc == Bitmap.Config.ARGB_8888) { 505 return Element.RGBA_8888(rs); 506 } 507 if (bc == Bitmap.Config.RGB_565) { 508 return Element.RGB_565(rs); 509 } 510 throw new RSInvalidStateException("Bad bitmap type: " + bc); 511 } 512 513 static Type typeFromBitmap(RenderScript rs, Bitmap b, 514 MipmapControl mip) { 515 Element e = elementFromBitmap(rs, b); 516 Type.Builder tb = new Type.Builder(rs, e); 517 tb.setX(b.getWidth()); 518 tb.setY(b.getHeight()); 519 tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); 520 return tb.create(); 521 } 522 523 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 524 MipmapControl mips, 525 int usage) { 526 rs.validate(); 527 Type t = typeFromBitmap(rs, b, mips); 528 529 int id = rs.nAllocationCreateFromBitmap(t.getID(), mips.mID, b, usage); 530 if (id == 0) { 531 throw new RSRuntimeException("Load failed."); 532 } 533 return new Allocation(id, rs, t, usage); 534 } 535 536 static public Allocation createFromBitmap(RenderScript rs, Bitmap b) { 537 return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 538 USAGE_GRAPHICS_TEXTURE); 539 } 540 541 /** 542 * Creates a cubemap allocation from a bitmap containing the 543 * horizontal list of cube faces. Each individual face must be 544 * the same size and power of 2 545 * 546 * @param rs 547 * @param b bitmap with cubemap faces layed out in the following 548 * format: right, left, top, bottom, front, back 549 * @param mips specifies desired mipmap behaviour for the cubemap 550 * @param usage bitfield specifying how the cubemap is utilized 551 * 552 **/ 553 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 554 MipmapControl mips, 555 int usage) { 556 rs.validate(); 557 558 int height = b.getHeight(); 559 int width = b.getWidth(); 560 561 if (width % 6 != 0) { 562 throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); 563 } 564 if (width / 6 != height) { 565 throw new RSIllegalArgumentException("Only square cube map faces supported"); 566 } 567 boolean isPow2 = (height & (height - 1)) == 0; 568 if (!isPow2) { 569 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 570 } 571 572 Element e = elementFromBitmap(rs, b); 573 Type.Builder tb = new Type.Builder(rs, e); 574 tb.setX(height); 575 tb.setY(height); 576 tb.setFaces(true); 577 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 578 Type t = tb.create(); 579 580 int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage); 581 if(id == 0) { 582 throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); 583 } 584 return new Allocation(id, rs, t, usage); 585 } 586 587 static public Allocation createCubemapFromBitmap(RenderScript rs, 588 Bitmap b) { 589 return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, 590 USAGE_GRAPHICS_TEXTURE); 591 } 592 593 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 594 Bitmap xpos, 595 Bitmap xneg, 596 Bitmap ypos, 597 Bitmap yneg, 598 Bitmap zpos, 599 Bitmap zneg, 600 MipmapControl mips, 601 int usage) { 602 int height = xpos.getHeight(); 603 if (xpos.getWidth() != height || 604 xneg.getWidth() != height || xneg.getHeight() != height || 605 ypos.getWidth() != height || ypos.getHeight() != height || 606 yneg.getWidth() != height || yneg.getHeight() != height || 607 zpos.getWidth() != height || zpos.getHeight() != height || 608 zneg.getWidth() != height || zneg.getHeight() != height) { 609 throw new RSIllegalArgumentException("Only square cube map faces supported"); 610 } 611 boolean isPow2 = (height & (height - 1)) == 0; 612 if (!isPow2) { 613 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 614 } 615 616 Element e = elementFromBitmap(rs, xpos); 617 Type.Builder tb = new Type.Builder(rs, e); 618 tb.setX(height); 619 tb.setY(height); 620 tb.setFaces(true); 621 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 622 Type t = tb.create(); 623 Allocation cubemap = Allocation.createTyped(rs, t, mips, usage); 624 625 AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap); 626 adapter.setFace(Type.CubemapFace.POSITVE_X); 627 adapter.copyFrom(xpos); 628 adapter.setFace(Type.CubemapFace.NEGATIVE_X); 629 adapter.copyFrom(xneg); 630 adapter.setFace(Type.CubemapFace.POSITVE_Y); 631 adapter.copyFrom(ypos); 632 adapter.setFace(Type.CubemapFace.NEGATIVE_Y); 633 adapter.copyFrom(yneg); 634 adapter.setFace(Type.CubemapFace.POSITVE_Z); 635 adapter.copyFrom(zpos); 636 adapter.setFace(Type.CubemapFace.NEGATIVE_Z); 637 adapter.copyFrom(zneg); 638 639 return cubemap; 640 } 641 642 static public Allocation createCubemapFromCubeFaces(RenderScript rs, 643 Bitmap xpos, 644 Bitmap xneg, 645 Bitmap ypos, 646 Bitmap yneg, 647 Bitmap zpos, 648 Bitmap zneg) { 649 return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg, 650 zpos, zneg, MipmapControl.MIPMAP_NONE, 651 USAGE_GRAPHICS_TEXTURE); 652 } 653 654 static public Allocation createFromBitmapResource(RenderScript rs, 655 Resources res, 656 int id, 657 MipmapControl mips, 658 int usage) { 659 660 rs.validate(); 661 Bitmap b = BitmapFactory.decodeResource(res, id); 662 Allocation alloc = createFromBitmap(rs, b, mips, usage); 663 b.recycle(); 664 return alloc; 665 } 666 667 static public Allocation createFromBitmapResource(RenderScript rs, 668 Resources res, 669 int id) { 670 return createFromBitmapResource(rs, res, id, 671 MipmapControl.MIPMAP_NONE, 672 USAGE_GRAPHICS_TEXTURE); 673 } 674 675 static public Allocation createFromString(RenderScript rs, 676 String str, 677 int usage) { 678 rs.validate(); 679 byte[] allocArray = null; 680 try { 681 allocArray = str.getBytes("UTF-8"); 682 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 683 alloc.copyFrom(allocArray); 684 return alloc; 685 } 686 catch (Exception e) { 687 throw new RSRuntimeException("Could not convert string to utf-8."); 688 } 689 } 690} 691 692 693