Archived

This topic is now archived and is closed to further replies.

Gf11speed

Need Faster Blt Routine

Recommended Posts

Gf11speed    140
I am using the generic Blt() function in DirectDraw to draw my sprites. However, I have some surfaces that are quite large, such as 800x600 background surfaces and other large bitmaps that are the width/height of the screen. I have noticed when drawing those larger surfaces to the screen (I draw to the backbuffer first, then flip(pageflipping)), the program gets very slow. What is causing this, and how else could I load these larger bitmaps, in order for them to blit faster. Help is appreciated. Thanks.

Share this post


Link to post
Share on other sites
LordElectro    122
You''ll want to use BltFast() when possible...

As for your problems with the drawing of large sprites, it''s likely inefficient memory allocation. In an ideal world, you''ll want to have ALL your surfaces in video memory, because even on top of the line systems, blting from system to video memory butchers frame rate. Alas, when your using 800x600 backgrounds, you''re running out of video memory and surfaces are getting placed into system memory.

Organize your program so your loading your most used surfaces first, so that the important stuff has the greatest chance of being placed in video memory.

If really need to keep a lot of surfaces in memory and are doing lots of blitng, you might find that creating an additional buffer in system memory (don''t confuse this with your back buffer, that MUST be in video memory or your frame rate will literally disappear), creating ALL your surfaces in system memory, blting them to the buffer in system memory, and then blting the buffer to video memory. That way you minimize the amount of transfers done between system memory and video memory, thereby actually increasing your frame rate, despite doing that addition blt.

I doubt you would be able to actually write a blt function that is faster than DirectDraw''s because modern video cards have special DD extensions that allow blts to be done incredibly fast. So unless you want to start messing with hardware at a really low level and write your own API INSTEAD of using DirectDraw, I''m afraid it''s unlikely. I could be wrong, but I''m pretty sure I''m right.

Share this post


Link to post
Share on other sites
Goku705    122
Or you can save yourself the trouble of reorganizing your program and hoping for the best by changing your surface descriptions a little bit. Say your surface description is named ddsd. Now, do this:
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;

Now DirectDraw will do its best to put that surface in video memory. If you set less important ones to use system memory (through DDSCAPS_SYSTEMMEMORY), you can keep more video memory free for the surface that need it.

Reorganization will also work; if a memory location isn''t specified as shown above, DirectDraw will try its best to create the surface in video memory. If it can''t (because there is none left), then it tries system memory.


-Goku
SANE Productions Homepage

Share this post


Link to post
Share on other sites
LordElectro    122
Goku705: Unfortunately if you use that flag then surface creation will fail if DirectDraw can''t place it in video memory.

And doing DDSCAPS_SYSTEMMEMORY for less important ones will keep you from taking advantage of hardware that has the memory to hold it all.

If you don''t want to load them in order of importance (which I agree is a bit inconvienent) at the very least you will have to check if creating the surface with DDSCAPS_VIDEOMEMORY failed and then try with DDSCAPS_SYSTEMMEMORY. But that doesn''t solve the problem of putting not important surfaces in DDSCAPS_SYSTEMMEMORY when there is enough video memory. So what you want to do if you have the time is keep track of all the surfaces, and have a priority for each. And then when creating a surface, if there''s lower priority surfaces taking up video memory and u dont have enough for this higher priority surface, put some of the lower priority surfaces in system memory. That''s what I plan on doing eventually, although it is a bit of a pain for the convience of being able to load surfaces in any order, and if you aren''t careful you might get to much flipping of surfaces between system and video.

Share this post


Link to post
Share on other sites
Gf11speed    140
For some reason I can''t get BltFast to work! I am not sure what I am doing wrong. The first function that draws the bitmap, uses Blt(which works fine, only seems to be slow), while the second part of the code uses the BltFast function, which is what I am having problems with. The BltFast function doesn''t draw anything to the screen for some reason. It just doesn''t draw.

Here is the Blt() code:

int DDDrawSprite( DDSPRITE sprite , int blt){ // blt = 1 or 2, Blt or BltFast

RECT DestRect,SourceRect;

DestRect.left=sprite.x;
DestRect.top=sprite.y;
DestRect.right=sprite.x + sprite.width;
DestRect.bottom=sprite.y + sprite.height;

SourceRect.left=1;
SourceRect.top=1;
SourceRect.right=sprite.width;
SourceRect.bottom=sprite.height;


if(lpddsback->Blt(&DestRect, sprite.images[ sprite.curr_frame ], NULL,DDBLT_WAIT | DDBLT_KEYSRC,NULL!=DD_OK))
return 0;

return 1;
} // End DDDrawSprite();


And now the BltFast() code:

int DDDrawSprite( DDSPRITE sprite , int blt){ // blt = 1 or 2, Blt or BltFast

RECT DestRect,SourceRect;

DestRect.left=sprite.x;
DestRect.top=sprite.y;
DestRect.right=sprite.x + sprite.width;
DestRect.bottom=sprite.y + sprite.height;

SourceRect.left=1;
SourceRect.top=1;
SourceRect.right=sprite.width;
SourceRect.bottom=sprite.height;


if(lpddsback->BltFast(sprite.x,sprite.y,sprite.images[sprite.curr_frame],&DestRect,DDBLTFAST_WAIT )!=DD_OK)
return 0;


return 1;
} // End DDDrawSprite();


So, with this code, what am I doing wrong here? Thanks.

Share this post


Link to post
Share on other sites
Beer Hunter    712
Is the sprite being drawn in such a position that it's partially off-screen? BltFast will fail under such circumstances. The blit has to be entirely onscreen.

By the way, if you want to pass structs to a function, it's more common to pass them by const reference:

void Blah(const DDSPRITE& Sprite)
{
int x = Sprite.x; // or whatever
}

Edited by - Beer Hunter on July 31, 2001 4:25:31 AM

Share this post


Link to post
Share on other sites
LordElectro    122
What Beer Hunter said is likely your problem. Another reason why BltFast() fails is if you have a clipper attached to the surface. Personally, I find clippers rather pointless, it''s not hard to do bounds checking, and it''s a pain not being able to use BltFast().

Share this post


Link to post
Share on other sites
Gf11speed    140
I made sure that the sprite was small, and not bounding any of the screen edges. I also took out the clipper. BltFast still doesn''t work. What else could it be?

Share this post


Link to post
Share on other sites