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