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