From 554430ab21afc691f4fb2f32ab5ef616093e04d7 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 26 Apr 2007 23:53:54 +0000 Subject: [PATCH] more fullscreen fixes --- panda/src/display/graphicsStateGuardian.cxx | 36 ++++++++++++------- panda/src/display/standardMunger.I | 2 +- panda/src/display/standardMunger.cxx | 20 +++++------ panda/src/display/standardMunger.h | 1 - panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 36 ++++++++++++++----- panda/src/dxgsg9/wdxGraphicsWindow9.cxx | 21 ++++++----- panda/src/gobj/geomMunger.I | 22 ++++++++++++ panda/src/gobj/geomMunger.cxx | 34 ++++++++++++++++-- panda/src/gobj/geomMunger.h | 8 ++++- panda/src/pgraph/stateMunger.I | 11 ++++++ panda/src/pgraph/stateMunger.h | 1 + panda/src/windisplay/winGraphicsWindow.cxx | 8 ++--- 12 files changed, 150 insertions(+), 50 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 6fe922cc53..aa16e2209c 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -39,6 +39,7 @@ #include "displayRegion.h" #include "graphicsOutput.h" #include "texturePool.h" +#include "geomMunger.h" #include #include @@ -192,6 +193,8 @@ GraphicsStateGuardian:: delete _stencil_render_states; _stencil_render_states = 0; } + + GeomMunger::unregister_mungers_for_gsg(this); } //////////////////////////////////////////////////////////////////// @@ -614,31 +617,40 @@ end_occlusion_query() { //////////////////////////////////////////////////////////////////// PT(GeomMunger) GraphicsStateGuardian:: get_geom_munger(const RenderState *state, Thread *current_thread) { + // We can cast the RenderState to a non-const object because we are + // only updating a cache within the RenderState, not really changing + // any of its properties. + RenderState *nc_state = ((RenderState *)state); + // Before we even look up the map, see if the _last_mi value points // to this GSG. This is likely because we tend to visit the same // state multiple times during a frame. Also, this might well be // the only GSG in the world anyway. - if (!state->_mungers.empty()) { - RenderState::Mungers::const_iterator mi = state->_last_mi; + if (!nc_state->_mungers.empty()) { + RenderState::Mungers::const_iterator mi = nc_state->_last_mi; if (!(*mi).first.was_deleted() && (*mi).first == this) { - return (*mi).second; + if ((*mi).second->is_registered()) { + return (*mi).second; + } } } // Nope, we have to look it up in the map. - RenderState::Mungers::const_iterator mi = state->_mungers.find(this); - if (mi != state->_mungers.end() && !(*mi).first.was_deleted()) { - ((RenderState *)state)->_last_mi = mi; - return (*mi).second; + RenderState::Mungers::iterator mi = nc_state->_mungers.find(this); + if (mi != nc_state->_mungers.end() && !(*mi).first.was_deleted()) { + if ((*mi).second->is_registered()) { + nc_state->_last_mi = mi; + return (*mi).second; + } + // This GeomMunger is no longer registered. Remove it from the + // map. + nc_state->_mungers.erase(mi); } // Nothing in the map; create a new entry. - PT(GeomMunger) munger = make_geom_munger(state, current_thread); + PT(GeomMunger) munger = make_geom_munger(nc_state, current_thread); + nassertr(munger->is_registered(), munger); - // Cast the RenderState to a non-const object. We can do this - // because we are only updating a cache within the RenderState, not - // really changing any of its properties. - RenderState *nc_state = (RenderState *)state; mi = nc_state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first; nc_state->_last_mi = mi; diff --git a/panda/src/display/standardMunger.I b/panda/src/display/standardMunger.I index 1a74e83b8b..b7da6f8b60 100644 --- a/panda/src/display/standardMunger.I +++ b/panda/src/display/standardMunger.I @@ -25,5 +25,5 @@ //////////////////////////////////////////////////////////////////// INLINE GraphicsStateGuardian *StandardMunger:: get_gsg() const { - return _gsg; + return (GraphicsStateGuardian *)GeomMunger::get_gsg(); } diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index 42635a2061..82f11c3516 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -38,11 +38,11 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, int num_components, StandardMunger::NumericType numeric_type, StandardMunger::Contents contents) : + StateMunger(gsg), _num_components(num_components), _numeric_type(numeric_type), _contents(contents) { - _gsg = DCAST(GraphicsStateGuardian, gsg); _render_mode = state->get_render_mode(); _munge_color = false; @@ -54,7 +54,7 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, if (color_attrib != (ColorAttrib *)NULL && color_attrib->get_color_type() == ColorAttrib::T_flat) { - if (!_gsg->get_color_scale_via_lighting()) { + if (!get_gsg()->get_color_scale_via_lighting()) { // We only need to munge the color directly if the GSG says it // can't cheat the color via lighting (presumably, in this case, // by applying a material). @@ -78,8 +78,8 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, // If the GSG says it can't cheat this RGB or alpha scale, we have // to apply the color scale directly. - if ((color_scale_attrib->has_rgb_scale() && !_gsg->get_color_scale_via_lighting()) || - (color_scale_attrib->has_alpha_scale() && !_gsg->get_alpha_scale_via_texture(tex_attrib))) { + if ((color_scale_attrib->has_rgb_scale() && !get_gsg()->get_color_scale_via_lighting()) || + (color_scale_attrib->has_alpha_scale() && !get_gsg()->get_alpha_scale_via_texture(tex_attrib))) { _munge_color_scale = true; } @@ -127,9 +127,9 @@ munge_data_impl(const GeomVertexData *data) { if (table != (TransformBlendTable *)NULL && table->get_num_transforms() != 0 && table->get_max_simultaneous_transforms() <= - _gsg->get_max_vertex_transforms()) { + get_gsg()->get_max_vertex_transforms()) { if (matrix_palette && - table->get_num_transforms() <= _gsg->get_max_vertex_transform_indices()) { + table->get_num_transforms() <= get_gsg()->get_max_vertex_transform_indices()) { if (table->get_num_transforms() == table->get_max_simultaneous_transforms()) { // We can support an indexed palette, but since that won't @@ -145,7 +145,7 @@ munge_data_impl(const GeomVertexData *data) { } } else if (table->get_num_transforms() <= - _gsg->get_max_vertex_transforms()) { + get_gsg()->get_max_vertex_transforms()) { // We can't support an indexed palette, but we have few enough // transforms that we can do a nonindexed table. animation.set_hardware(table->get_num_transforms(), false); @@ -172,7 +172,7 @@ munge_data_impl(const GeomVertexData *data) { bool StandardMunger:: munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data, Thread *current_thread) { - int supported_geom_rendering = _gsg->get_supported_geom_rendering(); + int supported_geom_rendering = get_gsg()->get_supported_geom_rendering(); int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering; if (unsupported_bits != 0) { @@ -225,10 +225,6 @@ int StandardMunger:: compare_to_impl(const GeomMunger *other) const { const StandardMunger *om = DCAST(StandardMunger, other); - if (_gsg != om->_gsg) { - return _gsg < om->_gsg ? -1 : 1; - } - if (_render_mode != om->_render_mode) { return _render_mode < om->_render_mode ? -1 : 1; } diff --git a/panda/src/display/standardMunger.h b/panda/src/display/standardMunger.h index 69029476ef..95235cc68b 100644 --- a/panda/src/display/standardMunger.h +++ b/panda/src/display/standardMunger.h @@ -56,7 +56,6 @@ private: int _num_components; NumericType _numeric_type; Contents _contents; - WPT(GraphicsStateGuardian) _gsg; CPT(RenderModeAttrib) _render_mode; bool _munge_color; diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 8449fd7d05..e0c39b1c80 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -159,6 +159,9 @@ DXGraphicsStateGuardian9(GraphicsPipe *pipe) : //////////////////////////////////////////////////////////////////// DXGraphicsStateGuardian9:: ~DXGraphicsStateGuardian9() { + dxgsg9_cat.debug() + << "DXGraphicsStateGuardian9 " << this << " destructing\n"; + if (IS_VALID_PTR(_d3d_device)) { _d3d_device->SetTexture(0, NULL); // this frees reference to the old texture } @@ -895,10 +898,16 @@ prepare_lens() { bool DXGraphicsStateGuardian9:: begin_frame(Thread *current_thread) { -DBG_S dxgsg9_cat.debug ( ) << "^^^^^^^^^^^ begin_frame \n"; DBG_E + DBG_S dxgsg9_cat.debug ( ) << "^^^^^^^^^^^ begin_frame \n"; DBG_E GraphicsStateGuardian::begin_frame(current_thread); + if (_d3d_device == NULL) { + dxgsg9_cat.debug() + << this << "::begin_frame(): no device.\n"; + return false; + } + if (_lru) { _lru -> begin_frame ( ); @@ -2369,8 +2378,11 @@ reset() { // TransformState::make_identity()); // want gsg to pass all state settings down so any non-matching defaults we set here get overwritten - assert(_screen->_d3d9 != NULL); - assert(_d3d_device != NULL); + nassertv(_screen->_d3d9 != NULL); + + if (_d3d_device == NULL) { + return; + } D3DCAPS9 d3d_caps; _d3d_device->GetDeviceCaps(&d3d_caps); @@ -2728,7 +2740,7 @@ reset() { } else { // every card is going to have vertex fog, since it's implemented // in d3d runtime. - assert((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0); + nassertv((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0); // vertex fog may look crappy if you have large polygons in the // foreground and they get clipped, so you may want to disable it @@ -4334,6 +4346,10 @@ set_context(DXScreenData *new_context) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian9:: set_render_target() { + if (_d3d_device == NULL) { + return; + } + LPDIRECT3DSURFACE9 back = NULL, stencil = NULL; UINT swap_chain; @@ -4566,9 +4582,9 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, DXScreenData **screen) { HRESULT hr; - assert(IS_VALID_PTR(presentation_params)); - assert(IS_VALID_PTR(_screen->_d3d9)); - assert(IS_VALID_PTR(_d3d_device)); + nassertr(IS_VALID_PTR(presentation_params), E_FAIL); + nassertr(IS_VALID_PTR(_screen->_d3d9), E_FAIL); + nassertr(IS_VALID_PTR(_d3d_device), E_FAIL); // for windowed mode make sure our format matches the desktop fmt, // in case the desktop mode has been changed @@ -4681,10 +4697,14 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, bool DXGraphicsStateGuardian9:: check_cooperative_level() { bool bDoReactivateWindow = false; + if (_d3d_device == NULL) { + return false; + } + HRESULT hr = _d3d_device->TestCooperativeLevel(); if (SUCCEEDED(hr)) { - assert(SUCCEEDED(_last_testcooplevel_result)); + nassertr(SUCCEEDED(_last_testcooplevel_result), false); return true; } diff --git a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx index c00d1a7d11..df4af42d7a 100755 --- a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx @@ -251,7 +251,11 @@ verify_window_sizes(int numsizes, int *dimen) { //////////////////////////////////////////////////////////////////// void wdxGraphicsWindow9:: close_window() { - wdxdisplay9_cat.debug() << "wdx closed window\n"; + if (wdxdisplay9_cat.is_debug()) { + wdxdisplay9_cat.debug() + << "wdxGraphicsWindow9::close_window() " << this << "\n"; + } + if (_gsg != (GraphicsStateGuardian *)NULL) { _gsg.clear(); _active = false; @@ -316,6 +320,7 @@ open_window() { wdxdisplay9_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n"; if (!create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer)) { wdxdisplay9_cat.error() << "Unable to create window with specified parameters.\n"; + close_window(); return false; } _dxgsg->get_pipe()->make_device((void*)(&_wcontext)); @@ -565,8 +570,8 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer PRINT_REFCNT(wdxdisplay9, _d3d9); - assert(_d3d9 != NULL); - assert(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION); + nassertr(_d3d9 != NULL, false); + nassertr(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION, false); bool do_sync = sync_video; @@ -993,14 +998,14 @@ choose_device() { bool wdxGraphicsWindow9:: consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) { - assert(dxpipe != NULL); + nassertr(dxpipe != NULL, false); WindowProperties properties = get_properties(); DWORD dwRenderWidth = properties.get_x_size(); DWORD dwRenderHeight = properties.get_y_size(); HRESULT hr; LPDIRECT3D9 _d3d9 = dxpipe->__d3d9; - assert(_dxgsg != NULL); + nassertr(_dxgsg != NULL, false); _wcontext._d3d9 = _d3d9; _wcontext._is_dx9_1 = dxpipe->__is_dx9_1; _wcontext._card_id = device_info->cardID; // could this change by end? @@ -1207,8 +1212,8 @@ init_resized_window() { DWORD newWidth = _wcontext._presentation_params.BackBufferWidth; DWORD newHeight = _wcontext._presentation_params.BackBufferHeight; - assert((newWidth != 0) && (newHeight != 0)); - assert(_wcontext._window != NULL); + nassertv((newWidth != 0) && (newHeight != 0)); + nassertv(_wcontext._window != NULL); if (_wcontext._presentation_params.Windowed) { POINT ul, lr; @@ -1231,7 +1236,7 @@ init_resized_window() { } // clear window to black ASAP - assert(_wcontext._window != NULL); + nassertv(_wcontext._window != NULL); ClearToBlack(_wcontext._window, get_properties()); // clear textures and VB's out of video&AGP mem, so cache is reset diff --git a/panda/src/gobj/geomMunger.I b/panda/src/gobj/geomMunger.I index 74c0347734..221c882097 100644 --- a/panda/src/gobj/geomMunger.I +++ b/panda/src/gobj/geomMunger.I @@ -17,6 +17,17 @@ //////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +// Function: GeomMunger::get_gsg +// Access: Public +// Description: Returns a pointer to the GSG that created this +// munger. +//////////////////////////////////////////////////////////////////// +INLINE GraphicsStateGuardianBase *GeomMunger:: +get_gsg() const { + return _gsg; +} + //////////////////////////////////////////////////////////////////// // Function: GeomMunger::is_registered // Access: Public @@ -50,6 +61,17 @@ register_munger(GeomMunger *munger, Thread *current_thread) { return get_registry()->register_munger(munger, current_thread); } +//////////////////////////////////////////////////////////////////// +// Function: GeomMunger::unregister_mungers_for_gsg +// Access: Public, Static +// Description: Removes all the mungers from the registry that are +// associated with the indicated GSG. +//////////////////////////////////////////////////////////////////// +INLINE void GeomMunger:: +unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg) { + get_registry()->unregister_mungers_for_gsg(gsg); +} + //////////////////////////////////////////////////////////////////// // Function: GeomMunger::munge_format // Access: Public diff --git a/panda/src/gobj/geomMunger.cxx b/panda/src/gobj/geomMunger.cxx index 15363471e2..57adbefd5f 100644 --- a/panda/src/gobj/geomMunger.cxx +++ b/panda/src/gobj/geomMunger.cxx @@ -33,7 +33,8 @@ PStatCollector GeomMunger::_munge_pcollector("*:Munge"); // Description: //////////////////////////////////////////////////////////////////// GeomMunger:: -GeomMunger() : +GeomMunger(GraphicsStateGuardianBase *gsg) : + _gsg(gsg), _is_registered(false) { #ifndef NDEBUG @@ -281,8 +282,8 @@ compare_to_impl(const GeomMunger *other) const { // they would produce a different answer to // munge_format(), munge_data(), or munge_geom(). (They // still might be different in other ways, but if they -// would produce the same answer, this function consider -// them to be the same.) +// would produce the same answer, this function will +// consider them to be the same.) //////////////////////////////////////////////////////////////////// int GeomMunger:: geom_compare_to_impl(const GeomMunger *other) const { @@ -417,3 +418,30 @@ unregister_munger(GeomMunger *munger) { munger->_registered_key = _mungers.end(); munger->do_unregister(); } + +//////////////////////////////////////////////////////////////////// +// Function: GeomMunger::Registry::unregister_mungers_for_gsg +// Access: Public +// Description: Removes all the mungers from the registry that are +// associated with the indicated GSG. +//////////////////////////////////////////////////////////////////// +void GeomMunger::Registry:: +unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg) { + MutexHolder holder(_registry_lock); + + Mungers::iterator mi = _mungers.begin(); + while (mi != _mungers.end()) { + GeomMunger *munger = (*mi); + Mungers::iterator mnext = mi; + ++mnext; + + if (munger->get_gsg() == gsg) { + nassertv(mi == munger->_registered_key); + _mungers.erase(mi); + munger->_registered_key = _mungers.end(); + munger->do_unregister(); + } + + mi = mnext; + } +} diff --git a/panda/src/gobj/geomMunger.h b/panda/src/gobj/geomMunger.h index 5f81f0a1fa..a9dcb2bc62 100644 --- a/panda/src/gobj/geomMunger.h +++ b/panda/src/gobj/geomMunger.h @@ -59,13 +59,16 @@ class Geom; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomMunger : public TypedReferenceCount, public GeomEnums { public: - GeomMunger(); + GeomMunger(GraphicsStateGuardianBase *gsg); GeomMunger(const GeomMunger ©); void operator = (const GeomMunger ©); virtual ~GeomMunger(); + INLINE GraphicsStateGuardianBase *get_gsg() const; + INLINE bool is_registered() const; INLINE static PT(GeomMunger) register_munger(GeomMunger *munger, Thread *current_thread); + INLINE static void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg); INLINE CPT(GeomVertexFormat) munge_format(const GeomVertexFormat *format, const GeomVertexAnimationSpec &animation) const; @@ -117,6 +120,8 @@ private: // This mutex protects the above. Mutex _formats_lock; + GraphicsStateGuardianBase *_gsg; + bool _is_registered; typedef pset > Mungers; class EXPCL_PANDA Registry { @@ -124,6 +129,7 @@ private: Registry(); PT(GeomMunger) register_munger(GeomMunger *munger, Thread *current_thread); void unregister_munger(GeomMunger *munger); + void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg); Mungers _mungers; Mutex _registry_lock; diff --git a/panda/src/pgraph/stateMunger.I b/panda/src/pgraph/stateMunger.I index d976176d69..6704538e80 100644 --- a/panda/src/pgraph/stateMunger.I +++ b/panda/src/pgraph/stateMunger.I @@ -16,3 +16,14 @@ // //////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: StateMunger::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE StateMunger:: +StateMunger(GraphicsStateGuardianBase *gsg) : + GeomMunger(gsg) +{ +} diff --git a/panda/src/pgraph/stateMunger.h b/panda/src/pgraph/stateMunger.h index c6e29cbdaa..16759bc4f6 100644 --- a/panda/src/pgraph/stateMunger.h +++ b/panda/src/pgraph/stateMunger.h @@ -33,6 +33,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA StateMunger : public GeomMunger { public: + INLINE StateMunger(GraphicsStateGuardianBase *gsg); virtual ~StateMunger(); CPT(RenderState) munge_state(const RenderState *state); diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index ffd852fc1f..3ab4893663 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -335,15 +335,15 @@ close_window() { set_cursor_out_of_window(); DestroyWindow(_hWnd); - // Remove the window handle from our global map. - _window_handles.erase(_hWnd); - _hWnd = (HWND)0; - if (is_fullscreen()) { // revert to default display mode. ChangeDisplaySettings(NULL, 0x0); } + // Remove the window handle from our global map. + _window_handles.erase(_hWnd); + _hWnd = (HWND)0; + GraphicsWindow::close_window(); }