reduced win32 raw mouse input latency and added cl_drawMouseLag

This commit is contained in:
myT 2017-05-06 22:01:14 +02:00
parent f9d4056e41
commit e4062a6c90
10 changed files with 78 additions and 42 deletions

View file

@ -56,6 +56,8 @@ fix: if requesting a resolution too high for the display, the image would be off
chg: updated mouse input for better grab (de-)activation and fixed window dragging not working chg: updated mouse input for better grab (de-)activation and fixed window dragging not working
chg: reduced raw mouse input latency and added cl_drawMouseLag
Linux: Linux:

View file

@ -295,6 +295,7 @@ void CL_MouseEvent( int dx, int dy, int time )
VM_Call( cgvm, CG_MOUSE_EVENT, dx, dy ); VM_Call( cgvm, CG_MOUSE_EVENT, dx, dy );
cl.mouseDx[cl.mouseIndex] += dx; cl.mouseDx[cl.mouseIndex] += dx;
cl.mouseDy[cl.mouseIndex] += dy; cl.mouseDy[cl.mouseIndex] += dy;
cl.mouseTime = time;
} }
} }
@ -454,6 +455,7 @@ static usercmd_t CL_CreateCmd()
// get basic movement from mouse // get basic movement from mouse
CL_MouseMove( &cmd ); CL_MouseMove( &cmd );
cl.userCmdTime = Sys_Milliseconds();
// get basic movement from joystick // get basic movement from joystick
CL_JoystickMove( &cmd ); CL_JoystickMove( &cmd );
@ -865,6 +867,8 @@ void CL_InitInput()
Cmd_AddCommand ("+mlook", IN_MLookDown); Cmd_AddCommand ("+mlook", IN_MLookDown);
Cmd_AddCommand ("-mlook", IN_MLookUp); Cmd_AddCommand ("-mlook", IN_MLookUp);
Cvar_Get( "cl_drawMouseLag", "0", 0 );
m_speed = Cvar_Get( "m_speed", "8", CVAR_ARCHIVE ); m_speed = Cvar_Get( "m_speed", "8", CVAR_ARCHIVE );
m_accel = Cvar_Get( "m_accel", "0", CVAR_ARCHIVE ); m_accel = Cvar_Get( "m_accel", "0", CVAR_ARCHIVE );
m_limit = Cvar_Get( "m_limit", "0", CVAR_ARCHIVE ); m_limit = Cvar_Get( "m_limit", "0", CVAR_ARCHIVE );

View file

@ -215,6 +215,39 @@ void SCR_Init()
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
static void SCR_DrawStats( float x, float y, float w, float h, int value )
{
if ( value < 0 || value >= 100 )
SCR_DrawString( x, y, w, h, " ?", qfalse );
else
SCR_DrawString( x, y, w, h, va( "%3d", value ), qfalse );
}
static void SCR_DrawInputStats( int stats, float x, float y, float w, float h, const char* header )
{
SCR_DrawString( x, y, w, h, header, qfalse );
x += 5.0f * w;
SCR_DrawStats( x, y, w, h, stats );
}
static void SCR_DrawMouseInputLatencies()
{
if ( !cls.cgameStarted || cls.state != CA_ACTIVE ||
!Cvar_VariableIntegerValue( "cl_drawMouseLag" ) )
return;
float x = 10, y = 10, w = 16, h = 24;
SCR_AdjustFrom640( &x, &y, 0, 0 );
SCR_DrawString( x, y, w, h, "mouse lag [ms]", qfalse );
y += 30;
SCR_DrawInputStats( cl.userCmdTime - cl.mouseTime, x, y, w, h, "netw" );
y += 30;
SCR_DrawInputStats( re_cameraMatrixTime - cl.mouseTime, x, y, w, h, "draw" );
}
// this will be called twice if rendering in stereo mode // this will be called twice if rendering in stereo mode
static void SCR_DrawScreenField( stereoFrame_t stereoFrame ) static void SCR_DrawScreenField( stereoFrame_t stereoFrame )
@ -283,6 +316,8 @@ static void SCR_DrawScreenField( stereoFrame_t stereoFrame )
VM_Call( uivm, UI_REFRESH, cls.realtime ); VM_Call( uivm, UI_REFRESH, cls.realtime );
} }
SCR_DrawMouseInputLatencies();
// console draws next // console draws next
Con_DrawConsole(); Con_DrawConsole();

View file

@ -105,6 +105,7 @@ typedef struct {
int mouseDx[2], mouseDy[2]; // added to by mouse events int mouseDx[2], mouseDy[2]; // added to by mouse events
int mouseIndex; int mouseIndex;
int mouseTime; // when the last mouse input was sampled, for cl_drawMouseLag
int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events
// cgame communicates a few values to the client system // cgame communicates a few values to the client system
@ -116,6 +117,7 @@ typedef struct {
usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds
int cmdNumber; // incremented each frame, because multiple int cmdNumber; // incremented each frame, because multiple
// frames may need to be packed into a single packet // frames may need to be packed into a single packet
int userCmdTime; // when the last usercmd_t was generated, for cl_drawMouseLag
outPacket_t outPackets[PACKET_BACKUP]; // information about each packet we have sent out outPacket_t outPackets[PACKET_BACKUP]; // information about each packet we have sent out

View file

@ -708,7 +708,7 @@ int Com_HashKey(char *string, int maxlen);
int Com_Filter( const char* filter, const char* name ); int Com_Filter( const char* filter, const char* name );
int Com_FilterPath( const char* filter, const char* name ); int Com_FilterPath( const char* filter, const char* name );
int Com_RealTime(qtime_t *qtime); int Com_RealTime(qtime_t *qtime);
qbool Com_SafeMode(); qbool Com_SafeMode();
void Com_StartupVariable( const char *match ); void Com_StartupVariable( const char *match );
// checks for and removes command line "+set var arg" constructs // checks for and removes command line "+set var arg" constructs

View file

@ -1272,6 +1272,9 @@ static void R_DebugGraphics()
} }
int re_cameraMatrixTime;
// a view may be either the actual camera view, or a mirror / remote location // a view may be either the actual camera view, or a mirror / remote location
void R_RenderView( const viewParms_t* parms ) void R_RenderView( const viewParms_t* parms )
@ -1289,6 +1292,7 @@ void R_RenderView( const viewParms_t* parms )
int firstLitSurf = tr.refdef.numLitSurfs; int firstLitSurf = tr.refdef.numLitSurfs;
// set viewParms.world // set viewParms.world
re_cameraMatrixTime = Sys_Milliseconds();
R_RotateForViewer(); R_RotateForViewer();
R_SetupFrustum(); R_SetupFrustum();

View file

@ -158,8 +158,6 @@ typedef struct {
qbool (*inPVS)( const vec3_t p1, const vec3_t p2 ); qbool (*inPVS)( const vec3_t p1, const vec3_t p2 );
void (*TakeVideoFrame)( int h, int w, byte* captureBuffer, byte *encodeBuffer, qbool motionJpeg ); void (*TakeVideoFrame)( int h, int w, byte* captureBuffer, byte *encodeBuffer, qbool motionJpeg );
// drakkar
void (*WindowFocus)(qbool focus);
} refexport_t; } refexport_t;
// //
@ -223,4 +221,8 @@ typedef struct {
// if the module can't init to a valid rendering state, it will return NULL // if the module can't init to a valid rendering state, it will return NULL
const refexport_t* GetRefAPI( const refimport_t* rimp ); const refexport_t* GetRefAPI( const refimport_t* rimp );
extern int re_cameraMatrixTime; // when the final model-view matrix is computed, for cl_drawMouseLag
#endif // __TR_PUBLIC_H #endif // __TR_PUBLIC_H

View file

@ -29,7 +29,6 @@ struct Mouse {
virtual qbool Activate( qbool active ); virtual qbool Activate( qbool active );
virtual void OnWindowMoved() {} virtual void OnWindowMoved() {}
virtual void Shutdown() {} virtual void Shutdown() {}
virtual void Read( int* mx, int* my ) = 0;
virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ) { return qfalse; } // returns true if the event was handled virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ) { return qfalse; } // returns true if the event was handled
Mouse() : active(qfalse), wheel(0) {} Mouse() : active(qfalse), wheel(0) {}
@ -78,10 +77,7 @@ void Mouse::UpdateWheel( int delta )
struct rawmouse_t : public Mouse { struct rawmouse_t : public Mouse {
virtual qbool Init(); virtual qbool Init();
virtual qbool Activate( qbool active ); virtual qbool Activate( qbool active );
virtual void Read( int* mx, int* my );
virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ); virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam );
int x, y;
}; };
static rawmouse_t rawmouse; static rawmouse_t rawmouse;
@ -109,14 +105,6 @@ qbool rawmouse_t::Activate( qbool active )
} }
void rawmouse_t::Read( int* mx, int* my )
{
*mx = rawmouse.x;
*my = rawmouse.y;
rawmouse.x = rawmouse.y = 0;
}
// MSDN says you have to always let DefWindowProc run for WM_INPUT // MSDN says you have to always let DefWindowProc run for WM_INPUT
// regardless of whether you process the message or not, so ALWAYS return false here // regardless of whether you process the message or not, so ALWAYS return false here
@ -138,8 +126,10 @@ qbool rawmouse_t::ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam )
if ( (ri.header.dwType != RIM_TYPEMOUSE) || (ri.data.mouse.usFlags != MOUSE_MOVE_RELATIVE) ) if ( (ri.header.dwType != RIM_TYPEMOUSE) || (ri.data.mouse.usFlags != MOUSE_MOVE_RELATIVE) )
return qfalse; return qfalse;
rawmouse.x += ri.data.mouse.lLastX; const int dx = (int)ri.data.mouse.lLastX;
rawmouse.y += ri.data.mouse.lLastY; const int dy = (int)ri.data.mouse.lLastY;
if (dx != 0 || dy != 0)
Sys_QueEvent( g_wv.sysMsgTime, SE_MOUSE, dx, dy, 0, NULL );
if (!ri.data.mouse.usButtonFlags) // no button or wheel transitions if (!ri.data.mouse.usButtonFlags) // no button or wheel transitions
return qfalse; return qfalse;
@ -173,12 +163,12 @@ qbool rawmouse_t::ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam )
struct winmouse_t : public Mouse { struct winmouse_t : public Mouse {
virtual qbool Activate( qbool active ); virtual qbool Activate( qbool active );
virtual void OnWindowMoved(); virtual void OnWindowMoved();
virtual void Read( int* mx, int* my );
virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ); virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam );
void UpdateWindowCenter(); void UpdateWindowCenter();
int window_center_x, window_center_y; int window_center_x, window_center_y;
qbool active;
}; };
static winmouse_t winmouse; static winmouse_t winmouse;
@ -197,9 +187,11 @@ void winmouse_t::UpdateWindowCenter()
} }
qbool winmouse_t::Activate(qbool active) qbool winmouse_t::Activate( qbool _active )
{ {
if (!active) active = _active;
if (!_active)
return qtrue; return qtrue;
UpdateWindowCenter(); UpdateWindowCenter();
@ -215,21 +207,23 @@ void winmouse_t::OnWindowMoved()
} }
void winmouse_t::Read( int* mx, int* my )
{
POINT p;
GetCursorPos( &p );
*mx = p.x - window_center_x;
*my = p.y - window_center_y;
SetCursorPos( window_center_x, window_center_y );
}
qbool winmouse_t::ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ) qbool winmouse_t::ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam )
{ {
if ( !active )
return qfalse;
#define QUEUE_WM_BUTTON( qbutton, mask ) \ #define QUEUE_WM_BUTTON( qbutton, mask ) \
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, qbutton, (wParam & mask), 0, NULL ); Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, qbutton, (wParam & mask), 0, NULL );
POINT p;
GetCursorPos( &p );
const int dx = p.x - window_center_x;
const int dy = p.y - window_center_y;
if (dx != 0 || dy != 0) {
Sys_QueEvent( g_wv.sysMsgTime, SE_MOUSE, dx, dy, 0, NULL );
SetCursorPos( window_center_x, window_center_y );
}
switch (msg) { switch (msg) {
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
case WM_LBUTTONUP: case WM_LBUTTONUP:
@ -408,14 +402,6 @@ void IN_Frame()
} }
IN_Activate( qtrue ); IN_Activate( qtrue );
int mx, my;
mouse->Read( &mx, &my );
if ( !mx && !my )
return;
Sys_QueEvent( 0, SE_MOUSE, mx, my, 0, NULL );
} }

View file

@ -63,8 +63,8 @@ typedef struct
qbool isMinimized; qbool isMinimized;
// when we get a windows message, we store the time off // when we get a windows message, we store the time off
// so keyboard processing can know the exact time of an event // using Sys_Milliseconds
unsigned sysMsgTime; int sysMsgTime;
RECT monitorRects[MAX_MONITOR_COUNT]; RECT monitorRects[MAX_MONITOR_COUNT];
HMONITOR hMonitors[MAX_MONITOR_COUNT]; HMONITOR hMonitors[MAX_MONITOR_COUNT];

View file

@ -35,7 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <VersionHelpers.h> #include <VersionHelpers.h>
WinVars_t g_wv; WinVars_t g_wv;
static qbool win_timePeriodActive = qfalse; static qbool win_timePeriodActive = qfalse;
@ -471,7 +471,8 @@ sysEvent_t Sys_GetEvent()
} }
// save the msg time, because wndprocs don't have access to the timestamp // save the msg time, because wndprocs don't have access to the timestamp
g_wv.sysMsgTime = msg.time; // msg.time seems to use values from GetTickCount
g_wv.sysMsgTime = Sys_Milliseconds();
TranslateMessage( &msg ); TranslateMessage( &msg );
DispatchMessage( &msg ); DispatchMessage( &msg );