Make this function faster!
int Blit_Text(char *text, int x, int y, LPDIRECTDRAWSURFACE7 lpdds)
{
int index, // character index
numofchars, // # of characters in string
cx; // x position in ascii surface
RECT character; // holds a 12x12 character...used for blitting
// get number of characters in string
numofchars = strlen(text);
// blit characters one by one
for (index = 0; index < numofchars; index++)
{
// find position of character in surface
cx = text[index] * 13 + 1;
// setup rectangle
character.left = cx;
character.top = 1;
character.right = cx + 12;
character.bottom = 13;
// blit helluva fast
lpdds->BltFast(x, y, ascii_surface, &character, DDBLTFAST_SRCCOLORKEY / DDBLTFAST_WAIT);
// move cursor for next letter
x += 12;
}
// return success
return(1);
}
////////////////////////////////////////////////////////////
Obviously the function blits text, but are there any optimizations to make it even faster? It''s actually pretty fast I guess, and I wrote it all by myself! During initialization the program copies a bitmap that has all the ascii characters to a surface (that''s in a different function). Then in this function it just extracts characters from the surface so that way I can use DirectDraw''s hardware acceleration. It runs fast on my computers, but a poor man with a shitty computer might not appreciate it if the text is too slow. The only potential optimization I can find is using bitshifting to do the multiplication, but I would have to change the size of the text because 13 isn''t a power of 2. Any other ideas?
Thanks,
Al
Alexbigshot@austin.rr.comFoolish man give wife grand piano. Wise man give wife upright organ.
You aren''t going to shave much off this, but there are a few things you can do - that might be worth it if there is a lot of text in your game. Remember, its never really worth optimizing something that doesn''t get called a lot in a time-critical context!
Here are some ideas.... n refers to the number of characters in the string.
Set character.top and character.bottom outside of the for loop - there is no point in setting it to the same value (numofchars) times. Thats worth around n*2 cycles.
You don''t really need to calculate the text position into cx and then assign it to character.left - you never use cx again, as far as I can see. You can save n cycles with this - although the compiler may well have picked up on it anyway.
If you are really paranoid about the time it takes for an IMUL and an add, you could create a small lookup table for cx (the position of character in surface). If you create the lookup table before the game itself starts, this should be worth n*2 cycles on a Pentium II (more on Pentiums).
Hope that helps!
Here are some ideas.... n refers to the number of characters in the string.
Set character.top and character.bottom outside of the for loop - there is no point in setting it to the same value (numofchars) times. Thats worth around n*2 cycles.
You don''t really need to calculate the text position into cx and then assign it to character.left - you never use cx again, as far as I can see. You can save n cycles with this - although the compiler may well have picked up on it anyway.
If you are really paranoid about the time it takes for an IMUL and an add, you could create a small lookup table for cx (the position of character in surface). If you create the lookup table before the game itself starts, this should be worth n*2 cycles on a Pentium II (more on Pentiums).
Hope that helps!
some pretty trivial stuff....
> for (index = 0; index < numofchars; index++)
change that to ''++index'', it''s technically faster.
> character.left = cx;
> character.top = 1;
> character.right = cx + 12;
> character.bottom = 13;
put the top and bottom assignment outside the loop, it''s a constant.
I''m not totally sure what bltfast is doing, but from what little i know about directx, you''re doing this to a secondary surface then swapping it right? if not, use a secondary surface, blt all the text then swap it. Text might appear a little later, but it will all be in one burst, if that''s what you''re looking for.
Like i said, that''s pretty trival stuff. But it save you a cycle or two.
"That which the flame does not consume...consumes the flame. "
> for (index = 0; index < numofchars; index++)
change that to ''++index'', it''s technically faster.
> character.left = cx;
> character.top = 1;
> character.right = cx + 12;
> character.bottom = 13;
put the top and bottom assignment outside the loop, it''s a constant.
I''m not totally sure what bltfast is doing, but from what little i know about directx, you''re doing this to a secondary surface then swapping it right? if not, use a secondary surface, blt all the text then swap it. Text might appear a little later, but it will all be in one burst, if that''s what you''re looking for.
Like i said, that''s pretty trival stuff. But it save you a cycle or two.
"That which the flame does not consume...consumes the flame. "
"That which the flame does not consume...consumes the flame. "
That was stupid of me to leave those constants in the loop. I probably forgot to take them out because when I was first writing the function I had to calculate the y position of the characters since the characters were stored in rows and columns, but then I just put all the characters in a single row to make it easier and faster.
Thanks for the advice!
Al
Thanks for the advice!
Al
Alexbigshot@austin.rr.comFoolish man give wife grand piano. Wise man give wife upright organ.
Hm. You could perhaps do 2 things not mentioned above...
You could use a pointer instead of your text[index] and use that pointer instead of indirect addressing. So you could simply caclulate the text''s end address and use that as the loop''s exit condition.Then you could increase the pointer directily instead.
The second thing is to unroll the loop. E.g. you could blit 2 characters at once. If the text''s length has not been even then you would have to perform a last blit outdside the loop.
But I think the time U loose/win heavily depends on the time the function call needs. So this may perhaps have no effect on performance
NextS
P.S. I hope someone actually reads this
You could use a pointer instead of your text[index] and use that pointer instead of indirect addressing. So you could simply caclulate the text''s end address and use that as the loop''s exit condition.Then you could increase the pointer directily instead.
The second thing is to unroll the loop. E.g. you could blit 2 characters at once. If the text''s length has not been even then you would have to perform a last blit outdside the loop.
But I think the time U loose/win heavily depends on the time the function call needs. So this may perhaps have no effect on performance

NextS
P.S. I hope someone actually reads this

well, if you get rid of the x, y, and change it to a pointer to a point structure instead, it will lower the number of arguments to 3, few enough to make the function call by register -- if in vc++ add __fastcall to the declaration
that will make a tiny difference, but when performance counts...
that will make a tiny difference, but when performance counts...
-PoesRaven
At the same time that you fill ascii_surface with
your text bitmaps, fill in an array (called
ascii_start below) with the starting x position
of each character. Then try this:
int Blit_Text( const char *text, int x, int y,
LPDIRECTDRAWSURFACE7 lpdds)
{
int index, // character index
RECT character; // holds a 12x12 character...used for blitting
character.top = 1;
character.bottom = 13;
const char *str = text;
// blit characters one by one
while( (index=*str++) ) // loop until character 0 is found
{
// find position of character in surface
character.left = ascii_start[index];
character.right = character.left + 12;
// blit helluva fast
lpdds->BltFast( x, y, ascii_surface, &character,
DDBLTFAST_SRCCOLORKEY / DDBLTFAST_WAIT);
// move cursor for next letter
x += 12;
}
// return success
return(1);
}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement