1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.renderscript;
18
19import java.util.BitSet;
20
21/**
22 * Utility class for packing arguments and structures from Android system objects to
23 * RenderScript objects.
24 *
25 * This class is only intended to be used to support the
26 * reflected code generated by the RS tool chain.  It should not
27 * be called directly.
28 *
29 **/
30public class FieldPacker {
31    public FieldPacker(int len) {
32        mPos = 0;
33        mLen = len;
34        mData = new byte[len];
35        mAlignment = new BitSet();
36    }
37
38    public FieldPacker(byte[] data) {
39        // Advance mPos to the end of the buffer, since we are copying in the
40        // full data input.
41        mPos = data.length;
42        mLen = data.length;
43        mData = data;
44        mAlignment = new BitSet();
45        // TODO: We should either have an actual FieldPacker copy constructor
46        // or drop support for computing alignment like this. As it stands,
47        // subAlign() can never work correctly for copied FieldPacker objects.
48    }
49
50    static FieldPacker createFromArray(Object[] args) {
51        FieldPacker fp = new FieldPacker(RenderScript.sPointerSize * 8);
52        for (Object arg : args) {
53            fp.addSafely(arg);
54        }
55        fp.resize(fp.mPos);
56        return fp;
57    }
58
59    public void align(int v) {
60        if ((v <= 0) || ((v & (v - 1)) != 0)) {
61            throw new RSIllegalArgumentException("argument must be a non-negative non-zero power of 2: " + v);
62        }
63
64        while ((mPos & (v - 1)) != 0) {
65            mAlignment.flip(mPos);
66            mData[mPos++] = 0;
67        }
68    }
69
70    public void subalign(int v) {
71        if ((v & (v - 1)) != 0) {
72            throw new RSIllegalArgumentException("argument must be a non-negative non-zero power of 2: " + v);
73        }
74
75        while ((mPos & (v - 1)) != 0) {
76            mPos--;
77        }
78
79        if (mPos > 0) {
80            while (mAlignment.get(mPos - 1) == true) {
81                mPos--;
82                mAlignment.flip(mPos);
83            }
84        }
85
86    }
87
88    public void reset() {
89        mPos = 0;
90    }
91    public void reset(int i) {
92        if ((i < 0) || (i > mLen)) {
93            throw new RSIllegalArgumentException("out of range argument: " + i);
94        }
95        mPos = i;
96    }
97
98    public void skip(int i) {
99        int res = mPos + i;
100        if ((res < 0) || (res > mLen)) {
101            throw new RSIllegalArgumentException("out of range argument: " + i);
102        }
103        mPos = res;
104    }
105
106    public void addI8(byte v) {
107        mData[mPos++] = v;
108    }
109
110    public byte subI8() {
111        subalign(1);
112        return mData[--mPos];
113    }
114
115    public void addI16(short v) {
116        align(2);
117        mData[mPos++] = (byte)(v & 0xff);
118        mData[mPos++] = (byte)(v >> 8);
119    }
120
121    public short subI16() {
122        subalign(2);
123        short v = 0;
124        v = (short)((mData[--mPos] & 0xff) << 8);
125        v = (short)(v | (short)(mData[--mPos] & 0xff));
126        return v;
127    }
128
129
130    public void addI32(int v) {
131        align(4);
132        mData[mPos++] = (byte)(v & 0xff);
133        mData[mPos++] = (byte)((v >> 8) & 0xff);
134        mData[mPos++] = (byte)((v >> 16) & 0xff);
135        mData[mPos++] = (byte)((v >> 24) & 0xff);
136    }
137
138    public int subI32() {
139        subalign(4);
140        int v = 0;
141        v = ((mData[--mPos] & 0xff) << 24);
142        v = v | ((mData[--mPos] & 0xff) << 16);
143        v = v | ((mData[--mPos] & 0xff) << 8);
144        v = v | ((mData[--mPos] & 0xff));
145        return v;
146    }
147
148
149    public void addI64(long v) {
150        align(8);
151        mData[mPos++] = (byte)(v & 0xff);
152        mData[mPos++] = (byte)((v >> 8) & 0xff);
153        mData[mPos++] = (byte)((v >> 16) & 0xff);
154        mData[mPos++] = (byte)((v >> 24) & 0xff);
155        mData[mPos++] = (byte)((v >> 32) & 0xff);
156        mData[mPos++] = (byte)((v >> 40) & 0xff);
157        mData[mPos++] = (byte)((v >> 48) & 0xff);
158        mData[mPos++] = (byte)((v >> 56) & 0xff);
159    }
160
161    public long subI64() {
162        subalign(8);
163        long v = 0;
164        byte x = 0;
165        x = ((mData[--mPos]));
166        v = (long)(v | (((long)x) & 0xff) << 56l);
167        x = ((mData[--mPos]));
168        v = (long)(v | (((long)x) & 0xff) << 48l);
169        x = ((mData[--mPos]));
170        v = (long)(v | (((long)x) & 0xff) << 40l);
171        x = ((mData[--mPos]));
172        v = (long)(v | (((long)x) & 0xff) << 32l);
173        x = ((mData[--mPos]));
174        v = (long)(v | (((long)x) & 0xff) << 24l);
175        x = ((mData[--mPos]));
176        v = (long)(v | (((long)x) & 0xff) << 16l);
177        x = ((mData[--mPos]));
178        v = (long)(v | (((long)x) & 0xff) << 8l);
179        x = ((mData[--mPos]));
180        v = (long)(v | (((long)x) & 0xff));
181        return v;
182    }
183
184    public void addU8(short v) {
185        if ((v < 0) || (v > 0xff)) {
186            android.util.Log.e("rs", "FieldPacker.addU8( " + v + " )");
187            throw new IllegalArgumentException("Saving value out of range for type");
188        }
189        mData[mPos++] = (byte)v;
190    }
191
192    public void addU16(int v) {
193        if ((v < 0) || (v > 0xffff)) {
194            android.util.Log.e("rs", "FieldPacker.addU16( " + v + " )");
195            throw new IllegalArgumentException("Saving value out of range for type");
196        }
197        align(2);
198        mData[mPos++] = (byte)(v & 0xff);
199        mData[mPos++] = (byte)(v >> 8);
200    }
201
202    public void addU32(long v) {
203        if ((v < 0) || (v > 0xffffffffL)) {
204            android.util.Log.e("rs", "FieldPacker.addU32( " + v + " )");
205            throw new IllegalArgumentException("Saving value out of range for type");
206        }
207        align(4);
208        mData[mPos++] = (byte)(v & 0xff);
209        mData[mPos++] = (byte)((v >> 8) & 0xff);
210        mData[mPos++] = (byte)((v >> 16) & 0xff);
211        mData[mPos++] = (byte)((v >> 24) & 0xff);
212    }
213
214    public void addU64(long v) {
215        if (v < 0) {
216            android.util.Log.e("rs", "FieldPacker.addU64( " + v + " )");
217            throw new IllegalArgumentException("Saving value out of range for type");
218        }
219        align(8);
220        mData[mPos++] = (byte)(v & 0xff);
221        mData[mPos++] = (byte)((v >> 8) & 0xff);
222        mData[mPos++] = (byte)((v >> 16) & 0xff);
223        mData[mPos++] = (byte)((v >> 24) & 0xff);
224        mData[mPos++] = (byte)((v >> 32) & 0xff);
225        mData[mPos++] = (byte)((v >> 40) & 0xff);
226        mData[mPos++] = (byte)((v >> 48) & 0xff);
227        mData[mPos++] = (byte)((v >> 56) & 0xff);
228    }
229
230    public void addF32(float v) {
231        addI32(Float.floatToRawIntBits(v));
232    }
233
234    public float subF32() {
235        return Float.intBitsToFloat(subI32());
236    }
237
238    public void addF64(double v) {
239        addI64(Double.doubleToRawLongBits(v));
240    }
241
242    public double subF64() {
243        return Double.longBitsToDouble(subI64());
244    }
245
246    public void addObj(BaseObj obj) {
247        if (obj != null) {
248            if (RenderScript.sPointerSize == 8) {
249                addI64(obj.getID(null));
250                addI64(0);
251                addI64(0);
252                addI64(0);
253            } else {
254                addI32((int)obj.getID(null));
255            }
256        } else {
257            if (RenderScript.sPointerSize == 8) {
258                addI64(0);
259                addI64(0);
260                addI64(0);
261                addI64(0);
262            } else {
263                addI32(0);
264            }
265        }
266    }
267
268    public void addF32(Float2 v) {
269        addF32(v.x);
270        addF32(v.y);
271    }
272    public void addF32(Float3 v) {
273        addF32(v.x);
274        addF32(v.y);
275        addF32(v.z);
276    }
277    public void addF32(Float4 v) {
278        addF32(v.x);
279        addF32(v.y);
280        addF32(v.z);
281        addF32(v.w);
282    }
283
284    public void addF64(Double2 v) {
285        addF64(v.x);
286        addF64(v.y);
287    }
288    public void addF64(Double3 v) {
289        addF64(v.x);
290        addF64(v.y);
291        addF64(v.z);
292    }
293    public void addF64(Double4 v) {
294        addF64(v.x);
295        addF64(v.y);
296        addF64(v.z);
297        addF64(v.w);
298    }
299
300    public void addI8(Byte2 v) {
301        addI8(v.x);
302        addI8(v.y);
303    }
304    public void addI8(Byte3 v) {
305        addI8(v.x);
306        addI8(v.y);
307        addI8(v.z);
308    }
309    public void addI8(Byte4 v) {
310        addI8(v.x);
311        addI8(v.y);
312        addI8(v.z);
313        addI8(v.w);
314    }
315
316    public void addU8(Short2 v) {
317        addU8(v.x);
318        addU8(v.y);
319    }
320    public void addU8(Short3 v) {
321        addU8(v.x);
322        addU8(v.y);
323        addU8(v.z);
324    }
325    public void addU8(Short4 v) {
326        addU8(v.x);
327        addU8(v.y);
328        addU8(v.z);
329        addU8(v.w);
330    }
331
332    public void addI16(Short2 v) {
333        addI16(v.x);
334        addI16(v.y);
335    }
336    public void addI16(Short3 v) {
337        addI16(v.x);
338        addI16(v.y);
339        addI16(v.z);
340    }
341    public void addI16(Short4 v) {
342        addI16(v.x);
343        addI16(v.y);
344        addI16(v.z);
345        addI16(v.w);
346    }
347
348    public void addU16(Int2 v) {
349        addU16(v.x);
350        addU16(v.y);
351    }
352    public void addU16(Int3 v) {
353        addU16(v.x);
354        addU16(v.y);
355        addU16(v.z);
356    }
357    public void addU16(Int4 v) {
358        addU16(v.x);
359        addU16(v.y);
360        addU16(v.z);
361        addU16(v.w);
362    }
363
364    public void addI32(Int2 v) {
365        addI32(v.x);
366        addI32(v.y);
367    }
368    public void addI32(Int3 v) {
369        addI32(v.x);
370        addI32(v.y);
371        addI32(v.z);
372    }
373    public void addI32(Int4 v) {
374        addI32(v.x);
375        addI32(v.y);
376        addI32(v.z);
377        addI32(v.w);
378    }
379
380    public void addU32(Long2 v) {
381        addU32(v.x);
382        addU32(v.y);
383    }
384    public void addU32(Long3 v) {
385        addU32(v.x);
386        addU32(v.y);
387        addU32(v.z);
388    }
389    public void addU32(Long4 v) {
390        addU32(v.x);
391        addU32(v.y);
392        addU32(v.z);
393        addU32(v.w);
394    }
395
396    public void addI64(Long2 v) {
397        addI64(v.x);
398        addI64(v.y);
399    }
400    public void addI64(Long3 v) {
401        addI64(v.x);
402        addI64(v.y);
403        addI64(v.z);
404    }
405    public void addI64(Long4 v) {
406        addI64(v.x);
407        addI64(v.y);
408        addI64(v.z);
409        addI64(v.w);
410    }
411
412    public void addU64(Long2 v) {
413        addU64(v.x);
414        addU64(v.y);
415    }
416    public void addU64(Long3 v) {
417        addU64(v.x);
418        addU64(v.y);
419        addU64(v.z);
420    }
421    public void addU64(Long4 v) {
422        addU64(v.x);
423        addU64(v.y);
424        addU64(v.z);
425        addU64(v.w);
426    }
427
428
429    public Float2 subFloat2() {
430        Float2 v = new Float2();
431        v.y = subF32();
432        v.x = subF32();
433        return v;
434    }
435    public Float3 subFloat3() {
436        Float3 v = new Float3();
437        v.z = subF32();
438        v.y = subF32();
439        v.x = subF32();
440        return v;
441    }
442    public Float4 subFloat4() {
443        Float4 v = new Float4();
444        v.w = subF32();
445        v.z = subF32();
446        v.y = subF32();
447        v.x = subF32();
448        return v;
449    }
450
451    public Double2 subDouble2() {
452        Double2 v = new Double2();
453        v.y = subF64();
454        v.x = subF64();
455        return v;
456    }
457    public Double3 subDouble3() {
458        Double3 v = new Double3();
459        v.z = subF64();
460        v.y = subF64();
461        v.x = subF64();
462        return v;
463    }
464    public Double4 subDouble4() {
465        Double4 v = new Double4();
466        v.w = subF64();
467        v.z = subF64();
468        v.y = subF64();
469        v.x = subF64();
470        return v;
471    }
472
473    public Byte2 subByte2() {
474        Byte2 v = new Byte2();
475        v.y = subI8();
476        v.x = subI8();
477        return v;
478    }
479    public Byte3 subByte3() {
480        Byte3 v = new Byte3();
481        v.z = subI8();
482        v.y = subI8();
483        v.x = subI8();
484        return v;
485    }
486    public Byte4 subByte4() {
487        Byte4 v = new Byte4();
488        v.w = subI8();
489        v.z = subI8();
490        v.y = subI8();
491        v.x = subI8();
492        return v;
493    }
494
495    public Short2 subShort2() {
496        Short2 v = new Short2();
497        v.y = subI16();
498        v.x = subI16();
499        return v;
500    }
501    public Short3 subShort3() {
502        Short3 v = new Short3();
503        v.z = subI16();
504        v.y = subI16();
505        v.x = subI16();
506        return v;
507    }
508    public Short4 subShort4() {
509        Short4 v = new Short4();
510        v.w = subI16();
511        v.z = subI16();
512        v.y = subI16();
513        v.x = subI16();
514        return v;
515    }
516
517    public Int2 subInt2() {
518        Int2 v = new Int2();
519        v.y = subI32();
520        v.x = subI32();
521        return v;
522    }
523    public Int3 subInt3() {
524        Int3 v = new Int3();
525        v.z = subI32();
526        v.y = subI32();
527        v.x = subI32();
528        return v;
529    }
530    public Int4 subInt4() {
531        Int4 v = new Int4();
532        v.w = subI32();
533        v.z = subI32();
534        v.y = subI32();
535        v.x = subI32();
536        return v;
537    }
538
539    public Long2 subLong2() {
540        Long2 v = new Long2();
541        v.y = subI64();
542        v.x = subI64();
543        return v;
544    }
545    public Long3 subLong3() {
546        Long3 v = new Long3();
547        v.z = subI64();
548        v.y = subI64();
549        v.x = subI64();
550        return v;
551    }
552    public Long4 subLong4() {
553        Long4 v = new Long4();
554        v.w = subI64();
555        v.z = subI64();
556        v.y = subI64();
557        v.x = subI64();
558        return v;
559    }
560
561
562
563    public void addMatrix(Matrix4f v) {
564        for (int i=0; i < v.mMat.length; i++) {
565            addF32(v.mMat[i]);
566        }
567    }
568
569    public Matrix4f subMatrix4f() {
570        Matrix4f v = new Matrix4f();
571        for (int i = v.mMat.length - 1; i >= 0; i--) {
572            v.mMat[i] = subF32();
573        }
574        return v;
575    }
576
577    public void addMatrix(Matrix3f v) {
578        for (int i=0; i < v.mMat.length; i++) {
579            addF32(v.mMat[i]);
580        }
581    }
582
583    public Matrix3f subMatrix3f() {
584        Matrix3f v = new Matrix3f();
585        for (int i = v.mMat.length - 1; i >= 0; i--) {
586            v.mMat[i] = subF32();
587        }
588        return v;
589    }
590
591    public void addMatrix(Matrix2f v) {
592        for (int i=0; i < v.mMat.length; i++) {
593            addF32(v.mMat[i]);
594        }
595    }
596
597    public Matrix2f subMatrix2f() {
598        Matrix2f v = new Matrix2f();
599        for (int i = v.mMat.length - 1; i >= 0; i--) {
600            v.mMat[i] = subF32();
601        }
602        return v;
603    }
604
605    public void addBoolean(boolean v) {
606        addI8((byte)(v ? 1 : 0));
607    }
608
609    public boolean subBoolean() {
610        byte v = subI8();
611        if (v == 1) {
612            return true;
613        }
614        return false;
615    }
616
617    public final byte[] getData() {
618        return mData;
619    }
620
621    /**
622     * Get the actual length used for the FieldPacker.
623     *
624     * @hide
625     */
626    public int getPos() {
627        return mPos;
628    }
629
630    private void add(Object obj) {
631        if (obj instanceof Boolean) {
632            addBoolean((Boolean)obj);
633            return;
634        }
635
636        if (obj instanceof Byte) {
637            addI8((Byte)obj);
638            return;
639        }
640
641        if (obj instanceof Short) {
642            addI16((Short)obj);
643            return;
644        }
645
646        if (obj instanceof Integer) {
647            addI32((Integer)obj);
648            return;
649        }
650
651        if (obj instanceof Long) {
652            addI64((Long)obj);
653            return;
654        }
655
656        if (obj instanceof Float) {
657            addF32((Float)obj);
658            return;
659        }
660
661        if (obj instanceof Double) {
662            addF64((Double)obj);
663            return;
664        }
665
666        if (obj instanceof Byte2) {
667            addI8((Byte2)obj);
668            return;
669        }
670
671        if (obj instanceof Byte3) {
672            addI8((Byte3)obj);
673            return;
674        }
675
676        if (obj instanceof Byte4) {
677            addI8((Byte4)obj);
678            return;
679        }
680
681        if (obj instanceof Short2) {
682            addI16((Short2)obj);
683            return;
684        }
685
686        if (obj instanceof Short3) {
687            addI16((Short3)obj);
688            return;
689        }
690
691        if (obj instanceof Short4) {
692            addI16((Short4)obj);
693            return;
694        }
695
696        if (obj instanceof Int2) {
697            addI32((Int2)obj);
698            return;
699        }
700
701        if (obj instanceof Int3) {
702            addI32((Int3)obj);
703            return;
704        }
705
706        if (obj instanceof Int4) {
707            addI32((Int4)obj);
708            return;
709        }
710
711        if (obj instanceof Long2) {
712            addI64((Long2)obj);
713            return;
714        }
715
716        if (obj instanceof Long3) {
717            addI64((Long3)obj);
718            return;
719        }
720
721        if (obj instanceof Long4) {
722            addI64((Long4)obj);
723            return;
724        }
725
726        if (obj instanceof Float2) {
727            addF32((Float2)obj);
728            return;
729        }
730
731        if (obj instanceof Float3) {
732            addF32((Float3)obj);
733            return;
734        }
735
736        if (obj instanceof Float4) {
737            addF32((Float4)obj);
738            return;
739        }
740
741        if (obj instanceof Double2) {
742            addF64((Double2)obj);
743            return;
744        }
745
746        if (obj instanceof Double3) {
747            addF64((Double3)obj);
748            return;
749        }
750
751        if (obj instanceof Double4) {
752            addF64((Double4)obj);
753            return;
754        }
755
756        if (obj instanceof Matrix2f) {
757            addMatrix((Matrix2f)obj);
758            return;
759        }
760
761        if (obj instanceof Matrix3f) {
762            addMatrix((Matrix3f)obj);
763            return;
764        }
765
766        if (obj instanceof Matrix4f) {
767            addMatrix((Matrix4f)obj);
768            return;
769        }
770
771        if (obj instanceof BaseObj) {
772            addObj((BaseObj)obj);
773            return;
774        }
775    }
776
777    private boolean resize(int newSize) {
778        if (newSize == mLen) {
779            return false;
780        }
781
782        byte[] newData = new byte[newSize];
783        System.arraycopy(mData, 0, newData, 0, mPos);
784        mData = newData;
785        mLen = newSize;
786        return true;
787    }
788
789    private void addSafely(Object obj) {
790        boolean retry;
791        final int oldPos = mPos;
792        do {
793            retry = false;
794            try {
795                add(obj);
796            } catch (ArrayIndexOutOfBoundsException e) {
797                mPos = oldPos;
798                resize(mLen * 2);
799                retry = true;
800            }
801        } while (retry);
802    }
803
804    private byte mData[];
805    private int mPos;
806    private int mLen;
807    private BitSet mAlignment;
808}
809