Buffer Swapping

Blitz3D Forums/Blitz3D Programming/Buffer Swapping

John Blackledge(Posted 2005) [#1]
I needed to copy the frontbuffer to the backbuffer.

This was because the image resize code I found somewhere on this site used the back buffer to create the resized image, and then Flip was a couple of lines later... whoops, screen flash.

It seemed obvious (after the resize had done it's job) to use :-
CopyRect 0,0,GraphicsWidth(),GraphicsHeight(),0,0,FrontBuffer(),BackBuffer()

but this appears to have no effect.

Am I doing this right?


Ross C(Posted 2005) [#2]
What might be happening is your using a cls command in there somewhere, that's clearing the buffer before it's copied?


John Blackledge(Posted 2005) [#3]
No. Whats happening is that I execute the command then do a Flip to bring Back to Front (which should be the usual 3D scene) but I'm still seeing the corrupted BackBuffer.

In other words the CopyRect hasn't worked.

That's why I'm asking - is this the right way to copy from Front to Back?


IPete2(Posted 2005) [#4]
John,

This may be a stupid question but are you using updateworld and renderworld before the flip? Perhaps try not using them.

IPete2.


John Blackledge(Posted 2005) [#5]
Hi Pete.

No. Exactly as described.
CopyRect, then Flip. No other complication.

I've also tried as an experiment inserting UpdateWorld + RenderWorld then Flip, and 'cause I'm going thru line-by-line in debug mode I can see, as expected, the BackBuffer moved to the FrontBuffer just fine.

It's simply as if CopyRect fails when used between the two Blitz system buffers.


RGR(Posted 2005) [#6]
Hmm - what shall be useful doing this operation?
You see the frontbuffer - then copy it to the backbuffer and flip to see the copied frontbuffer again ? Would be timesaving to do nothing.
And instead of CopyRect you could quicker do Flip anyway because this has the same effect - would be done in case you want to draw something on the former frontbuffer and to show this make flip again.


Ross C(Posted 2005) [#7]
Is the code your using the super fast resizing code by any chance?


Ross C(Posted 2005) [#8]
This was because the image resize code I found somewhere on this site used the back buffer to create the resized image, and then Flip was a couple of lines later... whoops, screen flash.


Why don't you alter the code, so the image resize code, doesn't use the back buffer to put the image?


nawi(Posted 2005) [#9]
nevermind :/


Nik Green(Posted 2005) [#10]
Hi John

CopyRect between frontbuffer and backbuffer should work as you want it to. I did a quick test and it worked fine:-

Graphics 800,600
Setbuffer Frontbuffer()
image = LoadImage("a suitable image")
DrawImage image,0,0
CopyRect 0,0,GraphicsWidth(),GraphicsHeight(),0,0,FronBuffer(),BackBuffer()
Flip
WaitKey()
Flip
Waitkey()

This displays the image after each flip as expected.

A stab in the dark but does the code Lock either of the buffers and not Unlock them again?


Shifty Geezer(Posted 2005) [#11]
He's a thought. Is the downscaling function going to be as fast as a GPU scaling a texture? If you're downsizing might it be quicker to render the texture to a pixel-perfect quad, render that to the backbuffer, and grab a rectangle of the downsized quad?


John Blackledge(Posted 2005) [#12]
@Shifty, I think that's exactly what the resize code is doing.

It's jfk's (clever sod) and unfortunately I don't understand it enough to change the buffer.

@Nik, there's no locking going on.

Let's see if I can explain it again....

As I said, after any fast-resize the next Flip causes a flash since the Backbuffer is corrupted.
Therefore the simple logic was to copy the FrontBuffer (last render) to the BackBuffer, then Flip. So far so good?

The copy doesn't work - literally the FrontBuffer fails to copy to the BackBuffer; the BackBuffer is still corrupted for the next Flip.

So, crude as it may seem, I now have a global called NoFlip set to 1 at the end of the fast-resize function.
Then:
If NoFLip=0
Flip
ELse


John Blackledge(Posted 2005) [#13]
(Damn, sorry - must have hit post before I was finished.
Here it is again:)

@Shifty, I think that's exactly what the resize code is doing.

It's jfk's (clever sod) and unfortunately I don't understand it enough to change the buffer.

@Nik, there's no locking going on.

Let's see if I can explain it again....

As I said, after any fast-resize the next Flip causes a flash since the Backbuffer is corrupted.
Therefore the simple logic was to copy the FrontBuffer (last render) to the BackBuffer, then Flip. So far so good?

The copy doesn't work - literally the FrontBuffer fails to copy to the BackBuffer; the BackBuffer is still corrupted for the next Flip.

So, crude as it may seem, I now have a global called NoFlip set to 1 at the end of the fast-resize function.
Then:
If NoFlip=0
Flip
Else
NoFlip=0
Endif


Nik Green(Posted 2005) [#14]
Hi John

In my humble opinion your 'crude' solution is better than the CopyRect solution, especially if you intended to CopyRect every program loop whether its needed or not.

Still doesn't explain why CopyRect didn't work though. Have you tried other (simpler) tests?

By the way, if you are using the fast resize code I think you are using you can't use a different buffer even if you understand the code. It uses RenderWorld which always uses the BackBuffer.

Nik Green


Shifty Geezer(Posted 2005) [#15]
Yes, it uses my idea. Or rather, I suggested jfk's idea. Erm...I think I'll patent the idea (despite jfk having it before me) and then sue anyone who uses it :p

But yeah, it renders the image to be scaled as a texture on a quad in the backbuffer, and grabs that to an image, and rendering is limited to the backbuffer only.


John Blackledge(Posted 2005) [#16]
NIck and Shifty - both correct on all counts.

I'm not doing CopyRect each cycle, just once for each image as it's loaded (sometimes 'in-game').

"Still doesn't explain why CopyRect didn't work though. Have you tried other (simpler) tests?"

What could be simpler?


Nik Green(Posted 2005) [#17]
Hi John

"What could be simpler?"

Write a quick test program that just copies the frontbuffer to the backbuffer using CopyRect. Try This:-

Graphics3D 800,600,32
SetBuffer BackBuffer()
ent = CreateSphere()
cam = CreateCamera()
PositionEntity cam,0,0,-2
RenderWorld
Text 0,0,"Original BackBuffer flipped from back to front"
Flip
Waitkey()
Cls
CopyRect 0,0,GraphicsWidth(),GraphicsHeight(),0,0,FrontBuffer(),BackBuffer()
Text 0,20,"...then copied from Front to Back and flipped again."
Flip
Waitkey()
End

Does it work?

If it does (and it does on my set up) then there is something in your code preventing CopyRect from copying as you want it to.

If it doesn't work then there must be a problem with CopyRect when used with the 'system' buffers on your set up.

Either way Good Luck :)

Nik Green


John Blackledge(Posted 2005) [#18]
Your code works perfectly. Thanks.

These are the two main lines of my code:-

; \/ This creates the reduced size image.
CopyRect (GraphicsWidth()/2.0)-(w/2.0),(GraphicsHeight()/2.0)-(h/2.0),w,h,0,0,BackBuffer(),ImageBuffer(img2)
; \/ And immediately my line is used to reinstate the BackBuffer.
CopyRect 0,0,GraphicsWidth(),GraphicsHeight(),0,0,FrontBuffer(),BackBuffer()

It CAN only be that that the first CopyRect somehow prevents the second (???).

Thanks for all your help, guys, but personally I'm tired of this (as I'm sure everyone else is too).
I'll use my global NoFlip = 1 to prevent the next Flip, and call it a day.