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