PDA

View Full Version : How to force the vsync with delphi?



fabiano.salles
02-10-2008, 03:45 PM
At the old days of DOS, I only needed to read the right hardware port ($3DA) and wait the bits became $00. But now, as we know, the WinXP blocks the access to the hardware ports (except for driver mode programs) so any tries to read using the mnemonic IN (or write with mnemonic OUT) cause an "Access Violation".
This is the code that works under TurboPascal:

procedure waitVSync; assembler;
begin
Mov dx,3DAh
@L1:
In al,dx
And al,08h
Jnz @L1
@L2:
In al,dx
And al,08h
Jz @L2
end;

And the same approach using Turbo C++:


void blit(void){
while( inportb(0x3DA) & 8);
while(!(inportb(0x3DA) & 8));
_fmemcpy(VGA, offScreen, 64000);
}

I wonder if there are some WIN32API function that could do the same or any tricks to read the port $3DA?

Thanks a lot.

JernejL
02-10-2008, 04:44 PM
zlioport component is a lpt port component which comes with a driver which gives your app access to hardware if you tell the component to use the driver (via usePM set to true).

JSoftware
02-10-2008, 06:28 PM
There's no reason to do that. Firstly it's bound to only work on vga hardware, which noone uses in win xp anymore, and you should much rather use the inbuilt support for double buffering anyway.

Afaik, if you set OpenGL to use VSync any call to FlipBuffers should block until VSync, and in DirectX the same happens when you call Present

I don't know what you would use for other api's, but the most logic way to do it for them, would be to just block(eg. wait) until vsync

fabiano.salles
02-10-2008, 07:17 PM
Wait until the VSync moment is excatly what I need, JSoftware. The problem is to know when it will happen since I'm using only VCL and Win32.

When in fullscreen, I can render at ~400fps with very simple graphics to blit. There is where my problem begins, since the program tries to render another frame before the prior frame could be totally displayed at the screen (due to the fact my monitor works at 70Mhz, I think).

JSoftware
02-10-2008, 07:35 PM
What do you mean by render? Using images on a canvas or using some component?

fabiano.salles
02-10-2008, 07:48 PM
By render I mean Bitblt() a buffer TBitmap.Canvas to a device context (DC) wich can be the TForm canvas or the TPaintBox Canvas.
:D

JSoftware
02-10-2008, 08:09 PM
You should be able to use doublebuffering then. You simply set the flag PFD_DOUBLEBUFFER when you choose the pixelformat for the device context. And then when you are done rendering, you call SwapBuffers, which swaps the backbuffer with the front buffer, and theoretically waits for vsync

fabiano.salles
02-10-2008, 08:53 PM
I did this modification and the program now run only at ~70fps wicht suggest it is doing the VSync. :D
But, now I have one more question (sorry for abusing your patience, hehe).

If the double buffer now is managed by the gdi, there is no need to keep my own backbuffer, ok?
I could use something like this pseudocode without trouble?


PROCEDURE DRAW_EVERYTHING
BEGIN
DRAW_ALL_OBJECTS_TO_CANVAS;
SWAPBUFFERS;
END

Thanks again!

JSoftware
02-10-2008, 10:21 PM
You would only slow rendering down by keeping your own buffer. But probably not much. It depends on what you likes to work with best, probably