RenderScript.java revision a33549e51d1ba585a349bbf7b49cd32dbca0def3
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.support.v8.renderscript;
18
19import java.io.File;
20import java.lang.reflect.Field;
21import java.lang.reflect.Method;
22import java.util.concurrent.locks.ReentrantReadWriteLock;
23
24import android.content.Context;
25import android.content.pm.ApplicationInfo;
26import android.content.pm.PackageManager;
27import android.content.res.AssetManager;
28import android.graphics.Bitmap;
29import android.graphics.BitmapFactory;
30import android.os.Process;
31import android.util.Log;
32import android.view.Surface;
33
34import android.os.SystemProperties;
35
36/**
37 * This class provides access to a RenderScript context, which controls RenderScript
38 * initialization, resource management, and teardown. An instance of the RenderScript
39 * class must be created before any other RS objects can be created.
40 *
41 * <div class="special reference">
42 * <h3>Developer Guides</h3>
43 * <p>For more information about creating an application that uses RenderScript, read the
44 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
45 * </div>
46 **/
47public class RenderScript {
48    static final String LOG_TAG = "RenderScript_jni";
49    static final boolean DEBUG  = false;
50    @SuppressWarnings({"UnusedDeclaration", "deprecation"})
51    static final boolean LOG_ENABLED = false;
52
53    private Context mApplicationContext;
54
55    /*
56     * We use a class initializer to allow the native code to cache some
57     * field offsets.
58     */
59    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
60    static boolean sInitialized;
61    static boolean sUseGCHooks;
62    static Object sRuntime;
63    static Method registerNativeAllocation;
64    static Method registerNativeFree;
65
66    static Object lock = new Object();
67
68    // Non-threadsafe functions.
69    native int  nDeviceCreate();
70    native void nDeviceDestroy(int dev);
71    native void nDeviceSetConfig(int dev, int param, int value);
72    native int nContextGetUserMessage(int con, int[] data);
73    native String nContextGetErrorMessage(int con);
74    native int  nContextPeekMessage(int con, int[] subID);
75    native void nContextInitToClient(int con);
76    native void nContextDeinitToClient(int con);
77
78    static boolean isNative = false;
79
80
81    static private int thunk = 0;
82    static private int sSdkVersion = -1;
83
84    /**
85     * Determines whether or not we should be thunking into the native
86     * RenderScript layer or actually using the compatibility library.
87     */
88    static private boolean setupThunk(int sdkVersion) {
89        if (thunk == 0) {
90            // use compat on Jelly Bean MR2 if we're requesting SDK 19+
91            if (android.os.Build.VERSION.SDK_INT == 18 && sdkVersion >= 19) {
92                thunk = -1;
93            }
94            else if ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
95                && (SystemProperties.getInt("debug.rs.forcecompat", 0) == 0)) {
96                thunk = 1;
97            } else {
98                thunk = -1;
99            }
100        }
101        if (thunk == 1) {
102            return true;
103        }
104        return false;
105    }
106
107    static boolean shouldThunk() {
108        return setupThunk(sSdkVersion);
109    }
110
111    /**
112     * Name of the file that holds the object cache.
113     */
114    private static final String CACHE_PATH = "com.android.renderscript.cache";
115    static String mCachePath;
116
117     /**
118     * Sets the directory to use as a persistent storage for the
119     * renderscript object file cache.
120     *
121     * @hide
122     * @param cacheDir A directory the current process can write to
123     */
124    public static void setupDiskCache(File cacheDir) {
125        File f = new File(cacheDir, CACHE_PATH);
126        mCachePath = f.getAbsolutePath();
127        f.mkdirs();
128    }
129
130    /**
131     * ContextType specifies the specific type of context to be created.
132     *
133     */
134    public enum ContextType {
135        /**
136         * NORMAL context, this is the default and what shipping apps should
137         * use.
138         */
139        NORMAL (0),
140
141        /**
142         * DEBUG context, perform extra runtime checks to validate the
143         * kernels and APIs are being used as intended.  Get and SetElementAt
144         * will be bounds checked in this mode.
145         */
146        DEBUG (1),
147
148        /**
149         * PROFILE context, Intended to be used once the first time an
150         * application is run on a new device.  This mode allows the runtime to
151         * do additional testing and performance tuning.
152         */
153        PROFILE (2);
154
155        int mID;
156        ContextType(int id) {
157            mID = id;
158        }
159    }
160
161    // Methods below are wrapped to protect the non-threadsafe
162    // lockless fifo.
163    native int  rsnContextCreate(int dev, int ver, int sdkVer, int contextType);
164    synchronized int nContextCreate(int dev, int ver, int sdkVer, int contextType) {
165        return rsnContextCreate(dev, ver, sdkVer, contextType);
166    }
167    native void rsnContextDestroy(int con);
168    synchronized void nContextDestroy() {
169        validate();
170
171        // take teardown lock
172        // teardown lock can only be taken when no objects are being destroyed
173        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
174        wlock.lock();
175
176        int curCon = mContext;
177        // context is considered dead as of this point
178        mContext = 0;
179
180        wlock.unlock();
181        rsnContextDestroy(curCon);
182    }
183    native void rsnContextSetPriority(int con, int p);
184    synchronized void nContextSetPriority(int p) {
185        validate();
186        rsnContextSetPriority(mContext, p);
187    }
188    native void rsnContextDump(int con, int bits);
189    synchronized void nContextDump(int bits) {
190        validate();
191        rsnContextDump(mContext, bits);
192    }
193    native void rsnContextFinish(int con);
194    synchronized void nContextFinish() {
195        validate();
196        rsnContextFinish(mContext);
197    }
198
199    native void rsnContextSendMessage(int con, int id, int[] data);
200    synchronized void nContextSendMessage(int id, int[] data) {
201        validate();
202        rsnContextSendMessage(mContext, id, data);
203    }
204
205    // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
206    native void rsnObjDestroy(int con, int id);
207    void nObjDestroy(int id) {
208        // There is a race condition here.  The calling code may be run
209        // by the gc while teardown is occuring.  This protects againts
210        // deleting dead objects.
211        if (mContext != 0) {
212            rsnObjDestroy(mContext, id);
213        }
214    }
215
216    native int  rsnElementCreate(int con, int type, int kind, boolean norm, int vecSize);
217    synchronized int nElementCreate(int type, int kind, boolean norm, int vecSize) {
218        validate();
219        return rsnElementCreate(mContext, type, kind, norm, vecSize);
220    }
221    native int  rsnElementCreate2(int con, int[] elements, String[] names, int[] arraySizes);
222    synchronized int nElementCreate2(int[] elements, String[] names, int[] arraySizes) {
223        validate();
224        return rsnElementCreate2(mContext, elements, names, arraySizes);
225    }
226    native void rsnElementGetNativeData(int con, int id, int[] elementData);
227    synchronized void nElementGetNativeData(int id, int[] elementData) {
228        validate();
229        rsnElementGetNativeData(mContext, id, elementData);
230    }
231    native void rsnElementGetSubElements(int con, int id,
232                                         int[] IDs, String[] names, int[] arraySizes);
233    synchronized void nElementGetSubElements(int id, int[] IDs, String[] names, int[] arraySizes) {
234        validate();
235        rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
236    }
237
238    native int rsnTypeCreate(int con, int eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
239    synchronized int nTypeCreate(int eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
240        validate();
241        return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
242    }
243    native void rsnTypeGetNativeData(int con, int id, int[] typeData);
244    synchronized void nTypeGetNativeData(int id, int[] typeData) {
245        validate();
246        rsnTypeGetNativeData(mContext, id, typeData);
247    }
248
249    native int  rsnAllocationCreateTyped(int con, int type, int mip, int usage, int pointer);
250    synchronized int nAllocationCreateTyped(int type, int mip, int usage, int pointer) {
251        validate();
252        return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
253    }
254    native int  rsnAllocationCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
255    synchronized int nAllocationCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
256        validate();
257        return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
258    }
259
260    native int  rsnAllocationCreateBitmapBackedAllocation(int con, int type, int mip, Bitmap bmp, int usage);
261    synchronized int nAllocationCreateBitmapBackedAllocation(int type, int mip, Bitmap bmp, int usage) {
262        validate();
263        return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage);
264    }
265
266
267    native int  rsnAllocationCubeCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
268    synchronized int nAllocationCubeCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
269        validate();
270        return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
271    }
272    native int  rsnAllocationCreateBitmapRef(int con, int type, Bitmap bmp);
273    synchronized int nAllocationCreateBitmapRef(int type, Bitmap bmp) {
274        validate();
275        return rsnAllocationCreateBitmapRef(mContext, type, bmp);
276    }
277    native int  rsnAllocationCreateFromAssetStream(int con, int mips, int assetStream, int usage);
278    synchronized int nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
279        validate();
280        return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
281    }
282
283    native void  rsnAllocationCopyToBitmap(int con, int alloc, Bitmap bmp);
284    synchronized void nAllocationCopyToBitmap(int alloc, Bitmap bmp) {
285        validate();
286        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
287    }
288
289
290    native void rsnAllocationSyncAll(int con, int alloc, int src);
291    synchronized void nAllocationSyncAll(int alloc, int src) {
292        validate();
293        rsnAllocationSyncAll(mContext, alloc, src);
294    }
295    native void rsnAllocationIoSend(int con, int alloc);
296    synchronized void nAllocationIoSend(int alloc) {
297        validate();
298        rsnAllocationIoSend(mContext, alloc);
299    }
300    native void rsnAllocationIoReceive(int con, int alloc);
301    synchronized void nAllocationIoReceive(int alloc) {
302        validate();
303        rsnAllocationIoReceive(mContext, alloc);
304    }
305
306
307    native void rsnAllocationGenerateMipmaps(int con, int alloc);
308    synchronized void nAllocationGenerateMipmaps(int alloc) {
309        validate();
310        rsnAllocationGenerateMipmaps(mContext, alloc);
311    }
312    native void  rsnAllocationCopyFromBitmap(int con, int alloc, Bitmap bmp);
313    synchronized void nAllocationCopyFromBitmap(int alloc, Bitmap bmp) {
314        validate();
315        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
316    }
317
318
319    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, int[] d, int sizeBytes);
320    synchronized void nAllocationData1D(int id, int off, int mip, int count, int[] d, int sizeBytes) {
321        validate();
322        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
323    }
324    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, short[] d, int sizeBytes);
325    synchronized void nAllocationData1D(int id, int off, int mip, int count, short[] d, int sizeBytes) {
326        validate();
327        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
328    }
329    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, byte[] d, int sizeBytes);
330    synchronized void nAllocationData1D(int id, int off, int mip, int count, byte[] d, int sizeBytes) {
331        validate();
332        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
333    }
334    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, float[] d, int sizeBytes);
335    synchronized void nAllocationData1D(int id, int off, int mip, int count, float[] d, int sizeBytes) {
336        validate();
337        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
338    }
339
340    native void rsnAllocationElementData1D(int con, int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
341    synchronized void nAllocationElementData1D(int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
342        validate();
343        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
344    }
345
346    native void rsnAllocationData2D(int con,
347                                    int dstAlloc, int dstXoff, int dstYoff,
348                                    int dstMip, int dstFace,
349                                    int width, int height,
350                                    int srcAlloc, int srcXoff, int srcYoff,
351                                    int srcMip, int srcFace);
352    synchronized void nAllocationData2D(int dstAlloc, int dstXoff, int dstYoff,
353                                        int dstMip, int dstFace,
354                                        int width, int height,
355                                        int srcAlloc, int srcXoff, int srcYoff,
356                                        int srcMip, int srcFace) {
357        validate();
358        rsnAllocationData2D(mContext,
359                            dstAlloc, dstXoff, dstYoff,
360                            dstMip, dstFace,
361                            width, height,
362                            srcAlloc, srcXoff, srcYoff,
363                            srcMip, srcFace);
364    }
365
366    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes);
367    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes) {
368        validate();
369        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
370    }
371    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes);
372    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes) {
373        validate();
374        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
375    }
376    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes);
377    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes) {
378        validate();
379        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
380    }
381    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes);
382    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes) {
383        validate();
384        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
385    }
386    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, Bitmap b);
387    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, Bitmap b) {
388        validate();
389        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
390    }
391
392    native void rsnAllocationData3D(int con,
393                                    int dstAlloc, int dstXoff, int dstYoff, int dstZoff,
394                                    int dstMip,
395                                    int width, int height, int depth,
396                                    int srcAlloc, int srcXoff, int srcYoff, int srcZoff,
397                                    int srcMip);
398    synchronized void nAllocationData3D(int dstAlloc, int dstXoff, int dstYoff, int dstZoff,
399                                        int dstMip,
400                                        int width, int height, int depth,
401                                        int srcAlloc, int srcXoff, int srcYoff, int srcZoff,
402                                        int srcMip) {
403        validate();
404        rsnAllocationData3D(mContext,
405                            dstAlloc, dstXoff, dstYoff, dstZoff,
406                            dstMip, width, height, depth,
407                            srcAlloc, srcXoff, srcYoff, srcZoff, srcMip);
408    }
409
410    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, byte[] d, int sizeBytes);
411    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, byte[] d, int sizeBytes) {
412        validate();
413        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
414    }
415    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, short[] d, int sizeBytes);
416    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, short[] d, int sizeBytes) {
417        validate();
418        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
419    }
420    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, int[] d, int sizeBytes);
421    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, int[] d, int sizeBytes) {
422        validate();
423        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
424    }
425    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, float[] d, int sizeBytes);
426    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, float[] d, int sizeBytes) {
427        validate();
428        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
429    }
430
431
432    native void rsnAllocationRead(int con, int id, byte[] d);
433    synchronized void nAllocationRead(int id, byte[] d) {
434        validate();
435        rsnAllocationRead(mContext, id, d);
436    }
437    native void rsnAllocationRead(int con, int id, short[] d);
438    synchronized void nAllocationRead(int id, short[] d) {
439        validate();
440        rsnAllocationRead(mContext, id, d);
441    }
442    native void rsnAllocationRead(int con, int id, int[] d);
443    synchronized void nAllocationRead(int id, int[] d) {
444        validate();
445        rsnAllocationRead(mContext, id, d);
446    }
447    native void rsnAllocationRead(int con, int id, float[] d);
448    synchronized void nAllocationRead(int id, float[] d) {
449        validate();
450        rsnAllocationRead(mContext, id, d);
451    }
452    native int  rsnAllocationGetType(int con, int id);
453    synchronized int nAllocationGetType(int id) {
454        validate();
455        return rsnAllocationGetType(mContext, id);
456    }
457
458    native void rsnAllocationResize1D(int con, int id, int dimX);
459    synchronized void nAllocationResize1D(int id, int dimX) {
460        validate();
461        rsnAllocationResize1D(mContext, id, dimX);
462    }
463    native void rsnAllocationResize2D(int con, int id, int dimX, int dimY);
464    synchronized void nAllocationResize2D(int id, int dimX, int dimY) {
465        validate();
466        rsnAllocationResize2D(mContext, id, dimX, dimY);
467    }
468
469    native void rsnScriptBindAllocation(int con, int script, int alloc, int slot);
470    synchronized void nScriptBindAllocation(int script, int alloc, int slot) {
471        validate();
472        rsnScriptBindAllocation(mContext, script, alloc, slot);
473    }
474    native void rsnScriptSetTimeZone(int con, int script, byte[] timeZone);
475    synchronized void nScriptSetTimeZone(int script, byte[] timeZone) {
476        validate();
477        rsnScriptSetTimeZone(mContext, script, timeZone);
478    }
479    native void rsnScriptInvoke(int con, int id, int slot);
480    synchronized void nScriptInvoke(int id, int slot) {
481        validate();
482        rsnScriptInvoke(mContext, id, slot);
483    }
484    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout, byte[] params);
485    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout);
486    native void rsnScriptForEachClipped(int con, int id, int slot, int ain, int aout, byte[] params,
487                                        int xstart, int xend, int ystart, int yend, int zstart, int zend);
488    native void rsnScriptForEachClipped(int con, int id, int slot, int ain, int aout,
489                                        int xstart, int xend, int ystart, int yend, int zstart, int zend);
490    synchronized void nScriptForEach(int id, int slot, int ain, int aout, byte[] params) {
491        validate();
492        if (params == null) {
493            rsnScriptForEach(mContext, id, slot, ain, aout);
494        } else {
495            rsnScriptForEach(mContext, id, slot, ain, aout, params);
496        }
497    }
498
499    synchronized void nScriptForEachClipped(int id, int slot, int ain, int aout, byte[] params,
500                                            int xstart, int xend, int ystart, int yend, int zstart, int zend) {
501        validate();
502        if (params == null) {
503            rsnScriptForEachClipped(mContext, id, slot, ain, aout, xstart, xend, ystart, yend, zstart, zend);
504        } else {
505            rsnScriptForEachClipped(mContext, id, slot, ain, aout, params, xstart, xend, ystart, yend, zstart, zend);
506        }
507    }
508
509    native void rsnScriptInvokeV(int con, int id, int slot, byte[] params);
510    synchronized void nScriptInvokeV(int id, int slot, byte[] params) {
511        validate();
512        rsnScriptInvokeV(mContext, id, slot, params);
513    }
514    native void rsnScriptSetVarI(int con, int id, int slot, int val);
515    synchronized void nScriptSetVarI(int id, int slot, int val) {
516        validate();
517        rsnScriptSetVarI(mContext, id, slot, val);
518    }
519    native void rsnScriptSetVarJ(int con, int id, int slot, long val);
520    synchronized void nScriptSetVarJ(int id, int slot, long val) {
521        validate();
522        rsnScriptSetVarJ(mContext, id, slot, val);
523    }
524    native void rsnScriptSetVarF(int con, int id, int slot, float val);
525    synchronized void nScriptSetVarF(int id, int slot, float val) {
526        validate();
527        rsnScriptSetVarF(mContext, id, slot, val);
528    }
529    native void rsnScriptSetVarD(int con, int id, int slot, double val);
530    synchronized void nScriptSetVarD(int id, int slot, double val) {
531        validate();
532        rsnScriptSetVarD(mContext, id, slot, val);
533    }
534    native void rsnScriptSetVarV(int con, int id, int slot, byte[] val);
535    synchronized void nScriptSetVarV(int id, int slot, byte[] val) {
536        validate();
537        rsnScriptSetVarV(mContext, id, slot, val);
538    }
539    native void rsnScriptSetVarVE(int con, int id, int slot, byte[] val,
540                                  int e, int[] dims);
541    synchronized void nScriptSetVarVE(int id, int slot, byte[] val,
542                                      int e, int[] dims) {
543        validate();
544        rsnScriptSetVarVE(mContext, id, slot, val, e, dims);
545    }
546    native void rsnScriptSetVarObj(int con, int id, int slot, int val);
547    synchronized void nScriptSetVarObj(int id, int slot, int val) {
548        validate();
549        rsnScriptSetVarObj(mContext, id, slot, val);
550    }
551
552    native int  rsnScriptCCreate(int con, String resName, String cacheDir,
553                                 byte[] script, int length);
554    synchronized int nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
555        validate();
556        return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
557    }
558
559    native int  rsnScriptIntrinsicCreate(int con, int id, int eid);
560    synchronized int nScriptIntrinsicCreate(int id, int eid) {
561        validate();
562        return rsnScriptIntrinsicCreate(mContext, id, eid);
563    }
564
565    native int  rsnScriptKernelIDCreate(int con, int sid, int slot, int sig);
566    synchronized int nScriptKernelIDCreate(int sid, int slot, int sig) {
567        validate();
568        return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
569    }
570
571    native int  rsnScriptFieldIDCreate(int con, int sid, int slot);
572    synchronized int nScriptFieldIDCreate(int sid, int slot) {
573        validate();
574        return rsnScriptFieldIDCreate(mContext, sid, slot);
575    }
576
577    native int  rsnScriptGroupCreate(int con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
578    synchronized int nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
579        validate();
580        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
581    }
582
583    native void rsnScriptGroupSetInput(int con, int group, int kernel, int alloc);
584    synchronized void nScriptGroupSetInput(int group, int kernel, int alloc) {
585        validate();
586        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
587    }
588
589    native void rsnScriptGroupSetOutput(int con, int group, int kernel, int alloc);
590    synchronized void nScriptGroupSetOutput(int group, int kernel, int alloc) {
591        validate();
592        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
593    }
594
595    native void rsnScriptGroupExecute(int con, int group);
596    synchronized void nScriptGroupExecute(int group) {
597        validate();
598        rsnScriptGroupExecute(mContext, group);
599    }
600
601    native int  rsnSamplerCreate(int con, int magFilter, int minFilter,
602                                 int wrapS, int wrapT, int wrapR, float aniso);
603    synchronized int nSamplerCreate(int magFilter, int minFilter,
604                                 int wrapS, int wrapT, int wrapR, float aniso) {
605        validate();
606        return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
607    }
608
609
610
611
612    int     mDev;
613    int     mContext;
614    ReentrantReadWriteLock mRWLock;
615    @SuppressWarnings({"FieldCanBeLocal"})
616    MessageThread mMessageThread;
617
618    Element mElement_U8;
619    Element mElement_I8;
620    Element mElement_U16;
621    Element mElement_I16;
622    Element mElement_U32;
623    Element mElement_I32;
624    Element mElement_U64;
625    Element mElement_I64;
626    Element mElement_F32;
627    Element mElement_F64;
628    Element mElement_BOOLEAN;
629
630    Element mElement_ELEMENT;
631    Element mElement_TYPE;
632    Element mElement_ALLOCATION;
633    Element mElement_SAMPLER;
634    Element mElement_SCRIPT;
635
636    Element mElement_A_8;
637    Element mElement_RGB_565;
638    Element mElement_RGB_888;
639    Element mElement_RGBA_5551;
640    Element mElement_RGBA_4444;
641    Element mElement_RGBA_8888;
642
643    Element mElement_FLOAT_2;
644    Element mElement_FLOAT_3;
645    Element mElement_FLOAT_4;
646
647    Element mElement_DOUBLE_2;
648    Element mElement_DOUBLE_3;
649    Element mElement_DOUBLE_4;
650
651    Element mElement_UCHAR_2;
652    Element mElement_UCHAR_3;
653    Element mElement_UCHAR_4;
654
655    Element mElement_CHAR_2;
656    Element mElement_CHAR_3;
657    Element mElement_CHAR_4;
658
659    Element mElement_USHORT_2;
660    Element mElement_USHORT_3;
661    Element mElement_USHORT_4;
662
663    Element mElement_SHORT_2;
664    Element mElement_SHORT_3;
665    Element mElement_SHORT_4;
666
667    Element mElement_UINT_2;
668    Element mElement_UINT_3;
669    Element mElement_UINT_4;
670
671    Element mElement_INT_2;
672    Element mElement_INT_3;
673    Element mElement_INT_4;
674
675    Element mElement_ULONG_2;
676    Element mElement_ULONG_3;
677    Element mElement_ULONG_4;
678
679    Element mElement_LONG_2;
680    Element mElement_LONG_3;
681    Element mElement_LONG_4;
682
683    Element mElement_MATRIX_4X4;
684    Element mElement_MATRIX_3X3;
685    Element mElement_MATRIX_2X2;
686
687    Sampler mSampler_CLAMP_NEAREST;
688    Sampler mSampler_CLAMP_LINEAR;
689    Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
690    Sampler mSampler_WRAP_NEAREST;
691    Sampler mSampler_WRAP_LINEAR;
692    Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
693    Sampler mSampler_MIRRORED_REPEAT_NEAREST;
694    Sampler mSampler_MIRRORED_REPEAT_LINEAR;
695    Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
696
697
698    ///////////////////////////////////////////////////////////////////////////////////
699    //
700
701    /**
702     * The base class from which an application should derive in order
703     * to receive RS messages from scripts. When a script calls {@code
704     * rsSendToClient}, the data fields will be filled, and the run
705     * method will be called on a separate thread.  This will occur
706     * some time after {@code rsSendToClient} completes in the script,
707     * as {@code rsSendToClient} is asynchronous. Message handlers are
708     * not guaranteed to have completed when {@link
709     * android.support.v8.renderscript.RenderScript#finish} returns.
710     *
711     */
712    public static class RSMessageHandler implements Runnable {
713        protected int[] mData;
714        protected int mID;
715        protected int mLength;
716        public void run() {
717        }
718    }
719    /**
720     * If an application is expecting messages, it should set this
721     * field to an instance of {@link RSMessageHandler}.  This
722     * instance will receive all the user messages sent from {@code
723     * sendToClient} by scripts from this context.
724     *
725     */
726    RSMessageHandler mMessageCallback = null;
727
728    public void setMessageHandler(RSMessageHandler msg) {
729        mMessageCallback = msg;
730        if (isNative) {
731            RenderScriptThunker rst = (RenderScriptThunker) this;
732            android.renderscript.RenderScript.RSMessageHandler newmsg =
733                new android.renderscript.RenderScript.RSMessageHandler() {
734                    public void run()  {
735                        mMessageCallback.mData = mData;
736                        mMessageCallback.mID = mID;
737                        mMessageCallback.mLength = mLength;
738                        mMessageCallback.run();
739                    }
740                };
741            rst.mN.setMessageHandler(newmsg);
742        }
743    }
744    public RSMessageHandler getMessageHandler() {
745        return mMessageCallback;
746    }
747
748    /**
749     * Place a message into the message queue to be sent back to the message
750     * handler once all previous commands have been executed.
751     *
752     * @hide
753     *
754     * @param id
755     * @param data
756     */
757    public void sendMessage(int id, int[] data) {
758        nContextSendMessage(id, data);
759    }
760
761    /**
762     * The runtime error handler base class.  An application should derive from this class
763     * if it wishes to install an error handler.  When errors occur at runtime,
764     * the fields in this class will be filled, and the run method will be called.
765     *
766     */
767    public static class RSErrorHandler implements Runnable {
768        protected String mErrorMessage;
769        protected int mErrorNum;
770        public void run() {
771        }
772    }
773
774    /**
775     * Application Error handler.  All runtime errors will be dispatched to the
776     * instance of RSAsyncError set here.  If this field is null a
777     * {@link RSRuntimeException} will instead be thrown with details about the error.
778     * This will cause program termaination.
779     *
780     */
781    RSErrorHandler mErrorCallback = null;
782
783    public void setErrorHandler(RSErrorHandler msg) {
784        mErrorCallback = msg;
785        if (isNative) {
786            RenderScriptThunker rst = (RenderScriptThunker) this;
787            android.renderscript.RenderScript.RSErrorHandler newmsg =
788                new android.renderscript.RenderScript.RSErrorHandler() {
789                    public void run()  {
790                        mErrorCallback.mErrorMessage = mErrorMessage;
791                        mErrorCallback.mErrorNum = mErrorNum;
792                        mErrorCallback.run();
793                    }
794                };
795            rst.mN.setErrorHandler(newmsg);
796        }
797    }
798    public RSErrorHandler getErrorHandler() {
799        return mErrorCallback;
800    }
801
802    /**
803     * RenderScript worker thread priority enumeration.  The default value is
804     * NORMAL.  Applications wishing to do background processing should set
805     * their priority to LOW to avoid starving forground processes.
806     */
807    public enum Priority {
808        LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
809        NORMAL (Process.THREAD_PRIORITY_DISPLAY);
810
811        int mID;
812        Priority(int id) {
813            mID = id;
814        }
815    }
816
817    void validate() {
818        if (mContext == 0) {
819            throw new RSInvalidStateException("Calling RS with no Context active.");
820        }
821    }
822
823
824    /**
825     * Change the priority of the worker threads for this context.
826     *
827     * @param p New priority to be set.
828     */
829    public void setPriority(Priority p) {
830        validate();
831        nContextSetPriority(p.mID);
832    }
833
834    static class MessageThread extends Thread {
835        RenderScript mRS;
836        boolean mRun = true;
837        int[] mAuxData = new int[2];
838
839        static final int RS_MESSAGE_TO_CLIENT_NONE = 0;
840        static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1;
841        static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2;
842        static final int RS_MESSAGE_TO_CLIENT_ERROR = 3;
843        static final int RS_MESSAGE_TO_CLIENT_USER = 4;
844
845        static final int RS_ERROR_FATAL_UNKNOWN = 0x1000;
846
847        MessageThread(RenderScript rs) {
848            super("RSMessageThread");
849            mRS = rs;
850
851        }
852
853        public void run() {
854            // This function is a temporary solution.  The final solution will
855            // used typed allocations where the message id is the type indicator.
856            int[] rbuf = new int[16];
857            mRS.nContextInitToClient(mRS.mContext);
858            while(mRun) {
859                rbuf[0] = 0;
860                int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData);
861                int size = mAuxData[1];
862                int subID = mAuxData[0];
863
864                if (msg == RS_MESSAGE_TO_CLIENT_USER) {
865                    if ((size>>2) >= rbuf.length) {
866                        rbuf = new int[(size + 3) >> 2];
867                    }
868                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
869                        RS_MESSAGE_TO_CLIENT_USER) {
870                        throw new RSDriverException("Error processing message from RenderScript.");
871                    }
872
873                    if(mRS.mMessageCallback != null) {
874                        mRS.mMessageCallback.mData = rbuf;
875                        mRS.mMessageCallback.mID = subID;
876                        mRS.mMessageCallback.mLength = size;
877                        mRS.mMessageCallback.run();
878                    } else {
879                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
880                    }
881                    continue;
882                }
883
884                if (msg == RS_MESSAGE_TO_CLIENT_ERROR) {
885                    String e = mRS.nContextGetErrorMessage(mRS.mContext);
886
887                    if (subID >= RS_ERROR_FATAL_UNKNOWN) {
888                        throw new RSRuntimeException("Fatal error " + subID + ", details: " + e);
889                    }
890
891                    if(mRS.mErrorCallback != null) {
892                        mRS.mErrorCallback.mErrorMessage = e;
893                        mRS.mErrorCallback.mErrorNum = subID;
894                        mRS.mErrorCallback.run();
895                    } else {
896                        android.util.Log.e(LOG_TAG, "non fatal RS error, " + e);
897                        // Do not throw here. In these cases, we do not have
898                        // a fatal error.
899                    }
900                    continue;
901                }
902
903                // 2: teardown.
904                // But we want to avoid starving other threads during
905                // teardown by yielding until the next line in the destructor
906                // can execute to set mRun = false
907                try {
908                    sleep(1, 0);
909                } catch(InterruptedException e) {
910                }
911            }
912            //Log.d(LOG_TAG, "MessageThread exiting.");
913        }
914    }
915
916    RenderScript(Context ctx) {
917        if (ctx != null) {
918            mApplicationContext = ctx.getApplicationContext();
919        }
920        mRWLock = new ReentrantReadWriteLock();
921    }
922
923    /**
924     * Gets the application context associated with the RenderScript context.
925     *
926     * @return The application context.
927     */
928    public final Context getApplicationContext() {
929        return mApplicationContext;
930    }
931
932    /**
933     * @hide
934     */
935    public static RenderScript create(Context ctx, int sdkVersion) {
936        return create(ctx, sdkVersion, ContextType.NORMAL);
937    }
938
939    /**
940     * Create a RenderScript context.
941     *
942     * @hide
943     * @param ctx The context.
944     * @return RenderScript
945     */
946    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct) {
947        RenderScript rs = new RenderScript(ctx);
948
949        if (sSdkVersion == -1) {
950            sSdkVersion = sdkVersion;
951        } else if (sSdkVersion != sdkVersion) {
952            throw new RSRuntimeException("Can't have two contexts with different SDK versions in support lib");
953        }
954
955        if (setupThunk(sSdkVersion)) {
956            android.util.Log.v(LOG_TAG, "RS native mode");
957            return RenderScriptThunker.create(ctx, sSdkVersion);
958        }
959        synchronized(lock) {
960            if (sInitialized == false) {
961                try {
962                    Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
963                    Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
964                    sRuntime = get_runtime.invoke(null);
965                    registerNativeAllocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE);
966                    registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE);
967                    sUseGCHooks = true;
968                } catch (Exception e) {
969                    Log.e(LOG_TAG, "No GC methods");
970                    sUseGCHooks = false;
971                }
972                try {
973                    System.loadLibrary("RSSupport");
974                    System.loadLibrary("rsjni");
975                    sInitialized = true;
976                } catch (UnsatisfiedLinkError e) {
977                    Log.e(LOG_TAG, "Error loading RS jni library: " + e);
978                    throw new RSRuntimeException("Error loading RS jni library: " + e);
979                }
980            }
981        }
982
983        android.util.Log.v(LOG_TAG, "RS compat mode");
984        rs.mDev = rs.nDeviceCreate();
985        rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion, ct.mID);
986        if (rs.mContext == 0) {
987            throw new RSDriverException("Failed to create RS context.");
988        }
989        rs.mMessageThread = new MessageThread(rs);
990        rs.mMessageThread.start();
991        return rs;
992    }
993
994    /**
995     * Create a RenderScript context.
996     *
997     * @param ctx The context.
998     * @return RenderScript
999     */
1000    public static RenderScript create(Context ctx) {
1001        return create(ctx, ContextType.NORMAL);
1002    }
1003
1004    /**
1005     * Create a RenderScript context.
1006     *
1007     * @hide
1008     *
1009     * @param ctx The context.
1010     * @param ct The type of context to be created.
1011     * @return RenderScript
1012     */
1013    public static RenderScript create(Context ctx, ContextType ct) {
1014        int v = ctx.getApplicationInfo().targetSdkVersion;
1015        return create(ctx, v, ct);
1016    }
1017
1018    /**
1019     * Print the currently available debugging information about the state of
1020     * the RS context to the log.
1021     *
1022     */
1023    public void contextDump() {
1024        validate();
1025        nContextDump(0);
1026    }
1027
1028    /**
1029     * Wait for any pending asynchronous opeations (such as copies to a RS
1030     * allocation or RS script executions) to complete.
1031     *
1032     */
1033    public void finish() {
1034        nContextFinish();
1035    }
1036
1037    /**
1038     * Destroys this RenderScript context.  Once this function is called,
1039     * using this context or any objects belonging to this context is
1040     * illegal.
1041     *
1042     */
1043    public void destroy() {
1044        validate();
1045        nContextFinish();
1046        nContextDeinitToClient(mContext);
1047        mMessageThread.mRun = false;
1048        try {
1049            mMessageThread.join();
1050        } catch(InterruptedException e) {
1051        }
1052
1053        nContextDestroy();
1054        nDeviceDestroy(mDev);
1055        mDev = 0;
1056    }
1057
1058    boolean isAlive() {
1059        return mContext != 0;
1060    }
1061
1062    int safeID(BaseObj o) {
1063        if(o != null) {
1064            return o.getID(this);
1065        }
1066        return 0;
1067    }
1068}
1069