Author Topic: Basics: Is a clustering of used GUI elements to one bitmap practicable?  (Read 5350 times)

Offline kbjansen

  • byte
  • *
  • Posts: 37
    • View Profile
Howdy!

short question about the storage of GUI elements that are obliged to blit via FrameBuffer:

What is better:
1. putting all GUI elements in one big bitmap that will be loaded as one single Texture to the TextureManager
or
2. for every small GUI element one single Texture-object that will be loaded to TextureManager?


My Problem:
I've chosen the first path because I've got about 60 GUI elements. All these elements are placed within a single
bitmap and are drawn to the screen via frameBuffer.blit(...) over their associated 'bitmap source coordinates' that are stored in a so called GUIMeasurements-Object.
The size of the bitmap is (please don't go berserk XD) 2048x2048 with a color depth of 16.

Is it necessary that this bitmap, which is only used for blitting, is loaded to the TextureManager?
At the moment the memory limit is reached while restarting the Activity, so I got a OOM - naturally.

The use of the method FrameBuffer.blit(int[], int, int, int, int, int, int, int, int, boolean) could be an alternative but is not recommended.

Any advice or hint?

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
2048*2048 = 16mb for the texture data in VM memory (which is always 32bit) plus the 16bit version on the gpu (8mb)=24mb for that single texture without any mip-maps. No wonder that you get an OOM...You can try to disable mip-mapping on that texture. You don't need it anyway for simple blits. However, i would rather create the gui out of single, smaller elements in this case. I don't get why you need such a large texture for the gui though...

For blitting, you don't have to add it to the TextureManager. But that doesn't help. The manager doesn't introduce any additional overhead larger than maybe a few bytes.

About the int[]-variant...don't even think about it. It will make things worse... ;)

Offline kbjansen

  • byte
  • *
  • Posts: 37
    • View Profile
mmh, ok.
The reason why i use such a huge texture:
I've got 60 elements for InGame GUI and Menu GUI that fill altogether around 20 screens.
Some of these elements are used several times. Each button has a active and a nonactive state (so 2 sub bitmaps per button).
I already combine the Standard Android GUI with this own custom GUI elements to reduce the bitmap using.
Each GUI element that is located within the texture is gauged for a 480x800 display - So the biggest element is about 435x752 and the smallest element is about 64x64.

I may reduce and replace some inefficient (repetetive) GUI elements from that texture/ bitmap. But i think the reduction would be not enough to get fit all elements in the next smallest bitmap texture (1024x1024) without a rescale.

Another way may be to scale down the bitmap from 2048x2048  to 1024x1024 an double scale each GUI element programatically.
But then , i guess, the GUI would look kinda crappy (even the reduction of my skybox bitmaps from 512² to 256² doesn't look nice)

BTW:
Is there a difference between loading one time a 2048² bitmap to memory or four times a 1024² ?
So is this statement true or not:
[(1024²+1024²+1024²+1024²) -> memory] = [(1024²) -> memory] + [(1024²) -> memory] + [(1024²) -> memory] + [(1024²) -> memory]

If the right term needs fewer memory than the left, then i could split the 2048² into four 1024² bitmaps and load them seperatly.
If not a splitting doesn't solve the OOM.

Another question:
Is there a way to manipulate the native Memory?
Because until Android Honeycomb the bitmaps are stored there and not in managed Heap.
Maybe i can free some memory associated with the huge bitmap whlie switching between Activties?


Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
4 times 1024*1024 is very much the same as one time 2048*2048, don't bother with that idea.

About your second question:

In older versions of Android, native memory usage hasn't been added to the vm memory usage when you try to determine how much memory is being used. However, it always accounted for the total memory usage, i.e. if you had 10mb free of vm memory and loaded an image of 5mb into native memory, you couldn't get another 2mb chunk of vm memory on a 16mb vm. In later versions, they changed this, but that doesn't deal with the actual problem. Now you can see better why you get an OOM, but you are still getting one. In later versions, the example above would simply report 15mb instead of 10mb being used. Using multiple Activities doesn't help here.

Offline kbjansen

  • byte
  • *
  • Posts: 37
    • View Profile
ok thanks Egon!

For everyone who wants to get more information about Memory Management in Android here is a very useful presentation that should answer all other questions relating to Memory Management and Memory Leak tracking in Android!

To the huge texture problem:
I' m scaling the 2048² bitmap down to 1024² and resize the GUI elements programmatically like I said before.
I believe I have to live with the maybe creepy results, we will see.
Another option is to completely change the GUI to a retro style with pixel graphics...

But, thanks again Egon, for your time invest!

Offline zammbi

  • float
  • ****
  • Posts: 361
    • View Profile
I would have every GUI image in there own image. Load up the main used GUI images at the start of the app. Then load up the images when you need them. Store all images in a cache(the ones that track memory usage), which will release any non used images when low on memory. If there isn't many large GUI images on screen at the same time then this would work nicely.

Offline kbjansen

  • byte
  • *
  • Posts: 37
    • View Profile
hi zammbi,
thanks for your idea, but I already managed that. All GUI elements are only loaded when needed.
But I could reorder, dismiss and group some GUI elements to save 'bitmap space'.

I tried a bitmap reduction from 2048² to 1024² and double scaled the elements programmatically.
Good: it worked! No OOM!
Bad: On first view it looks like 'eye cancer'  :D, but after a time you get familiar with it.

So a lil bit more optimization on those graphics and the work could finally continue.... :S

EDIT:
If I replace some buttons with a generic one and "blitted" text then a 2048x1024 bitmap is possible without losing quality.
Is anyone familiar with blitting text. The text should have a custom font style.

« Last Edit: June 29, 2012, 08:38:57 am by kbjansen »

Offline zammbi

  • float
  • ****
  • Posts: 361
    • View Profile
We had some crashes with OOM with android 3(annoying android 3.X bug which uses more memory) so we turned on
Code: [Select]
android:largeHeap="true"so that will help with that.

You could also use the Virtualizer class to help with some memory issues:
http://www.jpct.net/jpct-ae/doc/com/threed/jpct/Virtualizer.html

Quote
Is anyone familiar with blitting text. The text should have a custom font style.
There's some posts on that, just use the search.

Offline kbjansen

  • byte
  • *
  • Posts: 37
    • View Profile
thanks zammbi! that virtualizer-object seems to be a good workaround for later OOMs.
Anyway, for now the bitmap reduction should do it.
« Last Edit: June 29, 2012, 10:31:25 am by kbjansen »