Reputation: 1636
I have a GLSurfaceView and a Renderer which loads textures in onSurfaceCreated
. My textures are created like so :
public Texture3D(final GL10 gl, final int id) {
_pBitmap = BitmapFactory.decodeResource(Utils.getResources(), id);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
texture = newTextureID(gl);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, _pBitmap, 0);
_pBitmap.recycle();
_pBitmap = null;
gl.glEnable(GL10.GL_BLEND);
}
I store them in an HashMap :
textures.put(R.drawable.tile, new Texture3D(gl, R.drawable.tile));
My problem is when I create a texture from a large image (720x1280, 561 Ko) after I sometimes get the following error :
04-24 11:05:19.870: D/dalvikvm(27953): GC_CONCURRENT freed 26K, 18% free 50397K/60743K, paused 18ms+6ms, total 57ms
04-24 11:05:19.870: D/dalvikvm(27953): WAIT_FOR_CONCURRENT_GC blocked 2ms
04-24 11:05:19.895: D/dalvikvm(27953): GC_FOR_ALLOC freed 7K, 18% free 50390K/60743K, paused 25ms, total 25ms
04-24 11:05:19.900: I/dalvikvm-heap(27953): Forcing collection of SoftReferences for 14745616-byte allocation
04-24 11:05:19.940: D/dalvikvm(27953): GC_BEFORE_OOM freed 10K, 18% free 50380K/60743K, paused 41ms, total 41ms
04-24 11:05:19.940: E/dalvikvm-heap(27953): Out of memory on a 14745616-byte allocation.
04-24 11:05:19.940: I/dalvikvm(27953): "GLThread 11210" prio=5 tid=35 RUNNABLE
04-24 11:05:19.940: I/dalvikvm(27953): | group="main" sCount=0 dsCount=0 obj=0x42ec2008 self=0x6095d078
04-24 11:05:19.940: I/dalvikvm(27953): | sysTid=29199 nice=0 sched=0/0 cgrp=apps handle=1623155456
04-24 11:05:19.940: I/dalvikvm(27953): | schedstat=( 142147207 17456123 110 ) utm=11 stm=2 core=2
04-24 11:05:19.940: I/dalvikvm(27953): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
04-24 11:05:19.945: I/dalvikvm(27953): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
04-24 11:05:19.945: I/dalvikvm(27953): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:476)
04-24 11:05:19.945: I/dalvikvm(27953): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:499)
04-24 11:05:19.945: I/dalvikvm(27953): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:529)
04-24 11:05:19.945: I/dalvikvm(27953): at com.gbanga.opengl.Texture3D.<init>(Texture3D.java:73)
04-24 11:05:19.945: I/dalvikvm(27953): at com.gbanga.opengl.Texture3D.setupTextures(Texture3D.java:169)
04-24 11:05:19.945: I/dalvikvm(27953): at com.gbanga.opengl.OpenGLRenderer.onSurfaceCreated(OpenGLRenderer.java:440)
04-24 11:05:19.950: I/dalvikvm(27953): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1494)
04-24 11:05:19.950: I/dalvikvm(27953): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
That points to the first line of the constructor where I use BitmapFactory.decodeResource
. On my Galaxy S3 I get the error when I switch to another fragment and then I come back to the fragment that displays the GLSurfaceView
(onPause
and onResume
are called on the GLSurfaceView
).
How can I avoid this problem ? I tried this solution but I lose too much quality and in rare case the bug happens anyway (probably on old phones models).
Is there something wrong how I create / store my textures ? Also do you know why I don't always get this error ? (generally I get it the second time I load the textures).
Upvotes: 0
Views: 370
Reputation: 500
If your app will be dealing with a lot of large textures, and if you want to support older model phones it might be more advantageous for you to do your opengl processing on the native side.
The hello-gl2 sample in the NDK shows how this can be done. On the native side you will be free of the limits enforced by the app VM (you should however ensure you manage memory properly and not cause any leaks, because the process will keep running even if the user closes your activity)
Upvotes: 0
Reputation: 7226
Are you familiar with: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html Newer Androids have manifest paramether: largeHeap=true
Upvotes: 2
Reputation: 25267
You can try increasing the size of the VM heap by editing your AVD from Android Virtual Device Manager...
Upvotes: 0