1/* 2 * Copyright (C) 2013 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.lang.reflect.Field; 20import android.util.Log; 21 22/** 23 * <p>An Element represents one item within an {@link 24 * android.renderscript.Allocation}. An Element is roughly equivalent to a C 25 * type in a RenderScript kernel. Elements may be basic or complex. Some basic 26 * elements are</p> <ul> <li>A single float value (equivalent to a float in a 27 * kernel)</li> <li>A four-element float vector (equivalent to a float4 in a 28 * kernel)</li> <li>An unsigned 32-bit integer (equivalent to an unsigned int in 29 * a kernel)</li> <li>A single signed 8-bit integer (equivalent to a char in a 30 * kernel)</li> </ul> <p>A complex element is roughly equivalent to a C struct 31 * and contains a number of basic or complex Elements. From Java code, a complex 32 * element contains a list of sub-elements and names that represents a 33 * particular data structure. Structs used in RS scripts are available to Java 34 * code by using the {@code ScriptField_structname} class that is reflected from 35 * a particular script.</p> 36 * 37 * <p>Basic Elements are comprised of a {@link 38 * android.renderscript.Element.DataType} and a {@link 39 * android.renderscript.Element.DataKind}. The DataType encodes C type 40 * information of an Element, while the DataKind encodes how that Element should 41 * be interpreted by a {@link android.renderscript.Sampler}. Note that {@link 42 * android.renderscript.Allocation} objects with DataKind {@link 43 * android.renderscript.Element.DataKind#USER} cannot be used as input for a 44 * {@link android.renderscript.Sampler}. In general, {@link 45 * android.renderscript.Allocation} objects that are intended for use with a 46 * {@link android.renderscript.Sampler} should use bitmap-derived Elements such 47 * as {@link android.renderscript.Element#RGBA_8888} or {@link 48 * android.renderscript#Element.A_8}.</p> 49 * 50 * <div class="special reference"> 51 * <h3>Developer Guides</h3> 52 * <p>For more information about creating an application that uses RenderScript, read the 53 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p> 54 * </div> 55 **/ 56public class Element extends BaseObj { 57 int mSize; 58 Element[] mElements; 59 String[] mElementNames; 60 int[] mArraySizes; 61 int[] mOffsetInBytes; 62 63 int[] mVisibleElementMap; 64 65 DataType mType; 66 DataKind mKind; 67 boolean mNormalized; 68 int mVectorSize; 69 70 private void updateVisibleSubElements() { 71 if (mElements == null) { 72 return; 73 } 74 75 int noPaddingFieldCount = 0; 76 int fieldCount = mElementNames.length; 77 // Find out how many elements are not padding 78 for (int ct = 0; ct < fieldCount; ct ++) { 79 if (mElementNames[ct].charAt(0) != '#') { 80 noPaddingFieldCount ++; 81 } 82 } 83 mVisibleElementMap = new int[noPaddingFieldCount]; 84 85 // Make a map that points us at non-padding elements 86 for (int ct = 0, ctNoPadding = 0; ct < fieldCount; ct ++) { 87 if (mElementNames[ct].charAt(0) != '#') { 88 mVisibleElementMap[ctNoPadding ++] = ct; 89 } 90 } 91 } 92 93 /** 94 * @return element size in bytes 95 */ 96 public int getBytesSize() {return mSize;} 97 98 /** 99 * Returns the number of vector components. 2 for float2, 4 for 100 * float4, etc. 101 * @return element vector size 102 */ 103 public int getVectorSize() {return mVectorSize;} 104 105 106 /** 107 * DataType represents the basic type information for a basic element. The 108 * naming convention follows. For numeric types it is FLOAT, 109 * SIGNED, or UNSIGNED followed by the _BITS where BITS is the 110 * size of the data. BOOLEAN is a true / false (1,0) 111 * represented in an 8 bit container. The UNSIGNED variants 112 * with multiple bit definitions are for packed graphical data 113 * formats and represent vectors with per vector member sizes 114 * which are treated as a single unit for packing and alignment 115 * purposes. 116 * 117 * MATRIX the three matrix types contain FLOAT_32 elements and are treated 118 * as 32 bits for alignment purposes. 119 * 120 * RS_* objects. 32 bit opaque handles. 121 */ 122 public enum DataType { 123 NONE (0, 0), 124 //FLOAT_16 (1, 2), 125 FLOAT_32 (2, 4), 126 FLOAT_64 (3, 8), 127 SIGNED_8 (4, 1), 128 SIGNED_16 (5, 2), 129 SIGNED_32 (6, 4), 130 SIGNED_64 (7, 8), 131 UNSIGNED_8 (8, 1), 132 UNSIGNED_16 (9, 2), 133 UNSIGNED_32 (10, 4), 134 UNSIGNED_64 (11, 8), 135 136 BOOLEAN(12, 1), 137 138 UNSIGNED_5_6_5 (13, 2), 139 UNSIGNED_5_5_5_1 (14, 2), 140 UNSIGNED_4_4_4_4 (15, 2), 141 142 MATRIX_4X4 (16, 64), 143 MATRIX_3X3 (17, 36), 144 MATRIX_2X2 (18, 16), 145 146 RS_ELEMENT (1000, 4), 147 RS_TYPE (1001, 4), 148 RS_ALLOCATION (1002, 4), 149 RS_SAMPLER (1003, 4), 150 RS_SCRIPT (1004, 4), 151 RS_MESH (1005, 4), 152 RS_PROGRAM_FRAGMENT (1006, 4), 153 RS_PROGRAM_VERTEX (1007, 4), 154 RS_PROGRAM_RASTER (1008, 4), 155 RS_PROGRAM_STORE (1009, 4), 156 RS_FONT (1010, 4); 157 158 int mID; 159 int mSize; 160 DataType(int id, int size) { 161 mID = id; 162 mSize = size; 163 } 164 } 165 166 /** 167 * The special interpretation of the data if required. This is primarly 168 * useful for graphical data. USER indicates no special interpretation is 169 * expected. PIXEL is used in conjunction with the standard data types for 170 * representing texture formats. 171 */ 172 public enum DataKind { 173 USER (0), 174 175 PIXEL_L (7), 176 PIXEL_A (8), 177 PIXEL_LA (9), 178 PIXEL_RGB (10), 179 PIXEL_RGBA (11), 180 PIXEL_DEPTH (12), 181 PIXEL_YUV(13); 182 183 int mID; 184 DataKind(int id) { 185 mID = id; 186 } 187 } 188 189 /** 190 * Return if a element is too complex for use as a data source for a Mesh or 191 * a Program. 192 * 193 * @return boolean 194 */ 195 public boolean isComplex() { 196 if (mElements == null) { 197 return false; 198 } 199 for (int ct=0; ct < mElements.length; ct++) { 200 if (mElements[ct].mElements != null) { 201 return true; 202 } 203 } 204 return false; 205 } 206 207 /** 208 * Elements could be simple, such as an int or a float, or a 209 * structure with multiple sub elements, such as a collection of 210 * floats, float2, float4. This function returns zero for simple 211 * elements or the number of sub-elements otherwise. 212 * @return number of sub-elements in this element 213 */ 214 public int getSubElementCount() { 215 if (mVisibleElementMap == null) { 216 return 0; 217 } 218 return mVisibleElementMap.length; 219 } 220 221 /** 222 * For complex elements, this function will return the 223 * sub-element at index 224 * @param index index of the sub-element to return 225 * @return sub-element in this element at given index 226 */ 227 public Element getSubElement(int index) { 228 if (mVisibleElementMap == null) { 229 throw new RSIllegalArgumentException("Element contains no sub-elements"); 230 } 231 if (index < 0 || index >= mVisibleElementMap.length) { 232 throw new RSIllegalArgumentException("Illegal sub-element index"); 233 } 234 return mElements[mVisibleElementMap[index]]; 235 } 236 237 /** 238 * For complex elements, this function will return the 239 * sub-element name at index 240 * @param index index of the sub-element 241 * @return sub-element in this element at given index 242 */ 243 public String getSubElementName(int index) { 244 if (mVisibleElementMap == null) { 245 throw new RSIllegalArgumentException("Element contains no sub-elements"); 246 } 247 if (index < 0 || index >= mVisibleElementMap.length) { 248 throw new RSIllegalArgumentException("Illegal sub-element index"); 249 } 250 return mElementNames[mVisibleElementMap[index]]; 251 } 252 253 /** 254 * For complex elements, some sub-elements could be statically 255 * sized arrays. This function will return the array size for 256 * sub-element at index 257 * @param index index of the sub-element 258 * @return array size of sub-element in this element at given index 259 */ 260 public int getSubElementArraySize(int index) { 261 if (mVisibleElementMap == null) { 262 throw new RSIllegalArgumentException("Element contains no sub-elements"); 263 } 264 if (index < 0 || index >= mVisibleElementMap.length) { 265 throw new RSIllegalArgumentException("Illegal sub-element index"); 266 } 267 return mArraySizes[mVisibleElementMap[index]]; 268 } 269 270 /** 271 * This function specifies the location of a sub-element within 272 * the element 273 * @param index index of the sub-element 274 * @return offset in bytes of sub-element in this element at given index 275 */ 276 public int getSubElementOffsetBytes(int index) { 277 if (mVisibleElementMap == null) { 278 throw new RSIllegalArgumentException("Element contains no sub-elements"); 279 } 280 if (index < 0 || index >= mVisibleElementMap.length) { 281 throw new RSIllegalArgumentException("Illegal sub-element index"); 282 } 283 return mOffsetInBytes[mVisibleElementMap[index]]; 284 } 285 286 /** 287 * @return element data type 288 */ 289 public DataType getDataType() { 290 return mType; 291 } 292 293 /** 294 * @return element data kind 295 */ 296 public DataKind getDataKind() { 297 return mKind; 298 } 299 300 /** 301 * Utility function for returning an Element containing a single Boolean. 302 * 303 * @param rs Context to which the element will belong. 304 * 305 * @return Element 306 */ 307 public static Element BOOLEAN(RenderScript rs) { 308 if(rs.mElement_BOOLEAN == null) { 309 rs.mElement_BOOLEAN = createUser(rs, DataType.BOOLEAN); 310 } 311 return rs.mElement_BOOLEAN; 312 } 313 314 /** 315 * Utility function for returning an Element containing a single UNSIGNED_8. 316 * 317 * @param rs Context to which the element will belong. 318 * 319 * @return Element 320 */ 321 public static Element U8(RenderScript rs) { 322 if(rs.mElement_U8 == null) { 323 rs.mElement_U8 = createUser(rs, DataType.UNSIGNED_8); 324 } 325 return rs.mElement_U8; 326 } 327 328 /** 329 * Utility function for returning an Element containing a single SIGNED_8. 330 * 331 * @param rs Context to which the element will belong. 332 * 333 * @return Element 334 */ 335 public static Element I8(RenderScript rs) { 336 if(rs.mElement_I8 == null) { 337 rs.mElement_I8 = createUser(rs, DataType.SIGNED_8); 338 } 339 return rs.mElement_I8; 340 } 341 342 public static Element U16(RenderScript rs) { 343 if(rs.mElement_U16 == null) { 344 rs.mElement_U16 = createUser(rs, DataType.UNSIGNED_16); 345 } 346 return rs.mElement_U16; 347 } 348 349 public static Element I16(RenderScript rs) { 350 if(rs.mElement_I16 == null) { 351 rs.mElement_I16 = createUser(rs, DataType.SIGNED_16); 352 } 353 return rs.mElement_I16; 354 } 355 356 public static Element U32(RenderScript rs) { 357 if(rs.mElement_U32 == null) { 358 rs.mElement_U32 = createUser(rs, DataType.UNSIGNED_32); 359 } 360 return rs.mElement_U32; 361 } 362 363 public static Element I32(RenderScript rs) { 364 if(rs.mElement_I32 == null) { 365 rs.mElement_I32 = createUser(rs, DataType.SIGNED_32); 366 } 367 return rs.mElement_I32; 368 } 369 370 public static Element U64(RenderScript rs) { 371 if(rs.mElement_U64 == null) { 372 rs.mElement_U64 = createUser(rs, DataType.UNSIGNED_64); 373 } 374 return rs.mElement_U64; 375 } 376 377 public static Element I64(RenderScript rs) { 378 if(rs.mElement_I64 == null) { 379 rs.mElement_I64 = createUser(rs, DataType.SIGNED_64); 380 } 381 return rs.mElement_I64; 382 } 383 384 public static Element F32(RenderScript rs) { 385 if(rs.mElement_F32 == null) { 386 rs.mElement_F32 = createUser(rs, DataType.FLOAT_32); 387 } 388 return rs.mElement_F32; 389 } 390 391 public static Element F64(RenderScript rs) { 392 if(rs.mElement_F64 == null) { 393 rs.mElement_F64 = createUser(rs, DataType.FLOAT_64); 394 } 395 return rs.mElement_F64; 396 } 397 398 public static Element ELEMENT(RenderScript rs) { 399 if(rs.mElement_ELEMENT == null) { 400 rs.mElement_ELEMENT = createUser(rs, DataType.RS_ELEMENT); 401 } 402 return rs.mElement_ELEMENT; 403 } 404 405 public static Element TYPE(RenderScript rs) { 406 if(rs.mElement_TYPE == null) { 407 rs.mElement_TYPE = createUser(rs, DataType.RS_TYPE); 408 } 409 return rs.mElement_TYPE; 410 } 411 412 public static Element ALLOCATION(RenderScript rs) { 413 if(rs.mElement_ALLOCATION == null) { 414 rs.mElement_ALLOCATION = createUser(rs, DataType.RS_ALLOCATION); 415 } 416 return rs.mElement_ALLOCATION; 417 } 418 419 public static Element SAMPLER(RenderScript rs) { 420 if(rs.mElement_SAMPLER == null) { 421 rs.mElement_SAMPLER = createUser(rs, DataType.RS_SAMPLER); 422 } 423 return rs.mElement_SAMPLER; 424 } 425 426 public static Element SCRIPT(RenderScript rs) { 427 if(rs.mElement_SCRIPT == null) { 428 rs.mElement_SCRIPT = createUser(rs, DataType.RS_SCRIPT); 429 } 430 return rs.mElement_SCRIPT; 431 } 432 433 public static Element MESH(RenderScript rs) { 434 if(rs.mElement_MESH == null) { 435 rs.mElement_MESH = createUser(rs, DataType.RS_MESH); 436 } 437 return rs.mElement_MESH; 438 } 439 440 public static Element PROGRAM_FRAGMENT(RenderScript rs) { 441 if(rs.mElement_PROGRAM_FRAGMENT == null) { 442 rs.mElement_PROGRAM_FRAGMENT = createUser(rs, DataType.RS_PROGRAM_FRAGMENT); 443 } 444 return rs.mElement_PROGRAM_FRAGMENT; 445 } 446 447 public static Element PROGRAM_VERTEX(RenderScript rs) { 448 if(rs.mElement_PROGRAM_VERTEX == null) { 449 rs.mElement_PROGRAM_VERTEX = createUser(rs, DataType.RS_PROGRAM_VERTEX); 450 } 451 return rs.mElement_PROGRAM_VERTEX; 452 } 453 454 public static Element PROGRAM_RASTER(RenderScript rs) { 455 if(rs.mElement_PROGRAM_RASTER == null) { 456 rs.mElement_PROGRAM_RASTER = createUser(rs, DataType.RS_PROGRAM_RASTER); 457 } 458 return rs.mElement_PROGRAM_RASTER; 459 } 460 461 public static Element PROGRAM_STORE(RenderScript rs) { 462 if(rs.mElement_PROGRAM_STORE == null) { 463 rs.mElement_PROGRAM_STORE = createUser(rs, DataType.RS_PROGRAM_STORE); 464 } 465 return rs.mElement_PROGRAM_STORE; 466 } 467 468 public static Element FONT(RenderScript rs) { 469 if(rs.mElement_FONT == null) { 470 rs.mElement_FONT = createUser(rs, DataType.RS_FONT); 471 } 472 return rs.mElement_FONT; 473 } 474 475 476 public static Element A_8(RenderScript rs) { 477 if(rs.mElement_A_8 == null) { 478 rs.mElement_A_8 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_A); 479 } 480 return rs.mElement_A_8; 481 } 482 483 public static Element RGB_565(RenderScript rs) { 484 if(rs.mElement_RGB_565 == null) { 485 rs.mElement_RGB_565 = createPixel(rs, DataType.UNSIGNED_5_6_5, DataKind.PIXEL_RGB); 486 } 487 return rs.mElement_RGB_565; 488 } 489 490 public static Element RGB_888(RenderScript rs) { 491 if(rs.mElement_RGB_888 == null) { 492 rs.mElement_RGB_888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGB); 493 } 494 return rs.mElement_RGB_888; 495 } 496 497 public static Element RGBA_5551(RenderScript rs) { 498 if(rs.mElement_RGBA_5551 == null) { 499 rs.mElement_RGBA_5551 = createPixel(rs, DataType.UNSIGNED_5_5_5_1, DataKind.PIXEL_RGBA); 500 } 501 return rs.mElement_RGBA_5551; 502 } 503 504 public static Element RGBA_4444(RenderScript rs) { 505 if(rs.mElement_RGBA_4444 == null) { 506 rs.mElement_RGBA_4444 = createPixel(rs, DataType.UNSIGNED_4_4_4_4, DataKind.PIXEL_RGBA); 507 } 508 return rs.mElement_RGBA_4444; 509 } 510 511 public static Element RGBA_8888(RenderScript rs) { 512 if(rs.mElement_RGBA_8888 == null) { 513 rs.mElement_RGBA_8888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGBA); 514 } 515 return rs.mElement_RGBA_8888; 516 } 517 518 public static Element F32_2(RenderScript rs) { 519 if(rs.mElement_FLOAT_2 == null) { 520 rs.mElement_FLOAT_2 = createVector(rs, DataType.FLOAT_32, 2); 521 } 522 return rs.mElement_FLOAT_2; 523 } 524 525 public static Element F32_3(RenderScript rs) { 526 if(rs.mElement_FLOAT_3 == null) { 527 rs.mElement_FLOAT_3 = createVector(rs, DataType.FLOAT_32, 3); 528 } 529 return rs.mElement_FLOAT_3; 530 } 531 532 public static Element F32_4(RenderScript rs) { 533 if(rs.mElement_FLOAT_4 == null) { 534 rs.mElement_FLOAT_4 = createVector(rs, DataType.FLOAT_32, 4); 535 } 536 return rs.mElement_FLOAT_4; 537 } 538 539 public static Element F64_2(RenderScript rs) { 540 if(rs.mElement_DOUBLE_2 == null) { 541 rs.mElement_DOUBLE_2 = createVector(rs, DataType.FLOAT_64, 2); 542 } 543 return rs.mElement_DOUBLE_2; 544 } 545 546 public static Element F64_3(RenderScript rs) { 547 if(rs.mElement_DOUBLE_3 == null) { 548 rs.mElement_DOUBLE_3 = createVector(rs, DataType.FLOAT_64, 3); 549 } 550 return rs.mElement_DOUBLE_3; 551 } 552 553 public static Element F64_4(RenderScript rs) { 554 if(rs.mElement_DOUBLE_4 == null) { 555 rs.mElement_DOUBLE_4 = createVector(rs, DataType.FLOAT_64, 4); 556 } 557 return rs.mElement_DOUBLE_4; 558 } 559 560 public static Element U8_2(RenderScript rs) { 561 if(rs.mElement_UCHAR_2 == null) { 562 rs.mElement_UCHAR_2 = createVector(rs, DataType.UNSIGNED_8, 2); 563 } 564 return rs.mElement_UCHAR_2; 565 } 566 567 public static Element U8_3(RenderScript rs) { 568 if(rs.mElement_UCHAR_3 == null) { 569 rs.mElement_UCHAR_3 = createVector(rs, DataType.UNSIGNED_8, 3); 570 } 571 return rs.mElement_UCHAR_3; 572 } 573 574 public static Element U8_4(RenderScript rs) { 575 if(rs.mElement_UCHAR_4 == null) { 576 rs.mElement_UCHAR_4 = createVector(rs, DataType.UNSIGNED_8, 4); 577 } 578 return rs.mElement_UCHAR_4; 579 } 580 581 public static Element I8_2(RenderScript rs) { 582 if(rs.mElement_CHAR_2 == null) { 583 rs.mElement_CHAR_2 = createVector(rs, DataType.SIGNED_8, 2); 584 } 585 return rs.mElement_CHAR_2; 586 } 587 588 public static Element I8_3(RenderScript rs) { 589 if(rs.mElement_CHAR_3 == null) { 590 rs.mElement_CHAR_3 = createVector(rs, DataType.SIGNED_8, 3); 591 } 592 return rs.mElement_CHAR_3; 593 } 594 595 public static Element I8_4(RenderScript rs) { 596 if(rs.mElement_CHAR_4 == null) { 597 rs.mElement_CHAR_4 = createVector(rs, DataType.SIGNED_8, 4); 598 } 599 return rs.mElement_CHAR_4; 600 } 601 602 public static Element U16_2(RenderScript rs) { 603 if(rs.mElement_USHORT_2 == null) { 604 rs.mElement_USHORT_2 = createVector(rs, DataType.UNSIGNED_16, 2); 605 } 606 return rs.mElement_USHORT_2; 607 } 608 609 public static Element U16_3(RenderScript rs) { 610 if(rs.mElement_USHORT_3 == null) { 611 rs.mElement_USHORT_3 = createVector(rs, DataType.UNSIGNED_16, 3); 612 } 613 return rs.mElement_USHORT_3; 614 } 615 616 public static Element U16_4(RenderScript rs) { 617 if(rs.mElement_USHORT_4 == null) { 618 rs.mElement_USHORT_4 = createVector(rs, DataType.UNSIGNED_16, 4); 619 } 620 return rs.mElement_USHORT_4; 621 } 622 623 public static Element I16_2(RenderScript rs) { 624 if(rs.mElement_SHORT_2 == null) { 625 rs.mElement_SHORT_2 = createVector(rs, DataType.SIGNED_16, 2); 626 } 627 return rs.mElement_SHORT_2; 628 } 629 630 public static Element I16_3(RenderScript rs) { 631 if(rs.mElement_SHORT_3 == null) { 632 rs.mElement_SHORT_3 = createVector(rs, DataType.SIGNED_16, 3); 633 } 634 return rs.mElement_SHORT_3; 635 } 636 637 public static Element I16_4(RenderScript rs) { 638 if(rs.mElement_SHORT_4 == null) { 639 rs.mElement_SHORT_4 = createVector(rs, DataType.SIGNED_16, 4); 640 } 641 return rs.mElement_SHORT_4; 642 } 643 644 public static Element U32_2(RenderScript rs) { 645 if(rs.mElement_UINT_2 == null) { 646 rs.mElement_UINT_2 = createVector(rs, DataType.UNSIGNED_32, 2); 647 } 648 return rs.mElement_UINT_2; 649 } 650 651 public static Element U32_3(RenderScript rs) { 652 if(rs.mElement_UINT_3 == null) { 653 rs.mElement_UINT_3 = createVector(rs, DataType.UNSIGNED_32, 3); 654 } 655 return rs.mElement_UINT_3; 656 } 657 658 public static Element U32_4(RenderScript rs) { 659 if(rs.mElement_UINT_4 == null) { 660 rs.mElement_UINT_4 = createVector(rs, DataType.UNSIGNED_32, 4); 661 } 662 return rs.mElement_UINT_4; 663 } 664 665 public static Element I32_2(RenderScript rs) { 666 if(rs.mElement_INT_2 == null) { 667 rs.mElement_INT_2 = createVector(rs, DataType.SIGNED_32, 2); 668 } 669 return rs.mElement_INT_2; 670 } 671 672 public static Element I32_3(RenderScript rs) { 673 if(rs.mElement_INT_3 == null) { 674 rs.mElement_INT_3 = createVector(rs, DataType.SIGNED_32, 3); 675 } 676 return rs.mElement_INT_3; 677 } 678 679 public static Element I32_4(RenderScript rs) { 680 if(rs.mElement_INT_4 == null) { 681 rs.mElement_INT_4 = createVector(rs, DataType.SIGNED_32, 4); 682 } 683 return rs.mElement_INT_4; 684 } 685 686 public static Element U64_2(RenderScript rs) { 687 if(rs.mElement_ULONG_2 == null) { 688 rs.mElement_ULONG_2 = createVector(rs, DataType.UNSIGNED_64, 2); 689 } 690 return rs.mElement_ULONG_2; 691 } 692 693 public static Element U64_3(RenderScript rs) { 694 if(rs.mElement_ULONG_3 == null) { 695 rs.mElement_ULONG_3 = createVector(rs, DataType.UNSIGNED_64, 3); 696 } 697 return rs.mElement_ULONG_3; 698 } 699 700 public static Element U64_4(RenderScript rs) { 701 if(rs.mElement_ULONG_4 == null) { 702 rs.mElement_ULONG_4 = createVector(rs, DataType.UNSIGNED_64, 4); 703 } 704 return rs.mElement_ULONG_4; 705 } 706 707 public static Element I64_2(RenderScript rs) { 708 if(rs.mElement_LONG_2 == null) { 709 rs.mElement_LONG_2 = createVector(rs, DataType.SIGNED_64, 2); 710 } 711 return rs.mElement_LONG_2; 712 } 713 714 public static Element I64_3(RenderScript rs) { 715 if(rs.mElement_LONG_3 == null) { 716 rs.mElement_LONG_3 = createVector(rs, DataType.SIGNED_64, 3); 717 } 718 return rs.mElement_LONG_3; 719 } 720 721 public static Element I64_4(RenderScript rs) { 722 if(rs.mElement_LONG_4 == null) { 723 rs.mElement_LONG_4 = createVector(rs, DataType.SIGNED_64, 4); 724 } 725 return rs.mElement_LONG_4; 726 } 727 728 public static Element YUV(RenderScript rs) { 729 if (rs.mElement_YUV == null) { 730 rs.mElement_YUV = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_YUV); 731 } 732 return rs.mElement_YUV; 733 } 734 735 public static Element MATRIX_4X4(RenderScript rs) { 736 if(rs.mElement_MATRIX_4X4 == null) { 737 rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4); 738 } 739 return rs.mElement_MATRIX_4X4; 740 } 741 742 /** @deprecated use MATRIX_4X4 743 */ 744 public static Element MATRIX4X4(RenderScript rs) { 745 return MATRIX_4X4(rs); 746 } 747 748 public static Element MATRIX_3X3(RenderScript rs) { 749 if(rs.mElement_MATRIX_3X3 == null) { 750 rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3); 751 } 752 return rs.mElement_MATRIX_3X3; 753 } 754 755 public static Element MATRIX_2X2(RenderScript rs) { 756 if(rs.mElement_MATRIX_2X2 == null) { 757 rs.mElement_MATRIX_2X2 = createUser(rs, DataType.MATRIX_2X2); 758 } 759 return rs.mElement_MATRIX_2X2; 760 } 761 762 Element(int id, RenderScript rs, Element[] e, String[] n, int[] as) { 763 super(id, rs); 764 mSize = 0; 765 mVectorSize = 1; 766 mElements = e; 767 mElementNames = n; 768 mArraySizes = as; 769 mType = DataType.NONE; 770 mKind = DataKind.USER; 771 mOffsetInBytes = new int[mElements.length]; 772 for (int ct = 0; ct < mElements.length; ct++ ) { 773 mOffsetInBytes[ct] = mSize; 774 mSize += mElements[ct].mSize * mArraySizes[ct]; 775 } 776 updateVisibleSubElements(); 777 } 778 779 Element(int id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) { 780 super(id, rs); 781 if ((dt != DataType.UNSIGNED_5_6_5) && 782 (dt != DataType.UNSIGNED_4_4_4_4) && 783 (dt != DataType.UNSIGNED_5_5_5_1)) { 784 if (size == 3) { 785 mSize = dt.mSize * 4; 786 } else { 787 mSize = dt.mSize * size; 788 } 789 } else { 790 mSize = dt.mSize; 791 } 792 mType = dt; 793 mKind = dk; 794 mNormalized = norm; 795 mVectorSize = size; 796 } 797 798 Element(int id, RenderScript rs) { 799 super(id, rs); 800 } 801 802 @Override 803 void updateFromNative() { 804 super.updateFromNative(); 805 806 // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements 807 int[] dataBuffer = new int[5]; 808 mRS.nElementGetNativeData(getID(mRS), dataBuffer); 809 810 mNormalized = dataBuffer[2] == 1 ? true : false; 811 mVectorSize = dataBuffer[3]; 812 mSize = 0; 813 for (DataType dt: DataType.values()) { 814 if(dt.mID == dataBuffer[0]){ 815 mType = dt; 816 mSize = mType.mSize * mVectorSize; 817 } 818 } 819 for (DataKind dk: DataKind.values()) { 820 if(dk.mID == dataBuffer[1]){ 821 mKind = dk; 822 } 823 } 824 825 int numSubElements = dataBuffer[4]; 826 if(numSubElements > 0) { 827 mElements = new Element[numSubElements]; 828 mElementNames = new String[numSubElements]; 829 mArraySizes = new int[numSubElements]; 830 mOffsetInBytes = new int[numSubElements]; 831 832 int[] subElementIds = new int[numSubElements]; 833 mRS.nElementGetSubElements(getID(mRS), subElementIds, mElementNames, mArraySizes); 834 for(int i = 0; i < numSubElements; i ++) { 835 mElements[i] = new Element(subElementIds[i], mRS); 836 mElements[i].updateFromNative(); 837 mOffsetInBytes[i] = mSize; 838 mSize += mElements[i].mSize * mArraySizes[i]; 839 } 840 } 841 updateVisibleSubElements(); 842 } 843 844 /** 845 * Create a custom Element of the specified DataType. The DataKind will be 846 * set to USER and the vector size to 1 indicating non-vector. 847 * 848 * @param rs The context associated with the new Element. 849 * @param dt The DataType for the new element. 850 * @return Element 851 */ 852 static Element createUser(RenderScript rs, DataType dt) { 853 DataKind dk = DataKind.USER; 854 boolean norm = false; 855 int vecSize = 1; 856 int id = rs.nElementCreate(dt.mID, dk.mID, norm, vecSize); 857 return new Element(id, rs, dt, dk, norm, vecSize); 858 } 859 860 /** 861 * Create a custom vector element of the specified DataType and vector size. 862 * DataKind will be set to USER. Only primitive types (FLOAT_32, FLOAT_64, 863 * SIGNED_8, SIGNED_16, SIGNED_32, SIGNED_64, UNSIGNED_8, UNSIGNED_16, 864 * UNSIGNED_32, UNSIGNED_64, BOOLEAN) are supported. 865 * 866 * @param rs The context associated with the new Element. 867 * @param dt The DataType for the new Element. 868 * @param size Vector size for the new Element. Range 2-4 inclusive 869 * supported. 870 * 871 * @return Element 872 */ 873 public static Element createVector(RenderScript rs, DataType dt, int size) { 874 if (size < 2 || size > 4) { 875 throw new RSIllegalArgumentException("Vector size out of range 2-4."); 876 } 877 878 switch (dt) { 879 // Support only primitive integer/float/boolean types as vectors. 880 case FLOAT_32: 881 case FLOAT_64: 882 case SIGNED_8: 883 case SIGNED_16: 884 case SIGNED_32: 885 case SIGNED_64: 886 case UNSIGNED_8: 887 case UNSIGNED_16: 888 case UNSIGNED_32: 889 case UNSIGNED_64: 890 case BOOLEAN: { 891 DataKind dk = DataKind.USER; 892 boolean norm = false; 893 int id = rs.nElementCreate(dt.mID, dk.mID, norm, size); 894 return new Element(id, rs, dt, dk, norm, size); 895 } 896 897 default: { 898 throw new RSIllegalArgumentException("Cannot create vector of " + 899 "non-primitive type."); 900 } 901 } 902 } 903 904 /** 905 * Create a new pixel Element type. A matching DataType and DataKind must 906 * be provided. The DataType and DataKind must contain the same number of 907 * components. Vector size will be set to 1. 908 * 909 * @param rs The context associated with the new Element. 910 * @param dt The DataType for the new element. 911 * @param dk The DataKind to specify the mapping of each component in the 912 * DataType. 913 * 914 * @return Element 915 */ 916 public static Element createPixel(RenderScript rs, DataType dt, DataKind dk) { 917 if (!(dk == DataKind.PIXEL_L || 918 dk == DataKind.PIXEL_A || 919 dk == DataKind.PIXEL_LA || 920 dk == DataKind.PIXEL_RGB || 921 dk == DataKind.PIXEL_RGBA || 922 dk == DataKind.PIXEL_DEPTH || 923 dk == DataKind.PIXEL_YUV)) { 924 throw new RSIllegalArgumentException("Unsupported DataKind"); 925 } 926 if (!(dt == DataType.UNSIGNED_8 || 927 dt == DataType.UNSIGNED_16 || 928 dt == DataType.UNSIGNED_5_6_5 || 929 dt == DataType.UNSIGNED_4_4_4_4 || 930 dt == DataType.UNSIGNED_5_5_5_1)) { 931 throw new RSIllegalArgumentException("Unsupported DataType"); 932 } 933 if (dt == DataType.UNSIGNED_5_6_5 && dk != DataKind.PIXEL_RGB) { 934 throw new RSIllegalArgumentException("Bad kind and type combo"); 935 } 936 if (dt == DataType.UNSIGNED_5_5_5_1 && dk != DataKind.PIXEL_RGBA) { 937 throw new RSIllegalArgumentException("Bad kind and type combo"); 938 } 939 if (dt == DataType.UNSIGNED_4_4_4_4 && dk != DataKind.PIXEL_RGBA) { 940 throw new RSIllegalArgumentException("Bad kind and type combo"); 941 } 942 if (dt == DataType.UNSIGNED_16 && 943 dk != DataKind.PIXEL_DEPTH) { 944 throw new RSIllegalArgumentException("Bad kind and type combo"); 945 } 946 947 int size = 1; 948 switch (dk) { 949 case PIXEL_LA: 950 size = 2; 951 break; 952 case PIXEL_RGB: 953 size = 3; 954 break; 955 case PIXEL_RGBA: 956 size = 4; 957 break; 958 case PIXEL_DEPTH: 959 size = 2; 960 break; 961 } 962 963 boolean norm = true; 964 int id = rs.nElementCreate(dt.mID, dk.mID, norm, size); 965 return new Element(id, rs, dt, dk, norm, size); 966 } 967 968 /** 969 * Check if the current Element is compatible with another Element. 970 * Primitive Elements are compatible if they share the same underlying 971 * size and type (i.e. U8 is compatible with A_8). User-defined Elements 972 * must be equal in order to be compatible. This requires strict name 973 * equivalence for all sub-Elements (in addition to structural equivalence). 974 * 975 * @param e The Element to check compatibility with. 976 * 977 * @return boolean true if the Elements are compatible, otherwise false. 978 */ 979 public boolean isCompatible(Element e) { 980 // Try strict BaseObj equality to start with. 981 if (this.equals(e)) { 982 return true; 983 } 984 985 // Ignore mKind because it is allowed to be different (user vs. pixel). 986 // We also ignore mNormalized because it can be different. The mType 987 // field must not be NONE since we require name equivalence for 988 // all user-created Elements. 989 return ((mSize == e.mSize) && 990 (mType != DataType.NONE) && 991 (mType == e.mType) && 992 (mVectorSize == e.mVectorSize)); 993 } 994 995 /** 996 * Builder class for producing complex elements with matching field and name 997 * pairs. The builder starts empty. The order in which elements are added 998 * is retained for the layout in memory. 999 * 1000 */ 1001 public static class Builder { 1002 RenderScript mRS; 1003 Element[] mElements; 1004 String[] mElementNames; 1005 int[] mArraySizes; 1006 int mCount; 1007 int mSkipPadding; 1008 1009 /** 1010 * Create a builder object. 1011 * 1012 * @param rs 1013 */ 1014 public Builder(RenderScript rs) { 1015 mRS = rs; 1016 mCount = 0; 1017 mElements = new Element[8]; 1018 mElementNames = new String[8]; 1019 mArraySizes = new int[8]; 1020 } 1021 1022 /** 1023 * Add an array of elements to this element. 1024 * 1025 * @param element 1026 * @param name 1027 * @param arraySize 1028 */ 1029 public Builder add(Element element, String name, int arraySize) { 1030 if (arraySize < 1) { 1031 throw new RSIllegalArgumentException("Array size cannot be less than 1."); 1032 } 1033 1034 // Skip padding fields after a vector 3 type. 1035 if (mSkipPadding != 0) { 1036 if (name.startsWith("#padding_")) { 1037 mSkipPadding = 0; 1038 return this; 1039 } 1040 } 1041 1042 if (element.mVectorSize == 3) { 1043 mSkipPadding = 1; 1044 } else { 1045 mSkipPadding = 0; 1046 } 1047 1048 if(mCount == mElements.length) { 1049 Element[] e = new Element[mCount + 8]; 1050 String[] s = new String[mCount + 8]; 1051 int[] as = new int[mCount + 8]; 1052 System.arraycopy(mElements, 0, e, 0, mCount); 1053 System.arraycopy(mElementNames, 0, s, 0, mCount); 1054 System.arraycopy(mArraySizes, 0, as, 0, mCount); 1055 mElements = e; 1056 mElementNames = s; 1057 mArraySizes = as; 1058 } 1059 mElements[mCount] = element; 1060 mElementNames[mCount] = name; 1061 mArraySizes[mCount] = arraySize; 1062 mCount++; 1063 return this; 1064 } 1065 1066 /** 1067 * Add a single element to this Element. 1068 * 1069 * @param element 1070 * @param name 1071 */ 1072 public Builder add(Element element, String name) { 1073 return add(element, name, 1); 1074 } 1075 1076 /** 1077 * Create the element from this builder. 1078 * 1079 * 1080 * @return Element 1081 */ 1082 public Element create() { 1083 mRS.validate(); 1084 Element[] ein = new Element[mCount]; 1085 String[] sin = new String[mCount]; 1086 int[] asin = new int[mCount]; 1087 java.lang.System.arraycopy(mElements, 0, ein, 0, mCount); 1088 java.lang.System.arraycopy(mElementNames, 0, sin, 0, mCount); 1089 java.lang.System.arraycopy(mArraySizes, 0, asin, 0, mCount); 1090 1091 int[] ids = new int[ein.length]; 1092 for (int ct = 0; ct < ein.length; ct++ ) { 1093 ids[ct] = ein[ct].getID(mRS); 1094 } 1095 int id = mRS.nElementCreate2(ids, sin, asin); 1096 return new Element(id, mRS, ein, sin, asin); 1097 } 1098 } 1099} 1100 1101