diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx index 89cd07028d..8cf7e20067 100644 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ b/panda/src/dxgsg8/config_dxgsg8.cxx @@ -51,6 +51,15 @@ bool dx_cull_traversal = config_dxgsg.GetBool("dx-cull-traversal", true); // if true, if card only supports per-vertex fog, it will be treated as no-HW fog capability bool dx_no_vertex_fog = config_dxgsg.GetBool("dx-no-vertex-fog", false); +// if true, overwrite cursor bitmap tip with "D3D" to distinguish it from GDI cursor +bool dx_show_cursor_watermark = config_dxgsg.GetBool("dx-show-cursor-watermark", +#ifdef _DEBUG + true +#else + false +#endif + ); + // if true, triangle filter will be used to generate mipmap levels instead of default box filter bool dx_use_triangle_mipgen_filter = config_dxgsg.GetBool("dx-use-triangle-mipgen-filter", false); diff --git a/panda/src/dxgsg8/config_dxgsg8.h b/panda/src/dxgsg8/config_dxgsg8.h index f0d69d2928..d17d1e1ffa 100644 --- a/panda/src/dxgsg8/config_dxgsg8.h +++ b/panda/src/dxgsg8/config_dxgsg8.h @@ -30,6 +30,7 @@ extern bool dx_sync_video; extern bool dx_cull_traversal; extern bool dx_show_fps_meter; extern bool dx_no_vertex_fog; +extern bool dx_show_cursor_watermark; extern bool dx_full_screen_antialiasing; extern float dx_fps_meter_update_interval; extern bool dx_auto_normalize_lighting; diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index c7549feebc..9728bdccfb 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -848,7 +848,7 @@ dx_init(HCURSOR hMouseCursor) { // must check (scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon85, no on TNT) scrn.pD3DDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD); - hr = CreateDX8Cursor(scrn.pD3DDevice,hMouseCursor,true); + hr = CreateDX8Cursor(scrn.pD3DDevice,hMouseCursor,dx_show_cursor_watermark); if(FAILED(hr)) dxgsg_cat.error() << "CreateDX8Cursor failed!\n"; @@ -5254,7 +5254,8 @@ end_decal(GeomNode *base_geom) { // properly. // need to save the state we change on the stack, since we could get called - // recursively by the draw() method + // recursively by the draw() method, and the draw method could change any of + // the state below D3DBLEND saved_blend_source_func = _blend_source_func; D3DBLEND saved_blend_dest_func = _blend_dest_func; UINT saved_colorwritemask = _color_writemask; @@ -5271,7 +5272,6 @@ end_decal(GeomNode *base_geom) { enable_blend(true); call_dxBlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE); } else { - // note: not saving current colorwriteenable val, assumes this is always all 1's. bugbug is this OK? set_color_writemask(0x0); } diff --git a/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx b/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx index 4e0910da64..d44f4da31f 100644 --- a/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx +++ b/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx @@ -53,8 +53,6 @@ wdxGraphicsWindow* global_wdxwinptr = NULL; // need this for temporary windproc #define MAX_DISPLAYS 20 -extern bool dx_full_screen_antialiasing; // defined in dxgsg_config.cxx - #define PAUSED_TIMER_ID 7 // completely arbitrary choice #define DXREADY ((_dxgsg!=NULL)&&(_dxgsg->GetDXReady())) @@ -493,7 +491,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } #endif // old comment -- added SIZE_RESTORED to handle 3dfx case - if(dx_full_screen || ((_dxgsg==NULL) || (_dxgsg->scrn.hWnd==NULL)) || ((wparam != SIZE_RESTORED) && (wparam != SIZE_MAXIMIZED))) + if(_props._fullscreen || ((_dxgsg==NULL) || (_dxgsg->scrn.hWnd==NULL)) || ((wparam != SIZE_RESTORED) && (wparam != SIZE_MAXIMIZED))) break; width = LOWORD(lparam); height = HIWORD(lparam); @@ -645,7 +643,7 @@ void wdxGraphicsWindow::handle_windowed_resize(HWND hWnd,bool bDoDxReset) { // handles windowed, non-fullscreen resizing GdiFlush(); - assert(!dx_full_screen); + assert(!_props._fullscreen); if(bDoDxReset && (_dxgsg!=NULL)) { if(_dxgsg->scrn.pD3DDevice==NULL) { @@ -1172,8 +1170,8 @@ void wdxGraphicsWindow::config_window(wdxGraphicsWindowGroup *pParentGroup) { _return_control_to_app = false; _active_minimized_fullscreen = false; - if(dx_full_screen || _props._fullscreen) { - _props._fullscreen = dx_full_screen = true; + if(_props._fullscreen || _props._fullscreen) { + _props._fullscreen = _props._fullscreen = true; } _WindowAdjustingType = NotAdjusting; @@ -1525,7 +1523,7 @@ check_for_color_cursor_support(void) { DWORD load_flags = LR_LOADFROMFILE; - if(dx_full_screen) { + if(_props._fullscreen) { // I think cursors should use LR_CREATEDIBSECTION since they should not be mapped to the device palette (in the case of 256-color cursors) // since they are not going to be used on the desktop load_flags |= LR_CREATEDIBSECTION; @@ -1563,22 +1561,24 @@ int D3DFMT_to_DepthBits(D3DFORMAT fmt) { } } -bool wdxGraphicsWindow::FindBestDepthFormat(DXScreenData &Display,D3DFORMAT *pBestFmt,bool bWantStencil) { +bool wdxGraphicsWindow::FindBestDepthFormat(DXScreenData &Display,D3DDISPLAYMODE &TestDisplayMode,D3DFORMAT *pBestFmt,bool bWantStencil) const { // list fmts in order of preference #define NUM_TEST_ZFMTS 3 static D3DFORMAT NoStencilPrefList[NUM_TEST_ZFMTS]={D3DFMT_D32,D3DFMT_D24X8,D3DFMT_D16}; static D3DFORMAT StencilPrefList[NUM_TEST_ZFMTS]={D3DFMT_D24S8,D3DFMT_D24X4S4,D3DFMT_D15S1}; + + // do not use Display.DisplayMode since that is probably not set yet, use TestDisplayMode instead - // int want_depth_bits = _props._want_depth_bits; should we pay attn to these at some point? // int want_color_bits = _props._want_color_bits; + // int want_depth_bits = _props._want_depth_bits; should we pay attn to these so panda user can select bitdepth? *pBestFmt = D3DFMT_UNKNOWN; HRESULT hr; // nvidia likes zbuf depth to match rendertarget depth bool bOnlySelect16bpp= (dx_force_16bpp_zbuffer || - (IS_NVIDIA(Display.DXDeviceID) && ((Display.DisplayMode.Format==D3DFMT_X1R5G5B5) || - (Display.DisplayMode.Format==D3DFMT_R5G6B5)))); + (IS_NVIDIA(Display.DXDeviceID) && ((TestDisplayMode.Format==D3DFMT_X1R5G5B5) || + (TestDisplayMode.Format==D3DFMT_R5G6B5)))); for(int i=0;iCheckDeviceFormat(Display.CardIDNum,D3DDEVTYPE_HAL,Display.DisplayMode.Format, + hr = Display.pD3D8->CheckDeviceFormat(Display.CardIDNum,D3DDEVTYPE_HAL,TestDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,TestDepthFmt); - if(FAILED(hr)) - continue; - + if(FAILED(hr)) { + if(hr==D3DERR_NOTAVAILABLE) + continue; + + wdxdisplay_cat.error() << "unexpected CheckDeviceFormat failure, hr=" << D3DERRORSTRING(hr); + exit(1); + } + hr = Display.pD3D8->CheckDepthStencilMatch(Display.CardIDNum,D3DDEVTYPE_HAL, - Display.DisplayMode.Format, // adapter format - Display.DisplayMode.Format, // backbuffer fmt (should be the same in my apps) - TestDepthFmt); - if(!FAILED(hr)) { + TestDisplayMode.Format, // adapter format + TestDisplayMode.Format, // backbuffer fmt (should be the same in my apps) + TestDepthFmt); + + if(FAILED(hr) && (hr!=D3DERR_NOTAVAILABLE)) { + wdxdisplay_cat.error() << "unexpected CheckDepthStencilMatch failure, hr=" << D3DERRORSTRING(hr); + exit(1); + } + + if(SUCCEEDED(hr)) { *pBestFmt = TestDepthFmt; break; } @@ -1614,6 +1625,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn assert(_dxgsg!=NULL); _dxgsg->scrn.pD3D8 = pD3D8; + _dxgsg->scrn.CardIDNum=pDevInfo->cardID; // could this change by end? bool bWantStencil = ((_props._mask & W_STENCIL)!=0); @@ -1626,7 +1638,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn hr = pD3D8->GetDeviceCaps(pDevInfo->cardID,D3DDEVTYPE_HAL,&d3dcaps); if(FAILED(hr)) { if(hr==D3DERR_INVALIDDEVICE) { - wdxdisplay_cat.fatal() << "No D3D-capable 3D hardware detected! Exiting...\n"; + wdxdisplay_cat.fatal() << "No DirectX 8 D3D-capable 3D hardware detected! Exiting...\n"; } else { wdxdisplay_cat.fatal() << "GetDeviceCaps failed, hr = " << D3DERRORSTRING(hr); } @@ -1634,7 +1646,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn } if(d3dcaps.MaxStreams==0) { - wdxdisplay_cat.info() << "Warning: video driver predates DX8\n"; + wdxdisplay_cat.info() << "Warning: video driver is a pre-DX8-class driver\n"; } if(bWantStencil & (d3dcaps.StencilCaps==0x0)) { @@ -1671,6 +1683,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn _dxgsg->scrn.bIsTNLDevice=((d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)!=0); +#ifdef DO_LOWVIDMEM_CHKS // only way to get vidmem estimate prior to device creation and displaymode changing on DX8 is to use DX7 ddraw LPDIRECTDRAW7 pDD; @@ -1710,6 +1723,12 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn // assume buggy drivers (this means you, FireGL2) may return zero for dwVidMemTotal, so ignore value if its < CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD _dxgsg->scrn.bIsLowVidMemCard = ((dwVidMemTotal>CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) && (dwVidMemTotal< LOWVIDMEMTHRESHOLD)); +#else + _dxgsg->scrn.bIsLowVidMemCard = false; + _dxgsg->scrn.MaxAvailVidMem = 350000000; +#endif + + bool bNeedZBuffer = ((!(d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) && (_props._mask & W_DEPTH)); @@ -1752,7 +1771,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn if(bNeedZBuffer) { D3DFORMAT junk; - if(!FindBestDepthFormat(_dxgsg->scrn,&junk,bWantStencil)) { + if(!FindBestDepthFormat(_dxgsg->scrn,dispmode,&junk,bWantStencil)) { bCouldntFindValidZBuf=true; continue; } @@ -1808,6 +1827,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn return false; } + #ifdef DO_LOWVIDMEM_CHKS if(_dxgsg->scrn.bIsLowVidMemCard) { // hack: figuring out exactly what res to use is tricky, instead I will // just use 640x480 if we have < 3 meg avail @@ -1828,6 +1848,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn if(wdxdisplay_cat.is_info()) wdxdisplay_cat.info() << "Available VidMem (" << dwVidMemFree<<") is under " << LOWVIDMEMTHRESHOLD <<", using 640x480 16bpp rendertargets to save tex vidmem.\n"; } + #endif } else { D3DDISPLAYMODE dispmode; hr=pD3D8->GetAdapterDisplayMode(pDevInfo->cardID,&dispmode); @@ -1844,6 +1865,7 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevIn _dxgsg->scrn.DisplayMode.RefreshRate = D3DPRESENT_RATE_DEFAULT; _dxgsg->scrn.hMon=pDevInfo->hMon; _dxgsg->scrn.CardIDNum=pDevInfo->cardID; + _dxgsg->scrn.d3dcaps=d3dcaps; return true; } @@ -1860,7 +1882,7 @@ SetCoopLevelsAndDisplayModes(void) { DXScreenData *pScrn=&_windows[0]->_dxgsg->scrn; // All SetCoopLevels must use the parent window - if(!dx_full_screen) { + if(!_props._fullscreen) { if(FAILED(hr = pScrn->pDD->SetCooperativeLevel(_hParentWindow, SCL_FPUFlag | DDSCL_NORMAL))) { wdxdisplay_cat.fatal() << "SetCooperativeLevel failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); @@ -2004,13 +2026,13 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { } if(FAILED(pD3D8->CheckDeviceType(Display.CardIDNum,D3DDEVTYPE_HAL, Display.DisplayMode.Format,pPresParams->BackBufferFormat, - dx_full_screen))) { + _props._fullscreen))) { wdxdisplay_cat.error() << "device #"<BackBufferFormat) << endl; goto Fallback_to_16bpp_buffers; } if(Display.PresParams.EnableAutoDepthStencil) { - if(!FindBestDepthFormat(Display,&Display.PresParams.AutoDepthStencilFormat,bWantStencil)) { + if(!FindBestDepthFormat(Display,Display.DisplayMode,&Display.PresParams.AutoDepthStencilFormat,bWantStencil)) { wdxdisplay_cat.error() << "FindBestDepthFormat failed in CreateScreenBuffers for device #"<Windowed = _props._fullscreen; + pPresParams->Windowed = !_props._fullscreen; DWORD dwBehaviorFlags=0x0; if(dx_multisample_antialiasing_level>1) { @@ -2065,7 +2087,7 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { if(dx_preserve_fpu_state) dwBehaviorFlags|=D3DCREATE_FPU_PRESERVE; - if(dx_full_screen) { + if(_props._fullscreen) { pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD; // we dont care about preserving contents of old frame pPresParams->FullScreen_PresentationInterval = (dx_sync_video ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE); pPresParams->FullScreen_RefreshRateInHz = Display.DisplayMode.RefreshRate; @@ -2125,7 +2147,7 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { exit(1); } - pPresParams->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; // I believe this irrelevant for windowed mode, but whatever + pPresParams->FullScreen_PresentationInterval = 0; if(dx_multisample_antialiasing_level<2) { if(dx_sync_video) { diff --git a/panda/src/wdxdisplay8/wdxGraphicsWindow8.h b/panda/src/wdxdisplay8/wdxGraphicsWindow8.h index 48ebdc0c4f..dc789897af 100644 --- a/panda/src/wdxdisplay8/wdxGraphicsWindow8.h +++ b/panda/src/wdxdisplay8/wdxGraphicsWindow8.h @@ -91,7 +91,7 @@ protected: void config_window(wdxGraphicsWindowGroup *pParentGroup); void finish_window_setup(void); bool search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevinfo); - bool wdxGraphicsWindow::FindBestDepthFormat(DXScreenData &Display,D3DFORMAT *pBestFmt,bool bWantStencil); + bool FindBestDepthFormat(DXScreenData &Display,D3DDISPLAYMODE &TestDisplayMode,D3DFORMAT *pBestFmt,bool bWantStencil) const; void setup_colormap(void); INLINE void track_mouse_leaving(HWND hwnd);