|
[A5] al_draw_bitmap crash |
William Labbett
Member #4,486
March 2004
|
Hi, I'm getting a crash with al_draw_bitmap(). The ALLEGRO_BITMAP pointer isn't null. I can't figure it out. Hoping someone can help. gdb says :- Quote:
finished. Program received signal SIGSEGV, Segmentation fault. The code looks like this. The crash happens on the al_draw_bitmap line. printf("drawing bitmap.\n"); if(tiles_bitmap == NULL) printf("it's NULL.\n"); al_draw_bitmap(tiles_bitmap, 0, 0, 0); printf("calling al_flip_display.\n"); al_flip_display(); system("PAUSE"); Any ideas ?
|
Mark Oates
Member #1,146
March 2001
|
The only think I can think of is that the tiles_bitmap was somehow deleted, leaving a dangling pointer. -- |
William Labbett
Member #4,486
March 2004
|
could it be a thread safety issue ? EDIT : I removed the threads and now it works fine but still the problem of jerky scrolling is back :/
|
Matthew Leverton
Supreme Loser
January 1999
|
William Labbett said: could it be a thread safety issue ? Yes, it probably is. You have to remember that threads can operate in any order. Thread A could finish before Thread B does anything. Or Thread B could do a lot of things before Thread A does anything. No order between the two is guaranteed. In your case, the primary thread should not touch the bitmap until the secondary thread is finished updating it. To do that, you'll need to wait for the thread to finish via a join, and not touch the bitmap in the meantime. |
William Labbett
Member #4,486
March 2004
|
Right. I've seen what was wrong now and fixed the issue. Thanks for explaining that. I've done some further investigating to work out why the scrolling slows down when I use a thread. I profiled the code and there are some functions which get called a lot more than others but these are functions that only get called while a thread is running but the slowdown occurs even when the thread isn't running so I don't know what's causing it. Quote:
Each sample counts as 0.01 seconds. any suggestions ? EDIT : I guess that's not a lot to go on. The slow down starts after the first thread gets destroyed.
|
Matthew Leverton
Supreme Loser
January 1999
|
Which thread creates the bitmap? If the secondary thread is creating the bitmap, then it might not be compatible with the display. If the primary thread creates the bitmap, and the secondary thread locks it for write, does its stuff, and unlocks it, you shouldn't have any speed disadvantages. |
William Labbett
Member #4,486
March 2004
|
It's a secondary thread as it happens. How do I make it compatible with the display ? Or do I need to rethink the code ? Thanks.
|
Matthew Leverton
Supreme Loser
January 1999
|
I'm only speaking of which thread calls al_create_bitmap(). If the primary thread creates it, and passes it to the secondary thread, you should be fine. Otherwise, you may need to do something like this to make it compatible: ALLEGRO_BITMAP *bmp2 = al_clone_bitmap(bmp1); al_destroy_bitmap(bmp1); That code would go in the primary thread after the secondary thread is finished. However, if you can make the primary thread be the one that calls al_create_bitmap() on the original bitmap, it wouldn't be necessary. |
William Labbett
Member #4,486
March 2004
|
Joy. Now I know what I'm doing, maybe I can fulfil this idea afterall. Thanks EDIT : when calling al_set_target_bitmap in a secondary thread does it affect the target bitmap in the main thread ?
|
Trent Gamblin
Member #261
April 2000
|
To your edit: no. Target bitmap like some other things in A5 are per thread.
|
William Labbett
Member #4,486
March 2004
|
cheers Trent. That's not why nothing's getting drawn on the bitmap then. I've got this function here : 1void make_blot(ALLEGRO_BITMAP *b, ALLEGRO_BITMAP *tiles, unsigned char **tile_numbers, int w, int h, ALLEGRO_COLOR c1, ALLEGRO_COLOR c2)
2{
3 int x, y;
4
5 al_set_target_bitmap(b);
6
7 //al_save_bitmap("all_tiles_saved.png", tiles_bitmap);
8
9
10 for(y = 0; y < h; ++y)
11 {
12 for(x = 0; x < w; ++x)
13 {
14
15 al_draw_bitmap_region(tiles, tile_numbers[y][x] << 4, 0, 16, 16, x << 4, y << 4, 0);
16 }
17 }
18
19
20}
When I use it from the main thread it works but from a secondary thread it doesn't seem to draw anything on the target bitmap.
|
Trent Gamblin
Member #261
April 2000
|
I don't think drawing is thread safe. It has to be done from the thread that created the display.
|
William Labbett
Member #4,486
March 2004
|
What if I use an ALLEGRO_LOCKED_REGION ? Is that why matthew suggested doing that ?
|
Trent Gamblin
Member #261
April 2000
|
I don't think that'll work either. Anything tied to the OpenGL (or d3d?) context can only be accessed from one thread. Unless you mean using memory bitmaps. You can use those from multiple threads as long as you do it in a thread safe manner (a given I suppose) and you don't draw them to video bitmaps or the screen, ie the single thread for gpu stuff still applies. You can create and draw a memory bitmap in one thread and then when you're done draw it in a different thread, even to video bitmaps or screen.
|
William Labbett
Member #4,486
March 2004
|
Okay, I thought I could use a memory bitmap in the second thread and then use al_clone_bitmap() and change it into a video bitmap back in the primary thread. Would that work or does al_clone_bitmap ignore the current bitmap flags ?
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
al_clone_bitmap observes the current bitmap flags. 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 |
William Labbett
Member #4,486
March 2004
|
Cheers. I did a little test with al_get_bitmap_flags and it answered my question. Thanks for all the help guys. This question has definitely been answered helpfully. I've got the threads working now. I make a memory bitmap from the primary thread, then make it in the secondary and then when it's done, clone it into a video bitmap. The scrolling works really nicely now. Still there's a bit of speed change but it's acceptable. I'm pleased to have learnt about all this. Thanks.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
If the sizes of all your bitmaps don't change, then you should create all your memory and video bitmaps in your primary thread, and just draw to the memory bitmaps in the secondary thread. When that's done draw it to your video bitmap in the primary thread so it will be acclerated when you're drawing it to the screen. 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 |
William Labbett
Member #4,486
March 2004
|
William Labbett said: then make it in the secondary and then when it's done Sorry. When I said that, I meant lock it and set the pixels.
|
Thomas Fjellstrom
Member #476
June 2000
|
Trent Gamblin said: I don't think drawing is thread safe. It has to be done from the thread that created the display I would think if you surround access to that bitmap and possibly other items with a mutex, it should work unless I'm missing something. I'm not sure why a bitmap couldn't be used in a different thread, especially if its only used there. Then it shouldn't even need a mutex. -- |
William Labbett
Member #4,486
March 2004
|
I tried it but none of my al_draw_bitmap's to it seemed to do anything so I followed Trent's advice. Could there have been another reason ?
|
Thomas Fjellstrom
Member #476
June 2000
|
Hm, I seem to recall GL really hates it when you use stuff from one thread in other threads. Least I think that was one issue. -- |
William Labbett
Member #4,486
March 2004
|
FWIW I'm not using GL
|
|