|
What is the proper procedure for restoring bitmaps on Android? |
Max Savenkov
Member #4,613
May 2004
|
Android is driving me crazy. First, blend modes didn't work and I had to write a shader to subtract two textures, and now bitmaps are getting corrupted after I suspend and resume my game. So, what's happening: When I resume my game after going to background (via pressing Home button), I get not one, but two ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING events. If I recreate all bitmaps on both of them, all bitmaps with NO_PRESERVE_TEXTURE get corrupted very badly. For example, when I later draw a one-pixel line on such bitmap, it gets displayed as a wide band. If I only react to the first event, everything gets corrupted (as it should be, probably) If I only react to the second event (beyond calling al_acknowledge_drawing_resume), the picture is more correct, but there are still some problems with alpha channel. Here's the code I use: 1// Game.cpp, main loop:
2
3case DisplayEvent::DISPLAY_RESUME_DRAWING:
4 al_acknowledge_drawing_resume( al_get_current_display() );
5 render.SetGlobalScaling( SCALING_KEEP_ASPECT, SCREEN_W, SCREEN_H );
6 GetBitmapManager().ReloadAllResources();
7 m_forcedPause = false;
8 break;
9
10// Bitmap manager, a simplified code for ReloadAllResources():
11void BitmapManager::ReloadAllResources()
12{
13 const int oldFlags = al_get_new_bitmap_flags();
14
15 for ( ResVector::iterator iter = m_resources.begin();
16 iter != m_resources.end();
17 ++iter )
18 {
19 ALLEGRO_BITMAP *pOld = ((AllegroImage5*)iter->m_res)->GetBitmap();
20 ALLEGRO_BTIMAP *pNew = 0;
21 int newFlags = al_get_bitmap_flags( pOld );
22 al_set_new_bitmap_flags( newFlags );
23 if ( IsResourceFromFile( iter ) )
24 pNew = al_load_bitmap( iter->filename.c_str() );
25 else if ( !(newFlags & ALLEGRO_NO_PRESERVE_TEXTURE ))
26 pNew = al_clone_bitmap( pOld );
27 else
28 {
29 const int w = al_get_bitmap_width( pOld );
30 const int h = al_get_bitmap_height( pOld );
31 pNew = al_create_bitmap( w, h );
32 }
33
34 al_destroy_bitmap( pOld );
35 delete iter->m_res;
36 iter->m_res = new AllegroImage5( pNew );
37 }
38
39 al_set_new_bitmap_flags( oldFlags );
40}
So, what am I doing wrong? I've tried everything I could think of already.
|
bamccaig
Member #7,536
July 2006
|
I'm not really overly familiar with Allegro 5, let alone the Android port, but what stands out to me are oldFlags and newFlags. You extract the flags from the original bitmap, but you don't seem to apply them to the new bitmap. And the al_set_new_bitmap_flags doesn't appear to do anything since you just reassign the exact same flags that were already set. It's difficult to know though what Allegro does in the background with all this global state... I would have expected you to use al_set_new_bitmap_flags to temporary change the flags before creating the new bitmap and then restore the original setting at the end... -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Max Savenkov
Member #4,613
May 2004
|
Ah, sorry, I forgot to copy that line Amended.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Do you ever clear the new bitmaps? You create new bitmaps in the case of un-preserved textures and bitmaps not reloaded from a file. If you aren't drawing over the whole bitmaps then you could have uninitialized memory in them. That's all I can really see as you re-load bitmaps that were from files and you clone bitmaps that don't have the NO_PRESERVE_TEXTURE flag set. Are all your resources in m_resources bitmaps? Ie, are they all AllegroImage5 objects? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Max Savenkov
Member #4,613
May 2004
|
Yes, they are all stored in m_resources. I do not clear NO_PRESERVE_TEXTURE bitmaps, as they are usually drawn over completely on the next frame. It's still would be more proper to clear them, of course, than to rely on that, so I'll do that. What bothers me more, is those ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING events... Why am I getting two of them, and why recreating bitmaps twice screws things up royally (compared to a common screw up that happens if I only recreated them once, during handling of the second event)? I can't find any relevant references to surfaceChanged being called twice in Google... EDIT: I've done some digging, and it seems that I found the reason for some of my troubles. Based on attached log, I deduced the following sequence of events: 1) The game is paused, halt_drawing is acknowledged, the game goes to background This explains why things looks the best when I only react to the second resume_drawing event. I couldn't discern why onCreate is called twice, but there are mentions of such behaviour here and there. It seems like it's normal behaviour on Android sometimes. So the question is, how to make Allegro handle it correctly? The main problem I see is that Surface is destroyed when my own code is in the middle of work with bitmaps. Is there any way to postpone destruction of the old Surface? I don't quite see what to do here...
|
|