Quicker GrabImage?

BlitzPlus Forums/BlitzPlus Programming/Quicker GrabImage?

Grey Alien(Posted 2005) [#1]
This is slow:
w=800
h=640
Graphics w,h,32,2

stT = MilliSecs()
grab = CreateImage(w, h, 1, 1)
GrabImage(grab, 0, 0)
EndT = MilliSecs() - stT
Text 0,0,EndT + "ms"
Flip
WaitKey

200ms on my 3.2GHz P4, ATI 9800XT, 1Gb RAM.
If I change the last parameter of CreateImage to 2, it's 0ms. This is because the image held is on the videocard not in memory and thus it can be destroyed by Alt+Tabbing so this is not useful.

Can anyone thing of a quicker way to grab the backbuffer into a managed image? Btw I've tried locking it and reading the pixels with ReadPixelFast in a loop, but it's amost exactly the same speed!

I also tried this:
w=800
h=640
Graphics w,h,32,2

stT = MilliSecs()
grab = CreateImage(w, h, 1, 2)
second = CreateImage(w, h, 1, 1)
GrabImage(grab, 0, 0)
second = CopyImage(grab)
EndT = MilliSecs() - stT
Text 0,0,EndT + "ms"
Flip
WaitKey

Wondering if I could fool it. Notice the first image is dynamic and the second image is managed. This appears to give a very fast time. Wooo I thought until I alt+tabbed and discovered that the second image is now dyanmic too. Basically Copy image ignores the original flag state of the image (1) and actually copies the image in video memory (flag=2). This is practically a bug! What if you wanted to make a managed image in memory from an image grabbed in video RAM? You'd have to read each pixel out and copy it "manually", lame.

Thanks in advance.


TartanTangerine (was Indiepath)(Posted 2005) [#2]
Grabbing data from the backbuffer is always going to be a slow process. My suggestion would be to use a third buffer, one that resides in system ram. You draw all images to that 3rd buffer, calculate all your alpha and stuff and then send the complete buffer to the video card just before the flip.


Grey Alien(Posted 2005) [#3]
That's triple buffering isn't it? Thanks for the idea. Could try that but it means a fair bit or rewriting (maybe). However, it will make alpha stuff much faster where the background has to be read in. Hmm, I wonder how much faster!


TartanTangerine (was Indiepath)(Posted 2005) [#4]
Loads faster! You should never read from the backbuffer (if the back buffer is in VideoRam) - it's like trying to download a file over the internet via dialup.


Grey Alien(Posted 2005) [#5]
It stinks for sure!


Grey Alien(Posted 2005) [#6]
Well triple buffering has reduced my Dim Screen code from 230ms to 40ms which is great. But it has increased my draw time from 0-1ms to 4-5ms which is not great as this occurs every frame and could easily push people down a notch in FPS (i.e. halve it).

It seems that calling DrawBlock and DrawImage onto the backbuffer is VERY fast but calling them onto an Image Buffer e.g. SetBuffer ImageBuffer(Buffer3) is a lot slower. This is a shame. Naturally buffer3 was created with flag 1 on the end so it's managed so it doesn't corrupt when you alt+tab. If I change the flag to 2 (dynamic) the draw time per frame drops back to 0-1ms but the Dim Screen code goes back up to 230ms, it's like some kinda hideous see-saw!


TartanTangerine (was Indiepath)(Posted 2005) [#7]
Did you lock the buffers before writing? Would it be faster just to copy the memory to the buffer rather than using Blitz command set?

OR

Back to the old dirty rects scenario. Only Draw to the image buffer what has changed since the last frame. Only send to the back buffer those changes. Voila super fast thingie stuff.


Grey Alien(Posted 2005) [#8]
Thanks for the ideas.

You can't lockbuffer on an image buffer and then call DrawBlock or DrawImage, it doesn't work, I tried it (also says so in the docs, unless you know differently?). Only the ReadPixelFast and WritePixelFast functions work.

I wrote my own DrawBlock which locked the buffer and used the Fast commands but it was uh about 10 times slower. It was only two for loops, one nested (x and y), oh well. Not sure if the speed problem is the loop or the read/write pixelfast line. Could test I suppose.

How can I copy the memory back to the buffer? Command? I presume the image handle is a memory pointer (but it might be a pointer to a blitz internal object) but how do I get the memory address for the BackBuffer?

Perhaps I should just use a massive array and write all by own image draw routines that use the array and finally draw it onto the image buffer. Probably after trying this, I'll find out it's slower. However, this sort of thing was LOADS fast for calculating fades, and alpha blends, it's what I currently do.

I could go "back" to dirty rects, but that was how I did it in the Amiga days and I can't be arsed, sigh. Also on some screens there'd still be a lot of updates like when all the fruit fly around. But maybe ... Does your systemtrack which bits have been updated them and store them in a list so it can process/output them later?


Ross C(Posted 2005) [#9]
Isn't CopyRect, alot faster than GrabImage?