1

My last question was unanswered so I am trying a different approach. I load many textures (256x256 RGBA888) into memory on the fly and discard them when needed. Problem is that sometimes when I upload the texture to OpenGL ES it takes 40-80ms, rarely more. I figure out, that this slow time is after a garbage collection. Problem is, that this GC sometimes blocks the GL thread (FPS drop) and sometimes it blocks the texture loader thread (OK). Is there a good way to somehow not allow GC to happen on the GL thread?

I tried calling System.gc() on the texture loader thread after every 1, 2, 3...n textures are decoded and this effectively removed GC-ing on the GL thread, but now the textures load much slower, because that thread must wait for the GC to finish. Making the "n" bigger makes loading faster, but GC on the GL thread is more probable, thus choppy animations.

Is there some way to remove GC-ing on the GL thread for bitmaps decoded in a different thread? I do not decode/allocate any bitmaps on the GL thread and GC-ing happens only when new textures are loaded.

EDIT: App targets android 3.2 and newer, also phones. This happens on phones (HTC One S - 4.0.3) and also tablets (Nexus 7 - 4.1, Galaxy Tab 2 10.1 - 3.2 and 4.0, Acer Icona A200 - 4.0)

shelll
  • 3,234
  • 3
  • 33
  • 67
  • On what version of android you are testing? – Ali Imran Dec 17 '12 at 09:31
  • @Ali Imran edited my post to add devices and Androod versions – shelll Dec 17 '12 at 09:40
  • @Ali Imran That is also my question from very long time ago. It will not solve my current problem, as every BitmapFactory.decodeStream(...) will create a new bitmap, which will be GC-ed sometime in the future. I am using a similar approach from that question, but without "double buffering of bitmaps", which gave me no advantage in the end. – shelll Dec 17 '12 at 11:54
  • http://stackoverflow.com/questions/7236371/android-egl-opengl-es-frame-rate-stuttering – Ali Imran Dec 17 '12 at 12:42
  • @Ali Imran That did not help either :( I need to somehow move the GC in a different thread and not pausing the GL nor the bitmap loader thread – shelll Dec 17 '12 at 13:33

2 Answers2

2

You cannot completely disable garbage collection, it will be initiated by Dalvik VM without your intrusion.

You can minimize memory allocation and freeing by using some custom loading of textures, like using pre-allocated arrays to store source textures data, etc. As you mentioned, all your textures have the same dimensions and color depth so you will need a temp buffer of the same size (256x256x4 = 262144 bytes) for any image.

Ultimately, you can move OpenGL code to JNI C/C++ code to manage memory the way you want.

keaukraine
  • 5,315
  • 29
  • 54
  • I am thinking of moving the bitmap creation part into C, but I would also have to manage sending the bitmap to OpenGL's thread in C, so there is no Bitmap instance in java, which will be GC-ed. Can you direct me please how to send a Java InputStream (I open the PNGs from APK expansion files) into native code, decode it there and send it to the GL thread and set the texture id and ready flag in my Java class instace "Tile"? Thank you – shelll Dec 17 '12 at 13:47
  • I'm not good at JNI programming, I just propose you to use it because in native C code you will be able to manage memory any way you need. Alternatively, you can do it in Java but different way. Don't load PNG files into `Bitmap` but load prepared textures in binary RGBA888 format ready for direct loading to GPU. This way you will need one pre-allocated temporary buffer to load all your textures, please see my edit to answer. – keaukraine Dec 17 '12 at 13:53
  • Having them uncopressed in 8888 format is not the best idea in my case, that will be around 2GiB of data. I will probably have to look into native code and mix Java and native OpenGL ES calls. – shelll Dec 17 '12 at 14:04
  • If you don't need alpha, you can use ETC1 compression. It is supported on all devices with Android 2.2 and up. – keaukraine Dec 17 '12 at 14:17
  • compression is also not good for this app, because there are lot of gray scale images and images with smooth gradients. – shelll Dec 17 '12 at 14:27
0

Thanks to this video there is an easy solution for same sized tiles and targeting Android 3.0 and newer.

BitmapOptions.inBitmap which will reuse one Bitmap for every new tile, so no more furios GC-ing.

shelll
  • 3,234
  • 3
  • 33
  • 67