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