Archived

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

Fast 2D Pixel Scrolling on Windows

This topic is 4959 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

For a project at work, I need to display a HUGE bitmap (much larger than the 4GB memory limit on windows machines) so obviously I need to load it dynamically and only show the part being looked at. The bitmap is essentially a HUGE strip 1280 pixels across and LOTS of pixels down. It scrolls upward at a variable rate, so essentially the task simplifies to loading some number of lines of the bitmap, moving the current display up that number of lines and blitting the new lines on the screen. The bitmap is in a custom format with other data interleaved. It is indexed, and the palette is stored in a seperate file. I also need to have regular windows control at the bottom of the screen, so I can''t allocate the whole screen to some kind of drawing API (though changing the screen mode is required to make sure the bitmap fits on the screen without distortion, so I can change the BPP). What would be the fastest method of doing this? So far, I''ve tried using DIB sections and OpenGL(DrawPixels) in 32BPP mode (I do the palette translation manually as I load each line), and I get about 25FPS with the former and about 15FPS on the latter. The machine is a 1.6GHz with 256MB RAM and a GeForce 2 MX. 8 bit palete mode might be faster, but I''m not sure if it is an option because I don''t think the palette includes the system colors and I do need to display the exact palette as it is (with all 256 of its colors, plus possibly a few more for the controls depending on if it has the right colors or not). Any suggestions would be appreciated.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Might I suggest using standard old BitBlt() to copy the stuff already on screen to a new location also on-screen? This would be a video memory to video memory operation and should be insanely fast on any nvidia, ati or voodoo cards and can be done in standard GDI and its quite easy to impliment.

When areas of your window are invalidated, you would of course have to resort to slower operations on those areas .. as well as slower operations to fill in the new pixels just scrolled in.

But these areas should be relatively small relative to your whole window area while you are scrolling.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Thanks, your suggestion of usnig bitblt for the actual scrolling nearly doubled the FPS of the DIB version - its up to 50 FPS now and thats definitely a usable speed.

-Extrarius

Share this post


Link to post
Share on other sites
After taking your advice, I decided to find a profiler.After about 10 reboots (because the profiler, devpartner community edition, would only work properly once and then I''d need to reboot to clean up after it), I got it up to about 100 FPS under ideal conditions and about 70 in practical ones. It seems 90% of the slowdown (after changing the bitblt stuff) was stupid mistakes in the file loader I made (mainly because when I was making it I didn''t know how it would be used, but now that I''m experimenting with it I could optimize it for the task).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I had it running fairly fast, but then I found out it needed to be able to have dialogs above it as well as on the 'control area'. No problem, I thought, I'd just make it draw from the DIB to a compatable bitmap(associated with a comptable DC) and then blit the bitmap to the window.

Well, it works, kinda. It displays fine, but for some reason when I scroll upward (so the new lines are added to the bottom), I get very eratic delta times (it uses simple time based movement).

Some statistics on the delta times:
      Average         Count   Total       Min        Max        Median     STD Dev
Up 0.018378037 3265 60.00429 0.001719 0.119215 0.011727 0.013295628
Down 0.025896533 2317 60.002266 0.001067 0.045159 0.025385 0.002183364

As you can see, they have roughly equal averages (scrolling down actually being worse here), but scrolling down generally has a consistent delta so visually it scrolls much better. When scrolling up, the delta is quite eratic and within a block of ~15 frame tiems there are often a few grouped together with a time < 0.01 and then several between 0.01 and 0.02 and then a few with times of 0.04 or greater.

The way I scroll the bitmaps is identical except for the required differences (ie for moving down, copy bitmap down and draw new lines on top, for scrolling up it copies up and adds new lines no bottom).

Profiling reveals that the StretchDIBits function accounts for 86.7% of the execution time(with an average cost of 9127 microsecs) when moving down and the LoadImageLine function(which reads from disk each time) uses only 10%(287 microsecs) when moving down.

When scrolling upward, LoadImageLine takes 51%(265 microsecs) of the execution time with StretchDIBits taking only 27%(507 microsecs).

These numbers are very strange and I am at a loss for what could be causing them. I've run several tests(each ~1 minute to make sure it wasn't just a short-term problem related to startup or somesuch) and the results are consistently showing these results.

Any help would be greatly appreciated.

-Extrarius

Share this post


Link to post
Share on other sites
Quote:
Original post by Extrarius
So far, I''ve tried using DIB sections and OpenGL(DrawPixels) in 32BPP mode

glDrawPixels is about the slowest way to get pixels on screen with OpenGL, and you'll get a tiny fraction of the speed you could with other methods. If you try OpenGL again remember to use textured quads instead and you'll see an instantly faster program.

Share this post


Link to post
Share on other sites
Quote:
Original post by OrangyTang

Quote:
Original post by Extrarius
So far, I''ve tried using DIB sections and OpenGL(DrawPixels) in 32BPP mode

glDrawPixels is about the slowest way to get pixels on screen with OpenGL, and you'll get a tiny fraction of the speed you could with other methods. If you try OpenGL again remember to use textured quads instead and you'll see an instantly faster program.
It'd be a lot of work and quite messy to do it that way. If I can't get DIBs to work, I'll try direct draw(where I can just lock the surface and make the changes I need) before continually remapping textures to portions of the bitmap.

Share this post


Link to post
Share on other sites
That sounds reasonable. Any PC around today should be able to redraw the entire screen pixel by pixel fast enough. You dont't need to do that - you can copy what's onscreen up or down a bit in tne buffer and fill in the gap created. DDraw seems a good choice but with a system memory backbuffer assuming you get the choice.
How do you handle resizing the window?
Is the bitmap stored as one giant file or many small ones?
If you don't mind me asking, what's it a bitmap of?
Could it be changed to a more disk-frindly size to save on amount read from disk ie reduced bits per pixel or compressed on a per-row basis? This sounds a good plan for disk space and speed - a very simple compression on each row of pixels or maybe each 10 rows (or however much you page in at once - how much is this?) would save a lot I think.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I can't just copy the screen if there is a dialog or somesuch in the way. I was doing that before, but now I need to meet slightly different specs, which is why I moved to doing it in a bitmap instead of directly on a window.

I don't need to handle window ersiznig, because the app is full screen (but must be able to have standard windows controls, so I couldn't give opengl the whole screen. I think DX can handle that though).

The image is one HUGE paletted file (256 colors) with the palette stored seperately. Since the palette isn't compatable with the system palette, I can't change the resolution to one with 8 bit color. Right now, each line of the image is converted to 24 bit color on load. Making the DIB paletted would possibly speed things up a little, but again the screen needs to be in a higher color mode and so would the bitmap acting as a buffer, so I'm not sure it would speed things up much. The image quality cannot be reduced, and I'm not sure compression would make much difference since, when scrolling down at least (which reads the file in 'backwards' - bottom line, then the line above it, moving up the file towards offset 0) it runs perfectly smooth and at a fast enough framerate.

It loads lines on an as-needed basis (to achieve X pixels scrolled per second), and needs to be able to scroll each way. Since the lines are fixed sizes, it just seeks before each line read to load the line appropriate to the direction it is scrolling.

-Extrarius

Share this post


Link to post
Share on other sites
So nobody has any ideas on what might be causing these strange results in performance or how to fix them? I'm really very curious as to what might be causing such anomalous delta times.

Of course, I'm also still interested in ideas about the best way to meet the fast scrolling with normal windows controls requirement.

Share this post


Link to post
Share on other sites