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