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