Question about blitting speed
Usually one of the most expensive operations my game will do is clearing the screen before new stuff is drawn. I want to know, is there a speed difference between clear_bitmap(buffer) and blit(bmp,buffer,0,0,0,0,bmp->w,bmp->h)?
If i have a background image, i just do the blit line and bmp contains the background, but if i don't, i'm doing clear_bitmap.
It would be relatively fast because all it does is set's the entire bitmap to <colour>.
This wouldn't be too slow. What would be too slow is (for example) 20x20 tiles being drawn because of the overhead of blitting.
If you want to, you could look into video bitmaps which is like making your own 'screen' bitmap. If you make two video bitmaps (of the same size of the window/screen) then just show_video_bitmap(screen1 or screen2) for the bitmap you were just drawing on, it'll save the time of copying the backbuffer to the screen bitmap.
This is called Page Flipping.
Also, for your main question, you should do benchmarks --> record the time it takes to do 1000 clear_bitmaps and the time it takes to do 1000 screen sized blits.
Do you redraw the entire buffere every frame or will some pixels be unchanged? If you redraw it entirely then you can drop the clear_bitmap thingie.
Also, have you profiled your program to see how much does the clearing take time? I doubt it takes too much. Perhaps if you only draw a few small images to it and your game runs >250FPS clearing the bitmap could be a speed killer.
Oh, and one more thing: What kind of bitmaps do you use? Memory only for drawing to work bitmap and then blit it to video bitmap called buffer? If so you might want to use RLE sprites for blitting to work if you don't want to scale or rotate them. They are often faster than regular bitmaps. Also compiling Allegro in C-only mode can give you a huge speed increase on some operation (RLE and regular BITMAP drawing are one of these). Only problem is that in some colour depths the speed is not that big or even decreases a bit,
Some tests I made some while ago (under Linux)
I don't know what you are doing exactly, but I hope 'buffer' isn't the same bitmap per loop. The show_video_bitmap function actually sets the bitmap you send in, in this case 'buffer', to be what is shown on the screen. You only need to call it once unless you are switching between the bitmap that is shown on the screen (page flipping).
Ah, I didn't know that Archon, I've been calling show_video_bitmap() right after my blit for a loooong time. (/me goes back and correctly implements double buffering;D)
[EDIT]: Calling clear_bitmap(work) seems to be much, much faster than blitting a screen-sized background image onto it. I gain atleast 100 fps.
correctly implements double buffering
Page flipping is much faster since you don't have to do the final 'blit to screen'. Was my explanation of it unclear?
well i've changed my above drawing code to
current_buffer = (current_buffer+1)%2;
it now seems to properly vsync and lock my fps at 75. I'm assuming this is double buffering, and my previous method was page flipping?
this is double buffering, and my previous method was page flipping?
Stuff -> Back Buffer -> Screen
You draw onto the Back Buffer during the game loop. When you are finished you blit the (large) Back Buffer bitmap onto the screen. The user then sees what you did to screen.
Step 1) Stuff -> Buffer -> Show_Video_Bitmap(Buffer)
Step 2) Stuff -> Buffer -> Show_Video_Bitmap(Buffer)
You have to create 2 video bitmaps (Buffer and Buffer) of the same size of eachother and the screen/window. You are simply drawing onto the video bitmap that is not being shown.
Ok, then I'm currently page flipping. Thanks for clearing that up.
Well it looks like you're kind of doing both.
// Should be this
Although I don't know what is going on entirely.
I'm doing all my drawing operations on work, because buffer(s) are video bitmaps, which are slow with translucent stuff. Then i'm blitting work, which now contains my final image, onto buffer[current_buffer].
[EDIT]: here's my code:
|3|| int tics = 0;|
|5|| //Sound->Load("data/music/menu3.mp3", FMOD_CREATESTREAM | FMOD_LOOP_NORMAL);|
|6|| //Sound->Play("data/music/menu3.mp3", false);|
|12|| while (!g_ExitGame)|
|14|| //logic updates|
|15|| if (g_TTU)|
|17|| //reset the TTU|
|18|| g_TTU = 0;|
|20|| //logic update functions|
|26|| //input updates|
|29|| if (key[KEY_ESC])|
|30|| g_ExitGame = true;|
|32|| //subsystem updates|
|36|| //drawing updates|
|37|| clear_bitmap(GBUFFER); //GBUFFER is a macro for Graphics->GetBuffer(), which returns 'work'|
|40|| //FPS "calculation"|
|41|| if (tics == g_TicRate)|
|43|| tics = 0;|
|47|| //draw debug mouse|
|50|| //draw to the screen|
|3|| Function: Display()|
|5|| Description: Shows the graphics buffer onscreen.|
|11|| if (ScreenMode != GFX_TEXT)|
|13|| if (show_fps)|
|14|| Text->Printf(work,"arial",SCREEN_W,0,TEXT_RIGHT,makecol(255,255,255),1.0,"%i FPS",fps);|
|16|| blit (work,buffer[current_buffer],0,0,0,0,work->w,work->h);|
|18|| current_buffer = (current_buffer+1)%2;|
Since you're already double buffering to the 'work' bitmap, you may as well just blit that straight to the screen. Blitting it to a temp video bitmap and then flipping is creating unnecessary work.
And yes, clearing a bitmap will be faster than blitting, but blitting has the potential to look a lot better. It helps to make sure the background image is the same depth as the screen (eg. load it after setting the graphics mode).
So with page flipping, you're drawing everything directly onto video bitmaps, and skipping the "work" bitmap in my scenario? Wouldn't that completely kill the speed if translucency is involved?
Wouldn't that completely kill the speed if translucency is involved?
Yes it would.
As for transculency, you really should switch to c-only mode if you use it a lot. On a p4, in 32bit mode allegro's test of draw_trans_sprite() showed ~133% improvement in 32bit and more than 180% improvement in 24bit mode. In 16bit it was 250% faster and in 8bit mode 23% slower.
On p200@225 32, 24 and 16bit modes are faster and 8bit mode slower. For mode info see my three links I gave before.
I completely messed up the speed numbers.
I'm not entirely sure on this (depends on too many things), but I think that for the most part, using the work bitmap with your page-flipping mechanism is probably going to slow it down more than using a few alpha-blended sprites. If you plan to use a lot of alpha-blending, you might actually just want to use a double-buffer instead.
If you really want to go crazy, you could create a small test program that would test how many times it can complete each task over, lets say, 10 seconds. Task one would be to use the work bitmap with translucent sprites then use page-flipping, and task two to just use translucent sprites on the double-buffer. Try it with different number of sprites and see how the results differ. I'd be interested in seeing the results.
IonBlade, could you give out the code of your game so someone could make some tests on it? I could probably test c-only vs asm speed if you like. I'm not sure if I would go as far as to try out different buffering modes.
oh, and I messed up the speed numbers in my previous post. They should be fixed now. C can give up to 2.5x speed improvement on modern processors with draw_trans_sprite
If you're using a lot of translucency, you may want to look into using OpenGL (AllegroGL can help you with this). Contrary to popular belief, OpenGL is not only useful for 3d.. it can be used just fine with 2d stuff, and is wicked fast for translucency and alpha blending.
I've tried allegroGL a couple times in the past, so far i've been unable to wrap my head around the concepts. I plan on trying it again after i get this game up and running.
Thread #553919. Printed from Allegro.cc
For OpenGL OpenLayer might be a good option. It is basically a C++ 2d wrapper around OpenGL. it is somewhat similar to Allegro in a sense that it has bitmaps and some other similar things:)
Also, if a machine has any OpenGL acceleration it will be faster than the same thing in software.