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