Polled Input() with max gui?

BlitzMax Forums/BlitzMax Programming/Polled Input() with max gui?

Robert Cummings(Posted 2006) [#1]
Is it possible to use keyhit(), keydown() and mousehit() etc with max gui? for some reason I am having a bit of trouble getting mouse hits working using the mouse up event.


ImaginaryHuman(Posted 2006) [#2]
EnablePolledInput() ?


WendellM(Posted 2006) [#3]
Seems to work here:
Strict

Local win:TGadget = CreateWindow( "", 200,0, 400,300)
Local can:TGadget = CreateCanvas( 0,0, 400,300, win)
Local mX, mY, oldX, oldY

EnablePolledInput()
Repeat
	mX = MouseX()
	my = MouseY()
	If ( mX <> oldX ) Or ( mY <> oldY ) Then
		Print mX + ", " + mY
		oldX = mX
		oldY = mY
	EndIf
	If MouseHit(1) Then Print "MOUSE HIT"
Until KeyHit(KEY_ESCAPE) 



Grey Alien(Posted 2006) [#4]
let me know if you find any windows vertical tearing when using the GUI, thanks in advance :-)


Robert Cummings(Posted 2006) [#5]
Well that would be difficult for me to tell. My game shows zero tearing due to the nature of it. If you want to check it out, get the latest blitzmax demo, it includes maxgui as standard I think.

Then create a canvas on a window and draw to the canvas as you would normally.


Grey Alien(Posted 2006) [#6]
I've got the MaxGui, I just can't be arsed to program an event-based Canvas-based game to test if it tears or not.


ImaginaryHuman(Posted 2006) [#7]
So you hope he's going to do that hard work for you? ;-)

The tearing is based on copying/blitting the backbuffer to the front buffer which is part of the visible screen - and the blit getting overtaken by the vertical refresh/beam of the display. Is there any kind of tearing present in fullscreen mode?

You could try implementing your own `Flip` routine. In OpenGL at least, you can set the read and write buffers and probably can copy the backbuffer to the front buffer by yourself. This would also preserve the backbuffer which might be handy for some games. Maybe you can then split up the copy into sections, maybe do one half at a certain time in the loop and the other half later or something, so that you avoid the tearing region? Just an idea.. might not help.

I think you would only get tearing where the refresh rate of the display is faster or slower than the rate at which the backbuffer is blitted into view - ie the memory transfer rate. Even if you synchronize the flip with the vertical blank, you can't be sure that the data copy is going to be fast enough not to get overtaken by the refresh beam. Any form of copying data to the visible display is prone to becoming torn, unless it's able to always be `ahead` of the oncoming beam/refresh.

What you have is two competing refreshes and the tearing is the overlap. You need to make sure you are blitting the backbuffer to the front buffer BEFORE and always ahead of the refresh beam, but the blit must also not catch up to the beam. Ideally you need them to be about half-a-cycle/frame offset from each other. Doing the flip AT the vertical blank point is not a good idea because you're only going to have a short space of time between the beam being at the bottom of the display and starting to refresh at the top, to be ahead of the beam and have it not catch up.

You need to wait for half-a-frame prior to the vwait, and flip at that point. That would give you immediate update of the current frame. Otherwise you could wait for the vertical blank, THEN wait half a frame, then blit the backbuffer to the front, but this update would then not show until half a frame later, so slightly late.

You can find out what half a frame is by measuring the millisecs that each frame takes, or computing it.

Another option is do organize your code so that it flips halfway through a vertical refresh period .. ie, if you can't modify the flip code and you have to use Flip 1, and it is vblank synchronized, then maybe you can somehow have it draw half of the next frame, Flip 1, finish the second half of the previous frame and start the first half of the next.

This is where triple buffering becomes beneficial, which really is probably what you need for perfect refreshes.

I know that OpenGL *sometimes* has support for auxiliary buffers, which could be used as a second backbuffer.

I have a question though .... if you are going to be worried about synchronizing with the vertical blank, and you are looking to update things at the vertical blank, then if possible you could sort all your drawing operations into vertical order, and just draw then straight to the front buffer in order. Might have the same effect as a double or triple buffer since the user doesn't SEE the visible display until the refresh passes over it. This also removes the need to blit the whole display into view which means the game runs faster. But I know some games by design can't very easily do things in vertical order.

Just some ideas. Sorry to get off-topic.


Grey Alien(Posted 2006) [#8]
Some interesting ideas thanks, but probably a bit OTT/Technical and unfortunately some card drivers don't return a reliable scanline position, if any. Skidracer came up with a fix for tearing in windowed mode when using Graphics() (it's not perfect on some systems though) but others have been suggesting using a MaxGUI canvas instead of Graphics() for windowed mode and changing to event based programming. I just wondered if such a canvas does or does not show vertical tearing. If not then, it's a persuasive argument for using MaxGUI.


ImaginaryHuman(Posted 2006) [#9]
Try that demo ;-D


Grey Alien(Posted 2006) [#10]
what demo, I can't see it, sorry ...