Monitor Refresh Rate Question

BlitzMax Forums/BlitzMax Programming/Monitor Refresh Rate Question

I'm struggling to find a way to successfully have a Fullscreen display across a variety of laptops and desktop crts (all Windows at the moment - not ready to go Mac yet!) without screen flicker or tearing. I've read and re-read all the posts here and have learnt a lot!

But ...

The main thing I've learnt is that BlitzMax cannot tell you the monitor refresh rate so if you want to match the current desktop setting you'll have to calculate it yourself.

So my question is ... why does this code not work? I find it returns a wide variety of values although most are near the refresh rate.

<update>I've just tried this on an old laptop set to 60Hz but my program reports 30!</update>

Strict
Graphics 800,600
Repeat
Cls
DrawText refresh_rate(),10,10
Flip
Delay 1000
Until KeyHit(KEY_ESCAPE)
End

Function refresh_rate()
	Local ms,fps
	Flip(1)
	ms=MilliSecs()
	Flip(1)
	fps=1000/(MilliSecs()-ms)
	Return fps
End Function


Peter

Strict

?Win32
	Import Pub.Win32
	
	Extern "Win32"
		Function ReleaseDC(hWnd, hdc)
	End Extern
	
	Local hWnd = GetDesktopWindow()
	Local hdc = GetDC(hWnd)
	If hdc = Null Then End
	
	Print
	Print "Desktop Refresh Rate = " + GetDeviceCaps(hdc, VREFRESH)
	
	ReleaseDC(hWnd, hdc)
?

End


Using millisecs will never give you the true refresh rate for many many reasons. But if you want a few, here they are:

A) Your system is multitasking so you can never be sure the same line of code will execute in the same amount of time.

B) The refresh rate rarely will divide evenly into 1000 milliseconds. For example, at 60hz, the number of milliseconds per frame is 16.6666~.

C) Just because the screen refresh rate is 60hz doesn't mean it draws exactly 60 times a second every time. Your monitor isn't run by an atomic clock. :-)

In short, there's a lot of little time differences and timer accuracy issues which mean you'll never be able to read the HZ using the millisecond timer.

Though if you averaged it over a long enough period, I suppose you could get close. But you'll probably still end up with like 59.9999hz or something.

Tearing is caused by VSync, you can change this by using Flip 1 or Flip 0. Although the refresh rate is involved in whether the screen will tear or not, tearing can happen on any refresh rate, whether it is 60hz or 85hz.

Full screen programs will usually use whatever the desktop refresh rate last was for that mode. For example, if your program is 800x600 32-bit colour, set Windows desktop to that exact resolution. Now change the refresh rate to a desired level, and change the desktop back to your normal resolution. I THINK all fullscreen programs (that don't set the rate themselves) will use that refresh rate from now on for that exact mode.

A more complicated or perhaps better solution is to simply ask your user what he wants. Use the command to find you the list of supported resolutions and refresh rates, and ask the user to pick. Then if he wants to use 75hz he can, 60hz he can etc.

If you use GraphicsModes, you should get a mode with a good refresh rate.

Thank you all for taking the time to reply.

Yan, that code certainly delivered the answer - thank you!

sswift, I appreciate all the points you raise but that hardly explains the old laptop that consistently said "30" for "60" !

Sure I can use GraphicsModes - I came up with the idea of using the highest refresh rate for the resolution I wanted but the catch is it is the adapter reporting here and on one laptop the monitor wasn't up to the refresh rate and tearing resulted.

On the other hand if I use the default 60 as many have suggested elsewhere I get flickering on the crt that normally uses 75.

Allowing the user to choose is neat but my work is being used for disabled folk and for folk in care facilities.

Once again ... many thanks ... I'll try Yan's approach and worry about the Mac when I start working in that environment.

I'll add to this thread if I encounter any further issues.

Peter

There is a small module by dbug `desktopext` which provides cross-platform access to the desktop's dimensions, client area, bit depth, hz rate, etc.

Your plan assumes that the desktop refresh rate of the computers is already set up to an appriopriate level. Who ensures that?

I'm assuming someone that at least knows what he is doing will install your program on the computers. The setup program should ask what default rate to use and store it in a file.

As for tearing, did you try flip 1 and flip 0? I can't remember which is which but I think one forces VSync which reduces tearing.

Ah, how bizarre, I just ran into that for the first time myself. My previous compiles somehow never showed that kind of trouble.

It appears as though there's some sort of backbuffer trouble. It's very strange, since openGL and directX act as if they have specific modes that crisscross allow or deny backbuffers. (at least by the looks of it?!). More fascinating to me is the idea that I wasn't running into that earlier! I'm compiling with the SVN, if that could make any difference, but it might be that I wasn't using full res earlier?!?

However, I can claim that I've tried a lot of things and still can't come to a conclusion. Flip 0 ignornes the vblank, but ignoring it or not, that's not the problem as far as I can tell. Some laptops don't like flip 1 with openGL either, still ignoring the vblank.

Anyway... I wasn't helping, I know! :oP

IH - thanks for the cross platform heads up - will check that out

CF - my "plan" is a suite of programs - I want each to be standalone and capable of setting the res itself - I know I could use ini files but in the environment in which I'm working that's not the best approach.

If the desktop hertz is wrong already then all programs will be flickering and either this doesn't bother the user or someone will fix it!

I spent a lot of time experimenting with the flip flag - I felt it was being ignored on at least one old machine.

I'm very happy with Yan's code and have implemented it with complete success so I'm one happy camper at the moment.

Peter

P.S. Taron - sorry to hear that you're moving into the area I was in only yesterday!

Bottom line after lengthy research, etc, etc, yada, yada, yada..

Use Flip(1) all the time, and get used to it. This forces vsync which every game should do. Regardless if your game runs at 15fps or 75fps. The only reason to use Flip(0) is to test how fast your main loop is capable of.

Other Flip() parameters seem to be there to provide support for jurassic coders who want to code their game at 60fps on any monitor hz, and not have to use delta, tweening, etc. Avoid this line of thinking.

>> If your game runs faster then monitor refresh with Flip(1) then your GPU driver settings are set to ignore vsync.

>> If your GPU settings ARE set to vsync, and you use Flip(1) and still get tearing or high frame rates, then reinstall your drivers, something is broke. I've had peeps from day 1, play games with tearing and think it's "normal" then when they see the same games on their system with proper drivers installed and VSYNC is working, it's like night and day. ;)

Graphics(width,height,mode,hz)

>> Default for "hz" is 60, so if you ignore this parameter, in full screen mode BlitzMax will attempt to setup a 60hz refresh rate.

>> If you pass a parameter that is not supported by the driver, the driver will setup a default hz.

I would recommend passing 0 and letting the internals of the system setup a hz for you. Then in your game, use fixed logic, tweening, delta timing, etc, for your logic/render needs. ;)

I pretty much agree with MGE. A lot of people are using Flip -1 thinking that it will provide tear-free flipping, but it doesn't, especially I notieced it on my Mac, I had to change various examples to Flip 1 in order to properly sync with the vertical blank. I would recommend using Flip 1 all the time unless you want maximum/variable framerate in which case use Flip 0. You should be using some kind of dynamic logic timing (fixed rate, delta etc) regardless because the hardware may not be able to keep up with the amount of work you're asking it to do. On a lower end/mid-range machine, if there is too much work to do the framerate will drop even if it's vsync'd and then you have to deal with logic slowing down.

With my games I'm using Flip 1 for a while now, which is fantastic, particularely under directX, which shows some consistency across most gfxboards.
However, with my funny happy trees it has the wild problem that I would have to somehow alter the routines to execute the growing outside of the vsync loop, because they benefit greatly from faster machines, while the vsync would slow it down. No drama, naturally.

However, I can't yet confirm that the flip choice is responsible for the flickering, since even flip 1 flickers in the case of fullscreen on the laptop!

I had something extremely esotheric happening when I managed to have no flickers on the laptop, where it appeared like it was drawing empty colored boxes on the screen as opposed to the chosen images. I can't even begin to tell what might cause that?! Particularely because a windowed version nor the flickering fullscreen wouldn't show that.

It's possible that your driver/gfx card simply does not `report` the vertical blank properly/at all. Not all hardware supports that.

I agree with MGE, I mean I practically set the standard (after a ton of research couple of years back) ;-p They key is Flip 1 AND some decent game timing so if Vysnc is forced off in the GPU drivers, your game still runs at a normal speed.

Yeah, that 'extensive research' must have really taken it out of you...

http://www.blitzbasic.com/Community/posts.php?topic=57862#643780


;op

oops

haha, I did spend a long time reading up about it and running tests and posting test apps online, and then refining my timing method for MBax etc, so it sure feels like a ton of research to me :-)

Yo.. if you research anything with "frame rate" , "hz" , "fixed logic" , etc, etc, chance are GA's going to show up. So yah...I would say he's put in the hours. :)

@ ImaginaryHuman
Yep, but only for openGL, funny enough. DirectX reports proper Vblank normally.

@ the rest
I would testify to the flip 1 solution, particularely with using directX. It's very reliable and produces beautifully smooth performance. As far as I can tell, I didn't even have to bother with anything else, especially no delta timing mess. I might have been lucky with my last game, but it feels fine on either machine (8core and laptop). Only the above mentioned remains a problem (openGL troubles on mobiles).

Actually I was just making a silly comment for fun so don't wanna make a big deal of it :)

I had to look for your comment to get what you're saying there, hehe, but I actually mean it in regards to flip 1 and successfully being lazy. I have no idea what happens when a system has vsync turned off, but it led to my first successful smooth running game. (running maxgui)

I'd still like to know, if anyone had ever run into the wacky phenomenon, where either pixmaps don't seem to be generated, or images somehow can't get their content on the screen. (I should best show it, I know...)

And, naturally, the backbuffer/flicker weirdness in fullscreen modes. Does anyone know what this is or could be? (especially under directX (7))

ONE more thing... drawpixmap and grabimage... I found that with openGL and fullscreen a drawn pixmap may not be grabbed as image, but had to be drawn as image( loadimage...drawimage), while the circumstances are horribly ambiguous. If I started off drawing a pixmap to then go into the loop and grab image, it wouldn't get it, while during the loops, miraculously it will. Anything funky with memory dealings? There may well be stuff I havn't understood yet in regards to where an image ends up in memory and where it gets taken from again or how it ends up on the gfx memory and where grabimage actually takes it from?

Questions over questions...

I remember someone posting problems with grabimage in OGL. A search of the forum might help. Also "As far as I can tell, I didn't even have to bother with anything else, especially no delta timing mess. " well...that works ok when your game is running on capable hardware, but if running on lower end spec, or when your pc system has quirks, your game would run very choppy, have slow downs, etc, etc. And then if the system has vsync off, well your frame rate would be all over the place. ;) I've been running some recent ideas on a brand new Vaio pc with a nice Nvidia card, window games are choppy as hell, even my low end intel runs games better in window mode.

@Taron: Maybe you are simply failing to Cls and Flip each frame? Or yeah GrabPixmap doesn't work in OpenGL the same as for DirectX, I posted that on the bug forum a few months back but it has not been fixed. Guess it's low priority...



I'd still like to know, if anyone had ever run into the wacky phenomenon, where either pixmaps don't seem to be generated, or images somehow can't get their content on the screen. (I should best show it, I know...)


checked variables against NULL ? Or did you mean "draws nothing" - the "can't get their content on the screen" is a bit hm undefined.



And, naturally, the backbuffer/flicker weirdness in fullscreen modes.


Thought there is no real backbuffer-system in Bmax, only the one and only surface you are working with. So what do you mean with "flicker" - tearing? black-screens?...


Questions over questions...


questions upon questions...
no word by word translation from German to English please ;D


bye MB

It draws the box of the image in the chosen color with the chosen alpha, but non of the pixel values it should contain.

Yes there is a backbuffer system in Bmax, in fact that's the most commonly used ( flip, flipping the buffers. You always draw on the backbuffer and then flip it to the front! How far that's not a "real" backbuffer system I can't tell!)

Thanks for your lecture on the english language. Even after 10 years in L.A. I screw up some phrazes here and there. Try telling someone not to paint the devil on the wall! ;)

If you are finding that grabpixmap doesn't work in OpenGL, try calling glReadPixels yourself to download a rectangular area of pixels and store it in a pre-created pixmap.

"Yes there is a backbuffer system in Bmax, in fact that's the most commonly used ( flip, flipping the buffers. You always draw on the backbuffer and then flip it to the front! How far that's not a "real" backbuffer system I can't tell!)"

Correct. :)

But not like in the old days with double buffering or even triple buffering. you only can draw on one buffer at one time (ok, RTT is something very similar but its not included in a normal BMax-installation).

short: there is no SetBuffer (or SetTarget).



Garbage-Grabbing: Try using the method ImaginaryHuman suggests or give GrabImage a chance and grab your pixmap from there (this way it works for me even in OGL).



bye MB

Actually I was just making a silly comment for fun...
As was I. :o)

Still, looking on the bright side. It seems you've pulled. ;o)


Yo.. if you research anything with "frame rate" , "hz" , "fixed logic" , etc, etc, chance are GA's going to show up.
Yeah, I know. I was there. ;o)

I think GA is well used to my light hearted, if oft-sarcastic, leg pulling by now. :o)

Um, I'm using grabimage and then past the img.pixmap[0] into my pixmap! I noticed that grabpixmap didn't work very early on. Guess I forgot to mention that.

However, it's not the grabimage that really appears to fail. It's literally the drawimage of the images that goes wrong somehow...

I also did run into a few weird things with the image.pixmap[0] option. It also seems that creating an image doesn't allocate a pixmap until something is loaded into it, is that correct?

I think GA is well used to my light hearted, if oft-sarcastic, leg pulling by now. :o)
so much so my leg is a little loose.

paint the devil on the wall
Heard that in a Megadeth song...

As far as i know flip(1) is simply a request to vsync - driver options
can override this + if you dont specify a hz value for
refresh you get a default/safe value?... If a user has disabled vsync in
there driver options..you may have trouble detecting this - i dont think
there are any bmax system commands to test for this?...

Taron - did you lockImage your Timage before working on it or its childelements (pixmaps)?

Maybe that helps.


bye MB

Hmmm, nope, I didn't lock them, but I also don't have any troubles on my machine with them. Could it be that this effects only certain setups?

I've started to use Loadimage rather than lock and paste in order to get my pixmaps into the timages. Seems to work fine on my machine, but then I don't know if that could act differently on others?! (sorry for repeating myself there.)

I'll have a check for sure! Thanks!