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