I have an application with a spinner with lots of items and an image.
Every time a user choises an item of the list, a number (1 to 5) of renderscript scripts are performed to change image's pixels.
After making around 30 choices the application crashes with error.
Here is the stack trace.
03-20 13:56:59.366: ERROR/RenderScript(3405): Created fewer than expected number of RS threads.
03-20 13:57:02.990: ERROR/AndroidRuntime(3405): FATAL EXCEPTION: main
java.lang.RuntimeException: createWindowSurface failed EGL_BAD_ALLOC
at android.view.HardwareRenderer$GlRenderer.createSurface(HardwareRenderer.java:1064)
at android.view.HardwareRenderer$GlRenderer.createEglSurface(HardwareRenderer.java:961)
at android.view.HardwareRenderer$GlRenderer.initialize(HardwareRenderer.java:787)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1502)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
at android.view.Choreographer.doCallbacks(Choreographer.java:562)
at android.view.Choreographer.doFrame(Choreographer.java:532)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
I think I should somehow close the unnesessary threads used by renderscript or what?
UPDATE:
Sometimes the error is different:
03-20 16:09:42.293: ERROR/bcc(24984): !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
03-20 16:09:42.293: ERROR/bcc(24984): rslAssert [frameworks/compile/linkloader/include/ELFObject.h:86] SHNCommonDataPtr && "Must init common data size before use!"
03-20 16:09:42.293: ERROR/bcc(24984): !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
or
03-20 15:46:27.315: ERROR/AndroidRuntime(19330): FATAL EXCEPTION: Thread-3582
android.renderscript.RSRuntimeException: Loading of ScriptC script failed.
at android.renderscript.ScriptC.<init>(ScriptC.java:60)
at com.gfranq.android.ScriptC_BrightnessContrast.<init>(ScriptC_BrightnessContrast.java:41)
at com.gfranq.android.filters.logic.ImageFilter.brightnessContrastRs(ImageFilter.java:1438)
it points to the line
ScriptC_BrightnessContrast script = new ScriptC_BrightnessContrast(rs, context.getResources(),
R.raw.brightnesscontrast);
Update 2:
Here is the Brightness conrast filter. I suppose that creating new in and out allocations and the Script object every time eats the memory. Is it possible to use one allocation for a chain of renderscript actions? For example I make an allocation from a bitmap, then aplly to it the brightnesscontrastfilter and then some different filter with similar implementation?
public Bitmap brightnessContrastRs(Bitmap bmIn, int brightness, int contrast, Context context)
{
Bitmap bmOut = Bitmap.createBitmap(bmIn.getWidth(), bmIn.getHeight(),
bmIn.getConfig());
// RenderScript rs = RenderScript.create(context);
Allocation allocIn;
allocIn = Allocation.createFromBitmap(rs, bmIn,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
Allocation allocOut = Allocation.createTyped(rs, allocIn.getType());
ScriptC_BrightnessContrast script = new ScriptC_BrightnessContrast(rs, context.getResources(),
R.raw.brightnesscontrast);
script.set_in(allocIn);
allocIn.destroy();
script.set_out(allocOut);
script.set_script(script);
float rowContrast = ((100.0f + contrast) * (100.0f + contrast) / 10000.0f);
float rowBrightness = brightness / 255.f;
script.set_rowBrightness(rowBrightness);
script.set_rowContrast(rowContrast);
script.invoke_filter();
allocOut.copyTo(bmOut);
allocOut.destroy();
return bmOut;
}
And besides inside some actions I have rather large int arrays (360000 ints), as I understood every time I create S criptC object it allocates memory for every array, defined inside the renderscript, so the memory can leak rather fast.
When I posted the question the commented line that creates the RenderScript object every time was not commented and the memory leaked faster.
The device is nexus 4.
For example here is the RS file with an array (other files are similar to this but may contain no array)
rs_allocation out;
rs_allocation in;
rs_script script;
float opacity;
float alphas[360000];
int width;
void root(const uchar4* v_in, uchar4* v_out, const void* usrData, uint32_t x,
uint32_t y)
{
float4 current = rsUnpackColor8888(*v_in);
current.a = alphas[width * y + x] * opacity;
*v_out = rsPackColorTo8888(current.r, current.g, current.b, current.a);
}
void filter()
{
#if !defined(RS_VERSION) || (RS_VERSION < 14)
rsForEach(script, in, out, 0);
#else
rsForEach(script, in, out);
#endif
}
Yes it really took a lot of memory to make a new ScriptC object every time. I moved them to the class field variables and everithing works OK.