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