1/*
2 * Copyright (C) 2012 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;
21
22import android.content.Context;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.PackageManager;
25import android.content.res.AssetManager;
26import android.graphics.Bitmap;
27import android.graphics.BitmapFactory;
28import android.os.Process;
29import android.util.Log;
30import android.view.Surface;
31
32
33
34/**
35 * Renderscript base master class.  An instance of this class creates native
36 * worker threads for processing commands from this object.  This base class
37 * does not provide any extended capabilities beyond simple data processing.
38 * For extended capabilities use derived classes such as RenderScriptGL.
39 *
40 * <div class="special reference">
41 * <h3>Developer Guides</h3>
42 * <p>For more information about creating an application that uses Renderscript, read the
43 * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
44 * </div>
45 **/
46public class RenderScript {
47    static final String LOG_TAG = "RenderScript_jni";
48    static final boolean DEBUG  = false;
49    @SuppressWarnings({"UnusedDeclaration", "deprecation"})
50    static final boolean LOG_ENABLED = false;
51
52    private Context mApplicationContext;
53    boolean mUseNativeRS;
54
55    static class NRS {
56        android.renderscript.RenderScript mRS;
57
58        android.renderscript.RenderScript getRS() {
59            return mRS;
60        }
61    }
62    NRS mNRS;
63
64    /*
65     * We use a class initializer to allow the native code to cache some
66     * field offsets.
67     */
68    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
69    static boolean sInitialized;
70    native static void _nInit();
71
72
73    static {
74        sInitialized = false;
75        try {
76            System.loadLibrary("rsjni");
77            _nInit();
78            sInitialized = true;
79        } catch (UnsatisfiedLinkError e) {
80            Log.e(LOG_TAG, "Error loading RS jni library: " + e);
81            throw new RSRuntimeException("Error loading RS jni library: " + e);
82        }
83    }
84
85    // Non-threadsafe functions.
86    native int  nDeviceCreate();
87    native void nDeviceDestroy(int dev);
88    native void nDeviceSetConfig(int dev, int param, int value);
89    native int nContextGetUserMessage(int con, int[] data);
90    native String nContextGetErrorMessage(int con);
91    native int  nContextPeekMessage(int con, int[] subID);
92    native void nContextInitToClient(int con);
93    native void nContextDeinitToClient(int con);
94
95    /**
96     * Name of the file that holds the object cache.
97     */
98    private static final String CACHE_PATH = "com.android.renderscript.cache";
99    static String mCachePath;
100
101     /**
102     * Sets the directory to use as a persistent storage for the
103     * renderscript object file cache.
104     *
105     * @hide
106     * @param cacheDir A directory the current process can write to
107     */
108    public static void setupDiskCache(File cacheDir) {
109        File f = new File(cacheDir, CACHE_PATH);
110        mCachePath = f.getAbsolutePath();
111        f.mkdirs();
112    }
113
114
115    // Methods below are wrapped to protect the non-threadsafe
116    // lockless fifo.
117    native int  rsnContextCreate(int dev, int ver, int sdkVer);
118    synchronized int nContextCreate(int dev, int ver, int sdkVer) {
119        return rsnContextCreate(dev, ver, sdkVer);
120    }
121    native void rsnContextDestroy(int con);
122    synchronized void nContextDestroy() {
123        validate();
124        rsnContextDestroy(mContext);
125    }
126    native void rsnContextSetPriority(int con, int p);
127    synchronized void nContextSetPriority(int p) {
128        validate();
129        rsnContextSetPriority(mContext, p);
130    }
131    native void rsnContextDump(int con, int bits);
132    synchronized void nContextDump(int bits) {
133        validate();
134        rsnContextDump(mContext, bits);
135    }
136    native void rsnContextFinish(int con);
137    synchronized void nContextFinish() {
138        validate();
139        rsnContextFinish(mContext);
140    }
141
142    native void rsnObjDestroy(int con, int id);
143    synchronized void nObjDestroy(int id) {
144        // There is a race condition here.  The calling code may be run
145        // by the gc while teardown is occuring.  This protects againts
146        // deleting dead objects.
147        if (mContext != 0) {
148            rsnObjDestroy(mContext, id);
149        }
150    }
151
152    native int  rsnElementCreate(int con, int type, int kind, boolean norm, int vecSize);
153    synchronized int nElementCreate(int type, int kind, boolean norm, int vecSize) {
154        validate();
155        return rsnElementCreate(mContext, type, kind, norm, vecSize);
156    }
157    native int  rsnElementCreate2(int con, int[] elements, String[] names, int[] arraySizes);
158    synchronized int nElementCreate2(int[] elements, String[] names, int[] arraySizes) {
159        validate();
160        return rsnElementCreate2(mContext, elements, names, arraySizes);
161    }
162    native void rsnElementGetNativeData(int con, int id, int[] elementData);
163    synchronized void nElementGetNativeData(int id, int[] elementData) {
164        validate();
165        rsnElementGetNativeData(mContext, id, elementData);
166    }
167    native void rsnElementGetSubElements(int con, int id,
168                                         int[] IDs, String[] names, int[] arraySizes);
169    synchronized void nElementGetSubElements(int id, int[] IDs, String[] names, int[] arraySizes) {
170        validate();
171        rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
172    }
173
174    native int rsnTypeCreate(int con, int eid, int x, int y, int z, boolean mips, boolean faces);
175    synchronized int nTypeCreate(int eid, int x, int y, int z, boolean mips, boolean faces) {
176        validate();
177        return rsnTypeCreate(mContext, eid, x, y, z, mips, faces);
178    }
179    native void rsnTypeGetNativeData(int con, int id, int[] typeData);
180    synchronized void nTypeGetNativeData(int id, int[] typeData) {
181        validate();
182        rsnTypeGetNativeData(mContext, id, typeData);
183    }
184
185    native int  rsnAllocationCreateTyped(int con, int type, int mip, int usage, int pointer);
186    synchronized int nAllocationCreateTyped(int type, int mip, int usage, int pointer) {
187        validate();
188        return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
189    }
190    native int  rsnAllocationCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
191    synchronized int nAllocationCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
192        validate();
193        return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
194    }
195    native int  rsnAllocationCubeCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
196    synchronized int nAllocationCubeCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
197        validate();
198        return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
199    }
200    native int  rsnAllocationCreateBitmapRef(int con, int type, Bitmap bmp);
201    synchronized int nAllocationCreateBitmapRef(int type, Bitmap bmp) {
202        validate();
203        return rsnAllocationCreateBitmapRef(mContext, type, bmp);
204    }
205    native int  rsnAllocationCreateFromAssetStream(int con, int mips, int assetStream, int usage);
206    synchronized int nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
207        validate();
208        return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
209    }
210
211    native void  rsnAllocationCopyToBitmap(int con, int alloc, Bitmap bmp);
212    synchronized void nAllocationCopyToBitmap(int alloc, Bitmap bmp) {
213        validate();
214        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
215    }
216
217
218    native void rsnAllocationSyncAll(int con, int alloc, int src);
219    synchronized void nAllocationSyncAll(int alloc, int src) {
220        validate();
221        rsnAllocationSyncAll(mContext, alloc, src);
222    }
223
224
225    native void rsnAllocationGenerateMipmaps(int con, int alloc);
226    synchronized void nAllocationGenerateMipmaps(int alloc) {
227        validate();
228        rsnAllocationGenerateMipmaps(mContext, alloc);
229    }
230    native void  rsnAllocationCopyFromBitmap(int con, int alloc, Bitmap bmp);
231    synchronized void nAllocationCopyFromBitmap(int alloc, Bitmap bmp) {
232        validate();
233        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
234    }
235
236
237    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, int[] d, int sizeBytes);
238    synchronized void nAllocationData1D(int id, int off, int mip, int count, int[] d, int sizeBytes) {
239        validate();
240        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
241    }
242    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, short[] d, int sizeBytes);
243    synchronized void nAllocationData1D(int id, int off, int mip, int count, short[] d, int sizeBytes) {
244        validate();
245        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
246    }
247    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, byte[] d, int sizeBytes);
248    synchronized void nAllocationData1D(int id, int off, int mip, int count, byte[] d, int sizeBytes) {
249        validate();
250        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
251    }
252    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, float[] d, int sizeBytes);
253    synchronized void nAllocationData1D(int id, int off, int mip, int count, float[] d, int sizeBytes) {
254        validate();
255        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
256    }
257
258    native void rsnAllocationElementData1D(int con, int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
259    synchronized void nAllocationElementData1D(int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
260        validate();
261        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
262    }
263
264    native void rsnAllocationData2D(int con,
265                                    int dstAlloc, int dstXoff, int dstYoff,
266                                    int dstMip, int dstFace,
267                                    int width, int height,
268                                    int srcAlloc, int srcXoff, int srcYoff,
269                                    int srcMip, int srcFace);
270    synchronized void nAllocationData2D(int dstAlloc, int dstXoff, int dstYoff,
271                                        int dstMip, int dstFace,
272                                        int width, int height,
273                                        int srcAlloc, int srcXoff, int srcYoff,
274                                        int srcMip, int srcFace) {
275        validate();
276        rsnAllocationData2D(mContext,
277                            dstAlloc, dstXoff, dstYoff,
278                            dstMip, dstFace,
279                            width, height,
280                            srcAlloc, srcXoff, srcYoff,
281                            srcMip, srcFace);
282    }
283
284    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes);
285    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes) {
286        validate();
287        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
288    }
289    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes);
290    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes) {
291        validate();
292        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
293    }
294    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes);
295    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes) {
296        validate();
297        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
298    }
299    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes);
300    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes) {
301        validate();
302        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
303    }
304    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, Bitmap b);
305    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, Bitmap b) {
306        validate();
307        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
308    }
309
310    native void rsnAllocationRead(int con, int id, byte[] d);
311    synchronized void nAllocationRead(int id, byte[] d) {
312        validate();
313        rsnAllocationRead(mContext, id, d);
314    }
315    native void rsnAllocationRead(int con, int id, short[] d);
316    synchronized void nAllocationRead(int id, short[] d) {
317        validate();
318        rsnAllocationRead(mContext, id, d);
319    }
320    native void rsnAllocationRead(int con, int id, int[] d);
321    synchronized void nAllocationRead(int id, int[] d) {
322        validate();
323        rsnAllocationRead(mContext, id, d);
324    }
325    native void rsnAllocationRead(int con, int id, float[] d);
326    synchronized void nAllocationRead(int id, float[] d) {
327        validate();
328        rsnAllocationRead(mContext, id, d);
329    }
330    native int  rsnAllocationGetType(int con, int id);
331    synchronized int nAllocationGetType(int id) {
332        validate();
333        return rsnAllocationGetType(mContext, id);
334    }
335
336    native void rsnAllocationResize1D(int con, int id, int dimX);
337    synchronized void nAllocationResize1D(int id, int dimX) {
338        validate();
339        rsnAllocationResize1D(mContext, id, dimX);
340    }
341    native void rsnAllocationResize2D(int con, int id, int dimX, int dimY);
342    synchronized void nAllocationResize2D(int id, int dimX, int dimY) {
343        validate();
344        rsnAllocationResize2D(mContext, id, dimX, dimY);
345    }
346
347    native void rsnScriptBindAllocation(int con, int script, int alloc, int slot);
348    synchronized void nScriptBindAllocation(int script, int alloc, int slot) {
349        validate();
350        rsnScriptBindAllocation(mContext, script, alloc, slot);
351    }
352    native void rsnScriptSetTimeZone(int con, int script, byte[] timeZone);
353    synchronized void nScriptSetTimeZone(int script, byte[] timeZone) {
354        validate();
355        rsnScriptSetTimeZone(mContext, script, timeZone);
356    }
357    native void rsnScriptInvoke(int con, int id, int slot);
358    synchronized void nScriptInvoke(int id, int slot) {
359        validate();
360        rsnScriptInvoke(mContext, id, slot);
361    }
362    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout, byte[] params);
363    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout);
364    synchronized void nScriptForEach(int id, int slot, int ain, int aout, byte[] params) {
365        validate();
366        if (params == null) {
367            rsnScriptForEach(mContext, id, slot, ain, aout);
368        } else {
369            rsnScriptForEach(mContext, id, slot, ain, aout, params);
370        }
371    }
372    native void rsnScriptInvokeV(int con, int id, int slot, byte[] params);
373    synchronized void nScriptInvokeV(int id, int slot, byte[] params) {
374        validate();
375        rsnScriptInvokeV(mContext, id, slot, params);
376    }
377    native void rsnScriptSetVarI(int con, int id, int slot, int val);
378    synchronized void nScriptSetVarI(int id, int slot, int val) {
379        validate();
380        rsnScriptSetVarI(mContext, id, slot, val);
381    }
382    native void rsnScriptSetVarJ(int con, int id, int slot, long val);
383    synchronized void nScriptSetVarJ(int id, int slot, long val) {
384        validate();
385        rsnScriptSetVarJ(mContext, id, slot, val);
386    }
387    native void rsnScriptSetVarF(int con, int id, int slot, float val);
388    synchronized void nScriptSetVarF(int id, int slot, float val) {
389        validate();
390        rsnScriptSetVarF(mContext, id, slot, val);
391    }
392    native void rsnScriptSetVarD(int con, int id, int slot, double val);
393    synchronized void nScriptSetVarD(int id, int slot, double val) {
394        validate();
395        rsnScriptSetVarD(mContext, id, slot, val);
396    }
397    native void rsnScriptSetVarV(int con, int id, int slot, byte[] val);
398    synchronized void nScriptSetVarV(int id, int slot, byte[] val) {
399        validate();
400        rsnScriptSetVarV(mContext, id, slot, val);
401    }
402    native void rsnScriptSetVarVE(int con, int id, int slot, byte[] val,
403                                  int e, int[] dims);
404    synchronized void nScriptSetVarVE(int id, int slot, byte[] val,
405                                      int e, int[] dims) {
406        validate();
407        rsnScriptSetVarVE(mContext, id, slot, val, e, dims);
408    }
409    native void rsnScriptSetVarObj(int con, int id, int slot, int val);
410    synchronized void nScriptSetVarObj(int id, int slot, int val) {
411        validate();
412        rsnScriptSetVarObj(mContext, id, slot, val);
413    }
414
415    native int  rsnScriptCCreate(int con, String resName, String cacheDir,
416                                 byte[] script, int length);
417    synchronized int nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
418        validate();
419        return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
420    }
421
422    native int  rsnScriptIntrinsicCreate(int con, int id, int eid);
423    synchronized int nScriptIntrinsicCreate(int id, int eid) {
424        validate();
425        return rsnScriptIntrinsicCreate(mContext, id, eid);
426    }
427
428    native int  rsnScriptKernelIDCreate(int con, int sid, int slot, int sig);
429    synchronized int nScriptKernelIDCreate(int sid, int slot, int sig) {
430        validate();
431        return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
432    }
433
434    native int  rsnScriptFieldIDCreate(int con, int sid, int slot);
435    synchronized int nScriptFieldIDCreate(int sid, int slot) {
436        validate();
437        return rsnScriptFieldIDCreate(mContext, sid, slot);
438    }
439
440    native int  rsnScriptGroupCreate(int con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
441    synchronized int nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
442        validate();
443        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
444    }
445
446    native void rsnScriptGroupSetInput(int con, int group, int kernel, int alloc);
447    synchronized void nScriptGroupSetInput(int group, int kernel, int alloc) {
448        validate();
449        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
450    }
451
452    native void rsnScriptGroupSetOutput(int con, int group, int kernel, int alloc);
453    synchronized void nScriptGroupSetOutput(int group, int kernel, int alloc) {
454        validate();
455        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
456    }
457
458    native void rsnScriptGroupExecute(int con, int group);
459    synchronized void nScriptGroupExecute(int group) {
460        validate();
461        rsnScriptGroupExecute(mContext, group);
462    }
463
464    native int  rsnSamplerCreate(int con, int magFilter, int minFilter,
465                                 int wrapS, int wrapT, int wrapR, float aniso);
466    synchronized int nSamplerCreate(int magFilter, int minFilter,
467                                 int wrapS, int wrapT, int wrapR, float aniso) {
468        validate();
469        return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
470    }
471
472
473
474    int     mDev;
475    int     mContext;
476    @SuppressWarnings({"FieldCanBeLocal"})
477    MessageThread mMessageThread;
478
479    Element mElement_U8;
480    Element mElement_I8;
481    Element mElement_U16;
482    Element mElement_I16;
483    Element mElement_U32;
484    Element mElement_I32;
485    Element mElement_U64;
486    Element mElement_I64;
487    Element mElement_F32;
488    Element mElement_F64;
489    Element mElement_BOOLEAN;
490
491    Element mElement_ELEMENT;
492    Element mElement_TYPE;
493    Element mElement_ALLOCATION;
494    Element mElement_SAMPLER;
495    Element mElement_SCRIPT;
496
497    Element mElement_A_8;
498    Element mElement_RGB_565;
499    Element mElement_RGB_888;
500    Element mElement_RGBA_5551;
501    Element mElement_RGBA_4444;
502    Element mElement_RGBA_8888;
503
504    Element mElement_FLOAT_2;
505    Element mElement_FLOAT_3;
506    Element mElement_FLOAT_4;
507
508    Element mElement_DOUBLE_2;
509    Element mElement_DOUBLE_3;
510    Element mElement_DOUBLE_4;
511
512    Element mElement_UCHAR_2;
513    Element mElement_UCHAR_3;
514    Element mElement_UCHAR_4;
515
516    Element mElement_CHAR_2;
517    Element mElement_CHAR_3;
518    Element mElement_CHAR_4;
519
520    Element mElement_USHORT_2;
521    Element mElement_USHORT_3;
522    Element mElement_USHORT_4;
523
524    Element mElement_SHORT_2;
525    Element mElement_SHORT_3;
526    Element mElement_SHORT_4;
527
528    Element mElement_UINT_2;
529    Element mElement_UINT_3;
530    Element mElement_UINT_4;
531
532    Element mElement_INT_2;
533    Element mElement_INT_3;
534    Element mElement_INT_4;
535
536    Element mElement_ULONG_2;
537    Element mElement_ULONG_3;
538    Element mElement_ULONG_4;
539
540    Element mElement_LONG_2;
541    Element mElement_LONG_3;
542    Element mElement_LONG_4;
543
544    Element mElement_MATRIX_4X4;
545    Element mElement_MATRIX_3X3;
546    Element mElement_MATRIX_2X2;
547
548    Sampler mSampler_CLAMP_NEAREST;
549    Sampler mSampler_CLAMP_LINEAR;
550    Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
551    Sampler mSampler_WRAP_NEAREST;
552    Sampler mSampler_WRAP_LINEAR;
553    Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
554
555    ///////////////////////////////////////////////////////////////////////////////////
556    //
557
558    /**
559     * Base class application should derive from for handling RS messages
560     * coming from their scripts.  When a script calls sendToClient the data
561     * fields will be filled in and then the run method called by a message
562     * handling thread.  This will occur some time after sendToClient completes
563     * in the script.
564     *
565     */
566    public static class RSMessageHandler implements Runnable {
567        protected int[] mData;
568        protected int mID;
569        protected int mLength;
570        public void run() {
571        }
572    }
573    /**
574     * If an application is expecting messages it should set this field to an
575     * instance of RSMessage.  This instance will receive all the user messages
576     * sent from sendToClient by scripts from this context.
577     *
578     */
579    RSMessageHandler mMessageCallback = null;
580
581    public void setMessageHandler(RSMessageHandler msg) {
582        mMessageCallback = msg;
583    }
584    public RSMessageHandler getMessageHandler() {
585        return mMessageCallback;
586    }
587
588    /**
589     * Runtime error base class.  An application should derive from this class
590     * if it wishes to install an error handler.  When errors occur at runtime
591     * the fields in this class will be filled and the run method called.
592     *
593     */
594    public static class RSErrorHandler implements Runnable {
595        protected String mErrorMessage;
596        protected int mErrorNum;
597        public void run() {
598        }
599    }
600
601    /**
602     * Application Error handler.  All runtime errors will be dispatched to the
603     * instance of RSAsyncError set here.  If this field is null a
604     * RSRuntimeException will instead be thrown with details about the error.
605     * This will cause program termaination.
606     *
607     */
608    RSErrorHandler mErrorCallback = null;
609
610    public void setErrorHandler(RSErrorHandler msg) {
611        mErrorCallback = msg;
612    }
613    public RSErrorHandler getErrorHandler() {
614        return mErrorCallback;
615    }
616
617    /**
618     * RenderScript worker threads priority enumeration.  The default value is
619     * NORMAL.  Applications wishing to do background processing such as
620     * wallpapers should set their priority to LOW to avoid starving forground
621     * processes.
622     */
623    public enum Priority {
624        LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
625        NORMAL (Process.THREAD_PRIORITY_DISPLAY);
626
627        int mID;
628        Priority(int id) {
629            mID = id;
630        }
631    }
632
633    void validate() {
634        if (mContext == 0) {
635            throw new RSInvalidStateException("Calling RS with no Context active.");
636        }
637    }
638
639
640    /**
641     * Change the priority of the worker threads for this context.
642     *
643     * @param p New priority to be set.
644     */
645    public void setPriority(Priority p) {
646        validate();
647        nContextSetPriority(p.mID);
648    }
649
650    static class MessageThread extends Thread {
651        RenderScript mRS;
652        boolean mRun = true;
653        int[] mAuxData = new int[2];
654
655        static final int RS_MESSAGE_TO_CLIENT_NONE = 0;
656        static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1;
657        static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2;
658        static final int RS_MESSAGE_TO_CLIENT_ERROR = 3;
659        static final int RS_MESSAGE_TO_CLIENT_USER = 4;
660
661        static final int RS_ERROR_FATAL_UNKNOWN = 0x1000;
662
663        MessageThread(RenderScript rs) {
664            super("RSMessageThread");
665            mRS = rs;
666
667        }
668
669        public void run() {
670            // This function is a temporary solution.  The final solution will
671            // used typed allocations where the message id is the type indicator.
672            int[] rbuf = new int[16];
673            mRS.nContextInitToClient(mRS.mContext);
674            while(mRun) {
675                rbuf[0] = 0;
676                int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData);
677                int size = mAuxData[1];
678                int subID = mAuxData[0];
679
680                if (msg == RS_MESSAGE_TO_CLIENT_USER) {
681                    if ((size>>2) >= rbuf.length) {
682                        rbuf = new int[(size + 3) >> 2];
683                    }
684                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
685                        RS_MESSAGE_TO_CLIENT_USER) {
686                        throw new RSDriverException("Error processing message from Renderscript.");
687                    }
688
689                    if(mRS.mMessageCallback != null) {
690                        mRS.mMessageCallback.mData = rbuf;
691                        mRS.mMessageCallback.mID = subID;
692                        mRS.mMessageCallback.mLength = size;
693                        mRS.mMessageCallback.run();
694                    } else {
695                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
696                    }
697                    continue;
698                }
699
700                if (msg == RS_MESSAGE_TO_CLIENT_ERROR) {
701                    String e = mRS.nContextGetErrorMessage(mRS.mContext);
702
703                    if (subID >= RS_ERROR_FATAL_UNKNOWN) {
704                        throw new RSRuntimeException("Fatal error " + subID + ", details: " + e);
705                    }
706
707                    if(mRS.mErrorCallback != null) {
708                        mRS.mErrorCallback.mErrorMessage = e;
709                        mRS.mErrorCallback.mErrorNum = subID;
710                        mRS.mErrorCallback.run();
711                    } else {
712                        // Do not throw here. In these cases, we do not have
713                        // a fatal error.
714                    }
715                    continue;
716                }
717
718                // 2: teardown.
719                // But we want to avoid starving other threads during
720                // teardown by yielding until the next line in the destructor
721                // can execute to set mRun = false
722                try {
723                    sleep(1, 0);
724                } catch(InterruptedException e) {
725                }
726            }
727            Log.d(LOG_TAG, "MessageThread exiting.");
728        }
729    }
730
731    RenderScript(Context ctx) {
732        if (ctx != null) {
733            mApplicationContext = ctx.getApplicationContext();
734        }
735    }
736
737    /**
738     * Gets the application context associated with the RenderScript context.
739     *
740     * @return The application context.
741     */
742    public final Context getApplicationContext() {
743        return mApplicationContext;
744    }
745
746    /**
747     * Create a basic RenderScript context.
748     *
749     * @hide
750     * @param ctx The context.
751     * @return RenderScript
752     */
753    public static RenderScript create(Context ctx, int sdkVersion) {
754        RenderScript rs = new RenderScript(ctx);
755
756        rs.mDev = rs.nDeviceCreate();
757        rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion);
758        if (rs.mContext == 0) {
759            throw new RSDriverException("Failed to create RS context.");
760        }
761        rs.mMessageThread = new MessageThread(rs);
762        rs.mMessageThread.start();
763        return rs;
764    }
765
766    /**
767     * Create a basic RenderScript context.
768     *
769     * @param ctx The context.
770     * @return RenderScript
771     */
772    public static RenderScript create(Context ctx) {
773        int v = ctx.getApplicationInfo().targetSdkVersion;
774        return create(ctx, v);
775    }
776
777    /**
778     * Print the currently available debugging information about the state of
779     * the RS context to the log.
780     *
781     */
782    public void contextDump() {
783        validate();
784        nContextDump(0);
785    }
786
787    /**
788     * Wait for any commands in the fifo between the java bindings and native to
789     * be processed.
790     *
791     */
792    public void finish() {
793        nContextFinish();
794    }
795
796    /**
797     * Destroy this renderscript context.  Once this function is called its no
798     * longer legal to use this or any objects created by this context.
799     *
800     */
801    public void destroy() {
802        validate();
803        nContextDeinitToClient(mContext);
804        mMessageThread.mRun = false;
805        try {
806            mMessageThread.join();
807        } catch(InterruptedException e) {
808        }
809
810        nContextDestroy();
811        mContext = 0;
812
813        nDeviceDestroy(mDev);
814        mDev = 0;
815    }
816
817    boolean isAlive() {
818        return mContext != 0;
819    }
820
821    int safeID(BaseObj o) {
822        if(o != null) {
823            return o.getID(this);
824        }
825        return 0;
826    }
827}
828