- Added vid_maxfps cvar to limit the frame rate to some arbitrary rate between 35 and 1000 FPS. It

defaults to 200. Setting it to 0 will restore the previous behavior of having no frame rate
  limit. Note that vid_maxfps 35 is NOT the same as cl_capfps 1. cl_capfps caps the frame rate
  by tying the video update directly to the game timer. With vid_maxfps 35, the video update and
  game timer are running on separate timers, and results will not be as good as with cl_capfps 1,
  which uses only one timer.

SVN r3872 (trunk)
This commit is contained in:
Randy Heit 2012-09-16 04:40:56 +00:00
parent 1e234c9853
commit 11ca707485
8 changed files with 125 additions and 2 deletions

View File

@ -60,6 +60,7 @@
#include "p_lnspec.h"
#include "v_video.h"
#include "p_spec.h"
#include "hardware.h"
#include "intermission/intermission.h"
EXTERN_CVAR (Int, disableautosave)
@ -135,7 +136,18 @@ static int oldentertics;
extern bool advancedemo;
CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
// Do not use the separate FPS limit timer if we are limiting FPS with this.
if (self)
{
I_SetFPSLimit(0);
}
else
{
I_SetFPSLimit(-1);
}
}
// [RH] Special "ticcmds" get stored in here
static struct TicSpecial

View File

@ -177,6 +177,10 @@ void I_ClosestResolution (int *width, int *height, int bits)
}
}
void I_SetFPSLimit(int limit)
{
}
extern int NewWidth, NewHeight, NewBits, DisplayBits;
CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)

View File

@ -59,6 +59,8 @@ void I_InitGraphics ();
void I_ShutdownGraphics ();
void I_CreateRenderer();
void I_SetFPSLimit(int limit);
extern IVideo *Video;
#endif // __HARDWARE_H__

View File

@ -1208,6 +1208,11 @@ void D3DFB::Flip()
BlockSurface[BlockNum]->UnlockRect();
}
}
// Limiting the frame rate is as simple as waiting for the timer to signal this event.
if (FPSLimitEvent != NULL)
{
WaitForSingleObject(FPSLimitEvent, 1000);
}
D3DDevice->Present(NULL, NULL, NULL, NULL);
InScene = false;

View File

@ -1201,6 +1201,10 @@ void DDrawFB::Update ()
LockCount = 0;
UpdatePending = false;
if (FPSLimitEvent != NULL)
{
WaitForSingleObject(FPSLimitEvent, 1000);
}
if (!Windowed && AppActive && !SessionState /*&& !UseBlitter && !MustBuffer*/)
{
HRESULT hr = PrimarySurf->Flip (NULL, FlipFlags);

View File

@ -62,6 +62,9 @@ void I_CreateRenderer();
void I_SaveWindowedPos ();
void I_RestoreWindowedPos ();
void I_SetFPSLimit(int limit);
extern IVideo *Video;
#endif // __HARDWARE_H__

View File

@ -52,6 +52,8 @@
EXTERN_CVAR (Bool, vid_vsync)
extern HANDLE FPSLimitEvent;
class D3DTex;
class D3DPal;
struct FSoftwareRenderer;

View File

@ -41,6 +41,7 @@
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include <ddraw.h>
#include <d3d9.h>
@ -87,6 +88,8 @@ void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, in
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void StopFPSLimit();
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern HWND Window;
@ -98,20 +101,38 @@ extern bool VidResizing;
EXTERN_CVAR (Bool, fullscreen)
EXTERN_CVAR (Float, Gamma)
EXTERN_CVAR (Bool, cl_capfps)
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static HMODULE D3D9_dll;
static HMODULE DDraw_dll;
static UINT FPSLimitTimer;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
IDirectDraw2 *DDraw;
IDirect3D9 *D3D;
IDirect3DDevice9 *D3Device;
HANDLE FPSLimitEvent;
CVAR (Bool, vid_forceddraw, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR (Int, vid_adapter, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (vid_maxfps < TICRATE && vid_maxfps != 0)
{
vid_maxfps = TICRATE;
}
else if (vid_maxfps > 1000)
{
vid_maxfps = 1000;
}
else if (cl_capfps == 0)
{
I_SetFPSLimit(vid_maxfps);
}
}
#if VID_FILE_DEBUG
FILE *dbg;
@ -714,4 +735,74 @@ void Win32Video::SetWindowedScale (float scale)
// FIXME
}
// FrameBuffer implementation -----------------------------------------------
//==========================================================================
//
// SetFPSLimit
//
// Initializes an event timer to fire at a rate of <limit>/sec. The video
// update will wait for this timer to trigger before updating.
//
// Pass 0 as the limit for unlimited.
// Pass a negative value for the limit to use the value of vid_maxfps.
//
//==========================================================================
void I_SetFPSLimit(int limit)
{
if (limit < 0)
{
limit = vid_maxfps;
}
// Kill any leftover timer.
if (FPSLimitTimer != 0)
{
timeKillEvent(FPSLimitTimer);
FPSLimitTimer = 0;
}
if (limit == 0)
{ // no limit
if (FPSLimitEvent != NULL)
{
CloseHandle(FPSLimitEvent);
FPSLimitEvent = NULL;
}
DPrintf("FPS timer disabled\n");
}
else
{
if (FPSLimitEvent == NULL)
{
FPSLimitEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
if (FPSLimitEvent == NULL)
{ // Could not create event, so cannot use timer.
Printf("Failed to create FPS limitter event\n");
return;
}
}
atterm(StopFPSLimit);
// Set timer event as close as we can to limit/sec, in milliseconds.
UINT period = 1000 / limit;
FPSLimitTimer = timeSetEvent(period, 0, (LPTIMECALLBACK)FPSLimitEvent, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
if (FPSLimitTimer == 0)
{
CloseHandle(FPSLimitEvent);
FPSLimitEvent = NULL;
Printf("Failed to create FPS limitter timer\n");
return;
}
DPrintf("FPS timer set to %u ms\n", period);
}
}
//==========================================================================
//
// StopFPSLimit
//
// Used for cleanup during application shutdown.
//
//==========================================================================
static void StopFPSLimit()
{
I_SetFPSLimit(0);
}