User Tools

Site Tools


synchronizing_20with_20video_20refresh

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

synchronizing_20with_20video_20refresh [2018/03/31 13:19]
127.0.0.1 external edit
synchronizing_20with_20video_20refresh [2018/04/13 16:08] (current)
richardrussell Added syntax highlighting
Line 1: Line 1:
 =====Synchronizing with video refresh===== =====Synchronizing with video refresh=====
  
-//by Richard Russell, April 2007//\\ \\ //**(Note that the code in this article requires DirectX 7 or later).**//​\\ \\  To achieve perfectly smooth animated graphics it is necessary to synchronize the output from your program with the video refresh rate of your graphics card and monitor. For example, if your display is running at 75 Hz your program should update its output (preferably) 75 times per second, synchronized with the start of each video frame. If it cannot run that quickly, it should update its output at a sub-multiple of the video refresh rate (e.g. 37.5 or 25 times per second).\\ \\  The Windows **Graphical Device Interface** (GDI) provides no means of synchronizing with the video refresh rate, but **DirectX** (in particular its **Direct Draw** subsystem) does. It is not necessary to use DirectX to output the graphics themselves; you can use it solely for the purpose of synchronization.\\ \\  To achieve this you should first incorporate the following code in the initialisation section of your program:\\ \\ +//by Richard Russell, April 2007//\\ \\ //**(Note that the code in this article requires DirectX 7 or later).**//​\\ \\  To achieve perfectly smooth animated graphics it is necessary to synchronize the output from your program with the video refresh rate of your graphics card and monitor. For example, if your display is running at 75 Hz your program should update its output (preferably) 75 times per second, synchronized with the start of each video frame. If it cannot run that quickly, it should update its output at a sub-multiple of the video refresh rate (e.g. 37.5 or 25 times per second).\\ \\  The Windows **Graphical Device Interface** (GDI) provides no means of synchronizing with the video refresh rate, but **DirectX** (in particular its **Direct Draw** subsystem) does. It is not necessary to use DirectX to output the graphics themselves; you can use it solely for the purpose of synchronization.\\ \\  To achieve this you should first incorporate the following code in the initialisation section of your program: 
 + 
 +<code bb4w> ​
         SYS "​LoadLibrary",​ "​DDRAW.DLL"​ TO ddraw%         SYS "​LoadLibrary",​ "​DDRAW.DLL"​ TO ddraw%
         IF ddraw%=0 THEN ERROR 100, "​Direct Draw not available"​         IF ddraw%=0 THEN ERROR 100, "​Direct Draw not available"​
Line 22: Line 24:
         SYS `DirectDrawCreateEx`,​ 0, ^IDirectDraw%,​ IID_IDirectDraw7{},​ 0         SYS `DirectDrawCreateEx`,​ 0, ^IDirectDraw%,​ IID_IDirectDraw7{},​ 0
         !(^IDirectDraw{}+4) = !IDirectDraw%         !(^IDirectDraw{}+4) = !IDirectDraw%
-Here an error results if Direct Draw isn't available. In practice you may prefer not to issue an error but to fall back to using timers or the WAIT statement to set the frame rate. The animation will not be as smooth but at least your program will still run.\\ \\  The simplest way of achieving synchronization is to wait for the beginning of each video frame before updating your graphics output. To do that you can use code similar to the following (**do not use this method - see below**):\\ \\ +</​code>​ 
 + 
 +Here an error results if Direct Draw isn't available. In practice you may prefer not to issue an error but to fall back to using timers or the WAIT statement to set the frame rate. The animation will not be as smooth but at least your program will still run.\\ \\  The simplest way of achieving synchronization is to wait for the beginning of each video frame before updating your graphics output. To do that you can use code similar to the following (**do not use this method - see below**): 
 + 
 +<code bb4w>
         _DDWAITVB_BLOCKBEGIN = 1         _DDWAITVB_BLOCKBEGIN = 1
         REPEAT         REPEAT
Line 28: Line 34:
           PROCpaint           PROCpaint
         UNTIL FALSE         UNTIL FALSE
-Here it is assumed that your output will be updated in **PROCpaint**.\\ \\  Unfortunately there are a couple of shortcomings with this simple method. Firstly, the **WaitForVerticalBlank** function does not always work reliably. Secondly, it uses 100% CPU time while waiting for the next frame, which is undesirable (the importance of this will depend on how much time is spent '​waiting'​ and how much doing something useful).\\ \\  An alternative and more satisfactory approach is to poll for the beginning of the video frame as follows:\\ \\ +</​code>​ 
 + 
 +Here it is assumed that your output will be updated in **PROCpaint**.\\ \\  Unfortunately there are a couple of shortcomings with this simple method. Firstly, the **WaitForVerticalBlank** function does not always work reliably. Secondly, it uses 100% CPU time while waiting for the next frame, which is undesirable (the importance of this will depend on how much time is spent '​waiting'​ and how much doing something useful).\\ \\  An alternative and more satisfactory approach is to poll for the beginning of the video frame as follows: 
 + 
 +<code bb4w>
         SYS "​timeBeginPeriod",​ 1         SYS "​timeBeginPeriod",​ 1
         lastline% = 0         lastline% = 0
Line 37: Line 47:
           SYS "​Sleep",​ 1           SYS "​Sleep",​ 1
         UNTIL FALSE         UNTIL FALSE
-Again it is assumed that your output will be updated in **PROCpaint**. The call to **timeBeginPeriod** is to ensure that the **Sleep** function waits for the shortest possible (non-zero) period.\\ \\  This method may not result in as accurate synchronization as the previous one, but it avoids wasting CPU time and allows you to carry out low-priority '​background'​ tasks whilst waiting for the start of the next frame.\\ \\  When you have finished with the Direct Draw subsystem, execute the following code (for example on exit, by including it in a **cleanup** routine called from ON ERROR and ON CLOSE statements):​\\ \\ +</​code>​ 
 + 
 +Again it is assumed that your output will be updated in **PROCpaint**. The call to **timeBeginPeriod** is to ensure that the **Sleep** function waits for the shortest possible (non-zero) period.\\ \\  This method may not result in as accurate synchronization as the previous one, but it avoids wasting CPU time and allows you to carry out low-priority '​background'​ tasks whilst waiting for the start of the next frame.\\ \\  When you have finished with the Direct Draw subsystem, execute the following code (for example on exit, by including it in a **cleanup** routine called from ON ERROR and ON CLOSE statements):​ 
 + 
 +<code bb4w>
         SYS IDirectDraw.Release%,​ IDirectDraw%         SYS IDirectDraw.Release%,​ IDirectDraw%
 +</​code>​
synchronizing_20with_20video_20refresh.txt · Last modified: 2018/04/13 16:08 by richardrussell