• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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