Question about blitting speed
IonBlade

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.

Archon
Quote:

clear_bitmap(buffer)

It would be relatively fast because all it does is set's the entire bitmap to <colour>.

Quote:

blit(bmp,buffer,0,0,0,0,bmp->w,bmp->h)

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.

IonBlade

I'm doing

clear_bitmap(work);
Game->Draw(work);
blit(work,buffer,0,0,0,0,work->w,work->h);
show_video_bitmap(buffer);

HoHo

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,

[edit]
Some tests I made some while ago (under Linux)
http://www.allegro.cc/forums/thread/475231#target
http://www.allegro.cc/forums/thread/477775#target
http://www.allegro.cc/forums/thread/478181#target

Archon
clear_bitmap(work);
Game->Draw(work);
blit(work,buffer,0,0,0,0,work->w,work->h);
show_video_bitmap(buffer);

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).

IonBlade

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.

Archon
Quote:

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?

IonBlade

well i've changed my above drawing code to

clear_bitmap(work);
Game->Draw(work);
blit(work,buffer[current_buffer],0,0,0,0,work->w,work->h);
show_video_bitmap(buffer[current_buffer]);
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?

Archon
Quote:

this is double buffering, and my previous method was page flipping?

Double Buffering:
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.

Page Flipping:
Step 1) Stuff -> Buffer[1] -> Show_Video_Bitmap(Buffer[1])
Step 2) Stuff -> Buffer[2] -> Show_Video_Bitmap(Buffer[2])

You have to create 2 video bitmaps (Buffer[1] and Buffer[2]) of the same size of eachother and the screen/window. You are simply drawing onto the video bitmap that is not being shown.

IonBlade

Ok, then I'm currently page flipping. Thanks for clearing that up.

Archon

Well it looks like you're kind of doing both.

Game->Draw(work);
blit(work,buffer[current_buffer],0,0,0,0,work->w,work->h);

// Should be this
Game->Draw(buffer[current_buffer]);

Although I don't know what is going on entirely.

IonBlade

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:

1void DW_GameLoop()
2{
3 int tics = 0;
4 
5 //Sound->Load("data/music/menu3.mp3", FMOD_CREATESTREAM | FMOD_LOOP_NORMAL);
6 //Sound->Play("data/music/menu3.mp3", false);
7 
8 //Graphics->Enable(GFX_MOTIONBLUR);
9 
10 Game->Init();
11 
12 while (!g_ExitGame)
13 {
14 //logic updates
15 if (g_TTU)
16 {
17 //reset the TTU
18 g_TTU = 0;
19 
20 //logic update functions
21 Game->Update();
22 
23 tics++;
24 }
25 
26 //input updates
27 g_Input->Update();
28 
29 if (key[KEY_ESC])
30 g_ExitGame = true;
31 
32 //subsystem updates
33 Graphics->Update();
34 Sound->Update();
35 
36 //drawing updates
37 clear_bitmap(GBUFFER); //GBUFFER is a macro for Graphics->GetBuffer(), which returns 'work'
38 Game->Draw(GBUFFER);
39 
40 //FPS "calculation"
41 if (tics == g_TicRate)
42 {
43 tics = 0;
44 Graphics->SetFPS();
45 }
46 
47 //draw debug mouse
48 draw_sprite(GBUFFER,mouse_sprite,mouse_x,mouse_y);
49 
50 //draw to the screen
51 Graphics->Display();
52 }
53}

1/*=================================================================
2
3 Function: Display()
4
5 Description: Shows the graphics buffer onscreen.
6
7==================================================================*/
8void dwGFX_t::Display()
9{
10 
11 if (ScreenMode != GFX_TEXT)
12 {
13 if (show_fps)
14 Text->Printf(work,"arial",SCREEN_W,0,TEXT_RIGHT,makecol(255,255,255),1.0,"%i FPS",fps);
15 
16 blit (work,buffer[current_buffer],0,0,0,0,work->w,work->h);
17 show_video_bitmap(buffer[current_buffer]);
18 current_buffer = (current_buffer+1)%2;
19 
20 frames_drawn++;
21 }
22}

Kitty Cat

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).

IonBlade

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?

HoHo
Quote:

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.

[edit]
I completely messed up the speed numbers.

Elverion

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.

HoHo

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

Kitty Cat

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.

IonBlade

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.

HoHo

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.

Thread #553919. Printed from Allegro.cc