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