From 99bdb6641d3c66d6db764dee0f25b19fd7e3a4a9 Mon Sep 17 00:00:00 2001 From: cxgeorge <> Date: Wed, 18 Jul 2001 04:49:29 +0000 Subject: [PATCH] make window handling more robust --- panda/src/dxgsg/dxGraphicsStateGuardian.I | 2 +- panda/src/dxgsg/dxGraphicsStateGuardian.cxx | 105 +++++++++++++++----- panda/src/dxgsg/dxGraphicsStateGuardian.h | 6 +- 3 files changed, 83 insertions(+), 30 deletions(-) diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.I b/panda/src/dxgsg/dxGraphicsStateGuardian.I index 5189d650f5..68abe5bfc9 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.I +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.I @@ -114,7 +114,7 @@ enable_dither(bool val) { if (_dither_enabled != val) { _dither_enabled = val; - #ifdef NDEBUG + #ifdef _DEBUG { if(val && (_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)) dxgsg_cat.error() << "no HW support for color dithering!!\n"; diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx index 8d4d487256..0ccd49c1cf 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx @@ -412,15 +412,16 @@ init_dx( LPDIRECTDRAW7 context, SetRect(&clip_rect, 0,0,0,0); // no clip rect set - _d3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); - // Lighting, let's turn it off by default _lighting_enabled = true; enable_lighting(false); - // Dither, let's turn it off - _dither_enabled = true; - enable_dither(false); + // turn on dithering if the rendertarget is < 8bits/color channel + DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_back); + _back->GetSurfaceDesc(&ddsd_back); + _dither_enabled = ((ddsd_back.ddpfPixelFormat.dwRGBBitCount < 24) && + (_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)); + _d3dDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, _dither_enabled); // Stencil test is off by default _stencil_test_enabled = false; @@ -431,6 +432,8 @@ init_dx( LPDIRECTDRAW7 context, enable_line_smooth(false); // enable_multisample(true); + _d3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); + // technically DX7's front-end has no limit on the number of lights, but it's simpler for // this implementation to set a small GL-like limit to make the light array traversals short // and so I dont have to write code that reallocs light arrays @@ -449,6 +452,9 @@ init_dx( LPDIRECTDRAW7 context, _light_enabled[i] = false; } + if(dx_auto_normalize_lighting) + _d3dDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true); + // Set up the clip plane id map _max_clip_planes = D3DMAXUSERCLIPPLANES; _available_clip_plane_ids = PTA(PlaneNode*)(_max_clip_planes); @@ -511,9 +517,11 @@ init_dx( LPDIRECTDRAW7 context, if(dx_full_screen_antialiasing) { if(_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT) { _d3dDevice->SetRenderState(D3DRENDERSTATE_ANTIALIAS,D3DANTIALIAS_SORTINDEPENDENT); - dxgsg_cat.debug() << "enabling full-screen anti-aliasing\n"; + if(dxgsg_cat.is_debug()) + dxgsg_cat.debug() << "enabling full-screen anti-aliasing\n"; } else { - dxgsg_cat.debug() << "device doesnt support full-screen anti-aliasing\n"; + if(dxgsg_cat.is_debug()) + dxgsg_cat.debug() << "device doesnt support full-screen anti-aliasing\n"; } } @@ -524,13 +532,12 @@ init_dx( LPDIRECTDRAW7 context, _d3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling); } else { dx_force_backface_culling=0; - dxgsg_cat.debug() << "error, invalid value for dx-force-backface-culling\n"; + if(dxgsg_cat.is_debug()) + dxgsg_cat.debug() << "error, invalid value for dx-force-backface-culling\n"; } } #endif - if(dx_auto_normalize_lighting) - _d3dDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true); } //////////////////////////////////////////////////////////////////// @@ -1728,6 +1735,19 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { D3DMATRIX OldD3DWorldMatrix; _d3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &OldD3DWorldMatrix); + // ATI sez: most applications ignore the fact that since alpha blended primitives + // combine the data in the frame buffer with the data in the current pixel, pixels + // can be dithered multiple times and accentuate the dither pattern. This is particularly + // true in particle systems which rely on the cumulative visual effect of many overlapping + // alpha blended primitives. + + bool bReEnableDither=_dither_enabled; + if(bReEnableDither) { + enable_dither(false); + } + + _d3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &OldD3DWorldMatrix); + Geom::VertexIterator vi = geom->make_vertex_iterator(); Geom::ColorIterator ci = geom->make_color_iterator(); @@ -2018,6 +2038,9 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { // restore the matrices _d3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &OldD3DWorldMatrix); + + if(bReEnableDither) + enable_dither(true); } //////////////////////////////////////////////////////////////////// @@ -5358,33 +5381,59 @@ void DXGraphicsStateGuardian::init_type(void) { // Description: Clean up the DirectX environment. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -dx_cleanup() { +dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) { release_all_textures(); release_all_geoms(); - // Do a safe check for releasing the D3DDEVICE. RefCount should be zero. - if (_d3dDevice!=NULL) { - if (0 < _d3dDevice->Release()) { - dxgsg_cat.error() << "DXGraphicsStateGuardian::destructor - d3dDevice reference count > 0" << endl; + ULONG refcnt; + + // unsafe to do the D3D releases after exit() called, since DLL_PROCESS_DETACH + // msg already delivered to d3d.dll and it's unloaded itself + if(!bAtExitFnCalled) { + // Do a safe check for releasing the D3DDEVICE. RefCount should be zero. + // if we're called from exit(), _d3dDevice may already have been released + if (_d3dDevice!=NULL) { + if (0 < (refcnt = _d3dDevice->Release())) { + dxgsg_cat.error() << "dx_cleanup - d3dDevice reference count = " << refcnt << ", should be zero!\n"; + } } + _d3dDevice = NULL; // clear the pointer in the Gsg + + // Release the DDraw and D3D objects used by the app + RELEASE(_zbuf); + RELEASE(_back); + RELEASE(_pri); + + RELEASE(_d3d); } - // Release the DDraw and D3D objects used by the app - RELEASE(_zbuf); - RELEASE(_back); - RELEASE(_pri); - - RELEASE(_d3d); + // for some reason, DLL_PROCESS_DETACH has not yet been sent to ddraw, so we can still call its fns // Do a safe check for releasing DDRAW. RefCount should be zero. if (_pDD!=NULL) { - int val; - if (0 < (val = _pDD->Release())) { - dxgsg_cat.error() - << "DXGraphicsStateGuardian::destructor - IDDraw Obj reference count = " << val << ", should be zero!\n"; + if(bRestoreDisplayMode) { + HRESULT hr = _pDD->RestoreDisplayMode(); + if(dxgsg_cat.is_spam()) + dxgsg_cat.spam() << "dx_cleanup - Restoring original desktop DisplayMode\n"; + if(FAILED(hr)) { + dxgsg_cat.error() << "dx_cleanup - RestoreDisplayMode failed, hr = " << ConvD3DErrorToString(hr) << endl; + } } + + refcnt = _pDD->Release(); + + if(bAtExitFnCalled) { + // refcnt may be > 1 + while (refcnt>0) { + refcnt = _pDD->Release(); + } + } else { + if(refcnt>0) + dxgsg_cat.error() << "dx_cleanup - IDDraw Obj reference count = " << refcnt << ", should be zero!\n"; + } + _pDD = NULL; } } @@ -5591,13 +5640,15 @@ void DXGraphicsStateGuardian::show_full_screen_frame(void) { // This means that mode changes had taken place, surfaces // were lost but still we are in the original mode, so we // simply restore all surfaces and keep going. - _dx_ready = FALSE; #ifdef _DEBUG - if(dxgsg_cat.is_spam()) + if(dxgsg_cat.is_spam() && _dx_ready) { dxgsg_cat.spam() << "DXGraphicsStateGuardian:: no exclusive mode, waiting...\n"; + } #endif + _dx_ready = FALSE; + Sleep( 500 ); // Dont consume CPU. throw_event("PandaPaused"); // throw panda event to invoke network-only processing diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.h b/panda/src/dxgsg/dxGraphicsStateGuardian.h index 6696aaa1fa..41c687bbb7 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.h +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.h @@ -65,7 +65,7 @@ INLINE ostream &operator << (ostream &out, GLenum v) { ZeroMemory(&var, sizeof(type)); \ var.dwSize = sizeof(type); -#define RELEASE(object) if (object!=NULL) {object->Release(); object = NULL;} +#define RELEASE(OBJECT) if(((OBJECT)!=NULL)&&(!IsBadWritePtr((OBJECT),4))) {(OBJECT)->Release(); (OBJECT) = NULL;} #if defined(NOTIFY_DEBUG) || defined(DO_PSTATS) // This function now serves both to print a debug message to the @@ -412,7 +412,8 @@ public: INLINE bool GetDXReady(void) { return _dx_ready;} void DXGraphicsStateGuardian::SetTextureBlendMode(TextureApplyProperty::Mode TexBlendMode,bool bJustEnable); - void dx_cleanup(); + void dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled); + void dx_setup_after_resize(RECT viewrect,HWND mwindow) ; void show_frame(); void show_full_screen_frame(); @@ -425,6 +426,7 @@ public: LPDIRECT3DDEVICE7 d3dDevice, RECT viewrect); friend HRESULT CALLBACK EnumTexFmtsCallback( LPDDPIXELFORMAT pddpf, VOID* param ); + private: static TypeHandle _type_handle; };