RenderScript.java revision 6318b3424d0036b28343d9a4e7d587ec4760b818
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;
33
34import android.os.SystemProperties;
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
53    private Context mApplicationContext;
54
55    /*
56     * We use a class initializer to allow the native code to cache some
57     * field offsets.
58     */
59    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
60    static boolean sInitialized;
61    static boolean sUseGCHooks;
62    static Object sRuntime;
63    static Method registerNativeAllocation;
64    static Method registerNativeFree;
65
66    static Object lock = new Object();
67
68    // Non-threadsafe functions.
69    native int  nDeviceCreate();
70    native void nDeviceDestroy(int dev);
71    native void nDeviceSetConfig(int dev, int param, int value);
72    native int nContextGetUserMessage(int con, int[] data);
73    native String nContextGetErrorMessage(int con);
74    native int  nContextPeekMessage(int con, int[] subID);
75    native void nContextInitToClient(int con);
76    native void nContextDeinitToClient(int con);
77
78    static boolean isNative = false;
79
80    static private int sThunk = -1;
81    static private int sSdkVersion = -1;
82
83    static boolean shouldThunk() {
84        if (sThunk == -1) {
85            throw new RSRuntimeException("Can't use RS classes before setting up a RenderScript context");
86        } else if (sThunk == 1) {
87            return true;
88        }
89        return false;
90    }
91
92    /**
93     * Determines whether or not we should be thunking into the native
94     * RenderScript layer or actually using the compatibility library.
95     */
96    static private boolean setupThunk(int sdkVersion, Context ctx) {
97        if (sThunk == -1) {
98            // use compat on Jelly Bean MR2 if we're requesting SDK 19+
99            if (android.os.Build.VERSION.SDK_INT == 18 && sdkVersion >= 19) {
100                sThunk = 0;
101            }
102            else if ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
103                && (SystemProperties.getInt("debug.rs.forcecompat", 0) == 0)) {
104                sThunk = 1;
105            } else {
106                sThunk = 0;
107            }
108
109
110            if (sThunk == 1) {
111                // Workarounds that may disable thunking go here
112                ApplicationInfo info;
113                try {
114                    info = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(),
115                                                                      PackageManager.GET_META_DATA);
116                } catch (PackageManager.NameNotFoundException e) {
117                    // assume no workarounds needed
118                    return true;
119                }
120                long minorVersion = 0;
121
122                // load minorID from reflection
123                try {
124                    Class<?> javaRS = Class.forName("android.renderscript.RenderScript");
125                    Method getMinorID = javaRS.getDeclaredMethod("getMinorID");
126                    minorVersion = ((java.lang.Long)getMinorID.invoke(null)).longValue();
127                } catch (Exception e) {
128                    // minor version remains 0 on devices with no possible WARs
129                }
130
131                if (info.metaData != null) {
132                    // asynchronous teardown: minor version 1+
133                    if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableAsyncTeardown") == true) {
134                        if (minorVersion == 0) {
135                            sThunk = 0;
136                        }
137                    }
138
139                    // blur issues on some drivers with 4.4
140                    if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableBlurWorkaround") == true) {
141                        if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT) {
142                            //android.util.Log.e("rs", "war on");
143                            sThunk = 0;
144                        }
145                    }
146                }
147                // end of workarounds
148            }
149        }
150
151        if (sThunk == 1) {
152            return true;
153        }
154        return false;
155    }
156
157    /**
158     * Name of the file that holds the object cache.
159     */
160    private static final String CACHE_PATH = "com.android.renderscript.cache";
161    static String mCachePath;
162
163     /**
164     * Sets the directory to use as a persistent storage for the
165     * renderscript object file cache.
166     *
167     * @hide
168     * @param cacheDir A directory the current process can write to
169     */
170    public static void setupDiskCache(File cacheDir) {
171        File f = new File(cacheDir, CACHE_PATH);
172        mCachePath = f.getAbsolutePath();
173        f.mkdirs();
174    }
175
176    /**
177     * ContextType specifies the specific type of context to be created.
178     *
179     */
180    public enum ContextType {
181        /**
182         * NORMAL context, this is the default and what shipping apps should
183         * use.
184         */
185        NORMAL (0),
186
187        /**
188         * DEBUG context, perform extra runtime checks to validate the
189         * kernels and APIs are being used as intended.  Get and SetElementAt
190         * will be bounds checked in this mode.
191         */
192        DEBUG (1),
193
194        /**
195         * PROFILE context, Intended to be used once the first time an
196         * application is run on a new device.  This mode allows the runtime to
197         * do additional testing and performance tuning.
198         */
199        PROFILE (2);
200
201        int mID;
202        ContextType(int id) {
203            mID = id;
204        }
205    }
206
207    // Methods below are wrapped to protect the non-threadsafe
208    // lockless fifo.
209    native int  rsnContextCreate(int dev, int ver, int sdkVer, int contextType);
210    synchronized int nContextCreate(int dev, int ver, int sdkVer, int contextType) {
211        return rsnContextCreate(dev, ver, sdkVer, contextType);
212    }
213    native void rsnContextDestroy(int con);
214    synchronized void nContextDestroy() {
215        validate();
216
217        // take teardown lock
218        // teardown lock can only be taken when no objects are being destroyed
219        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
220        wlock.lock();
221
222        int curCon = mContext;
223        // context is considered dead as of this point
224        mContext = 0;
225
226        wlock.unlock();
227        rsnContextDestroy(curCon);
228    }
229    native void rsnContextSetPriority(int con, int p);
230    synchronized void nContextSetPriority(int p) {
231        validate();
232        rsnContextSetPriority(mContext, p);
233    }
234    native void rsnContextDump(int con, int bits);
235    synchronized void nContextDump(int bits) {
236        validate();
237        rsnContextDump(mContext, bits);
238    }
239    native void rsnContextFinish(int con);
240    synchronized void nContextFinish() {
241        validate();
242        rsnContextFinish(mContext);
243    }
244
245    native void rsnContextSendMessage(int con, int id, int[] data);
246    synchronized void nContextSendMessage(int id, int[] data) {
247        validate();
248        rsnContextSendMessage(mContext, id, data);
249    }
250
251    // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
252    native void rsnObjDestroy(int con, int id);
253    void nObjDestroy(int id) {
254        // There is a race condition here.  The calling code may be run
255        // by the gc while teardown is occuring.  This protects againts
256        // deleting dead objects.
257        if (mContext != 0) {
258            rsnObjDestroy(mContext, id);
259        }
260    }
261
262    native int  rsnElementCreate(int con, int type, int kind, boolean norm, int vecSize);
263    synchronized int nElementCreate(int type, int kind, boolean norm, int vecSize) {
264        validate();
265        return rsnElementCreate(mContext, type, kind, norm, vecSize);
266    }
267    native int  rsnElementCreate2(int con, int[] elements, String[] names, int[] arraySizes);
268    synchronized int nElementCreate2(int[] elements, String[] names, int[] arraySizes) {
269        validate();
270        return rsnElementCreate2(mContext, elements, names, arraySizes);
271    }
272    native void rsnElementGetNativeData(int con, int id, int[] elementData);
273    synchronized void nElementGetNativeData(int id, int[] elementData) {
274        validate();
275        rsnElementGetNativeData(mContext, id, elementData);
276    }
277    native void rsnElementGetSubElements(int con, int id,
278                                         int[] IDs, String[] names, int[] arraySizes);
279    synchronized void nElementGetSubElements(int id, int[] IDs, String[] names, int[] arraySizes) {
280        validate();
281        rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
282    }
283
284    native int rsnTypeCreate(int con, int eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
285    synchronized int nTypeCreate(int eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
286        validate();
287        return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
288    }
289    native void rsnTypeGetNativeData(int con, int id, int[] typeData);
290    synchronized void nTypeGetNativeData(int id, int[] typeData) {
291        validate();
292        rsnTypeGetNativeData(mContext, id, typeData);
293    }
294
295    native int  rsnAllocationCreateTyped(int con, int type, int mip, int usage, int pointer);
296    synchronized int nAllocationCreateTyped(int type, int mip, int usage, int pointer) {
297        validate();
298        return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
299    }
300    native int  rsnAllocationCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
301    synchronized int nAllocationCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
302        validate();
303        return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
304    }
305
306    native int  rsnAllocationCreateBitmapBackedAllocation(int con, int type, int mip, Bitmap bmp, int usage);
307    synchronized int nAllocationCreateBitmapBackedAllocation(int type, int mip, Bitmap bmp, int usage) {
308        validate();
309        return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage);
310    }
311
312
313    native int  rsnAllocationCubeCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
314    synchronized int nAllocationCubeCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
315        validate();
316        return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
317    }
318    native int  rsnAllocationCreateBitmapRef(int con, int type, Bitmap bmp);
319    synchronized int nAllocationCreateBitmapRef(int type, Bitmap bmp) {
320        validate();
321        return rsnAllocationCreateBitmapRef(mContext, type, bmp);
322    }
323    native int  rsnAllocationCreateFromAssetStream(int con, int mips, int assetStream, int usage);
324    synchronized int nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
325        validate();
326        return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
327    }
328
329    native void  rsnAllocationCopyToBitmap(int con, int alloc, Bitmap bmp);
330    synchronized void nAllocationCopyToBitmap(int alloc, Bitmap bmp) {
331        validate();
332        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
333    }
334
335
336    native void rsnAllocationSyncAll(int con, int alloc, int src);
337    synchronized void nAllocationSyncAll(int alloc, int src) {
338        validate();
339        rsnAllocationSyncAll(mContext, alloc, src);
340    }
341    native void rsnAllocationIoSend(int con, int alloc);
342    synchronized void nAllocationIoSend(int alloc) {
343        validate();
344        rsnAllocationIoSend(mContext, alloc);
345    }
346    native void rsnAllocationIoReceive(int con, int alloc);
347    synchronized void nAllocationIoReceive(int alloc) {
348        validate();
349        rsnAllocationIoReceive(mContext, alloc);
350    }
351
352
353    native void rsnAllocationGenerateMipmaps(int con, int alloc);
354    synchronized void nAllocationGenerateMipmaps(int alloc) {
355        validate();
356        rsnAllocationGenerateMipmaps(mContext, alloc);
357    }
358    native void  rsnAllocationCopyFromBitmap(int con, int alloc, Bitmap bmp);
359    synchronized void nAllocationCopyFromBitmap(int alloc, Bitmap bmp) {
360        validate();
361        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
362    }
363
364
365    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, int[] d, int sizeBytes);
366    synchronized void nAllocationData1D(int id, int off, int mip, int count, int[] d, int sizeBytes) {
367        validate();
368        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
369    }
370    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, short[] d, int sizeBytes);
371    synchronized void nAllocationData1D(int id, int off, int mip, int count, short[] d, int sizeBytes) {
372        validate();
373        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
374    }
375    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, byte[] d, int sizeBytes);
376    synchronized void nAllocationData1D(int id, int off, int mip, int count, byte[] d, int sizeBytes) {
377        validate();
378        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
379    }
380    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, float[] d, int sizeBytes);
381    synchronized void nAllocationData1D(int id, int off, int mip, int count, float[] d, int sizeBytes) {
382        validate();
383        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
384    }
385
386    native void rsnAllocationElementData1D(int con, int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
387    synchronized void nAllocationElementData1D(int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
388        validate();
389        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
390    }
391
392    native void rsnAllocationData2D(int con,
393                                    int dstAlloc, int dstXoff, int dstYoff,
394                                    int dstMip, int dstFace,
395                                    int width, int height,
396                                    int srcAlloc, int srcXoff, int srcYoff,
397                                    int srcMip, int srcFace);
398    synchronized void nAllocationData2D(int dstAlloc, int dstXoff, int dstYoff,
399                                        int dstMip, int dstFace,
400                                        int width, int height,
401                                        int srcAlloc, int srcXoff, int srcYoff,
402                                        int srcMip, int srcFace) {
403        validate();
404        rsnAllocationData2D(mContext,
405                            dstAlloc, dstXoff, dstYoff,
406                            dstMip, dstFace,
407                            width, height,
408                            srcAlloc, srcXoff, srcYoff,
409                            srcMip, srcFace);
410    }
411
412    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes);
413    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes) {
414        validate();
415        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
416    }
417    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes);
418    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes) {
419        validate();
420        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
421    }
422    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes);
423    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes) {
424        validate();
425        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
426    }
427    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes);
428    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes) {
429        validate();
430        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
431    }
432    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, Bitmap b);
433    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, Bitmap b) {
434        validate();
435        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
436    }
437
438    native void rsnAllocationData3D(int con,
439                                    int dstAlloc, int dstXoff, int dstYoff, int dstZoff,
440                                    int dstMip,
441                                    int width, int height, int depth,
442                                    int srcAlloc, int srcXoff, int srcYoff, int srcZoff,
443                                    int srcMip);
444    synchronized void nAllocationData3D(int dstAlloc, int dstXoff, int dstYoff, int dstZoff,
445                                        int dstMip,
446                                        int width, int height, int depth,
447                                        int srcAlloc, int srcXoff, int srcYoff, int srcZoff,
448                                        int srcMip) {
449        validate();
450        rsnAllocationData3D(mContext,
451                            dstAlloc, dstXoff, dstYoff, dstZoff,
452                            dstMip, width, height, depth,
453                            srcAlloc, srcXoff, srcYoff, srcZoff, srcMip);
454    }
455
456    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, byte[] d, int sizeBytes);
457    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, byte[] d, int sizeBytes) {
458        validate();
459        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
460    }
461    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, short[] d, int sizeBytes);
462    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, short[] d, int sizeBytes) {
463        validate();
464        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
465    }
466    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, int[] d, int sizeBytes);
467    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, int[] d, int sizeBytes) {
468        validate();
469        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
470    }
471    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, float[] d, int sizeBytes);
472    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, float[] d, int sizeBytes) {
473        validate();
474        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
475    }
476
477
478    native void rsnAllocationRead(int con, int id, byte[] d);
479    synchronized void nAllocationRead(int id, byte[] d) {
480        validate();
481        rsnAllocationRead(mContext, id, d);
482    }
483    native void rsnAllocationRead(int con, int id, short[] d);
484    synchronized void nAllocationRead(int id, short[] d) {
485        validate();
486        rsnAllocationRead(mContext, id, d);
487    }
488    native void rsnAllocationRead(int con, int id, int[] d);
489    synchronized void nAllocationRead(int id, int[] d) {
490        validate();
491        rsnAllocationRead(mContext, id, d);
492    }
493    native void rsnAllocationRead(int con, int id, float[] d);
494    synchronized void nAllocationRead(int id, float[] d) {
495        validate();
496        rsnAllocationRead(mContext, id, d);
497    }
498    native int  rsnAllocationGetType(int con, int id);
499    synchronized int nAllocationGetType(int id) {
500        validate();
501        return rsnAllocationGetType(mContext, id);
502    }
503
504    native void rsnAllocationResize1D(int con, int id, int dimX);
505    synchronized void nAllocationResize1D(int id, int dimX) {
506        validate();
507        rsnAllocationResize1D(mContext, id, dimX);
508    }
509    native void rsnAllocationResize2D(int con, int id, int dimX, int dimY);
510    synchronized void nAllocationResize2D(int id, int dimX, int dimY) {
511        validate();
512        rsnAllocationResize2D(mContext, id, dimX, dimY);
513    }
514
515    native void rsnScriptBindAllocation(int con, int script, int alloc, int slot);
516    synchronized void nScriptBindAllocation(int script, int alloc, int slot) {
517        validate();
518        rsnScriptBindAllocation(mContext, script, alloc, slot);
519    }
520    native void rsnScriptSetTimeZone(int con, int script, byte[] timeZone);
521    synchronized void nScriptSetTimeZone(int script, byte[] timeZone) {
522        validate();
523        rsnScriptSetTimeZone(mContext, script, timeZone);
524    }
525    native void rsnScriptInvoke(int con, int id, int slot);
526    synchronized void nScriptInvoke(int id, int slot) {
527        validate();
528        rsnScriptInvoke(mContext, id, slot);
529    }
530    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout, byte[] params);
531    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout);
532    native void rsnScriptForEachClipped(int con, int id, int slot, int ain, int aout, byte[] params,
533                                        int xstart, int xend, int ystart, int yend, int zstart, int zend);
534    native void rsnScriptForEachClipped(int con, int id, int slot, int ain, int aout,
535                                        int xstart, int xend, int ystart, int yend, int zstart, int zend);
536    synchronized void nScriptForEach(int id, int slot, int ain, int aout, byte[] params) {
537        validate();
538        if (params == null) {
539            rsnScriptForEach(mContext, id, slot, ain, aout);
540        } else {
541            rsnScriptForEach(mContext, id, slot, ain, aout, params);
542        }
543    }
544
545    synchronized void nScriptForEachClipped(int id, int slot, int ain, int aout, byte[] params,
546                                            int xstart, int xend, int ystart, int yend, int zstart, int zend) {
547        validate();
548        if (params == null) {
549            rsnScriptForEachClipped(mContext, id, slot, ain, aout, xstart, xend, ystart, yend, zstart, zend);
550        } else {
551            rsnScriptForEachClipped(mContext, id, slot, ain, aout, params, xstart, xend, ystart, yend, zstart, zend);
552        }
553    }
554
555    native void rsnScriptInvokeV(int con, int id, int slot, byte[] params);
556    synchronized void nScriptInvokeV(int id, int slot, byte[] params) {
557        validate();
558        rsnScriptInvokeV(mContext, id, slot, params);
559    }
560    native void rsnScriptSetVarI(int con, int id, int slot, int val);
561    synchronized void nScriptSetVarI(int id, int slot, int val) {
562        validate();
563        rsnScriptSetVarI(mContext, id, slot, val);
564    }
565    native void rsnScriptSetVarJ(int con, int id, int slot, long val);
566    synchronized void nScriptSetVarJ(int id, int slot, long val) {
567        validate();
568        rsnScriptSetVarJ(mContext, id, slot, val);
569    }
570    native void rsnScriptSetVarF(int con, int id, int slot, float val);
571    synchronized void nScriptSetVarF(int id, int slot, float val) {
572        validate();
573        rsnScriptSetVarF(mContext, id, slot, val);
574    }
575    native void rsnScriptSetVarD(int con, int id, int slot, double val);
576    synchronized void nScriptSetVarD(int id, int slot, double val) {
577        validate();
578        rsnScriptSetVarD(mContext, id, slot, val);
579    }
580    native void rsnScriptSetVarV(int con, int id, int slot, byte[] val);
581    synchronized void nScriptSetVarV(int id, int slot, byte[] val) {
582        validate();
583        rsnScriptSetVarV(mContext, id, slot, val);
584    }
585    native void rsnScriptSetVarVE(int con, int id, int slot, byte[] val,
586                                  int e, int[] dims);
587    synchronized void nScriptSetVarVE(int id, int slot, byte[] val,
588                                      int e, int[] dims) {
589        validate();
590        rsnScriptSetVarVE(mContext, id, slot, val, e, dims);
591    }
592    native void rsnScriptSetVarObj(int con, int id, int slot, int val);
593    synchronized void nScriptSetVarObj(int id, int slot, int val) {
594        validate();
595        rsnScriptSetVarObj(mContext, id, slot, val);
596    }
597
598    native int  rsnScriptCCreate(int con, String resName, String cacheDir,
599                                 byte[] script, int length);
600    synchronized int nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
601        validate();
602        return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
603    }
604
605    native int  rsnScriptIntrinsicCreate(int con, int id, int eid);
606    synchronized int nScriptIntrinsicCreate(int id, int eid) {
607        validate();
608        return rsnScriptIntrinsicCreate(mContext, id, eid);
609    }
610
611    native int  rsnScriptKernelIDCreate(int con, int sid, int slot, int sig);
612    synchronized int nScriptKernelIDCreate(int sid, int slot, int sig) {
613        validate();
614        return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
615    }
616
617    native int  rsnScriptFieldIDCreate(int con, int sid, int slot);
618    synchronized int nScriptFieldIDCreate(int sid, int slot) {
619        validate();
620        return rsnScriptFieldIDCreate(mContext, sid, slot);
621    }
622
623    native int  rsnScriptGroupCreate(int con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
624    synchronized int nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
625        validate();
626        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
627    }
628
629    native void rsnScriptGroupSetInput(int con, int group, int kernel, int alloc);
630    synchronized void nScriptGroupSetInput(int group, int kernel, int alloc) {
631        validate();
632        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
633    }
634
635    native void rsnScriptGroupSetOutput(int con, int group, int kernel, int alloc);
636    synchronized void nScriptGroupSetOutput(int group, int kernel, int alloc) {
637        validate();
638        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
639    }
640
641    native void rsnScriptGroupExecute(int con, int group);
642    synchronized void nScriptGroupExecute(int group) {
643        validate();
644        rsnScriptGroupExecute(mContext, group);
645    }
646
647    native int  rsnSamplerCreate(int con, int magFilter, int minFilter,
648                                 int wrapS, int wrapT, int wrapR, float aniso);
649    synchronized int nSamplerCreate(int magFilter, int minFilter,
650                                 int wrapS, int wrapT, int wrapR, float aniso) {
651        validate();
652        return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
653    }
654
655
656
657
658    int     mDev;
659    int     mContext;
660    ReentrantReadWriteLock mRWLock;
661    @SuppressWarnings({"FieldCanBeLocal"})
662    MessageThread mMessageThread;
663
664    Element mElement_U8;
665    Element mElement_I8;
666    Element mElement_U16;
667    Element mElement_I16;
668    Element mElement_U32;
669    Element mElement_I32;
670    Element mElement_U64;
671    Element mElement_I64;
672    Element mElement_F32;
673    Element mElement_F64;
674    Element mElement_BOOLEAN;
675
676    Element mElement_ELEMENT;
677    Element mElement_TYPE;
678    Element mElement_ALLOCATION;
679    Element mElement_SAMPLER;
680    Element mElement_SCRIPT;
681
682    Element mElement_A_8;
683    Element mElement_RGB_565;
684    Element mElement_RGB_888;
685    Element mElement_RGBA_5551;
686    Element mElement_RGBA_4444;
687    Element mElement_RGBA_8888;
688
689    Element mElement_FLOAT_2;
690    Element mElement_FLOAT_3;
691    Element mElement_FLOAT_4;
692
693    Element mElement_DOUBLE_2;
694    Element mElement_DOUBLE_3;
695    Element mElement_DOUBLE_4;
696
697    Element mElement_UCHAR_2;
698    Element mElement_UCHAR_3;
699    Element mElement_UCHAR_4;
700
701    Element mElement_CHAR_2;
702    Element mElement_CHAR_3;
703    Element mElement_CHAR_4;
704
705    Element mElement_USHORT_2;
706    Element mElement_USHORT_3;
707    Element mElement_USHORT_4;
708
709    Element mElement_SHORT_2;
710    Element mElement_SHORT_3;
711    Element mElement_SHORT_4;
712
713    Element mElement_UINT_2;
714    Element mElement_UINT_3;
715    Element mElement_UINT_4;
716
717    Element mElement_INT_2;
718    Element mElement_INT_3;
719    Element mElement_INT_4;
720
721    Element mElement_ULONG_2;
722    Element mElement_ULONG_3;
723    Element mElement_ULONG_4;
724
725    Element mElement_LONG_2;
726    Element mElement_LONG_3;
727    Element mElement_LONG_4;
728
729    Element mElement_MATRIX_4X4;
730    Element mElement_MATRIX_3X3;
731    Element mElement_MATRIX_2X2;
732
733    Sampler mSampler_CLAMP_NEAREST;
734    Sampler mSampler_CLAMP_LINEAR;
735    Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
736    Sampler mSampler_WRAP_NEAREST;
737    Sampler mSampler_WRAP_LINEAR;
738    Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
739    Sampler mSampler_MIRRORED_REPEAT_NEAREST;
740    Sampler mSampler_MIRRORED_REPEAT_LINEAR;
741    Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
742
743
744    ///////////////////////////////////////////////////////////////////////////////////
745    //
746
747    /**
748     * The base class from which an application should derive in order
749     * to receive RS messages from scripts. When a script calls {@code
750     * rsSendToClient}, the data fields will be filled, and the run
751     * method will be called on a separate thread.  This will occur
752     * some time after {@code rsSendToClient} completes in the script,
753     * as {@code rsSendToClient} is asynchronous. Message handlers are
754     * not guaranteed to have completed when {@link
755     * android.support.v8.renderscript.RenderScript#finish} returns.
756     *
757     */
758    public static class RSMessageHandler implements Runnable {
759        protected int[] mData;
760        protected int mID;
761        protected int mLength;
762        public void run() {
763        }
764    }
765    /**
766     * If an application is expecting messages, it should set this
767     * field to an instance of {@link RSMessageHandler}.  This
768     * instance will receive all the user messages sent from {@code
769     * sendToClient} by scripts from this context.
770     *
771     */
772    RSMessageHandler mMessageCallback = null;
773
774    public void setMessageHandler(RSMessageHandler msg) {
775        mMessageCallback = msg;
776        if (isNative) {
777            RenderScriptThunker rst = (RenderScriptThunker) this;
778            rst.setMessageHandler(msg);
779        }
780    }
781    public RSMessageHandler getMessageHandler() {
782        return mMessageCallback;
783    }
784
785    /**
786     * Place a message into the message queue to be sent back to the message
787     * handler once all previous commands have been executed.
788     *
789     * @hide
790     *
791     * @param id
792     * @param data
793     */
794    public void sendMessage(int id, int[] data) {
795        nContextSendMessage(id, data);
796    }
797
798    /**
799     * The runtime error handler base class.  An application should derive from this class
800     * if it wishes to install an error handler.  When errors occur at runtime,
801     * the fields in this class will be filled, and the run method will be called.
802     *
803     */
804    public static class RSErrorHandler implements Runnable {
805        protected String mErrorMessage;
806        protected int mErrorNum;
807        public void run() {
808        }
809    }
810
811    /**
812     * Application Error handler.  All runtime errors will be dispatched to the
813     * instance of RSAsyncError set here.  If this field is null a
814     * {@link RSRuntimeException} will instead be thrown with details about the error.
815     * This will cause program termaination.
816     *
817     */
818    RSErrorHandler mErrorCallback = null;
819
820    public void setErrorHandler(RSErrorHandler msg) {
821        mErrorCallback = msg;
822        if (isNative) {
823            RenderScriptThunker rst = (RenderScriptThunker) this;
824            rst.setErrorHandler(msg);
825        }
826    }
827    public RSErrorHandler getErrorHandler() {
828        return mErrorCallback;
829    }
830
831    /**
832     * RenderScript worker thread priority enumeration.  The default value is
833     * NORMAL.  Applications wishing to do background processing should set
834     * their priority to LOW to avoid starving forground processes.
835     */
836    public enum Priority {
837        LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
838        NORMAL (Process.THREAD_PRIORITY_DISPLAY);
839
840        int mID;
841        Priority(int id) {
842            mID = id;
843        }
844    }
845
846    void validate() {
847        if (mContext == 0) {
848            throw new RSInvalidStateException("Calling RS with no Context active.");
849        }
850    }
851
852
853    /**
854     * Change the priority of the worker threads for this context.
855     *
856     * @param p New priority to be set.
857     */
858    public void setPriority(Priority p) {
859        validate();
860        nContextSetPriority(p.mID);
861    }
862
863    static class MessageThread extends Thread {
864        RenderScript mRS;
865        boolean mRun = true;
866        int[] mAuxData = new int[2];
867
868        static final int RS_MESSAGE_TO_CLIENT_NONE = 0;
869        static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1;
870        static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2;
871        static final int RS_MESSAGE_TO_CLIENT_ERROR = 3;
872        static final int RS_MESSAGE_TO_CLIENT_USER = 4;
873
874        static final int RS_ERROR_FATAL_UNKNOWN = 0x1000;
875
876        MessageThread(RenderScript rs) {
877            super("RSMessageThread");
878            mRS = rs;
879
880        }
881
882        public void run() {
883            // This function is a temporary solution.  The final solution will
884            // used typed allocations where the message id is the type indicator.
885            int[] rbuf = new int[16];
886            mRS.nContextInitToClient(mRS.mContext);
887            while(mRun) {
888                rbuf[0] = 0;
889                int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData);
890                int size = mAuxData[1];
891                int subID = mAuxData[0];
892
893                if (msg == RS_MESSAGE_TO_CLIENT_USER) {
894                    if ((size>>2) >= rbuf.length) {
895                        rbuf = new int[(size + 3) >> 2];
896                    }
897                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
898                        RS_MESSAGE_TO_CLIENT_USER) {
899                        throw new RSDriverException("Error processing message from RenderScript.");
900                    }
901
902                    if(mRS.mMessageCallback != null) {
903                        mRS.mMessageCallback.mData = rbuf;
904                        mRS.mMessageCallback.mID = subID;
905                        mRS.mMessageCallback.mLength = size;
906                        mRS.mMessageCallback.run();
907                    } else {
908                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
909                    }
910                    continue;
911                }
912
913                if (msg == RS_MESSAGE_TO_CLIENT_ERROR) {
914                    String e = mRS.nContextGetErrorMessage(mRS.mContext);
915
916                    if (subID >= RS_ERROR_FATAL_UNKNOWN) {
917                        throw new RSRuntimeException("Fatal error " + subID + ", details: " + e);
918                    }
919
920                    if(mRS.mErrorCallback != null) {
921                        mRS.mErrorCallback.mErrorMessage = e;
922                        mRS.mErrorCallback.mErrorNum = subID;
923                        mRS.mErrorCallback.run();
924                    } else {
925                        android.util.Log.e(LOG_TAG, "non fatal RS error, " + e);
926                        // Do not throw here. In these cases, we do not have
927                        // a fatal error.
928                    }
929                    continue;
930                }
931
932                // 2: teardown.
933                // But we want to avoid starving other threads during
934                // teardown by yielding until the next line in the destructor
935                // can execute to set mRun = false
936                try {
937                    sleep(1, 0);
938                } catch(InterruptedException e) {
939                }
940            }
941            //Log.d(LOG_TAG, "MessageThread exiting.");
942        }
943    }
944
945    RenderScript(Context ctx) {
946        if (ctx != null) {
947            mApplicationContext = ctx.getApplicationContext();
948        }
949        mRWLock = new ReentrantReadWriteLock();
950    }
951
952    /**
953     * Gets the application context associated with the RenderScript context.
954     *
955     * @return The application context.
956     */
957    public final Context getApplicationContext() {
958        return mApplicationContext;
959    }
960
961    /**
962     * @hide
963     */
964    public static RenderScript create(Context ctx, int sdkVersion) {
965        return create(ctx, sdkVersion, ContextType.NORMAL);
966    }
967
968    /**
969     * Create a RenderScript context.
970     *
971     * @hide
972     * @param ctx The context.
973     * @return RenderScript
974     */
975    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct) {
976        RenderScript rs = new RenderScript(ctx);
977
978        if (sSdkVersion == -1) {
979            sSdkVersion = sdkVersion;
980        } else if (sSdkVersion != sdkVersion) {
981            throw new RSRuntimeException("Can't have two contexts with different SDK versions in support lib");
982        }
983
984        if (setupThunk(sSdkVersion, ctx)) {
985            android.util.Log.v(LOG_TAG, "RS native mode");
986            return RenderScriptThunker.create(ctx, sSdkVersion);
987        }
988        synchronized(lock) {
989            if (sInitialized == false) {
990                try {
991                    Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
992                    Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
993                    sRuntime = get_runtime.invoke(null);
994                    registerNativeAllocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE);
995                    registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE);
996                    sUseGCHooks = true;
997                } catch (Exception e) {
998                    Log.e(LOG_TAG, "No GC methods");
999                    sUseGCHooks = false;
1000                }
1001                try {
1002                    System.loadLibrary("RSSupport");
1003                    System.loadLibrary("rsjni");
1004                    sInitialized = true;
1005                } catch (UnsatisfiedLinkError e) {
1006                    Log.e(LOG_TAG, "Error loading RS jni library: " + e);
1007                    throw new RSRuntimeException("Error loading RS jni library: " + e);
1008                }
1009            }
1010        }
1011
1012        android.util.Log.v(LOG_TAG, "RS compat mode");
1013        rs.mDev = rs.nDeviceCreate();
1014        rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion, ct.mID);
1015        if (rs.mContext == 0) {
1016            throw new RSDriverException("Failed to create RS context.");
1017        }
1018        rs.mMessageThread = new MessageThread(rs);
1019        rs.mMessageThread.start();
1020        return rs;
1021    }
1022
1023    /**
1024     * Create a RenderScript context.
1025     *
1026     * @param ctx The context.
1027     * @return RenderScript
1028     */
1029    public static RenderScript create(Context ctx) {
1030        return create(ctx, ContextType.NORMAL);
1031    }
1032
1033    /**
1034     * Create a RenderScript context.
1035     *
1036     * @hide
1037     *
1038     * @param ctx The context.
1039     * @param ct The type of context to be created.
1040     * @return RenderScript
1041     */
1042    public static RenderScript create(Context ctx, ContextType ct) {
1043        int v = ctx.getApplicationInfo().targetSdkVersion;
1044        return create(ctx, v, ct);
1045    }
1046
1047    /**
1048     * Print the currently available debugging information about the state of
1049     * the RS context to the log.
1050     *
1051     */
1052    public void contextDump() {
1053        validate();
1054        nContextDump(0);
1055    }
1056
1057    /**
1058     * Wait for any pending asynchronous opeations (such as copies to a RS
1059     * allocation or RS script executions) to complete.
1060     *
1061     */
1062    public void finish() {
1063        nContextFinish();
1064    }
1065
1066    /**
1067     * Destroys this RenderScript context.  Once this function is called,
1068     * using this context or any objects belonging to this context is
1069     * illegal.
1070     *
1071     */
1072    public void destroy() {
1073        validate();
1074        nContextFinish();
1075        nContextDeinitToClient(mContext);
1076        mMessageThread.mRun = false;
1077        try {
1078            mMessageThread.join();
1079        } catch(InterruptedException e) {
1080        }
1081
1082        nContextDestroy();
1083        nDeviceDestroy(mDev);
1084        mDev = 0;
1085    }
1086
1087    boolean isAlive() {
1088        return mContext != 0;
1089    }
1090
1091    int safeID(BaseObj o) {
1092        if(o != null) {
1093            return o.getID(this);
1094        }
1095        return 0;
1096    }
1097}
1098