fix cursor flickering

This commit is contained in:
cxgeorge 2001-10-18 23:17:35 +00:00
parent fa35929f1d
commit c4cb56acff
8 changed files with 194 additions and 67 deletions

View File

@ -70,8 +70,12 @@ Filename get_icon_filename() {
return ExecutionEnvironment::expand_string(iconname);
}
// cant use global var cleanly because global var static init executed after init_libwdxdisplay(), incorrectly reiniting var
Filename get_cursor_filename() {
string cursorname = config_wdxdisplay.GetString("win32-cursor","");
Filename get_color_cursor_filename() {
string cursorname = config_wdxdisplay.GetString("win32-color-cursor","");
return ExecutionEnvironment::expand_string(cursorname);
}
Filename get_mono_cursor_filename() {
string cursorname = config_wdxdisplay.GetString("win32-mono-cursor","");
return ExecutionEnvironment::expand_string(cursorname);
}

View File

@ -28,7 +28,8 @@ NotifyCategoryDecl(wdxdisplay, EXPCL_PANDADX, EXPTP_PANDADX);
extern bool bResponsive_minimized_fullscreen_window;
extern bool dx_force_16bpp_zbuffer;
extern Filename get_icon_filename();
extern Filename get_cursor_filename();
extern Filename get_mono_cursor_filename();
extern Filename get_color_cursor_filename();
extern EXPCL_PANDADX void init_libwdxdisplay();

View File

@ -202,6 +202,9 @@ void wdxGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
}
if(_mwindow!=NULL) {
if(_bLoadedCustomCursor && _hMouseCursor!=NULL)
DestroyCursor(_hMouseCursor);
DestroyWindow(_mwindow);
hwnd_pandawin_map.erase(_mwindow);
_mwindow = NULL;
@ -289,10 +292,17 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if(!DXREADY)
break;
x = LOWORD(lparam);
y = HIWORD(lparam);
if(x & 1 << 15) x -= (1 << 16);
if(y & 1 << 15) y -= (1 << 16);
// Win32 doesn't return the same numbers as X does when the mouse
// goes beyond the upper or left side of the window
#define SET_MOUSE_COORD(iVal,VAL) { \
iVal = VAL; \
if(iVal & 0x8000) \
iVal -= 0x10000; \
}
SET_MOUSE_COORD(x,LOWORD(lparam));
SET_MOUSE_COORD(y,HIWORD(lparam));
if(mouse_motion_enabled()
&& wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
handle_mouse_motion(x, y);
@ -371,12 +381,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if(button < 0)
button = 2;
SetCapture(hwnd);
// Win32 doesn't return the same numbers as X does when the mouse
// goes beyond the upper or left side of the window
x = LOWORD(lparam);
y = HIWORD(lparam);
if(x & 1 << 15) x -= (1 << 16);
if(y & 1 << 15) y -= (1 << 16);
SET_MOUSE_COORD(x,LOWORD(lparam));
SET_MOUSE_COORD(y,HIWORD(lparam));
handle_keypress(MouseButton::button(button), x, y);
return 0;
@ -393,10 +399,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
button = 2;
ReleaseCapture();
#if 0
x = LOWORD(lparam);
y = HIWORD(lparam);
if(x & 1 << 15) x -= (1 << 16);
if(y & 1 << 15) y -= (1 << 16);
SET_MOUSE_COORD(x,LOWORD(lparam));
SET_MOUSE_COORD(y,HIWORD(lparam));
#endif
handle_keyrelease(MouseButton::button(button));
return 0;
@ -876,14 +880,14 @@ void wdxGraphicsWindow::config(void) {
wc.hInstance = hinstance;
string windows_icon_filename = get_icon_filename().to_os_specific();
string windows_cursor_filename = get_cursor_filename().to_os_specific();
string windows_mono_cursor_filename = get_mono_cursor_filename().to_os_specific();
if(!windows_icon_filename.empty()) {
// Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings)
// if icon is more than 8bpp
// loads a .ico fmt file
wc.hIcon = (HICON) LoadImage(NULL, windows_icon_filename.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
wc.hIcon = (HICON) LoadImage(NULL, windows_icon_filename.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE );
if(wc.hIcon==NULL) {
wdxdisplay_cat.warning() << "windows icon filename '" << windows_icon_filename << "' not found!!\n";
@ -892,16 +896,20 @@ void wdxGraphicsWindow::config(void) {
wc.hIcon = NULL; // use default app icon
}
if(!windows_cursor_filename.empty()) {
_bLoadedCustomCursor=false;
if(!windows_mono_cursor_filename.empty()) {
// Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings)
// if icon is more than 8bpp
// loads a .cur fmt file
_hMouseCursor = (HCURSOR) LoadImage(NULL, windows_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
_hMouseCursor = (HCURSOR) LoadImage(NULL, windows_mono_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
if(_hMouseCursor==NULL) {
wdxdisplay_cat.warning() << "windows cursor filename '" << windows_cursor_filename << "' not found!!\n";
wdxdisplay_cat.warning() << "windows cursor filename '" << windows_mono_cursor_filename << "' not found!!\n";
_hMouseCursor = LoadCursor(NULL, IDC_ARROW);
}
_bLoadedCustomCursor=true;
} else {
_hMouseCursor = LoadCursor(NULL, IDC_ARROW);
}
@ -967,12 +975,12 @@ void wdxGraphicsWindow::config(void) {
_mouse_motion_enabled = false;
_mouse_passive_motion_enabled = false;
_mouse_entry_enabled = false;
_entry_state = -1;
// Enable detection of mouse input
enable_mouse_input(true);
enable_mouse_motion(true);
enable_mouse_passive_motion(true);
// enable_mouse_entry(true); re-enable this??
// Now indicate that we have our keyboard/mouse device ready.
GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
@ -1184,6 +1192,63 @@ verify_window_sizes(unsigned int numsizes,unsigned int *dimen) {
return num_valid_modes;
}
// imperfect method to ID NVid? could also scan desc str, but that isnt fullproof either
#define IS_NVIDIA(DDDEVICEID) ((DDDEVICEID.dwVendorId==0x10DE) || (DDDEVICEID.dwVendorId==0x12D2))
#define IS_ATI(DDDEVICEID) (DDDEVICEID.dwVendorId==0x1002)
#define IS_MATROX(DDDEVICEID) (DDDEVICEID.dwVendorId==0x102B)
void wdxGraphicsWindow::
check_for_color_cursor_support(void) {
// card support for non-black/white GDI cursors varies greatly. if the cursor is not supported,
// it is rendered in software by GDI, which causes a flickering effect (because it's not synced
// with flip?). GDI transparently masks what's happening so there is no easy way for app to detect
// if HW cursor support exists. alternatives are to tie cursor motion to frame rate using DDraw blts
// or overlays, or to have separate thread draw cursor (sync issues?). instead we do mono cursor
// unless card is known to support 256 color cursors
string windows_color_cursor_filename = get_color_cursor_filename().to_os_specific();
if(windows_color_cursor_filename.empty())
return;
bool bSupportsColorCursor=false;
if(IS_NVIDIA(_DXDeviceID)) {
// all nvidia seem to support 256 color
bSupportsColorCursor=true;
} else if(IS_ATI(_DXDeviceID)) {
// radeons seem to be in the 5100 range and support color, assume anything in 6000 or above
// is newer than radeon and supports 256 color
if(((_DXDeviceID.dwDeviceId>=0x5100) && (_DXDeviceID.dwDeviceId<=0x5200)) ||
(_DXDeviceID.dwDeviceId>=0x6000))
bSupportsColorCursor=true;
} else if IS_MATROX(_DXDeviceID) {
if(_DXDeviceID.dwDeviceId==0x0525) // G400 seems to support color cursors, havent tested other matrox
bSupportsColorCursor=true;
}
// TODO: add more cards as more testing is done
if(bSupportsColorCursor) {
// Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings)
// if icon is more than 8bpp
// loads a .cur fmt file
HCURSOR hNewMouseCursor = (HCURSOR) LoadImage(NULL, windows_color_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
if(hNewMouseCursor==NULL) {
wdxdisplay_cat.warning() << "windows color cursor filename '" << windows_color_cursor_filename << "' not found!!\n";
return;
}
SetClassLongPtr(_mwindow, GCLP_HCURSOR, (LONG_PTR) hNewMouseCursor);
SetCursor(hNewMouseCursor);
if(_bLoadedCustomCursor)
DestroyCursor(_hMouseCursor);
_hMouseCursor = hNewMouseCursor;
}
}
////////////////////////////////////////////////////////////////////
// Function: dx_setup
// Description: Set up the DirectX environment. The size of the
@ -1243,8 +1308,7 @@ dx_setup() {
wdxdisplay_cat.debug() << " GfxCard: " << _DXDeviceID.szDescription << "; DriverFile: '" << _DXDeviceID.szDriver << "'; VendorID: " <<_DXDeviceID.dwVendorId <<"; DriverVer: " << HIWORD(_DXDeviceID.liDriverVersion.HighPart) << "." << LOWORD(_DXDeviceID.liDriverVersion.HighPart) << "." << HIWORD(_DXDeviceID.liDriverVersion.LowPart) << "." << LOWORD(_DXDeviceID.liDriverVersion.LowPart) << endl;
#endif
// imperfect method to ID NVid, could also scan desc str, but that isnt fullproof either
#define ISNVIDIA(DDDEVICEID) ((DDDEVICEID.dwVendorId==0x10DE) || (DDDEVICEID.dwVendorId==0x12D2))
check_for_color_cursor_support();
// Query DirectDraw for access to Direct3D
@ -1730,7 +1794,7 @@ CreateScreenBuffersAndDevice(DWORD dwRenderWidth, DWORD dwRenderHeight,LPDIRECTD
exit(1);
}
if(ISNVIDIA(_DXDeviceID)) {
if(IS_NVIDIA(_DXDeviceID)) {
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_pri)
pPrimaryDDSurf->GetSurfaceDesc(&ddsd_pri);

View File

@ -94,6 +94,7 @@ protected:
void enable_mouse_motion(bool val);
void enable_mouse_passive_motion(bool val);
void enable_mouse_entry(bool val);
void check_for_color_cursor_support(void);
DDDEVICEIDENTIFIER2 _DXDeviceID;
public:
@ -107,14 +108,13 @@ private:
typedef enum { NotAdjusting,MovingOrResizing,Resizing } WindowAdjustType;
WindowAdjustType _WindowAdjustingType;
bool _bIsLowVidMemCard;
bool _bLoadedCustomCursor;
HCURSOR _hMouseCursor;
bool _bSizeIsMaximized;
bool _mouse_input_enabled;
bool _mouse_motion_enabled;
bool _mouse_passive_motion_enabled;
bool _mouse_entry_enabled;
int _entry_state;
bool _ignore_key_repeat;
bool _exiting_window;
bool _window_inactive;
bool _active_minimized_fullscreen;

View File

@ -78,7 +78,12 @@ Filename get_icon_filename_2() {
return ExecutionEnvironment::expand_string(iconname);
}
Filename get_cursor_filename_2() {
string cursorname = config_wgldisplay.GetString("win32-cursor","");
Filename get_color_cursor_filename_2() {
string cursorname = config_wgldisplay.GetString("win32-color-cursor","");
return ExecutionEnvironment::expand_string(cursorname);
}
Filename get_mono_cursor_filename_2() {
string cursorname = config_wgldisplay.GetString("win32-mono-cursor","");
return ExecutionEnvironment::expand_string(cursorname);
}

View File

@ -28,7 +28,8 @@ NotifyCategoryDecl(wgldisplay, EXPCL_PANDAGL, EXPTP_PANDAGL);
// for some reason there is a conflict with the pandadx versions of get_icon_filename during linking,
// so appended '_2' to name
extern Filename get_icon_filename_2();
extern Filename get_cursor_filename_2();
extern Filename get_color_cursor_filename_2();
extern Filename get_mono_cursor_filename_2();
extern bool gl_show_fps_meter;
extern float gl_fps_meter_update_interval;

View File

@ -21,8 +21,6 @@
#include "config_wgldisplay.h"
#include <keyboardButton.h>
#include <mouseButton.h>
//#include <throw_event.h>
//#include <eventQueue.h>
#include <glGraphicsStateGuardian.h>
#include <errno.h>
#include <time.h>
@ -32,6 +30,8 @@
#include <tchar.h>
#include <map>
#include <throw_event.h>
//#include <eventQueue.h>
#include <string.h>
#define WGL_WGLEXT_PROTOTYPES
#include "wglext.h"
@ -145,6 +145,9 @@ void wglGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
}
if(_mwindow!=NULL) {
if(_bLoadedCustomCursor && _hMouseCursor!=NULL)
DestroyCursor(_hMouseCursor);
DestroyWindow(_mwindow);
hwnd_pandawin_map.erase(_mwindow);
_mwindow = NULL;
@ -327,7 +330,6 @@ void wglGraphicsWindow::config(void) {
_mouse_motion_enabled = false;
_mouse_passive_motion_enabled = false;
_mouse_entry_enabled = false;
_entry_state = -1;
_context = NULL;
_hdc = NULL;
_window_inactive = false;
@ -345,7 +347,7 @@ void wglGraphicsWindow::config(void) {
wc.hInstance = hinstance;
string windows_icon_filename = get_icon_filename_2().to_os_specific();
string windows_cursor_filename = get_cursor_filename_2().to_os_specific();
string windows_mono_cursor_filename = get_mono_cursor_filename_2().to_os_specific();
if(!windows_icon_filename.empty()) {
// Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings)
@ -361,16 +363,18 @@ void wglGraphicsWindow::config(void) {
wc.hIcon = NULL; // use default app icon
}
if(!windows_cursor_filename.empty()) {
_bLoadedCustomCursor = false;
if(!windows_mono_cursor_filename.empty()) {
// Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings)
// if icon is more than 8bpp
// loads a .cur fmt file
_hMouseCursor = (HCURSOR) LoadImage(NULL, windows_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
_hMouseCursor = (HCURSOR) LoadImage(NULL, windows_mono_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
if(_hMouseCursor==NULL) {
wgldisplay_cat.warning() << "windows cursor filename '" << windows_cursor_filename << "' not found!!\n";
wgldisplay_cat.warning() << "windows cursor filename '" << windows_mono_cursor_filename << "' not found!!\n";
}
_bLoadedCustomCursor = true;
} else {
_hMouseCursor = LoadCursor(NULL, IDC_ARROW);
}
@ -546,6 +550,8 @@ void wglGraphicsWindow::config(void) {
make_current();
make_gsg();
check_for_color_cursor_support();
// _glgsg = DCAST(GLGraphicsStateGuardian, _gsg); dont need this now
string tmpstr((char*)glGetString(GL_EXTENSIONS));
@ -613,6 +619,57 @@ void wglGraphicsWindow::config(void) {
}
}
void wglGraphicsWindow::
check_for_color_cursor_support(void) {
// card support for non-black/white GDI cursors varies greatly. if the cursor is not supported,
// it is rendered in software by GDI, which causes a flickering effect (because it's not synced
// with flip?). GDI transparently masks what's happening so there is no easy way for app to detect
// if HW cursor support exists. alternatives are to tie cursor motion to frame rate using DDraw blts
// or overlays, or to have separate thread draw cursor (sync issues?). instead we do mono cursor
// unless card is known to support 256 color cursors
string windows_color_cursor_filename = get_color_cursor_filename_2().to_os_specific();
if(windows_color_cursor_filename.empty())
return;
bool bSupportsColorCursor=false;
const GLubyte *vendorname=glGetString(GL_VENDOR);
if(vendorname==NULL) {
return;
}
char vendorstr[500];
strncpy(vendorstr,(const char *)vendorname,sizeof(vendorstr));
_strlwr(vendorstr);
if(strstr(vendorstr,"nvidia")!=NULL)
bSupportsColorCursor=true;
// for now, just assume only nvidia supports color. need to add more checks for other cards
// like in DX l8r.
if(bSupportsColorCursor) {
// Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings)
// if icon is more than 8bpp
// loads a .cur fmt file
HCURSOR hNewMouseCursor = (HCURSOR) LoadImage(NULL, windows_color_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
if(hNewMouseCursor==NULL) {
wgldisplay_cat.warning() << "windows color cursor filename '" << windows_color_cursor_filename << "' not found!!\n";
return;
}
SetClassLongPtr(_mwindow, GCLP_HCURSOR, (LONG_PTR) hNewMouseCursor);
SetCursor(hNewMouseCursor);
if(_bLoadedCustomCursor)
DestroyCursor(_hMouseCursor);
_hMouseCursor = hNewMouseCursor;
if(wgldisplay_cat.is_spam())
wgldisplay_cat.spam() << "loaded color cursor\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: Constructor
// Access:
@ -1590,18 +1647,22 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
case WM_MBUTTONDOWN:
if (button < 0)
button = 1;
case WM_RBUTTONDOWN:
if (button < 0)
button = 2;
SetCapture(hwnd);
// Win32 doesn't return the same numbers as X does when the mouse
// goes beyond the upper or left side of the window
x = LOWORD(lparam);
y = HIWORD(lparam);
if (x & 1 << 15)
x -= (1 << 16);
if (y & 1 << 15)
y -= (1 << 16);
#define SET_MOUSE_COORD(iVal,VAL) { \
iVal = VAL; \
if(iVal & 0x8000) \
iVal -= 0x10000; \
}
SET_MOUSE_COORD(x,LOWORD(lparam));
SET_MOUSE_COORD(y,HIWORD(lparam));
// make_current(); what does OGL have to do with mouse input??
handle_keypress(MouseButton::button(button), x, y);
break;
@ -1615,24 +1676,17 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
button = 2;
ReleaseCapture();
#if 0
x = LOWORD(lparam);
y = HIWORD(lparam);
if (x & 1 << 15)
x -= (1 << 16);
if (y & 1 << 15)
y -= (1 << 16);
SET_MOUSE_COORD(x,LOWORD(lparam));
SET_MOUSE_COORD(y,HIWORD(lparam));
// make_current(); what does OGL have to do with mouse input??
#endif
handle_keyrelease(MouseButton::button(button));
break;
case WM_MOUSEMOVE:
x = LOWORD(lparam);
y = HIWORD(lparam);
if (x & 1 << 15)
x -= (1 << 16);
if (y & 1 << 15)
y -= (1 << 16);
SET_MOUSE_COORD(x,LOWORD(lparam));
SET_MOUSE_COORD(y,HIWORD(lparam));
if (mouse_motion_enabled() &&
(wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) {
// make_current(); what does OGL have to do with mouse input??

View File

@ -118,6 +118,7 @@ private:
DEVMODE *_pCurrent_display_settings;
bool _bIsLowVidMemCard;
bool _bLoadedCustomCursor;
bool _window_inactive;
bool _active_minimized_fullscreen;
@ -128,10 +129,6 @@ private:
bool _mouse_motion_enabled;
bool _mouse_passive_motion_enabled;
bool _mouse_entry_enabled;
int _entry_state;
bool _ignore_key_repeat;
int _full_height, _full_width;
// vars for frames/sec meter
DWORD _start_time;
@ -157,13 +154,14 @@ public:
virtual unsigned int verify_window_sizes(unsigned int numsizes,unsigned int *dimen);
protected:
virtual void do_close_window();
virtual void do_close_window(void);
void check_for_color_cursor_support(void);
private:
static TypeHandle _type_handle;
};
extern void set_global_parameters();
extern void restore_global_parameters();
extern void set_global_parameters(void);
extern void restore_global_parameters(void);
#endif