|
This thread is locked; no one can reply to it. |
1
2
|
Reusing bitmaps after creating a new display |
torhu
Member #2,727
September 2002
|
I've implemented switching between fullscreen and windowed modes in my game. I destroy the old display, then create a new one. The next step is to reload the bitmaps, so I don't get FPS in the single digits. Just loading them from disk again works fine. Then I tried using al_clone_bitmap() to speed up the process: for (i = 0; i < NUMBER_OF_BITMAPS; i++) { old = bitmaps[i]; if (!(bitmaps[i] = al_clone_bitmap(old))) exit_message("Feil under konvertering av bitmaps til nytt display."); al_destroy_bitmap(old); } After doing this, some of the bitmaps have been replaced by just white boxes. Any ideas? |
Trent Gamblin
Member #261
April 2000
|
I'm not sure, but I'm going to be committing a change soon that should help. It adds an ALLEGRO_PRESERVE_TEXTURE flag (default off so nothing changes) that when used, will save your textures in system memory. Then in combination with ALLEGRO_CONVERT_BITMAP, you can simply destroy a display and create a new one and all the bitmaps are automatically converted.
|
torhu
Member #2,727
September 2002
|
Ok, cool. I was under the impression that reuploading of bitmaps to the video card would happen automatically with 5.1, but I guess that's not the case? I'm using 5.0.5, by the way. |
Trent Gamblin
Member #261
April 2000
|
Yeah, I guess if your scenario is like... user presses button, toggle fullscreen, then you don't really need the ALLEGRO_PRESERVE_TEXTURE flag, in which case your code should work, provided that you are not cloning the bitmaps after destroying the display... but then they should be converted to memory bitmaps so I don't know why it isn't working. The use case for the ALLEGRO_PRESERVE_TEXTURE flag is when the bitmaps can become invalidated at any time, such as hotplugging monitors. Short answer: not sure, can you post more code?
|
torhu
Member #2,727
September 2002
|
This is the code that does the switching, and creates the lovely white boxes. I tried waiting until after I created the new display with destroying the old one, but that didn't work. When switching from fullscreen to windowed, I got a window of the correct size, but that had no title bar, and was glued to the top left of the screen. Like the old and the new display conflicted somehow. 1void toggle_fullscreen_mode(ALLEGRO_EVENT_QUEUE* event_queue)
2{
3 int i;
4 ALLEGRO_BITMAP *old;
5 bool window = al_get_new_display_flags() & ALLEGRO_WINDOWED;
6
7 al_destroy_display(display);
8 al_set_new_display_flags(window ? ALLEGRO_FULLSCREEN : ALLEGRO_WINDOWED);
9 display = al_create_display(GFX_WIDTH, GFX_HEIGHT);
10
11 /* if it didn't work, go back to the previous mode */
12 if (!display) {
13 al_set_new_display_flags(window ? ALLEGRO_WINDOWED : ALLEGRO_FULLSCREEN);
14 display = al_create_display(GFX_WIDTH, GFX_HEIGHT);
15 }
16 assert(display);
17
18 /* redo some of the setup that was originally done by init(), main(), and
19 graphics_init() */
20 al_hide_mouse_cursor(display);
21 al_set_window_title(display, WINDOW_TITLE);
22 al_register_event_source(event_queue, al_get_display_event_source(display));
23 if (!(font = al_grab_font_from_bitmap(font_bitmap, 4, font_ranges)))
24 exit_message("Feil under konvertering av font til nytt display.");
25
26 /* have to reupload all bitmaps to the graphics card */
27 for (i = 0; i < NUMBER_OF_BITMAPS; i++) {
28 old = bitmaps[i];
29 if (!(bitmaps[i] = al_clone_bitmap(old)))
30 exit_message("Feil under konvertering av bitmaps til nytt display.");
31 al_destroy_bitmap(old);
32 }
33 backgr = bitmaps[BACKGR_IMAGE];
34}
|
Trent Gamblin
Member #261
April 2000
|
Does 5.0.5 have the bitmap auto-conversion that Elias and Matthew added? If so it seems like it's not working. In fact, some part of me thinks that I fixed a bug in that code while doing the ALLEGRO_PRESERVE_TEXTURE code... actually I'm almost sure of it. I can send you a patch to that file so you can look for changes I made, if you want, but you'll have to just ignore the big chunks I added... the only thing holding this patch up from being committed to 5.1 is that there is a race condition I couldn't pin down and put in an al_rest(1) for the time being (in the iphone display creation code).
|
torhu
Member #2,727
September 2002
|
I'm not sure if the auto-conversion is present in 5.0.5 or not. I can't find it in the docs. Working around it by loading the files from disk again works fine at the moment, since I have only 30 relatively small bitmaps. |
Matthew Leverton
Supreme Loser
January 1999
|
The auto conversion stuff is not in 5.0. It needs more testing before that happens. And before you commit anything that alters its behavior, you should probably post on AD first just to make sure the bug isn't actually a feature. Elias wrote the code, so I don't know it is implemented, but I know how it's supposed to work. |
Trent Gamblin
Member #261
April 2000
|
Ok, I looked at it and I didn't actually change anything except adding a conditional branch. But it shouldn't matter AFAIK, destroying a display has always been supposed to convert to memory bitmaps. One quick fix might be to clone the bitmaps before destroying the display (save them in an array or some such, then copy them back.) Sounds like a hack though. This really sounds like the problems I was having with hot-plugging displays, except my textures were all black or had some noise in them. Are you using D3D or OpenGL?
|
torhu
Member #2,727
September 2002
|
Looks I'm using Direct3D, I checked the log file. I tried cloning all the bitmaps (with al_clone_bitmap) after calling al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP), before destroying the old display. Then I called al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP) after destroying the old and creating the new display, and then cloned all bitmaps again. But it just crashed. |
Trent Gamblin
Member #261
April 2000
|
Did you destroy the video bitmaps after cloning them, before destroying the display?
|
torhu
Member #2,727
September 2002
|
Yes. EDIT: This code works: 1void toggle_fullscreen_mode(ALLEGRO_EVENT_QUEUE* event_queue)
2{
3 int i;
4 ALLEGRO_BITMAP *old;
5 ALLEGRO_BITMAP *backup[NUMBER_OF_BITMAPS];
6 bool window = al_get_new_display_flags() & ALLEGRO_WINDOWED;
7
8 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
9 for (i = 0; i < NUMBER_OF_BITMAPS; i++) {
10 old = bitmaps[i];
11 if (!(backup[i] = al_clone_bitmap(old)))
12 exit_message("Feil under kopiering av bitmaps før fullskjermsbyte.");
13 al_destroy_bitmap(old);
14 }
15
16 al_destroy_display(display);
17 al_set_new_display_flags(window ? ALLEGRO_FULLSCREEN : ALLEGRO_WINDOWED);
18 display = al_create_display(GFX_WIDTH, GFX_HEIGHT);
19
20 /* if it didn't work, go back to the previous mode */
21 if (!display) {
22 al_set_new_display_flags(window ? ALLEGRO_WINDOWED : ALLEGRO_FULLSCREEN);
23 display = al_create_display(GFX_WIDTH, GFX_HEIGHT);
24 }
25 assert(display);
26
27 /* redo some of the setup that was originally done by init(), main(), and
28 graphics_init() */
29 al_hide_mouse_cursor(display);
30 al_set_window_title(display, WINDOW_TITLE);
31 al_register_event_source(event_queue, al_get_display_event_source(display));
32 if (!(font = al_grab_font_from_bitmap(font_bitmap, 4, font_ranges)))
33 exit_message("Feil under konvertering av font til nytt display.");
34
35 /* have to reupload all bitmaps to the graphics card */
36 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
37 for (i = 0; i < NUMBER_OF_BITMAPS; i++) {
38 old = backup[i];
39 if (!(bitmaps[i] = al_clone_bitmap(old)))
40 exit_message("Feil under konvertering av bitmaps til nytt display.");
41 al_destroy_bitmap(old);
42 }
43 backgr = bitmaps[BACKGR_IMAGE];
44}
|
Trent Gamblin
Member #261
April 2000
|
So I wonder if the conversion is happening too late in the d3d driver..
|
Matthew Leverton
Supreme Loser
January 1999
|
Trent Gamblin said: But it shouldn't matter AFAIK, destroying a display has always been supposed to convert to memory bitmaps. Reading back through the discussion, it looks like no definitive answer was ever given regarding that. There were three things suggested:
I'm not sure which Elias implemented. I would prefer the first option because it is the most consistent: Allegro only tries to manage bitmaps marked with the auto-convert tag. |
Trent Gamblin
Member #261
April 2000
|
Yes, I was talking about before the AUTO_CONVERT flag was introduced. At that time there was no conversion except for destroy display->displays video bitmaps converted to memory, and all platforms did it. I'm not sure either which of those 3 is used now, but I guess it could be relevant. I'd have to ask Elias which is used, which might tell us why the first code snippet of torhu's didn't work.
|
Elias
Member #358
May 2000
|
I think destroying a display always converts all display bitmaps to memory bitmaps (if it is the last display sharing the bitmaps). Both in 5.0 and 5.1. The reason was to never have zombie bitmaps I think. I'm all for changing it, so that a VIDEO bitmap would never be a MEMORY bitmap unless it is set to auto convert (which it would be by default). The drawback is that we'd have to introduce the concept of zombie bitmaps, i.e. bitmaps which cannot be drawn at all, not even as memory bitmaps. The only valid operation on them would be destroying them. -- |
torhu
Member #2,727
September 2002
|
When I tried just destroying the old display and creating a new one, all the bitmaps seemed to be ok. So the automatic conversion to memory bitmaps works. It's when I cloned them after creating the new display that some of them turned into white boxes. EDIT: |
Matthew Leverton
Supreme Loser
January 1999
|
Elias said: The drawback is that we'd have to introduce the concept of zombie bitmaps, i.e. bitmaps which cannot be drawn at all, not even as memory bitmaps. The only valid operation on them would be destroying them. If video bitmaps were to be invalidated, Peter's comment was: Quote: They should be 0x0 bitmaps without any data associated. I'm not sure if he meant that those bitmaps should be able to be drawn (null op) or not. Regardless of whether they can or not, I still prefer it (zombie bitmaps) because I think it makes it easier to document, explain, and understand when conversions happen: if you don't set the conversion flag, the bitmap will never be converted, and if you destroy the last display, the bitmap is lost. |
torhu
Member #2,727
September 2002
|
The al_clone_bitmap() call in the first loop in my function has a tendency to return NULL. Is there a limit to how many bitmaps I can create or something? I destroy the old ones, but maybe there's some resource that gets depleted. |
Thomas Fjellstrom
Member #476
June 2000
|
Video Bitmaps live in the video card memory, if you run out of that, it tends to fail. -- |
torhu
Member #2,727
September 2002
|
Yes, but the video memory should be freed when I call al_destroy_bitmap, right? |
Thomas Fjellstrom
Member #476
June 2000
|
yeah, but if you just create too many, then you have no recourse. -- |
torhu
Member #2,727
September 2002
|
I think I have no more than 32 bitmaps at any given time, so it's not the number of bitmaps that the problem. |
Thomas Fjellstrom
Member #476
June 2000
|
It's not really the number that matters, but the amount of video memory they use up, and how much free video memory you have. -- |
Arthur Kalliokoski
Second in Command
February 2005
|
Even the cheapest video cards have half a gig of memory nowadays. They all watch too much MSNBC... they get ideas. |
|
1
2
|