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