Fast grabimage

BlitzMax Forums/BlitzMax Beginners Area/Fast grabimage

Juiceter(Posted 2016) [#1]
Hey,

has anyone written a standalone function that replaces the very slow native grabimage function? Blitzmax would be all the much better for it if this command was optimised.

I've seen a few snippets of code around that state they speed this command up by a lot but it's never explained how to run it.

Thanks for any pointers anyone may be able to provide.


Juiceter(Posted 2016) [#2]
I've found Grabimage to be very useful for picking up bits of screen that don't change between frames.

OK, it isn't as fast as redrawing everything, but it IS convenient in terms of code (what you gain doing something one way you loose in another way!). It's a pity that the default command is so slow (100's of ms rather than 10s.)


Kryzon(Posted 2016) [#3]
Hi. If you follow the source on what happens when you call GrabImage you get to two different implementations, one for OpenGL and another for D3D 9, and you can see what it's being used to grab the screen pixels:

- https://github.com/blitz-research/blitzmax/blob/master/mod/brl.mod/glmax2d.mod/glmax2d.bmx#L507

- https://github.com/blitz-research/blitzmax/blob/master/mod/brl.mod/d3d9max2d.mod/d3d9max2d.bmx#L592

It's slow because the screen content resides in video memory, so transferring data from there to system memory (RAM) takes a while.
One of the ways to help with this is to make it asynchronous: you 'issue' a screen read, and while it happens you do other things. Then when you are going to use that data it's already been transferred, so there's no delay.

But having to read from the screen is usually an extreme method, there must be a simpler way to do what you want. Why do you need to read the screen at all?


Juiceter(Posted 2016) [#4]
Thanks for your comment!

I just find it useful sometimes. I'm writing a strategy game where, when scrolling, a lot of the screen stays the same, so instead of rendering all the tiles again, it is easier to grab the proportion of the screen map that doesn't change and move it over 16 pixels using grabimage, then render the 12-or so new tiles that come into view.

I have heard that someone wrote a grabimage routine which is up to 16 times faster. It's detailed in the forum somewhere but I'm not sure how to use it.

If it were this good I'm not sure why Mr Sibly didn't include it in his source instead of the slow grabimage implementation we've got. I find it can be immensely useful sometimes.


Juiceter(Posted 2016) [#5]
It's a turn based strategy game btw, not real-time. Still, if someone has made a faster implementation then why not use it? Speed is always a good thing if you can get it!

I'm assuming that the faster version is less "safe".


Kryzon(Posted 2016) [#6]
Yeah, a faster version requires a certain feature to be available in the graphics card (in GL it's the Pixel Buffer Object), and the different way of using it (asynchronous, so usually delayed by one frame).
By design Max2D is supposed to be simple to use, so the current way is immediate and more compatible, at the cost of performance.

- - - - -
About the scrolling, I think redrawing the entire screen--or at least just the region that changed--is the simplest way and you should try it first, to see if there's the need for any optimisation. What you're looking for is a comfortable CPU usage at 60 FPS.

If you do think that recycling parts of the screen are needed since the brute-force screen rendering is too slow, instead of glReadPixels (used in GrabImage), you can try glCopyPixels (copies from one region of the screen to another at the current raster position set by glRasterPos).
For D3D9 I think the StretchRect function between a render-target surface onto the backbuffer surface is the closest equivalent. There's some example code of D3D9 render targets here: http://www.blitzbasic.com/Community/posts.php?topic=104977#1275668


Juiceter(Posted 2016) [#7]
That's very kind of you Kryzon, usfeul infor there. Thank you, and it's nice to see the blitz community is still so active (it deserves to be, it's a great language)!

I used to use blitz on the Amiga, then Blitz 2D on the PC (with its backbufferers etc.). Now I'm converting everything to blitzmax.

I'm assuming, though, that most if not all gfx cards made at least after 2010 would have such a feature due to "standards" (ha - I remember when so-called PC standards wern't ;-)).