RenderScript.java revision b7a5e4de32a9042b582373377a15c6d8bfbe41be
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;
33import java.util.ArrayList;
34
35/**
36 * This class provides access to a RenderScript context, which controls RenderScript
37 * initialization, resource management, and teardown. An instance of the RenderScript
38 * class must be created before any other RS objects can be created.
39 *
40 * <div class="special reference">
41 * <h3>Developer Guides</h3>
42 * <p>For more information about creating an application that uses RenderScript, read the
43 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
44 * </div>
45 **/
46public class RenderScript {
47    static final String LOG_TAG = "RenderScript_jni";
48    static final boolean DEBUG  = false;
49    @SuppressWarnings({"UnusedDeclaration", "deprecation"})
50    static final boolean LOG_ENABLED = false;
51
52    static private ArrayList<RenderScript> mProcessContextList = new ArrayList<RenderScript>();
53    private boolean mIsProcessContext = false;
54    private int mContextFlags = 0;
55    private int mContextSdkVersion = 0;
56
57
58    private Context mApplicationContext;
59    private String mNativeLibDir;
60
61    /*
62     * We use a class initializer to allow the native code to cache some
63     * field offsets.
64     */
65    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
66    static boolean sInitialized;
67    static boolean sUseGCHooks;
68    static Object sRuntime;
69    static Method registerNativeAllocation;
70    static Method registerNativeFree;
71
72    static Object lock = new Object();
73
74    // Non-threadsafe functions.
75    native boolean nLoadSO(boolean useNative, int deviceApi);
76    native boolean nLoadIOSO();
77    native long nDeviceCreate();
78    native void nDeviceDestroy(long dev);
79    native void nDeviceSetConfig(long dev, int param, int value);
80    native int nContextGetUserMessage(long con, int[] data);
81    native String nContextGetErrorMessage(long con);
82    native int  nContextPeekMessage(long con, int[] subID);
83    native void nContextInitToClient(long con);
84    native void nContextDeinitToClient(long con);
85
86    static private int sNative = -1;
87    static private int sSdkVersion = -1;
88    static private boolean useIOlib = false;
89    static private boolean useNative;
90
91    /*
92     * Context creation flag that specifies a normal context.
93     * RenderScript Support lib only support normal context.
94     */
95    public static final int CREATE_FLAG_NONE = 0x0000;
96
97
98    boolean isUseNative() {
99        return useNative;
100    }
101    /*
102     * Detect the bitness of the VM to allow FieldPacker to do the right thing.
103     */
104    static native int rsnSystemGetPointerSize();
105    static int sPointerSize;
106
107    /**
108     * Determines whether or not we should be thunking into the native
109     * RenderScript layer or actually using the compatibility library.
110     */
111    static private boolean setupNative(int sdkVersion, Context ctx) {
112        // if targetSdkVersion is higher than the device api version, always use compat mode.
113        // Workaround for KK
114        if (android.os.Build.VERSION.SDK_INT < sdkVersion &&
115            android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
116            sNative = 0;
117        }
118
119        if (sNative == -1) {
120
121            // get the value of the debug.rs.forcecompat property
122            int forcecompat = 0;
123            try {
124                Class<?> sysprop = Class.forName("android.os.SystemProperties");
125                Class[] signature = {String.class, Integer.TYPE};
126                Method getint = sysprop.getDeclaredMethod("getInt", signature);
127                Object[] args = {"debug.rs.forcecompat", new Integer(0)};
128                forcecompat = ((java.lang.Integer)getint.invoke(null, args)).intValue();
129            } catch (Exception e) {
130
131            }
132
133            if ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
134                     && forcecompat == 0) {
135                sNative = 1;
136            } else {
137                sNative = 0;
138            }
139
140
141            if (sNative == 1) {
142                // Workarounds that may disable thunking go here
143                ApplicationInfo info;
144                try {
145                    info = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(),
146                                                                      PackageManager.GET_META_DATA);
147                } catch (PackageManager.NameNotFoundException e) {
148                    // assume no workarounds needed
149                    return true;
150                }
151                long minorVersion = 0;
152
153                // load minorID from reflection
154                try {
155                    Class<?> javaRS = Class.forName("android.renderscript.RenderScript");
156                    Method getMinorID = javaRS.getDeclaredMethod("getMinorID");
157                    minorVersion = ((java.lang.Long)getMinorID.invoke(null)).longValue();
158                } catch (Exception e) {
159                    // minor version remains 0 on devices with no possible WARs
160                }
161
162                if (info.metaData != null) {
163                    // asynchronous teardown: minor version 1+
164                    if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableAsyncTeardown") == true) {
165                        if (minorVersion == 0) {
166                            sNative = 0;
167                        }
168                    }
169
170                    // blur issues on some drivers with 4.4
171                    if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableBlurWorkaround") == true) {
172                        if (android.os.Build.VERSION.SDK_INT <= 19) {
173                            //android.util.Log.e("rs", "war on");
174                            sNative = 0;
175                        }
176                    }
177                }
178                // end of workarounds
179            }
180        }
181
182        if (sNative == 1) {
183            return true;
184        }
185        return false;
186    }
187
188    /**
189     * Name of the file that holds the object cache.
190     */
191    private static final String CACHE_PATH = "com.android.renderscript.cache";
192    static String mCachePath;
193
194     /**
195     * Sets the directory to use as a persistent storage for the
196     * renderscript object file cache.
197     *
198     * @hide
199     * @param cacheDir A directory the current process can write to
200     */
201    public static void setupDiskCache(File cacheDir) {
202        File f = new File(cacheDir, CACHE_PATH);
203        mCachePath = f.getAbsolutePath();
204        f.mkdirs();
205    }
206
207    /**
208     * ContextType specifies the specific type of context to be created.
209     *
210     */
211    public enum ContextType {
212        /**
213         * NORMAL context, this is the default and what shipping apps should
214         * use.
215         */
216        NORMAL (0),
217
218        /**
219         * DEBUG context, perform extra runtime checks to validate the
220         * kernels and APIs are being used as intended.  Get and SetElementAt
221         * will be bounds checked in this mode.
222         */
223        DEBUG (1),
224
225        /**
226         * PROFILE context, Intended to be used once the first time an
227         * application is run on a new device.  This mode allows the runtime to
228         * do additional testing and performance tuning.
229         */
230        PROFILE (2);
231
232        int mID;
233        ContextType(int id) {
234            mID = id;
235        }
236    }
237
238    ContextType mContextType;
239    // Methods below are wrapped to protect the non-threadsafe
240    // lockless fifo.
241
242    native long  rsnContextCreate(long dev, int ver, int sdkVer, int contextType, String nativeLibDir);
243    synchronized long nContextCreate(long dev, int ver, int sdkVer, int contextType, String nativeLibDir) {
244        return rsnContextCreate(dev, ver, sdkVer, contextType, nativeLibDir);
245    }
246    native void rsnContextDestroy(long con);
247    synchronized void nContextDestroy() {
248        validate();
249
250        // take teardown lock
251        // teardown lock can only be taken when no objects are being destroyed
252        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
253        wlock.lock();
254
255        long curCon = mContext;
256        // context is considered dead as of this point
257        mContext = 0;
258
259        wlock.unlock();
260        rsnContextDestroy(curCon);
261    }
262    native void rsnContextSetPriority(long con, int p);
263    synchronized void nContextSetPriority(int p) {
264        validate();
265        rsnContextSetPriority(mContext, p);
266    }
267    native void rsnContextDump(long con, int bits);
268    synchronized void nContextDump(int bits) {
269        validate();
270        rsnContextDump(mContext, bits);
271    }
272    native void rsnContextFinish(long con);
273    synchronized void nContextFinish() {
274        validate();
275        rsnContextFinish(mContext);
276    }
277
278    native void rsnContextSendMessage(long con, int id, int[] data);
279    synchronized void nContextSendMessage(int id, int[] data) {
280        validate();
281        rsnContextSendMessage(mContext, id, data);
282    }
283
284    // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
285    native void rsnObjDestroy(long con, long id);
286    void nObjDestroy(long id) {
287        // There is a race condition here.  The calling code may be run
288        // by the gc while teardown is occuring.  This protects againts
289        // deleting dead objects.
290        if (mContext != 0) {
291            rsnObjDestroy(mContext, id);
292        }
293    }
294
295    native long  rsnElementCreate(long con, long type, int kind, boolean norm, int vecSize);
296    synchronized long nElementCreate(long type, int kind, boolean norm, int vecSize) {
297        validate();
298        return rsnElementCreate(mContext, type, kind, norm, vecSize);
299    }
300    native long  rsnElementCreate2(long con, long[] elements, String[] names, int[] arraySizes);
301    synchronized long nElementCreate2(long[] elements, String[] names, int[] arraySizes) {
302        validate();
303        return rsnElementCreate2(mContext, elements, names, arraySizes);
304    }
305    native void rsnElementGetNativeData(long con, long id, int[] elementData);
306    synchronized void nElementGetNativeData(long id, int[] elementData) {
307        validate();
308        rsnElementGetNativeData(mContext, id, elementData);
309    }
310    native void rsnElementGetSubElements(long con, long id,
311                                         long[] IDs, String[] names, int[] arraySizes);
312    synchronized void nElementGetSubElements(long id, long[] IDs, String[] names, int[] arraySizes) {
313        validate();
314        rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
315    }
316
317    native long rsnTypeCreate(long con, long eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
318    synchronized long nTypeCreate(long eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
319        validate();
320        return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
321    }
322
323    native void rsnTypeGetNativeData(long con, long id, long[] typeData);
324    synchronized void nTypeGetNativeData(long id, long[] typeData) {
325        validate();
326        rsnTypeGetNativeData(mContext, id, typeData);
327    }
328
329    native long  rsnAllocationCreateTyped(long con, long type, int mip, int usage, long pointer);
330    synchronized long nAllocationCreateTyped(long type, int mip, int usage, long pointer) {
331        validate();
332        return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
333    }
334    native long  rsnAllocationCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
335    synchronized long nAllocationCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
336        validate();
337        return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
338    }
339
340    native long  rsnAllocationCreateBitmapBackedAllocation(long con, long type, int mip, Bitmap bmp, int usage);
341    synchronized long nAllocationCreateBitmapBackedAllocation(long type, int mip, Bitmap bmp, int usage) {
342        validate();
343        return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage);
344    }
345
346
347    native long  rsnAllocationCubeCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
348    synchronized long nAllocationCubeCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
349        validate();
350        return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
351    }
352    native long  rsnAllocationCreateBitmapRef(long con, long type, Bitmap bmp);
353    synchronized long nAllocationCreateBitmapRef(long type, Bitmap bmp) {
354        validate();
355        return rsnAllocationCreateBitmapRef(mContext, type, bmp);
356    }
357    native long  rsnAllocationCreateFromAssetStream(long con, int mips, int assetStream, int usage);
358    synchronized long nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
359        validate();
360        return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
361    }
362
363    native void  rsnAllocationCopyToBitmap(long con, long alloc, Bitmap bmp);
364    synchronized void nAllocationCopyToBitmap(long alloc, Bitmap bmp) {
365        validate();
366        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
367    }
368
369
370    native void rsnAllocationSyncAll(long con, long alloc, int src);
371    synchronized void nAllocationSyncAll(long alloc, int src) {
372        validate();
373        rsnAllocationSyncAll(mContext, alloc, src);
374    }
375
376    native void rsnAllocationSetSurface(long con, long alloc, Surface sur);
377    synchronized void nAllocationSetSurface(long alloc, Surface sur) {
378        validate();
379        rsnAllocationSetSurface(mContext, alloc, sur);
380    }
381
382    native void rsnAllocationIoSend(long con, long alloc);
383    synchronized void nAllocationIoSend(long alloc) {
384        validate();
385        rsnAllocationIoSend(mContext, alloc);
386    }
387    native void rsnAllocationIoReceive(long con, long alloc);
388    synchronized void nAllocationIoReceive(long alloc) {
389        validate();
390        rsnAllocationIoReceive(mContext, alloc);
391    }
392
393
394    native void rsnAllocationGenerateMipmaps(long con, long alloc);
395    synchronized void nAllocationGenerateMipmaps(long alloc) {
396        validate();
397        rsnAllocationGenerateMipmaps(mContext, alloc);
398    }
399    native void  rsnAllocationCopyFromBitmap(long con, long alloc, Bitmap bmp);
400    synchronized void nAllocationCopyFromBitmap(long alloc, Bitmap bmp) {
401        validate();
402        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
403    }
404
405
406    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, Object d, int sizeBytes, int dt,
407                                    int mSize, boolean usePadding);
408    synchronized void nAllocationData1D(long id, int off, int mip, int count, Object d, int sizeBytes, Element.DataType dt,
409                                        int mSize, boolean usePadding) {
410        validate();
411        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID, mSize, usePadding);
412    }
413
414    native void rsnAllocationElementData1D(long con,long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
415    synchronized void nAllocationElementData1D(long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
416        validate();
417        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
418    }
419    /*
420    native void rsnAllocationElementData(long con,long id, int xoff, int yoff, int zoff, int mip, int compIdx, byte[] d, int sizeBytes);
421    synchronized void nAllocationElementData(long id, int xoff, int yoff, int zoff, int mip, int compIdx, byte[] d, int sizeBytes) {
422        validate();
423        rsnAllocationElementData(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes);
424    }
425    */
426
427    native void rsnAllocationData2D(long con,
428                                    long dstAlloc, int dstXoff, int dstYoff,
429                                    int dstMip, int dstFace,
430                                    int width, int height,
431                                    long srcAlloc, int srcXoff, int srcYoff,
432                                    int srcMip, int srcFace);
433    synchronized void nAllocationData2D(long dstAlloc, int dstXoff, int dstYoff,
434                                        int dstMip, int dstFace,
435                                        int width, int height,
436                                        long srcAlloc, int srcXoff, int srcYoff,
437                                        int srcMip, int srcFace) {
438        validate();
439        rsnAllocationData2D(mContext,
440                            dstAlloc, dstXoff, dstYoff,
441                            dstMip, dstFace,
442                            width, height,
443                            srcAlloc, srcXoff, srcYoff,
444                            srcMip, srcFace);
445    }
446
447    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face,
448                                    int w, int h, Object d, int sizeBytes, int dt,
449                                    int mSize, boolean usePadding);
450    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face,
451                                        int w, int h, Object d, int sizeBytes, Element.DataType dt,
452                                        int mSize, boolean usePadding) {
453        validate();
454        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID, mSize, usePadding);
455    }
456
457    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face, Bitmap b);
458    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face, Bitmap b) {
459        validate();
460        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
461    }
462
463    native void rsnAllocationData3D(long con,
464                                    long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
465                                    int dstMip,
466                                    int width, int height, int depth,
467                                    long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
468                                    int srcMip);
469    synchronized void nAllocationData3D(long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
470                                        int dstMip,
471                                        int width, int height, int depth,
472                                        long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
473                                        int srcMip) {
474        validate();
475        rsnAllocationData3D(mContext,
476                            dstAlloc, dstXoff, dstYoff, dstZoff,
477                            dstMip, width, height, depth,
478                            srcAlloc, srcXoff, srcYoff, srcZoff, srcMip);
479    }
480
481
482    native void rsnAllocationData3D(long con, long id, int xoff, int yoff, int zoff, int mip,
483                                    int w, int h, int depth, Object d, int sizeBytes, int dt,
484                                    int mSize, boolean usePadding);
485    synchronized void nAllocationData3D(long id, int xoff, int yoff, int zoff, int mip,
486                                        int w, int h, int depth, Object d, int sizeBytes, Element.DataType dt,
487                                        int mSize, boolean usePadding) {
488        validate();
489        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes,
490                            dt.mID, mSize, usePadding);
491    }
492
493    native void rsnAllocationRead(long con, long id, Object d, int dt, int mSize, boolean usePadding);
494    synchronized void nAllocationRead(long id, Object d, Element.DataType dt, int mSize, boolean usePadding) {
495        validate();
496        rsnAllocationRead(mContext, id, d, dt.mID, mSize, usePadding);
497    }
498
499    native void rsnAllocationRead1D(long con, long id, int off, int mip, int count, Object d,
500                                    int sizeBytes, int dt, int mSize, boolean usePadding);
501    synchronized void nAllocationRead1D(long id, int off, int mip, int count, Object d,
502                                        int sizeBytes, Element.DataType dt, int mSize, boolean usePadding) {
503        validate();
504        rsnAllocationRead1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID, mSize, usePadding);
505    }
506
507    /*
508    native void rsnAllocationElementRead(long con,long id, int xoff, int yoff, int zoff,
509                                         int mip, int compIdx, byte[] d, int sizeBytes);
510    synchronized void nAllocationElementRead(long id, int xoff, int yoff, int zoff,
511                                             int mip, int compIdx, byte[] d, int sizeBytes) {
512        validate();
513        rsnAllocationElementRead(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes);
514    }
515    */
516
517    native void rsnAllocationRead2D(long con, long id, int xoff, int yoff, int mip, int face,
518                                    int w, int h, Object d, int sizeBytes, int dt,
519                                    int mSize, boolean usePadding);
520    synchronized void nAllocationRead2D(long id, int xoff, int yoff, int mip, int face,
521                                        int w, int h, Object d, int sizeBytes, Element.DataType dt,
522                                        int mSize, boolean usePadding) {
523        validate();
524        rsnAllocationRead2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID, mSize, usePadding);
525    }
526
527    /*
528    native void rsnAllocationRead3D(long con, long id, int xoff, int yoff, int zoff, int mip,
529                                    int w, int h, int depth, Object d, int sizeBytes, int dt,
530                                    int mSize, boolean usePadding);
531    synchronized void nAllocationRead3D(long id, int xoff, int yoff, int zoff, int mip,
532                                        int w, int h, int depth, Object d, int sizeBytes, Element.DataType dt,
533                                        int mSize, boolean usePadding) {
534        validate();
535        rsnAllocationRead3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes, dt.mID, mSize, usePadding);
536    }
537    */
538
539    native long  rsnAllocationGetType(long con, long id);
540    synchronized long nAllocationGetType(long id) {
541        validate();
542        return rsnAllocationGetType(mContext, id);
543    }
544
545    native void rsnAllocationResize1D(long con, long id, int dimX);
546    synchronized void nAllocationResize1D(long id, int dimX) {
547        validate();
548        rsnAllocationResize1D(mContext, id, dimX);
549    }
550    native void rsnAllocationResize2D(long con, long id, int dimX, int dimY);
551    synchronized void nAllocationResize2D(long id, int dimX, int dimY) {
552        validate();
553        rsnAllocationResize2D(mContext, id, dimX, dimY);
554    }
555
556    native void rsnScriptBindAllocation(long con, long script, long alloc, int slot, boolean mUseInc);
557    synchronized void nScriptBindAllocation(long script, long alloc, int slot, boolean mUseInc) {
558        validate();
559        long curCon = mContext;
560        if (mUseInc) {
561            curCon = mIncCon;
562        }
563        rsnScriptBindAllocation(curCon, script, alloc, slot, mUseInc);
564    }
565    native void rsnScriptSetTimeZone(long con, long script, byte[] timeZone, boolean mUseInc);
566    synchronized void nScriptSetTimeZone(long script, byte[] timeZone, boolean mUseInc) {
567        validate();
568        long curCon = mContext;
569        if (mUseInc) {
570            curCon = mIncCon;
571        }
572        rsnScriptSetTimeZone(curCon, script, timeZone, mUseInc);
573    }
574    native void rsnScriptInvoke(long con, long id, int slot, boolean mUseInc);
575    synchronized void nScriptInvoke(long id, int slot, boolean mUseInc) {
576        validate();
577        long curCon = mContext;
578        if (mUseInc) {
579            curCon = mIncCon;
580        }
581        rsnScriptInvoke(curCon, id, slot, mUseInc);
582    }
583    native void rsnScriptForEach(long con, long incCon, long id, int slot, long ain, long aout, byte[] params, boolean mUseInc);
584    native void rsnScriptForEach(long con, long incCon, long id, int slot, long ain, long aout, boolean mUseInc);
585    native void rsnScriptForEachClipped(long con, long incCon, long id, int slot, long ain, long aout, byte[] params,
586                                        int xstart, int xend, int ystart, int yend, int zstart, int zend, boolean mUseInc);
587    native void rsnScriptForEachClipped(long con, long incCon, long id, int slot, long ain, long aout,
588                                        int xstart, int xend, int ystart, int yend, int zstart, int zend, boolean mUseInc);
589    synchronized void nScriptForEach(long id, int slot, long ain, long aout, byte[] params, boolean mUseInc) {
590        validate();
591        if (params == null) {
592            rsnScriptForEach(mContext, mIncCon, id, slot, ain, aout, mUseInc);
593        } else {
594            rsnScriptForEach(mContext, mIncCon, id, slot, ain, aout, params, mUseInc);
595        }
596    }
597
598    synchronized void nScriptForEachClipped(long id, int slot, long ain, long aout, byte[] params,
599                                            int xstart, int xend, int ystart, int yend, int zstart, int zend, boolean mUseInc) {
600        validate();
601        if (params == null) {
602            rsnScriptForEachClipped(mContext, mIncCon, id, slot, ain, aout, xstart, xend, ystart, yend, zstart, zend, mUseInc);
603        } else {
604            rsnScriptForEachClipped(mContext, mIncCon, id, slot, ain, aout, params, xstart, xend, ystart, yend, zstart, zend, mUseInc);
605        }
606    }
607
608    native void rsnScriptInvokeV(long con, long id, int slot, byte[] params, boolean mUseInc);
609    synchronized void nScriptInvokeV(long id, int slot, byte[] params, boolean mUseInc) {
610        validate();
611        long curCon = mContext;
612        if (mUseInc) {
613            curCon = mIncCon;
614        }
615        rsnScriptInvokeV(curCon, id, slot, params, mUseInc);
616    }
617    native void rsnScriptSetVarI(long con, long id, int slot, int val, boolean mUseInc);
618    synchronized void nScriptSetVarI(long id, int slot, int val, boolean mUseInc) {
619        validate();
620        long curCon = mContext;
621        if (mUseInc) {
622            curCon = mIncCon;
623        }
624        rsnScriptSetVarI(curCon, id, slot, val, mUseInc);
625    }
626    native void rsnScriptSetVarJ(long con, long id, int slot, long val, boolean mUseInc);
627    synchronized void nScriptSetVarJ(long id, int slot, long val, boolean mUseInc) {
628        validate();
629        long curCon = mContext;
630        if (mUseInc) {
631            curCon = mIncCon;
632        }
633        rsnScriptSetVarJ(curCon, id, slot, val, mUseInc);
634    }
635    native void rsnScriptSetVarF(long con, long id, int slot, float val, boolean mUseInc);
636    synchronized void nScriptSetVarF(long id, int slot, float val, boolean mUseInc) {
637        validate();
638        long curCon = mContext;
639        if (mUseInc) {
640            curCon = mIncCon;
641        }
642        rsnScriptSetVarF(curCon, id, slot, val, mUseInc);
643    }
644    native void rsnScriptSetVarD(long con, long id, int slot, double val, boolean mUseInc);
645    synchronized void nScriptSetVarD(long id, int slot, double val, boolean mUseInc) {
646        validate();
647        long curCon = mContext;
648        if (mUseInc) {
649            curCon = mIncCon;
650        }
651        rsnScriptSetVarD(curCon, id, slot, val, mUseInc);
652    }
653    native void rsnScriptSetVarV(long con, long id, int slot, byte[] val, boolean mUseInc);
654    synchronized void nScriptSetVarV(long id, int slot, byte[] val, boolean mUseInc) {
655        validate();
656        long curCon = mContext;
657        if (mUseInc) {
658            curCon = mIncCon;
659        }
660        rsnScriptSetVarV(curCon, id, slot, val, mUseInc);
661    }
662    native void rsnScriptSetVarVE(long con, long id, int slot, byte[] val,
663                                  long e, int[] dims, boolean mUseInc);
664    synchronized void nScriptSetVarVE(long id, int slot, byte[] val,
665                                      long e, int[] dims, boolean mUseInc) {
666        validate();
667        long curCon = mContext;
668        if (mUseInc) {
669            curCon = mIncCon;
670        }
671        rsnScriptSetVarVE(curCon, id, slot, val, e, dims, mUseInc);
672    }
673    native void rsnScriptSetVarObj(long con, long id, int slot, long val, boolean mUseInc);
674    synchronized void nScriptSetVarObj(long id, int slot, long val, boolean mUseInc) {
675        validate();
676        long curCon = mContext;
677        if (mUseInc) {
678            curCon = mIncCon;
679        }
680        rsnScriptSetVarObj(curCon, id, slot, val, mUseInc);
681    }
682
683    native long  rsnScriptCCreate(long con, String resName, String cacheDir,
684                                 byte[] script, int length);
685    synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
686        validate();
687        return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
688    }
689
690    native long  rsnScriptIntrinsicCreate(long con, int id, long eid, boolean mUseInc);
691    synchronized long nScriptIntrinsicCreate(int id, long eid, boolean mUseInc) {
692        validate();
693        if (mUseInc) {
694            if (!mIncLoaded) {
695                try {
696                    System.loadLibrary("RSSupport");
697                } catch (UnsatisfiedLinkError e) {
698                    Log.e(LOG_TAG, "Error loading RS Compat library for Incremental Intrinsic Support: " + e);
699                    throw new RSRuntimeException("Error loading RS Compat library for Incremental Intrinsic Support: " + e);
700                }
701                if (!nIncLoadSO(sSdkVersion)) {
702                    throw new RSRuntimeException("Error loading libRSSupport library for Incremental Intrinsic Support");
703                }
704                mIncLoaded = true;
705            }
706            if (mIncDev == 0) {
707                mIncDev = nIncDeviceCreate();
708            }
709            if (mIncCon == 0) {
710                //Create a dummy compat context (synchronous).
711                mIncCon = nIncContextCreate(mIncDev, 0, 0, 0);
712            }
713            return rsnScriptIntrinsicCreate(mIncCon, id, eid, mUseInc);
714        } else {
715            return rsnScriptIntrinsicCreate(mContext, id, eid, mUseInc);
716        }
717    }
718
719    native long  rsnScriptKernelIDCreate(long con, long sid, int slot, int sig, boolean mUseInc);
720    synchronized long nScriptKernelIDCreate(long sid, int slot, int sig, boolean mUseInc) {
721        validate();
722        long curCon = mContext;
723        if (mUseInc) {
724            curCon = mIncCon;
725        }
726        return rsnScriptKernelIDCreate(curCon, sid, slot, sig, mUseInc);
727    }
728
729    native long  rsnScriptInvokeIDCreate(long con, long sid, int slot);
730    synchronized long nScriptInvokeIDCreate(long sid, int slot) {
731        validate();
732        return rsnScriptInvokeIDCreate(mContext, sid, slot);
733    }
734
735    native long  rsnScriptFieldIDCreate(long con, long sid, int slot, boolean mUseInc);
736    synchronized long nScriptFieldIDCreate(long sid, int slot, boolean mUseInc) {
737        validate();
738        long curCon = mContext;
739        if (mUseInc) {
740            curCon = mIncCon;
741        }
742        return rsnScriptFieldIDCreate(curCon, sid, slot, mUseInc);
743    }
744
745    native long  rsnScriptGroupCreate(long con, long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types);
746    synchronized long nScriptGroupCreate(long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types) {
747        validate();
748        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
749    }
750
751    native void rsnScriptGroupSetInput(long con, long group, long kernel, long alloc);
752    synchronized void nScriptGroupSetInput(long group, long kernel, long alloc) {
753        validate();
754        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
755    }
756
757    native void rsnScriptGroupSetOutput(long con, long group, long kernel, long alloc);
758    synchronized void nScriptGroupSetOutput(long group, long kernel, long alloc) {
759        validate();
760        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
761    }
762
763    native void rsnScriptGroupExecute(long con, long group);
764    synchronized void nScriptGroupExecute(long group) {
765        validate();
766        rsnScriptGroupExecute(mContext, group);
767    }
768
769    native long  rsnSamplerCreate(long con, int magFilter, int minFilter,
770                                 int wrapS, int wrapT, int wrapR, float aniso);
771    synchronized long nSamplerCreate(int magFilter, int minFilter,
772                                 int wrapS, int wrapT, int wrapR, float aniso) {
773        validate();
774        return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
775    }
776
777// entry points for ScriptGroup2
778    native long rsnClosureCreate(long con, long kernelID, long returnValue,
779        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
780        long[] depFieldIDs);
781    synchronized long nClosureCreate(long kernelID, long returnValue,
782        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
783        long[] depFieldIDs) {
784      validate();
785      long c = rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
786          sizes, depClosures, depFieldIDs);
787      if (c == 0) {
788          throw new RSRuntimeException("Failed creating closure.");
789      }
790      return c;
791    }
792
793    native long rsnInvokeClosureCreate(long con, long invokeID, byte[] params,
794        long[] fieldIDs, long[] values, int[] sizes);
795    synchronized long nInvokeClosureCreate(long invokeID, byte[] params,
796        long[] fieldIDs, long[] values, int[] sizes) {
797      validate();
798      long c = rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
799          values, sizes);
800      if (c == 0) {
801          throw new RSRuntimeException("Failed creating closure.");
802      }
803      return c;
804    }
805
806    native void rsnClosureSetArg(long con, long closureID, int index,
807      long value, int size);
808    synchronized void nClosureSetArg(long closureID, int index, long value,
809        int size) {
810      validate();
811      rsnClosureSetArg(mContext, closureID, index, value, size);
812    }
813
814    native void rsnClosureSetGlobal(long con, long closureID, long fieldID,
815        long value, int size);
816    // Does this have to be synchronized?
817    synchronized void nClosureSetGlobal(long closureID, long fieldID,
818        long value, int size) {
819      validate(); // TODO: is this necessary?
820      rsnClosureSetGlobal(mContext, closureID, fieldID, value, size);
821    }
822
823    native long rsnScriptGroup2Create(long con, String name, String cachePath,
824                                      long[] closures);
825    synchronized long nScriptGroup2Create(String name, String cachePath,
826                                          long[] closures) {
827      validate();
828      return rsnScriptGroup2Create(mContext, name, cachePath, closures);
829    }
830
831    native void rsnScriptGroup2Execute(long con, long groupID);
832    synchronized void nScriptGroup2Execute(long groupID) {
833      validate();
834      rsnScriptGroup2Execute(mContext, groupID);
835    }
836
837
838// Additional Entry points For inc libRSSupport
839
840    native boolean nIncLoadSO(int deviceApi);
841    native long nIncDeviceCreate();
842    native void nIncDeviceDestroy(long dev);
843    // Methods below are wrapped to protect the non-threadsafe
844    // lockless fifo.
845    native long  rsnIncContextCreate(long dev, int ver, int sdkVer, int contextType);
846    synchronized long nIncContextCreate(long dev, int ver, int sdkVer, int contextType) {
847        return rsnIncContextCreate(dev, ver, sdkVer, contextType);
848    }
849    native void rsnIncContextDestroy(long con);
850    synchronized void nIncContextDestroy() {
851        validate();
852
853        // take teardown lock
854        // teardown lock can only be taken when no objects are being destroyed
855        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
856        wlock.lock();
857
858        long curCon = mIncCon;
859        // context is considered dead as of this point
860        mIncCon = 0;
861
862        wlock.unlock();
863        rsnIncContextDestroy(curCon);
864    }
865
866    native void rsnIncContextFinish(long con);
867    synchronized void nIncContextFinish() {
868        validate();
869        rsnIncContextFinish(mIncCon);
870    }
871
872    native void rsnIncObjDestroy(long con, long id);
873    void nIncObjDestroy(long id) {
874        // There is a race condition here.  The calling code may be run
875        // by the gc while teardown is occuring.  This protects againts
876        // deleting dead objects.
877        if (mIncCon != 0) {
878            rsnIncObjDestroy(mIncCon, id);
879        }
880    }
881    native long  rsnIncElementCreate(long con, long type, int kind, boolean norm, int vecSize);
882    synchronized long nIncElementCreate(long type, int kind, boolean norm, int vecSize) {
883        validate();
884        return rsnIncElementCreate(mIncCon, type, kind, norm, vecSize);
885    }
886    native long rsnIncTypeCreate(long con, long eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
887    synchronized long nIncTypeCreate(long eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
888        validate();
889        return rsnIncTypeCreate(mIncCon, eid, x, y, z, mips, faces, yuv);
890    }
891    native long  rsnIncAllocationCreateTyped(long con, long incCon, long alloc, long type);
892    synchronized long nIncAllocationCreateTyped(long alloc, long type) {
893        validate();
894        return rsnIncAllocationCreateTyped(mContext, mIncCon, alloc, type);
895    }
896
897    long     mDev;
898    long     mContext;
899    //Dummy device & context for Inc Support Lib
900    long     mIncDev;
901    long     mIncCon;
902    //indicator of whether inc support lib has been loaded or not.
903    boolean  mIncLoaded;
904    ReentrantReadWriteLock mRWLock;
905    @SuppressWarnings({"FieldCanBeLocal"})
906    MessageThread mMessageThread;
907
908    Element mElement_U8;
909    Element mElement_I8;
910    Element mElement_U16;
911    Element mElement_I16;
912    Element mElement_U32;
913    Element mElement_I32;
914    Element mElement_U64;
915    Element mElement_I64;
916    Element mElement_F32;
917    Element mElement_F64;
918    Element mElement_BOOLEAN;
919
920    Element mElement_ELEMENT;
921    Element mElement_TYPE;
922    Element mElement_ALLOCATION;
923    Element mElement_SAMPLER;
924    Element mElement_SCRIPT;
925
926    Element mElement_A_8;
927    Element mElement_RGB_565;
928    Element mElement_RGB_888;
929    Element mElement_RGBA_5551;
930    Element mElement_RGBA_4444;
931    Element mElement_RGBA_8888;
932
933    Element mElement_FLOAT_2;
934    Element mElement_FLOAT_3;
935    Element mElement_FLOAT_4;
936
937    Element mElement_DOUBLE_2;
938    Element mElement_DOUBLE_3;
939    Element mElement_DOUBLE_4;
940
941    Element mElement_UCHAR_2;
942    Element mElement_UCHAR_3;
943    Element mElement_UCHAR_4;
944
945    Element mElement_CHAR_2;
946    Element mElement_CHAR_3;
947    Element mElement_CHAR_4;
948
949    Element mElement_USHORT_2;
950    Element mElement_USHORT_3;
951    Element mElement_USHORT_4;
952
953    Element mElement_SHORT_2;
954    Element mElement_SHORT_3;
955    Element mElement_SHORT_4;
956
957    Element mElement_UINT_2;
958    Element mElement_UINT_3;
959    Element mElement_UINT_4;
960
961    Element mElement_INT_2;
962    Element mElement_INT_3;
963    Element mElement_INT_4;
964
965    Element mElement_ULONG_2;
966    Element mElement_ULONG_3;
967    Element mElement_ULONG_4;
968
969    Element mElement_LONG_2;
970    Element mElement_LONG_3;
971    Element mElement_LONG_4;
972
973    Element mElement_MATRIX_4X4;
974    Element mElement_MATRIX_3X3;
975    Element mElement_MATRIX_2X2;
976
977    Sampler mSampler_CLAMP_NEAREST;
978    Sampler mSampler_CLAMP_LINEAR;
979    Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
980    Sampler mSampler_WRAP_NEAREST;
981    Sampler mSampler_WRAP_LINEAR;
982    Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
983    Sampler mSampler_MIRRORED_REPEAT_NEAREST;
984    Sampler mSampler_MIRRORED_REPEAT_LINEAR;
985    Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
986
987
988    ///////////////////////////////////////////////////////////////////////////////////
989    //
990
991    /**
992     * The base class from which an application should derive in order
993     * to receive RS messages from scripts. When a script calls {@code
994     * rsSendToClient}, the data fields will be filled, and the run
995     * method will be called on a separate thread.  This will occur
996     * some time after {@code rsSendToClient} completes in the script,
997     * as {@code rsSendToClient} is asynchronous. Message handlers are
998     * not guaranteed to have completed when {@link
999     * android.support.v8.renderscript.RenderScript#finish} returns.
1000     *
1001     */
1002    public static class RSMessageHandler implements Runnable {
1003        protected int[] mData;
1004        protected int mID;
1005        protected int mLength;
1006        public void run() {
1007        }
1008    }
1009    /**
1010     * If an application is expecting messages, it should set this
1011     * field to an instance of {@link RSMessageHandler}.  This
1012     * instance will receive all the user messages sent from {@code
1013     * sendToClient} by scripts from this context.
1014     *
1015     */
1016    RSMessageHandler mMessageCallback = null;
1017
1018    public void setMessageHandler(RSMessageHandler msg) {
1019        mMessageCallback = msg;
1020    }
1021    public RSMessageHandler getMessageHandler() {
1022        return mMessageCallback;
1023    }
1024
1025    /**
1026     * Place a message into the message queue to be sent back to the message
1027     * handler once all previous commands have been executed.
1028     *
1029     * @param id
1030     * @param data
1031     */
1032    public void sendMessage(int id, int[] data) {
1033        nContextSendMessage(id, data);
1034    }
1035
1036    /**
1037     * The runtime error handler base class.  An application should derive from this class
1038     * if it wishes to install an error handler.  When errors occur at runtime,
1039     * the fields in this class will be filled, and the run method will be called.
1040     *
1041     */
1042    public static class RSErrorHandler implements Runnable {
1043        protected String mErrorMessage;
1044        protected int mErrorNum;
1045        public void run() {
1046        }
1047    }
1048
1049    /**
1050     * Application Error handler.  All runtime errors will be dispatched to the
1051     * instance of RSAsyncError set here.  If this field is null a
1052     * {@link RSRuntimeException} will instead be thrown with details about the error.
1053     * This will cause program termaination.
1054     *
1055     */
1056    RSErrorHandler mErrorCallback = null;
1057
1058    public void setErrorHandler(RSErrorHandler msg) {
1059        mErrorCallback = msg;
1060    }
1061    public RSErrorHandler getErrorHandler() {
1062        return mErrorCallback;
1063    }
1064
1065    /**
1066     * RenderScript worker thread priority enumeration.  The default value is
1067     * NORMAL.  Applications wishing to do background processing should set
1068     * their priority to LOW to avoid starving forground processes.
1069     */
1070    public enum Priority {
1071        LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
1072        NORMAL (Process.THREAD_PRIORITY_DISPLAY);
1073
1074        int mID;
1075        Priority(int id) {
1076            mID = id;
1077        }
1078    }
1079
1080    void validate() {
1081        if (mContext == 0) {
1082            throw new RSInvalidStateException("Calling RS with no Context active.");
1083        }
1084    }
1085
1086    /**
1087     * check if IO support lib is available.
1088     */
1089    boolean usingIO() {
1090        return useIOlib;
1091    }
1092    /**
1093     * Change the priority of the worker threads for this context.
1094     *
1095     * @param p New priority to be set.
1096     */
1097    public void setPriority(Priority p) {
1098        validate();
1099        nContextSetPriority(p.mID);
1100    }
1101
1102    static class MessageThread extends Thread {
1103        RenderScript mRS;
1104        boolean mRun = true;
1105        int[] mAuxData = new int[2];
1106
1107        static final int RS_MESSAGE_TO_CLIENT_NONE = 0;
1108        static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1;
1109        static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2;
1110        static final int RS_MESSAGE_TO_CLIENT_ERROR = 3;
1111
1112        static final int RS_MESSAGE_TO_CLIENT_USER = 4;
1113        static final int RS_ERROR_FATAL_UNKNOWN = 0x1000;
1114
1115        MessageThread(RenderScript rs) {
1116            super("RSMessageThread");
1117            mRS = rs;
1118
1119        }
1120
1121        public void run() {
1122            // This function is a temporary solution.  The final solution will
1123            // used typed allocations where the message id is the type indicator.
1124            int[] rbuf = new int[16];
1125            mRS.nContextInitToClient(mRS.mContext);
1126            while(mRun) {
1127                rbuf[0] = 0;
1128                int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData);
1129                int size = mAuxData[1];
1130                int subID = mAuxData[0];
1131
1132                if (msg == RS_MESSAGE_TO_CLIENT_USER) {
1133                    if ((size>>2) >= rbuf.length) {
1134                        rbuf = new int[(size + 3) >> 2];
1135                    }
1136                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
1137                        RS_MESSAGE_TO_CLIENT_USER) {
1138                        throw new RSDriverException("Error processing message from RenderScript.");
1139                    }
1140
1141                    if(mRS.mMessageCallback != null) {
1142                        mRS.mMessageCallback.mData = rbuf;
1143                        mRS.mMessageCallback.mID = subID;
1144                        mRS.mMessageCallback.mLength = size;
1145                        mRS.mMessageCallback.run();
1146                    } else {
1147                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
1148                    }
1149                    continue;
1150                }
1151
1152                if (msg == RS_MESSAGE_TO_CLIENT_ERROR) {
1153                    String e = mRS.nContextGetErrorMessage(mRS.mContext);
1154
1155                    if (subID >= RS_ERROR_FATAL_UNKNOWN) {
1156                        throw new RSRuntimeException("Fatal error " + subID + ", details: " + e);
1157                    }
1158
1159                    if(mRS.mErrorCallback != null) {
1160                        mRS.mErrorCallback.mErrorMessage = e;
1161                        mRS.mErrorCallback.mErrorNum = subID;
1162                        mRS.mErrorCallback.run();
1163                    } else {
1164                        android.util.Log.e(LOG_TAG, "non fatal RS error, " + e);
1165                        // Do not throw here. In these cases, we do not have
1166                        // a fatal error.
1167                    }
1168                    continue;
1169                }
1170
1171                // 2: teardown.
1172                // But we want to avoid starving other threads during
1173                // teardown by yielding until the next line in the destructor
1174                // can execute to set mRun = false
1175                try {
1176                    sleep(1, 0);
1177                } catch(InterruptedException e) {
1178                }
1179            }
1180            //Log.d(LOG_TAG, "MessageThread exiting.");
1181        }
1182    }
1183
1184    RenderScript(Context ctx) {
1185        mContextType = ContextType.NORMAL;
1186        if (ctx != null) {
1187            mApplicationContext = ctx.getApplicationContext();
1188            mNativeLibDir = mApplicationContext.getApplicationInfo().nativeLibraryDir;
1189        }
1190        mIncDev = 0;
1191        mIncCon = 0;
1192        mIncLoaded = false;
1193        mRWLock = new ReentrantReadWriteLock();
1194    }
1195
1196    /**
1197     * Gets the application context associated with the RenderScript context.
1198     *
1199     * @return The application context.
1200     */
1201    public final Context getApplicationContext() {
1202        return mApplicationContext;
1203    }
1204
1205    /**
1206     * Create a RenderScript context.
1207     *
1208     * @param ctx The context.
1209     * @return RenderScript
1210     */
1211    private static RenderScript internalCreate(Context ctx, int sdkVersion, ContextType ct, int flags) {
1212        RenderScript rs = new RenderScript(ctx);
1213
1214        if (sSdkVersion == -1) {
1215            sSdkVersion = sdkVersion;
1216        } else if (sSdkVersion != sdkVersion) {
1217            throw new RSRuntimeException("Can't have two contexts with different SDK versions in support lib");
1218        }
1219        useNative = setupNative(sSdkVersion, ctx);
1220        synchronized(lock) {
1221            if (sInitialized == false) {
1222                try {
1223                    Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
1224                    Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
1225                    sRuntime = get_runtime.invoke(null);
1226                    registerNativeAllocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE);
1227                    registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE);
1228                    sUseGCHooks = true;
1229                } catch (Exception e) {
1230                    Log.e(LOG_TAG, "No GC methods");
1231                    sUseGCHooks = false;
1232                }
1233                try {
1234                    System.loadLibrary("rsjni");
1235                    sInitialized = true;
1236                    sPointerSize = rsnSystemGetPointerSize();
1237                } catch (UnsatisfiedLinkError e) {
1238                    Log.e(LOG_TAG, "Error loading RS jni library: " + e);
1239                    throw new RSRuntimeException("Error loading RS jni library: " + e);
1240                }
1241            }
1242        }
1243
1244        if (useNative) {
1245            android.util.Log.v(LOG_TAG, "RS native mode");
1246        } else {
1247            android.util.Log.v(LOG_TAG, "RS compat mode");
1248        }
1249
1250        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1251            useIOlib = true;
1252        }
1253        if (!rs.nLoadSO(useNative, sdkVersion)) {
1254            if (useNative) {
1255                android.util.Log.v(LOG_TAG, "Unable to load libRS.so, falling back to compat mode");
1256                useNative = false;
1257            }
1258            try {
1259                System.loadLibrary("RSSupport");
1260            } catch (UnsatisfiedLinkError e) {
1261                Log.e(LOG_TAG, "Error loading RS Compat library: " + e);
1262                throw new RSRuntimeException("Error loading RS Compat library: " + e);
1263            }
1264            if (!rs.nLoadSO(false, sdkVersion)) {
1265                throw new RSRuntimeException("Error loading libRSSupport library");
1266            }
1267        }
1268
1269        if (useIOlib) {
1270            try {
1271                System.loadLibrary("RSSupportIO");
1272            } catch (UnsatisfiedLinkError e) {
1273                useIOlib = false;
1274            }
1275            if (!useIOlib || !rs.nLoadIOSO()) {
1276                android.util.Log.v(LOG_TAG, "Unable to load libRSSupportIO.so, USAGE_IO not supported");
1277                useIOlib = false;
1278            }
1279        }
1280
1281        rs.mDev = rs.nDeviceCreate();
1282        rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion, ct.mID, rs.mNativeLibDir);
1283        rs.mContextType = ct;
1284        rs.mContextFlags = flags;
1285        rs.mContextSdkVersion = sdkVersion;
1286        if (rs.mContext == 0) {
1287            throw new RSDriverException("Failed to create RS context.");
1288        }
1289        rs.mMessageThread = new MessageThread(rs);
1290        rs.mMessageThread.start();
1291        return rs;
1292    }
1293
1294    /**
1295     * Create a RenderScript context.
1296     *
1297     * See documentation for @create for details
1298     *
1299     * @param ctx The context.
1300     * @return RenderScript
1301     */
1302    public static RenderScript create(Context ctx) {
1303        return create(ctx, ContextType.NORMAL);
1304    }
1305
1306    /**
1307     * calls create(ctx, ct, CREATE_FLAG_NONE)
1308     *
1309     * See documentation for @create for details
1310     *
1311     * @param ctx The context.
1312     * @param ct The type of context to be created.
1313     * @return RenderScript
1314     */
1315    public static RenderScript create(Context ctx, ContextType ct) {
1316        return create(ctx, ct, CREATE_FLAG_NONE);
1317    }
1318
1319    /**
1320     * Gets or creates a RenderScript context of the specified type.
1321     *
1322     * The returned context will be cached for future reuse within
1323     * the process. When an application is finished using
1324     * RenderScript it should call releaseAllContexts()
1325     *
1326     * A process context is a context designed for easy creation and
1327     * lifecycle management.  Multiple calls to this function will
1328     * return the same object provided they are called with the same
1329     * options.  This allows it to be used any time a RenderScript
1330     * context is needed.
1331     *
1332     *
1333     * @param ctx The context.
1334     * @param ct The type of context to be created.
1335     * @param flags The OR of the CREATE_FLAG_* options desired
1336     * @return RenderScript
1337     */
1338    public static RenderScript create(Context ctx, ContextType ct, int flags) {
1339        int v = ctx.getApplicationInfo().targetSdkVersion;
1340        return create(ctx, v, ct, flags);
1341    }
1342
1343    /**
1344     * calls create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE)
1345     *
1346     * Used by the RenderScriptThunker to maintain backward compatibility.
1347     *
1348     * @hide
1349     * @param ctx The context.
1350     * @param sdkVersion The target SDK Version.
1351     * @return RenderScript
1352     */
1353    public static RenderScript create(Context ctx, int sdkVersion) {
1354        return create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE);
1355    }
1356
1357
1358    /**
1359     * calls create(ctx, sdkVersion, ct, CREATE_FLAG_NONE)
1360     * Create a RenderScript context.
1361     *
1362     * @hide
1363     * @param ctx The context.
1364     * @return RenderScript
1365     */
1366    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct) {
1367        return create(ctx, sdkVersion, ct, CREATE_FLAG_NONE);
1368    }
1369
1370     /**
1371     * Gets or creates a RenderScript context of the specified type.
1372     *
1373     * @param ctx The context.
1374     * @param ct The type of context to be created.
1375     * @param sdkVersion The target SDK Version.
1376     * @param flags The OR of the CREATE_FLAG_* options desired
1377     * @return RenderScript
1378     */
1379    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct, int flags) {
1380        synchronized (mProcessContextList) {
1381            for (RenderScript prs : mProcessContextList) {
1382                if ((prs.mContextType == ct) &&
1383                    (prs.mContextFlags == flags) &&
1384                    (prs.mContextSdkVersion == sdkVersion)) {
1385
1386                    return prs;
1387                }
1388            }
1389
1390            RenderScript prs = internalCreate(ctx, sdkVersion, ct, flags);
1391            prs.mIsProcessContext = true;
1392            mProcessContextList.add(prs);
1393            return prs;
1394        }
1395    }
1396
1397    /**
1398     *
1399     * Releases all the process contexts.  This is the same as
1400     * calling .destroy() on each unique context retreived with
1401     * create(...). If no contexts have been created this
1402     * function does nothing.
1403     *
1404     * Typically you call this when your application is losing focus
1405     * and will not be using a context for some time.
1406     *
1407     * This has no effect on a context created with
1408     * createMultiContext()
1409     */
1410    public static void releaseAllContexts() {
1411        ArrayList<RenderScript> oldList;
1412        synchronized (mProcessContextList) {
1413            oldList = mProcessContextList;
1414            mProcessContextList = new ArrayList<RenderScript>();
1415        }
1416
1417        for (RenderScript prs : oldList) {
1418            prs.mIsProcessContext = false;
1419            prs.destroy();
1420        }
1421        oldList.clear();
1422    }
1423
1424
1425
1426    /**
1427     * Create a RenderScript context.
1428     *
1429     * This is an advanced function intended for applications which
1430     * need to create more than one RenderScript context to be used
1431     * at the same time.
1432     *
1433     * If you need a single context please use create()
1434     *
1435     * @param ctx The context.
1436     * @return RenderScript
1437     */
1438    public static RenderScript createMultiContext(Context ctx, ContextType ct, int flags, int API_number) {
1439        return internalCreate(ctx, API_number, ct, flags);
1440    }
1441
1442    /**
1443     * Print the currently available debugging information about the state of
1444     * the RS context to the log.
1445     *
1446     */
1447    public void contextDump() {
1448        validate();
1449        nContextDump(0);
1450    }
1451
1452    /**
1453     * Wait for any pending asynchronous opeations (such as copies to a RS
1454     * allocation or RS script executions) to complete.
1455     *
1456     */
1457    public void finish() {
1458        nContextFinish();
1459    }
1460
1461    /**
1462     * Destroys this RenderScript context.  Once this function is called,
1463     * using this context or any objects belonging to this context is
1464     * illegal.
1465     *
1466     * This function is a NOP if the context was created
1467     * with create().  Please use releaseAllContexts() to clean up
1468     * contexts created with the create function.
1469     */
1470    public void destroy() {
1471        if (mIsProcessContext) {
1472            // users cannot destroy a process context
1473            return;
1474        }
1475        validate();
1476        nContextFinish();
1477        if (mIncCon != 0) {
1478            nIncContextFinish();
1479            nIncContextDestroy();
1480            mIncCon = 0;
1481        }
1482        nContextDeinitToClient(mContext);
1483        mMessageThread.mRun = false;
1484        try {
1485            mMessageThread.join();
1486        } catch(InterruptedException e) {
1487        }
1488
1489        nContextDestroy();
1490        nDeviceDestroy(mDev);
1491        if (mIncDev != 0) {
1492            nIncDeviceDestroy(mIncDev);
1493            mIncDev = 0;
1494        }
1495        mDev = 0;
1496    }
1497
1498    boolean isAlive() {
1499        return mContext != 0;
1500    }
1501
1502    long safeID(BaseObj o) {
1503        if(o != null) {
1504            return o.getID(this);
1505        }
1506        return 0;
1507    }
1508}
1509