Corrupt picture when using Flip Command ?

BlitzMax Forums/BlitzMax Beginners Area/Corrupt picture when using Flip Command ?

Drex(Posted 2013) [#1]
I have just done a random screen fill routine to display a picture.

In windowed mode it works fine,but in full screen mode it draws the picture,and then steps back to an unfinished picture,with thousands of missing pixels.

If I plot the picture randomly,and do a flip at the end,the picture is fine.

If I do multiple flips to see the picture being drawn,then the picture looks corrupted.

Any idea why ?


matibee(Posted 2013) [#2]
Are you drawing the entire image before the screen flip or just adding a few pixels to the back buffer and expecting it to update accordingly?

You can't rely on the contents of the back buffer after a flip has been made.


Drex(Posted 2013) [#3]
I am drawing a few pixels to the backbuffer,then perform the flip.

And do this over and over again until the picture is drawn.


*(Posted 2013) [#4]
I think tbh we would need to see the code, there are loads of things that could come into play here. A nice checklist to check for is:
1) Full screen depth compared to desktop depth making sure its the correct depth for the image.
2) resolution
3) plotting the pixel at the correct x, y coordinate (simple I know but sometimes overlooked)
4) Try a different renderer with SetGraphicsDriver sometimes you may get strange results depending on your hardware in this instance change the graphics driver and see if it helps (yes I have had this with a Intel GMA 945)
5) try it with a different image.

:P


Drex(Posted 2013) [#5]
I am too embarrassed to show you my code.....lol

But will go through your checklist.

Reagrding point 5.

I was having exactly the same results when i was plotting plain pixels,let alone plotting a picture.


*(Posted 2013) [#6]
how are you loading the image, if your doing plotting I would load it as a pixmap and plot from the RGB values of that this way it will be easier for you to get all the relevant data from the image.


Floyd(Posted 2013) [#7]
You can't rely on the contents of the back buffer after a flip has been made.

That's almost certainly the real issue. You might expect that after a Flip the backbuffer will hold whatever was previously on screen, i.e. the front buffer.

But there are no guarantees. The graphics driver can do anything it likes to the back buffer after a flip. It could clear it, or not. It might even use it for "scratch paper" in preparation for whatever it will do during the actual rendering.


Drex(Posted 2013) [#8]
Have yet to learn about pixmaps :(

I think firstly,I should try to get it behaving properly,with plotting plain white pixels ?

My code is obviously quite rough....hmmm


Drex(Posted 2013) [#9]
So,how can I guarantee the contents of the backbuffer ?


*(Posted 2013) [#10]
You can use CLS to clear the buffer before drawing operations but this will clear anything you drew to it after the last flip


Drex(Posted 2013) [#11]
yeah,I tried CLS,but couldn't see anything being drawn.....lol


*(Posted 2013) [#12]
try this, change image.png to your own image

'plot test

Graphics 1024, 768, 32		'fullscreen

Global Image:TPixmap = LoadPixmap( "image.png" )

Global Temp:TPixmap = CreatePixmap( Image.Width, Image.Height, PF_RGBA8888 )

Local X:Int, Y:Int		'variables for plotting
Local Pixel:Int

While KeyDown( KEY_ESCAPE )=0
		Cls							'clear the buffers
		X = Rand( Image.Width -1 )
		Y = Rand( Image.Height -1 )
		Pixel = ReadPixel( Image, X, Y )
		WritePixel( Temp, X, Y, Pixel )  
		DrawPixmap Temp, 0, 0
		Flip
		Delay( 1 )						'to stop 100% CPU usage
Wend
End


its not fast but will give you an idea :)

Basically create a temp pixmap that will hold what the user will see, read a pixel from the image pixmap that we loaded and plot it on the temp one then render that.


Drex(Posted 2013) [#13]
Thanks for the code.

Will LoadPixmap load .jpg as well as .png ?

because I loaded a .jpg and changed the resolution to 1920 x 1080.

but the program just hung ?


*(Posted 2013) [#14]
Try this one, this uses the standard LoadImage :)

'plot test

Graphics 1024, 768, 32		'fullscreen

Global Image:TImage = LoadImage( "image.png" )
Global ImagePixmap:TPixmap

Global Temp:TPixmap = CreatePixmap( Image.Width, Image.Height, PF_RGBA8888 )

Local X:Int, Y:Int		'variables for plotting
Local Pixel:Int

While KeyDown( KEY_ESCAPE )=0
		Cls							'clear the buffers
		X = Rand( ImageWidth( Image ) -1 )
		Y = Rand( ImageHeight( Image ) -1 )
		ImagePixmap = LockImage( Image )
		Pixel = ReadPixel( ImagePixmap, X, Y )
		UnlockImage( Image )
		WritePixel( Temp, X, Y, Pixel )  
		DrawPixmap Temp, 0, 0
		Flip
		Delay( 1 )						'to stop 100% CPU usage
Wend
End


:)


Drex(Posted 2013) [#15]
This is mad.....

I tried the second code sample,

Changed the resolution to 1920 x 1080 and the image to a .jpg.

It still bombed ?


*(Posted 2013) [#16]
I have tested the above code with the resolution you require and tested different formats like jpg, png, bmp and tga and it works perfectly I would in this instance update the video drivers for your graphics card.


Drex(Posted 2013) [#17]
How strange,

I have an Nvidia 660 GTX with the latest drivers installed.

hmmmm.

Maybe the problems I am having are with the graphics driver then ?


*(Posted 2013) [#18]
I have a NVidia 9400M here with the latest drivers for the card and it works perfectly as expected.

Try adding
SetGraphicsDriver GLMax2DDriver()


to the beginning of the source code before the Graphics statement and see if it helps :)


Drex(Posted 2013) [#19]
Well I updated the graphics drivers,and tried adding the GLMax2DDriver,but still nothing is working ?

Should I reinstall Blitzmax,maybe its corrupted ?


Drex(Posted 2013) [#20]
I installed codeblocks recently,maybe thats cocked something up ?


*(Posted 2013) [#21]
It is a weird one indeed, on my machine it works perfectly as expected but on yours it bombs, are you trying it in debug mode Programs>>Build Options>>Debug should be ticked also Programs>>Build Options>>Build GUI App should also be ticked :). It might shed light as to whats wrong.


Drex(Posted 2013) [#22]
Build GUI App ( wasn't ticked ) ?

I will try the code om my other PC.


Drex(Posted 2013) [#23]
You aint gonna believe this,

I just copied and pasted your code into blitz and compiled it from there and nothing happened right ?

But when I saved it,then compiled it,it worked :)


*(Posted 2013) [#24]
As this uses graphics you HAVE TO HAVE 'Build GUI App' ticked otherwise it will 'bomb' :)


Drex(Posted 2013) [#25]
Damm ! Sorry :(

Will your routine randomly fill the entire picture without picking previously plotted pixels again ?


*(Posted 2013) [#26]
dont apologise we all make those mistakes the build gui app one we have all made at least once or twice when start using BlitzMax.

The code just picks a random pixel and then plots it to a pixmap then displays it, it doesnt check for already used pixels so it can overwrite pixels with other pixels. I created the code merely to demonstrate the idea and a good way of going about it, yes there are numerous ways to go about it but this to me is one of the better ones :)


Drex(Posted 2013) [#27]
I will have a look at your code in more detail.

And thanks for the insight into pixmaps........will try to use this.

Thanks again,I appreciate it :)


ImaginaryHuman(Posted 2013) [#28]
When you do a Flip, the backbuffer content is copied to the visible screen and then the backbuffer is trashed, or becomes part of a chain of several backbuffers whose content is trashed. After you flip you must then do a clear-screen and then draw something. You will only see what is drawn IN THE CURRENT FRAME and nothing else. So if you want to see a progressive update then you either have to redraw everything from the start all the way up to your progress point, or before you do a Flip you need to grab the backbuffer into an image and then redraw that image at the start of the next frame before you pick up the drawing where you left off.


Drex(Posted 2013) [#29]
Ok,I think I understand....

So if I plot some pixels to the pixmap and then flip,and then add some more pixels to the pixmap then do another flip and so on ?

because the pixmap will be constant, and the backbuffer will be not ?


ImaginaryHuman(Posted 2013) [#30]
That's one way, yes, though somewhat slow perhaps.


ImaginaryHuman(Posted 2013) [#31]
You can either

a) draw to a pixmap and then drawpixmap every frame

b) draw to the backbuffer then grab it into an image and draw that image each frame

c) draw to the backbuffer from the beginning of the `drawing` up to a stopping point each frame, starting from scratch each time.


TaskMaster(Posted 2013) [#32]
This begs the question...

Could BlitzMax be modified to allow us access to these back buffers? So, we can be sure to keep them around and be able to use the same one over and over, or flip between two different back buffers, etc...

Or, is this part of the code out of our reach?


xlsior(Posted 2013) [#33]
The backbuffers seem to be graphics-card specific too -- depending on the card (and drivers) I've seen anywhere from 2 to 4 different backbuffers that get cycled through.

Never assume that the backbuffer contents remain after a flip.


Drex(Posted 2013) [#34]
You can either

a) draw to a pixmap and then drawpixmap every frame

b) draw to the backbuffer then grab it into an image and draw that image each frame

c) draw to the backbuffer from the beginning of the `drawing` up to a stopping point each frame, starting from scratch each time.

-ImaginaryHuman-


Ok,have been messing around with the A & C options,and these are my findings.

The times it took to perform my task are based on a 1920 x 1080 resolution and drawing 5760 pixels per flip.

a) This is the best method so far....40 Seconds

b) Haven't tried this yet,but would it be quicker than a ?

c) This took the longest time,180 seconds.

My original method finished in 10 seconds,but as you guys pointed out to me,you can't rely on the backbuffer,so my routine was pretty useless,as it
just trashed the graphics at the end.


Derron(Posted 2013) [#35]
If you "grabimage" each frame it will be slow. Instead just "cache" the image for every eg. minute. After that time period you just refresh the cache. So you have an image of "up to a minute ago + pixels to draw for that minute". If you do this eg. every 10 seconds you average out the time it needs to do that "heavy" grabimage.


Another idea is to split the screen into chunks. If a chunk is 100% "filled", just display its SubImage (DrawSubImageRect) as this should be faster than single-plotting them. The smaller the split-settings are (eg. 20x20 tiles) the faster they get 100% filled - but the more tiles have to get drawn each flip.

bye
Ron


TomToad(Posted 2013) [#36]
I thought about this problem myself. Solved it by adding a command to the max2d modules which change the behavior of the MASKBLEND option of SetBlend. I posted the changes here http://blitzbasic.com/Community/posts.php?topic=100428


ImaginaryHuman(Posted 2013) [#37]
Grabbing to an image is not all that quick but drawing the image afterwards is 10x or more faster than drawing a pixmap. So as mentioned above you could grab the image once every x number of frames and then use that as your baseline of where to draw newer pixels from. Bear in mind also though that drawing pixels to the backbuffer requires uploading geometry over the graphics bus to the gpu which is likely a lot slower than drawing to the pixmap using the cpu. So there are tradeoffs.

You can't get direct access to the backbuffer like you used to be able to `in the old days` because it is now `owned` by the OpenGL or DirectX API's which have their own interface to the resources they've allocated on the hardware... so the backbuffer is kind of inside of OGL/DX and it's unknown exactly what format the data will be stored in.. it could be ARGB, BGRA, RGBA, could be 32-bit, could be 16-bit, could be floating point, whatever. So it's basically not something that the API's have exposed in order to allow you to use the same API on different hardware without worrying about lots of different possible storage formats.

You could partly get around that using a framebuffer/render-texture and then drawing to the texture and then at the end drawing the texture to the backbuffer. However even then the internal format of the texture is not necessarily known regardless of what format you asked it to be.


Drex(Posted 2013) [#38]
Ok,have been messing around with the A & C options,and these are my findings.

The times it took to perform my task are based on a 1920 x 1080 resolution and drawing 5760 pixels per flip.

a) This is the best method so far....40 Seconds

b) Haven't tried this yet,but would it be quicker than a ?

c) This took the longest time,180 seconds.

My original method finished in 10 seconds,but as you guys pointed out to me,you can't rely on the backbuffer,so my routine was pretty useless,as it
just trashed the graphics at the end.


Oh dear :(

I didn't realise that having debug ticked,slowed the programs down so much.

Option a) doesn't take 40 seconds at all,it takes 5 :)

Thanks for all your help guys,

Sorry for being such a noob.....lol

At least i'm in the right forum section :)