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: reduced raw mouse input latency and added cl_drawMouseLag
Linux:

View file

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

View file

@ -105,6 +105,7 @@ typedef struct {
int mouseDx[2], mouseDy[2]; // added to by mouse events
int mouseIndex;
int mouseTime; // when the last mouse input was sampled, for cl_drawMouseLag
int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events
// 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
int cmdNumber; // incremented each frame, because multiple
// 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

View file

@ -708,7 +708,7 @@ int Com_HashKey(char *string, int maxlen);
int Com_Filter( const char* filter, const char* name );
int Com_FilterPath( const char* filter, const char* name );
int Com_RealTime(qtime_t *qtime);
qbool Com_SafeMode();
qbool Com_SafeMode();
void Com_StartupVariable( const char *match );
// 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
void R_RenderView( const viewParms_t* parms )
@ -1289,6 +1292,7 @@ void R_RenderView( const viewParms_t* parms )
int firstLitSurf = tr.refdef.numLitSurfs;
// set viewParms.world
re_cameraMatrixTime = Sys_Milliseconds();
R_RotateForViewer();
R_SetupFrustum();

View file

@ -158,8 +158,6 @@ typedef struct {
qbool (*inPVS)( const vec3_t p1, const vec3_t p2 );
void (*TakeVideoFrame)( int h, int w, byte* captureBuffer, byte *encodeBuffer, qbool motionJpeg );
// drakkar
void (*WindowFocus)(qbool focus);
} refexport_t;
//
@ -223,4 +221,8 @@ typedef struct {
// if the module can't init to a valid rendering state, it will return NULL
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

View file

@ -29,7 +29,6 @@ struct Mouse {
virtual qbool Activate( qbool active );
virtual void OnWindowMoved() {}
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
Mouse() : active(qfalse), wheel(0) {}
@ -78,10 +77,7 @@ void Mouse::UpdateWheel( int delta )
struct rawmouse_t : public Mouse {
virtual qbool Init();
virtual qbool Activate( qbool active );
virtual void Read( int* mx, int* my );
virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam );
int x, y;
};
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
// 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) )
return qfalse;
rawmouse.x += ri.data.mouse.lLastX;
rawmouse.y += ri.data.mouse.lLastY;
const int dx = (int)ri.data.mouse.lLastX;
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
return qfalse;
@ -173,12 +163,12 @@ qbool rawmouse_t::ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam )
struct winmouse_t : public Mouse {
virtual qbool Activate( qbool active );
virtual void OnWindowMoved();
virtual void Read( int* mx, int* my );
virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam );
void UpdateWindowCenter();
int window_center_x, window_center_y;
qbool active;
};
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;
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 )
{
if ( !active )
return qfalse;
#define QUEUE_WM_BUTTON( qbutton, mask ) \
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) {
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
@ -408,14 +402,6 @@ void IN_Frame()
}
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;
// when we get a windows message, we store the time off
// so keyboard processing can know the exact time of an event
unsigned sysMsgTime;
// using Sys_Milliseconds
int sysMsgTime;
RECT monitorRects[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>
WinVars_t g_wv;
WinVars_t g_wv;
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
g_wv.sysMsgTime = msg.time;
// msg.time seems to use values from GetTickCount
g_wv.sysMsgTime = Sys_Milliseconds();
TranslateMessage( &msg );
DispatchMessage( &msg );