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
17package android.renderscript;
18
19import android.util.SparseArray;
20
21/**
22 * The parent class for all executable scripts. This should not be used by
23 * applications.
24 **/
25public class Script extends BaseObj {
26
27    /**
28     * KernelID is an identifier for a Script + root function pair. It is used
29     * as an identifier for ScriptGroup creation.
30     *
31     * This class should not be directly created. Instead use the method in the
32     * reflected or intrinsic code "getKernelID_funcname()".
33     *
34     */
35    public static final class KernelID extends BaseObj {
36        Script mScript;
37        int mSlot;
38        int mSig;
39        KernelID(long id, RenderScript rs, Script s, int slot, int sig) {
40            super(id, rs);
41            mScript = s;
42            mSlot = slot;
43            mSig = sig;
44        }
45    }
46
47    private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>();
48    /**
49     * Only to be used by generated reflected classes.
50     */
51    protected KernelID createKernelID(int slot, int sig, Element ein, Element eout) {
52        KernelID k = mKIDs.get(slot);
53        if (k != null) {
54            return k;
55        }
56
57        long id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig);
58        if (id == 0) {
59            throw new RSDriverException("Failed to create KernelID");
60        }
61
62        k = new KernelID(id, mRS, this, slot, sig);
63        mKIDs.put(slot, k);
64        return k;
65    }
66
67    /**
68     * FieldID is an identifier for a Script + exported field pair. It is used
69     * as an identifier for ScriptGroup creation.
70     *
71     * This class should not be directly created. Instead use the method in the
72     * reflected or intrinsic code "getFieldID_funcname()".
73     *
74     */
75    public static final class FieldID extends BaseObj {
76        Script mScript;
77        int mSlot;
78        FieldID(long id, RenderScript rs, Script s, int slot) {
79            super(id, rs);
80            mScript = s;
81            mSlot = slot;
82        }
83    }
84
85    private final SparseArray<FieldID> mFIDs = new SparseArray();
86    /**
87     * Only to be used by generated reflected classes.
88     */
89    protected FieldID createFieldID(int slot, Element e) {
90        FieldID f = mFIDs.get(slot);
91        if (f != null) {
92            return f;
93        }
94
95        long id = mRS.nScriptFieldIDCreate(getID(mRS), slot);
96        if (id == 0) {
97            throw new RSDriverException("Failed to create FieldID");
98        }
99
100        f = new FieldID(id, mRS, this, slot);
101        mFIDs.put(slot, f);
102        return f;
103    }
104
105
106    /**
107     * Only intended for use by generated reflected code.
108     *
109     */
110    protected void invoke(int slot) {
111        mRS.nScriptInvoke(getID(mRS), slot);
112    }
113
114    /**
115     * Only intended for use by generated reflected code.
116     *
117     */
118    protected void invoke(int slot, FieldPacker v) {
119        if (v != null) {
120            mRS.nScriptInvokeV(getID(mRS), slot, v.getData());
121        } else {
122            mRS.nScriptInvoke(getID(mRS), slot);
123        }
124    }
125
126    /**
127     * Only intended for use by generated reflected code.
128     *
129     */
130    protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v) {
131        mRS.validate();
132        mRS.validateObject(ain);
133        mRS.validateObject(aout);
134        if (ain == null && aout == null) {
135            throw new RSIllegalArgumentException(
136                "At least one of ain or aout is required to be non-null.");
137        }
138        long in_id = 0;
139        if (ain != null) {
140            in_id = ain.getID(mRS);
141        }
142        long out_id = 0;
143        if (aout != null) {
144            out_id = aout.getID(mRS);
145        }
146        byte[] params = null;
147        if (v != null) {
148            params = v.getData();
149        }
150        mRS.nScriptForEach(getID(mRS), slot, in_id, out_id, params);
151    }
152
153    /**
154     * Only intended for use by generated reflected code.
155     *
156     */
157    protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v, LaunchOptions sc) {
158        mRS.validate();
159        mRS.validateObject(ain);
160        mRS.validateObject(aout);
161        if (ain == null && aout == null) {
162            throw new RSIllegalArgumentException(
163                "At least one of ain or aout is required to be non-null.");
164        }
165
166        if (sc == null) {
167            forEach(slot, ain, aout, v);
168            return;
169        }
170        long in_id = 0;
171        if (ain != null) {
172            in_id = ain.getID(mRS);
173        }
174        long out_id = 0;
175        if (aout != null) {
176            out_id = aout.getID(mRS);
177        }
178        byte[] params = null;
179        if (v != null) {
180            params = v.getData();
181        }
182        mRS.nScriptForEachClipped(getID(mRS), slot, in_id, out_id, params, sc.xstart, sc.xend, sc.ystart, sc.yend, sc.zstart, sc.zend);
183    }
184
185    /**
186     * Only intended for use by generated reflected code.
187     *
188     * @hide
189     */
190    protected void forEach(int slot, Allocation[] ains, Allocation aout, FieldPacker v) {
191        forEach(slot, ains, aout, v, new LaunchOptions());
192    }
193
194    /**
195     * Only intended for use by generated reflected code.
196     *
197     * @hide
198     */
199    protected void forEach(int slot, Allocation[] ains, Allocation aout, FieldPacker v, LaunchOptions sc) {
200        mRS.validate();
201
202        for (Allocation ain : ains) {
203          mRS.validateObject(ain);
204        }
205
206        mRS.validateObject(aout);
207        if (ains == null && aout == null) {
208            throw new RSIllegalArgumentException(
209                "At least one of ain or aout is required to be non-null.");
210        }
211
212        if (sc == null) {
213            forEach(slot, ains, aout, v);
214            return;
215        }
216
217        long[] in_ids = new long[ains.length];
218        for (int index = 0; index < ains.length; ++index) {
219            in_ids[index] = ains[index].getID(mRS);
220        }
221
222        long out_id = 0;
223        if (aout != null) {
224            out_id = aout.getID(mRS);
225        }
226        byte[] params = null;
227        if (v != null) {
228            params = v.getData();
229        }
230        mRS.nScriptForEachMultiClipped(getID(mRS), slot, in_ids, out_id, params, sc.xstart, sc.xend, sc.ystart, sc.yend, sc.zstart, sc.zend);
231    }
232
233    Script(long id, RenderScript rs) {
234        super(id, rs);
235    }
236
237
238    /**
239     * Only intended for use by generated reflected code.
240     *
241     */
242    public void bindAllocation(Allocation va, int slot) {
243        mRS.validate();
244        mRS.validateObject(va);
245        if (va != null) {
246            if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 20) {
247                final Type t = va.mType;
248                if (t.hasMipmaps() || t.hasFaces() || (t.getY() != 0) || (t.getZ() != 0)) {
249                    throw new RSIllegalArgumentException(
250                        "API 20+ only allows simple 1D allocations to be used with bind.");
251                }
252            }
253            mRS.nScriptBindAllocation(getID(mRS), va.getID(mRS), slot);
254        } else {
255            mRS.nScriptBindAllocation(getID(mRS), 0, slot);
256        }
257    }
258
259    /**
260     * Only intended for use by generated reflected code.
261     *
262     */
263    public void setVar(int index, float v) {
264        mRS.nScriptSetVarF(getID(mRS), index, v);
265    }
266    public float getVarF(int index) {
267        return mRS.nScriptGetVarF(getID(mRS), index);
268    }
269
270    /**
271     * Only intended for use by generated reflected code.
272     *
273     */
274    public void setVar(int index, double v) {
275        mRS.nScriptSetVarD(getID(mRS), index, v);
276    }
277    public double getVarD(int index) {
278        return mRS.nScriptGetVarD(getID(mRS), index);
279    }
280
281    /**
282     * Only intended for use by generated reflected code.
283     *
284     */
285    public void setVar(int index, int v) {
286        mRS.nScriptSetVarI(getID(mRS), index, v);
287    }
288    public int getVarI(int index) {
289        return mRS.nScriptGetVarI(getID(mRS), index);
290    }
291
292
293    /**
294     * Only intended for use by generated reflected code.
295     *
296     */
297    public void setVar(int index, long v) {
298        mRS.nScriptSetVarJ(getID(mRS), index, v);
299    }
300    public long getVarJ(int index) {
301        return mRS.nScriptGetVarJ(getID(mRS), index);
302    }
303
304
305    /**
306     * Only intended for use by generated reflected code.
307     *
308     */
309    public void setVar(int index, boolean v) {
310        mRS.nScriptSetVarI(getID(mRS), index, v ? 1 : 0);
311    }
312    public boolean getVarB(int index) {
313        return mRS.nScriptGetVarI(getID(mRS), index) > 0 ? true : false;
314    }
315
316    /**
317     * Only intended for use by generated reflected code.
318     *
319     */
320    public void setVar(int index, BaseObj o) {
321        mRS.validate();
322        mRS.validateObject(o);
323        mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS));
324    }
325
326    /**
327     * Only intended for use by generated reflected code.
328     *
329     */
330    public void setVar(int index, FieldPacker v) {
331        mRS.nScriptSetVarV(getID(mRS), index, v.getData());
332    }
333
334    /**
335     * Only intended for use by generated reflected code.
336     *
337     */
338    public void setVar(int index, FieldPacker v, Element e, int[] dims) {
339        mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), e.getID(mRS), dims);
340    }
341
342    /**
343     * Only intended for use by generated reflected code.
344     *
345     */
346    public void getVarV(int index, FieldPacker v) {
347        mRS.nScriptGetVarV(getID(mRS), index, v.getData());
348    }
349
350    public void setTimeZone(String timeZone) {
351        mRS.validate();
352        try {
353            mRS.nScriptSetTimeZone(getID(mRS), timeZone.getBytes("UTF-8"));
354        } catch (java.io.UnsupportedEncodingException e) {
355            throw new RuntimeException(e);
356        }
357    }
358
359    /**
360     * Only intended for use by generated reflected code.
361     *
362     */
363    public static class Builder {
364        RenderScript mRS;
365
366        Builder(RenderScript rs) {
367            mRS = rs;
368        }
369    }
370
371
372    /**
373     * Only intended for use by generated reflected code.
374     *
375     */
376    public static class FieldBase {
377        protected Element mElement;
378        protected Allocation mAllocation;
379
380        protected void init(RenderScript rs, int dimx) {
381            mAllocation = Allocation.createSized(rs, mElement, dimx, Allocation.USAGE_SCRIPT);
382        }
383
384        protected void init(RenderScript rs, int dimx, int usages) {
385            mAllocation = Allocation.createSized(rs, mElement, dimx, Allocation.USAGE_SCRIPT | usages);
386        }
387
388        protected FieldBase() {
389        }
390
391        public Element getElement() {
392            return mElement;
393        }
394
395        public Type getType() {
396            return mAllocation.getType();
397        }
398
399        public Allocation getAllocation() {
400            return mAllocation;
401        }
402
403        //@Override
404        public void updateAllocation() {
405        }
406    }
407
408
409    /**
410     * Class used to specify clipping for a kernel launch.
411     *
412     */
413    public static final class LaunchOptions {
414        private int xstart = 0;
415        private int ystart = 0;
416        private int xend = 0;
417        private int yend = 0;
418        private int zstart = 0;
419        private int zend = 0;
420        private int strategy;
421
422        /**
423         * Set the X range.  If the end value is set to 0 the X dimension is not
424         * clipped.
425         *
426         * @param xstartArg Must be >= 0
427         * @param xendArg Must be >= xstartArg
428         *
429         * @return LaunchOptions
430         */
431        public LaunchOptions setX(int xstartArg, int xendArg) {
432            if (xstartArg < 0 || xendArg <= xstartArg) {
433                throw new RSIllegalArgumentException("Invalid dimensions");
434            }
435            xstart = xstartArg;
436            xend = xendArg;
437            return this;
438        }
439
440        /**
441         * Set the Y range.  If the end value is set to 0 the Y dimension is not
442         * clipped.
443         *
444         * @param ystartArg Must be >= 0
445         * @param yendArg Must be >= ystartArg
446         *
447         * @return LaunchOptions
448         */
449        public LaunchOptions setY(int ystartArg, int yendArg) {
450            if (ystartArg < 0 || yendArg <= ystartArg) {
451                throw new RSIllegalArgumentException("Invalid dimensions");
452            }
453            ystart = ystartArg;
454            yend = yendArg;
455            return this;
456        }
457
458        /**
459         * Set the Z range.  If the end value is set to 0 the Z dimension is not
460         * clipped.
461         *
462         * @param zstartArg Must be >= 0
463         * @param zendArg Must be >= zstartArg
464         *
465         * @return LaunchOptions
466         */
467        public LaunchOptions setZ(int zstartArg, int zendArg) {
468            if (zstartArg < 0 || zendArg <= zstartArg) {
469                throw new RSIllegalArgumentException("Invalid dimensions");
470            }
471            zstart = zstartArg;
472            zend = zendArg;
473            return this;
474        }
475
476
477        /**
478         * Returns the current X start
479         *
480         * @return int current value
481         */
482        public int getXStart() {
483            return xstart;
484        }
485        /**
486         * Returns the current X end
487         *
488         * @return int current value
489         */
490        public int getXEnd() {
491            return xend;
492        }
493        /**
494         * Returns the current Y start
495         *
496         * @return int current value
497         */
498        public int getYStart() {
499            return ystart;
500        }
501        /**
502         * Returns the current Y end
503         *
504         * @return int current value
505         */
506        public int getYEnd() {
507            return yend;
508        }
509        /**
510         * Returns the current Z start
511         *
512         * @return int current value
513         */
514        public int getZStart() {
515            return zstart;
516        }
517        /**
518         * Returns the current Z end
519         *
520         * @return int current value
521         */
522        public int getZEnd() {
523            return zend;
524        }
525
526    }
527}
528