diff --git a/panda/src/chancfg/chancfg.cxx b/panda/src/chancfg/chancfg.cxx index 89b23b2efe..dc3b2c505b 100644 --- a/panda/src/chancfg/chancfg.cxx +++ b/panda/src/chancfg/chancfg.cxx @@ -424,26 +424,29 @@ ChanConfig::ChanConfig(GraphicsEngine *engine, GraphicsPipe* pipe, float win_background_b = chanconfig.GetFloat("win-background-b", 0.41); // visual? nope, that's handled with the mode. - int framebuffer_mode = - WindowProperties::FM_rgba | - WindowProperties::FM_double_buffer | - WindowProperties::FM_depth; - framebuffer_mode = overrides.defined(ChanCfgOverrides::Mask) ? - overrides.getUInt(ChanCfgOverrides::Mask) : framebuffer_mode; + int frame_buffer_mode = + FrameBufferProperties::FM_rgba | + FrameBufferProperties::FM_double_buffer | + FrameBufferProperties::FM_depth; + frame_buffer_mode = overrides.defined(ChanCfgOverrides::Mask) ? + overrides.getUInt(ChanCfgOverrides::Mask) : frame_buffer_mode; + std::string title = cfg; title = overrides.defined(ChanCfgOverrides::Title) ? overrides.getString(ChanCfgOverrides::Title) : title; + FrameBufferProperties fbprops; + fbprops.set_frame_buffer_mode(frame_buffer_mode); + fbprops.set_depth_bits(want_depth_bits); + fbprops.set_color_bits(want_color_bits); + WindowProperties props; props.set_open(true); props.set_origin(origX, origY); props.set_size(sizeX, sizeY); props.set_title(title); - props.set_framebuffer_mode(framebuffer_mode); props.set_undecorated(undecorated); props.set_fullscreen(fullscreen); - props.set_depth_bits(want_depth_bits); - props.set_color_bits(want_color_bits); props.set_cursor_hidden(!use_cursor); @@ -454,7 +457,9 @@ ChanConfig::ChanConfig(GraphicsEngine *engine, GraphicsPipe* pipe, overrides.getBool(ChanCfgOverrides::Cameras) : true; // open that sucker - PT(GraphicsWindow) win = engine->make_window(pipe); + PT(GraphicsStateGuardian) gsg = + engine->make_gsg(pipe, fbprops, engine->get_threading_model()); + PT(GraphicsWindow) win = engine->make_window(pipe, gsg); if(win == (GraphicsWindow *)NULL) { chancfg_cat.error() << "Could not create window" << endl; _graphics_window = (GraphicsWindow *)NULL; diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index 1169fa4385..1b9314bd5a 100644 --- a/panda/src/display/Sources.pp +++ b/panda/src/display/Sources.pp @@ -15,6 +15,7 @@ displayRegion.I displayRegion.h \ displayRegionStack.I \ displayRegionStack.h \ + frameBufferProperties.I frameBufferProperties.h \ frameBufferStack.I frameBufferStack.h \ geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ graphicsChannel.I graphicsChannel.h \ @@ -24,6 +25,7 @@ graphicsPipeSelection.I graphicsPipeSelection.h \ graphicsStateGuardian.I \ graphicsStateGuardian.h graphicsWindow.I \ + graphicsThreadingModel.I graphicsThreadingModel.h \ graphicsWindow.h graphicsWindowInputDevice.I \ graphicsWindowInputDevice.h \ windowProperties.I windowProperties.h \ @@ -36,11 +38,13 @@ config_display.cxx \ clearableRegion.cxx \ displayRegion.cxx \ + frameBufferProperties.cxx \ geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \ graphicsEngine.cxx \ graphicsLayer.cxx graphicsPipe.cxx \ graphicsPipeSelection.cxx \ graphicsStateGuardian.cxx \ + graphicsThreadingModel.cxx \ graphicsWindow.cxx graphicsWindowInputDevice.cxx \ windowProperties.cxx \ hardwareChannel.cxx \ @@ -51,6 +55,7 @@ clearableRegion.I clearableRegion.h \ displayRegion.I displayRegion.h displayRegionStack.I \ displayRegionStack.h \ + frameBufferProperties.I frameBufferProperties.h \ frameBufferStack.I frameBufferStack.h \ geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ graphicsChannel.I graphicsChannel.h \ @@ -60,6 +65,7 @@ graphicsPipeSelection.I graphicsPipeSelection.h \ graphicsStateGuardian.I \ graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \ + graphicsThreadingModel.I graphicsThreadingModel.h \ graphicsWindowInputDevice.I graphicsWindowInputDevice.h \ windowProperties.I windowProperties.h \ hardwareChannel.I hardwareChannel.h \ diff --git a/panda/src/display/display_composite2.cxx b/panda/src/display/display_composite2.cxx index ca3133cd3d..f6fc886537 100644 --- a/panda/src/display/display_composite2.cxx +++ b/panda/src/display/display_composite2.cxx @@ -1,5 +1,7 @@ #include "config_display.cxx" +#include "frameBufferProperties.cxx" #include "graphicsPipeSelection.cxx" +#include "graphicsThreadingModel.cxx" #include "hardwareChannel.cxx" #include "savedFrameBuffer.cxx" #include "windowProperties.cxx" diff --git a/panda/src/display/graphicsEngine.I b/panda/src/display/graphicsEngine.I index ecc6405a4f..3c358eeac3 100644 --- a/panda/src/display/graphicsEngine.I +++ b/panda/src/display/graphicsEngine.I @@ -56,17 +56,53 @@ get_auto_flip() const { } //////////////////////////////////////////////////////////////////// -// Function: GraphicsEngine::make_window +// Function: GraphicsEngine::make_gsg // Access: Published -// Description: Creates a new window using the indicated GraphicsPipe -// and returns it. The GraphicsEngine becomes the owner -// of the window; it will persist at least until -// remove_window() is called later. +// Description: Creates a new gsg using the indicated GraphicsPipe +// and returns it. The GraphicsEngine does not +// officially own the pointer to the gsg; but if any +// windows are created using this GSG, the +// GraphicsEngine will own the pointers to these +// windows, which in turn will own the pointer to the +// GSG. // -// This flavor of make_window() uses the default +// There is no explicit way to release a GSG, but it +// will be destructed when all windows that reference it +// are destructed, and the draw thread that owns the GSG +// runs one more time. +// +// This flavor of make_gsg() uses the default // threading model, specified via set_threading_model(). //////////////////////////////////////////////////////////////////// -INLINE GraphicsWindow *GraphicsEngine:: -make_window(GraphicsPipe *pipe) { - return make_window(pipe, get_threading_model()); +INLINE PT(GraphicsStateGuardian) GraphicsEngine:: +make_gsg(GraphicsPipe *pipe) { + return make_gsg(pipe, get_frame_buffer_properties(), get_threading_model()); +} + + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::make_window +// Access: Published +// Description: Creates a new window using the indicated +// GraphicsStateGuardian and returns it. The +// GraphicsEngine becomes the owner of the window; it +// will persist at least until remove_window() is called +// later. +//////////////////////////////////////////////////////////////////// +INLINE GraphicsWindow *GraphicsEngine:: +make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) { + return make_window(pipe, gsg, get_threading_model()); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::close_gsg +// Access: Published +// Description: Calls GraphicsPipe::close_gsg() on the indicated pipe +// and GSG. This function mainly exists to allow +// GraphicsEngine::WindowRenderer to call the protected +// method GraphicsPipe::close_gsg(). +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsEngine:: +close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) { + pipe->close_gsg(gsg); } diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 8b6487fe5d..396c2bc6b7 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -50,8 +50,17 @@ GraphicsEngine(Pipeline *pipeline) : if (_pipeline == (Pipeline *)NULL) { _pipeline = Pipeline::get_render_pipeline(); } - set_threading_model(threading_model); - if (!_threading_model.empty()) { + + // Default frame buffer properties. + _frame_buffer_properties.set_depth_bits(1); + _frame_buffer_properties.set_color_bits(1); + _frame_buffer_properties.set_frame_buffer_mode + (FrameBufferProperties::FM_rgba | + FrameBufferProperties::FM_double_buffer | + FrameBufferProperties::FM_depth); + + set_threading_model(GraphicsThreadingModel(threading_model)); + if (!_threading_model.is_default()) { display_cat.info() << "Using threading model " << _threading_model << "\n"; } @@ -70,49 +79,46 @@ GraphicsEngine:: remove_all_windows(); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::set_frame_buffer_properties +// Access: Published +// Description: Specifies the default frame buffer properties for +// future gsg's created using the one-parameter +// make_gsg() method. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +set_frame_buffer_properties(const FrameBufferProperties &properties) { + MutexHolder holder(_lock); + _frame_buffer_properties = properties; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::get_frame_buffer_properties +// Access: Published +// Description: Returns the current default threading model. See +// set_frame_buffer_properties(). +//////////////////////////////////////////////////////////////////// +FrameBufferProperties GraphicsEngine:: +get_frame_buffer_properties() const { + FrameBufferProperties result; + { + MutexHolder holder(_lock); + result = _frame_buffer_properties; + } + return result; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::set_threading_model // Access: Published // Description: Specifies how windows created using future calls to -// the one-parameter version of make_window() will be -// threaded. (The two-parameter flavor of make_window() -// allows this to be specified on a per-window basis.) -// -// The threading model is a string representing the -// names of the two threads that will process cull and -// draw for the given window, separated by a slash. The -// names are completely arbitrary and are used only to -// differentiate threads. The two names may be the -// same, meaning the same thread, or each may be the -// empty string, which represents the previous thread. -// -// Thus, for example, "cull/draw" indicates that the -// window will be culled in a thread called "cull", and -// drawn in a separate thread called "draw". -// "draw/draw" or simply "draw/" indicates the window -// will be culled and drawn in the same thread, "draw". -// On the other hand, "/draw" indicates the thread will -// be culled in the main, or app thread, and drawn in a -// separate thread named "draw". The empty string, "" -// or "/", indicates the thread will be culled and drawn -// in the main thread; that is to say, a single-process -// model. -// -// Finally, if the threading model begins with a "-" -// character, then cull and draw are run simultaneously, -// in the same thread, with no binning or state sorting. -// It simplifies the cull process but it forces the -// scene to render in scene graph order; state sorting -// and alpha sorting is lost. -// -// You can create as many different threads as you like; -// each thread is uniquified based on its name, so -// multiple windows may easily be handled by the same or -// different threads. +// the one-parameter version of make_gsg() will be +// threaded. //////////////////////////////////////////////////////////////////// void GraphicsEngine:: -set_threading_model(const string &threading_model) { - if (!threading_model.empty() && !Thread::is_threading_supported()) { +set_threading_model(const GraphicsThreadingModel &threading_model) { + if (!threading_model.is_single_threaded() && + !Thread::is_threading_supported()) { display_cat.warning() << "Threading model " << threading_model << " requested but threading not supported.\n"; @@ -128,9 +134,9 @@ set_threading_model(const string &threading_model) { // Description: Returns the current default threading model. See // set_threading_model(). //////////////////////////////////////////////////////////////////// -string GraphicsEngine:: +GraphicsThreadingModel GraphicsEngine:: get_threading_model() const { - string result; + GraphicsThreadingModel result; { MutexHolder holder(_lock); result = _threading_model; @@ -138,51 +144,64 @@ get_threading_model() const { return result; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::make_gsg +// Access: Published +// Description: Creates a new gsg using the indicated GraphicsPipe +// and returns it. The GraphicsEngine does not +// officially own the pointer to the gsg; but if any +// windows are created using this GSG, the +// GraphicsEngine will own the pointers to these +// windows, which in turn will own the pointer to the +// GSG. +// +// There is no explicit way to release a GSG, but it +// will be destructed when all windows that reference it +// are destructed, and the draw thread that owns the GSG +// runs one more time. +//////////////////////////////////////////////////////////////////// +PT(GraphicsStateGuardian) GraphicsEngine:: +make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties, + const GraphicsThreadingModel &threading_model) { + // TODO: ask the draw thread to make the GSG. + PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties); + if (gsg != (GraphicsStateGuardian *)NULL) { + gsg->_threading_model = threading_model; + gsg->_pipe = pipe; + } + + return gsg; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::make_window // Access: Published -// Description: Creates a new window using the indicated GraphicsPipe -// and returns it. The GraphicsEngine becomes the owner -// of the window; it will persist at least until -// remove_window() is called later. +// Description: Creates a new window using the indicated +// GraphicsStateGuardian and returns it. The +// GraphicsEngine becomes the owner of the window; it +// will persist at least until remove_window() is called +// later. //////////////////////////////////////////////////////////////////// GraphicsWindow *GraphicsEngine:: -make_window(GraphicsPipe *pipe, const string &threading_model) { - PT(GraphicsWindow) window = pipe->make_window(); +make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, + const GraphicsThreadingModel &threading_model) { + if (gsg != (GraphicsStateGuardian *)NULL) { + nassertr(pipe == gsg->get_pipe(), NULL); + nassertr(threading_model.get_draw_name() == + gsg->get_threading_model().get_draw_name(), NULL); + } + + // TODO: ask the window thread to make the window. + PT(GraphicsWindow) window = pipe->make_window(gsg); if (window != (GraphicsWindow *)NULL) { MutexHolder holder(_lock); _windows.insert(window); - // Now figure out the threading model. - string cull_name; - string draw_name; - bool cull_sorting = true; - size_t start = 0; - if (!threading_model.empty() && threading_model[0] == '-') { - start = 1; - cull_sorting = false; - } + WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name()); + WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name()); + draw->add_gsg(gsg); - size_t slash = threading_model.find('/', start); - if (slash == string::npos) { - cull_name = threading_model; - } else { - cull_name = threading_model.substr(start, slash - start); - draw_name = threading_model.substr(slash + 1); - } - if (!cull_sorting || draw_name.empty()) { - draw_name = cull_name; - } - - /* - cerr << "cull_name = " << cull_name << " draw_name = " << draw_name - << " cull_sorting = " << cull_sorting << "\n"; - */ - - WindowRenderer *cull = get_window_renderer(cull_name); - WindowRenderer *draw = get_window_renderer(draw_name); - - if (cull_sorting) { + if (threading_model.get_cull_sorting()) { cull->add_window(cull->_cull, window); draw->add_window(draw->_draw, window); } else { @@ -869,6 +888,18 @@ get_window_renderer(const string &name) { return thread.p(); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::WindowRenderer::add_gsg +// Access: Public +// Description: Adds a new GSG to the _gsg list, if it is not already +// there. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine::WindowRenderer:: +add_gsg(GraphicsStateGuardian *gsg) { + MutexHolder holder(_wl_lock); + _gsgs.insert(gsg); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::WindowRenderer::add_window // Access: Public @@ -958,6 +989,26 @@ do_frame(GraphicsEngine *engine) { engine->cull_bin_draw(_cull); engine->cull_and_draw_together(_cdraw); engine->process_events(_window); + + // If any GSG's on the list have no more outstanding pointers, clean + // them up. (We are in the draw thread for all of these GSG's.) + if (any_done_gsgs()) { + GSGs new_gsgs; + GSGs::iterator gi; + for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) { + GraphicsStateGuardian *gsg = (*gi); + if (gsg->get_ref_count() == 1) { + // This one has no outstanding pointers; clean it up. + GraphicsPipe *pipe = gsg->get_pipe(); + engine->close_gsg(pipe, gsg); + } else { + // This one is ok; preserve it. + new_gsgs.insert(gsg); + } + } + + _gsgs.swap(new_gsgs); + } } //////////////////////////////////////////////////////////////////// @@ -995,7 +1046,7 @@ do_release(GraphicsEngine *) { // Description: Closes all the windows on the _window list. //////////////////////////////////////////////////////////////////// void GraphicsEngine::WindowRenderer:: -do_close(GraphicsEngine *) { +do_close(GraphicsEngine *engine) { WindowProperties close_properties; close_properties.set_open(false); @@ -1005,6 +1056,23 @@ do_close(GraphicsEngine *) { GraphicsWindow *win = (*wi); win->set_properties_now(close_properties); } + + // Also close all of the GSG's. + GSGs new_gsgs; + GSGs::iterator gi; + for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) { + GraphicsStateGuardian *gsg = (*gi); + if (gsg->get_ref_count() == 1) { + // This one has no outstanding pointers; clean it up. + GraphicsPipe *pipe = gsg->get_pipe(); + engine->close_gsg(pipe, gsg); + } else { + // This one is ok; preserve it. + new_gsgs.insert(gsg); + } + } + + _gsgs.swap(new_gsgs); } //////////////////////////////////////////////////////////////////// @@ -1049,6 +1117,26 @@ do_pending(GraphicsEngine *engine) { } } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::WindowRenderer::any_done_gsgs +// Access: Public +// Description: Returns true if any of the GSG's on this thread's +// draw list are done (they have no outstanding pointers +// other than this one), or false if all of them are +// still good. +//////////////////////////////////////////////////////////////////// +bool GraphicsEngine::WindowRenderer:: +any_done_gsgs() const { + GSGs::const_iterator gi; + for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) { + if ((*gi)->get_ref_count() == 1) { + return true; + } + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::RenderThread::Constructor // Access: Public diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index 613eeccdfc..f1a8c7615b 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -21,6 +21,8 @@ #include "pandabase.h" #include "graphicsWindow.h" +#include "frameBufferProperties.h" +#include "graphicsThreadingModel.h" #include "sceneSetup.h" #include "pointerTo.h" #include "thread.h" @@ -32,6 +34,7 @@ class Pipeline; class DisplayRegion; class GraphicsPipe; +class FrameBufferProperties; //////////////////////////////////////////////////////////////////// // Class : GraphicsEngine @@ -53,15 +56,25 @@ PUBLISHED: GraphicsEngine(Pipeline *pipeline = NULL); ~GraphicsEngine(); - void set_threading_model(const string &threading_model); - string get_threading_model() const; + void set_frame_buffer_properties(const FrameBufferProperties &properties); + FrameBufferProperties get_frame_buffer_properties() const; + + void set_threading_model(const GraphicsThreadingModel &threading_model); + GraphicsThreadingModel get_threading_model() const; INLINE void set_auto_flip(bool auto_flip); INLINE bool get_auto_flip() const; - INLINE GraphicsWindow *make_window(GraphicsPipe *pipe); + INLINE PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe); + PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe, + const FrameBufferProperties &properties, + const GraphicsThreadingModel &threading_model); + + INLINE GraphicsWindow *make_window(GraphicsPipe *pipe, + GraphicsStateGuardian *gsg); GraphicsWindow *make_window(GraphicsPipe *pipe, - const string &threading_model); + GraphicsStateGuardian *gsg, + const GraphicsThreadingModel &threading_model); bool remove_window(GraphicsWindow *window); void remove_all_windows(); bool is_empty() const; @@ -75,6 +88,7 @@ PUBLISHED: private: typedef pset< PT(GraphicsWindow) > Windows; + typedef pset< PT(GraphicsStateGuardian) > GSGs; void cull_and_draw_together(const Windows &wlist); void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr); @@ -86,6 +100,7 @@ private: void flip_windows(const GraphicsEngine::Windows &wlist); void do_sync_frame(); void do_flip_frame(); + INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); PT(SceneSetup) setup_scene(const NodePath &camera, GraphicsStateGuardian *gsg); @@ -104,6 +119,7 @@ private: // process, and the list of windows for each stage. class WindowRenderer { public: + void add_gsg(GraphicsStateGuardian *gsg); void add_window(Windows &wlist, GraphicsWindow *window); void remove_window(GraphicsWindow *window); void do_frame(GraphicsEngine *engine); @@ -111,6 +127,7 @@ private: void do_release(GraphicsEngine *engine); void do_close(GraphicsEngine *engine); void do_pending(GraphicsEngine *engine); + bool any_done_gsgs() const; Windows _cull; // cull stage Windows _cdraw; // cull-and-draw-together stage @@ -118,6 +135,7 @@ private: Windows _window; // window stage, i.e. process windowing events Windows _pending_release; // moved from _draw, pending release_gsg. Windows _pending_close; // moved from _window, pending close. + GSGs _gsgs; // draw stage Mutex _wl_lock; }; @@ -148,7 +166,8 @@ private: WindowRenderer _app; typedef pmap Threads; Threads _threads; - string _threading_model; + FrameBufferProperties _frame_buffer_properties; + GraphicsThreadingModel _threading_model; bool _auto_flip; enum FlipState { diff --git a/panda/src/display/graphicsPipe.cxx b/panda/src/display/graphicsPipe.cxx index fa68fa755a..a7f5394f95 100644 --- a/panda/src/display/graphicsPipe.cxx +++ b/panda/src/display/graphicsPipe.cxx @@ -100,3 +100,35 @@ HardwareChannel *GraphicsPipe:: get_hw_channel(GraphicsWindow *, int) { return (HardwareChannel*)0L; } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsPipe::make_gsg +// Access: Protected, Virtual +// Description: Creates a new GSG to use the pipe (but no windows +// have been created yet for the GSG). This method will +// be called in the draw thread for the GSG. +//////////////////////////////////////////////////////////////////// +PT(GraphicsStateGuardian) GraphicsPipe:: +make_gsg(const FrameBufferProperties &properties) { + // shouldnt this method really be pure virtual? it's an error for a pipe to not implement it + display_cat.error() << "Error: make_gsg() unimplemented by graphicsPipe!\n"; + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsPipe::close_gsg +// Access: Protected, Virtual +// Description: This will be called in the draw thread (the same +// thread in which the GSG was created via make_gsg, +// above) to close the indicated GSG and free its +// associated graphics objects just before it is +// destructed. This method exists to provide a hook for +// the graphics pipe to do any necessary cleanup, if +// any. +//////////////////////////////////////////////////////////////////// +void GraphicsPipe:: +close_gsg(GraphicsStateGuardian *gsg) { + if (gsg != (GraphicsStateGuardian *)NULL) { + gsg->close_gsg(); + } +} diff --git a/panda/src/display/graphicsPipe.h b/panda/src/display/graphicsPipe.h index ef8a531e6a..55abd9a273 100644 --- a/panda/src/display/graphicsPipe.h +++ b/panda/src/display/graphicsPipe.h @@ -28,6 +28,8 @@ class HardwareChannel; class GraphicsWindow; +class GraphicsStateGuardian; +class FrameBufferProperties; //////////////////////////////////////////////////////////////////// // Class : GraphicsPipe @@ -69,11 +71,12 @@ public: virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index); protected: - // The make_window() interface on GraphicsPipe is protected; don't - // try to call it directly. Instead, use - // GraphicsEngine::make_window() to make a new window on a - // particular pipe. - virtual PT(GraphicsWindow) make_window()=0; + // The make_window() and make_gsg() interfaces on GraphicsPipe are + // protected; don't try to call them directly. Instead, use + // the interface on GraphicsEngine to make a new window or gsg. + virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties); + virtual void close_gsg(GraphicsStateGuardian *gsg); + virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg)=0; Mutex _lock; diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 2418325544..11e77d796b 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -41,15 +41,37 @@ ClipPlaneInfo() { //////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::is_closed +// Function: GraphicsStateGuardian::get_properties // Access: Public -// Description: Returns true if the window associated with this GSG -// has been closed, and hence the resources associated -// with this GSG have been freed. +// Description: Returns the frame buffer properties requested for +// this GSG. All windows created for this GSG must be +// created with the same properties. //////////////////////////////////////////////////////////////////// -INLINE bool GraphicsStateGuardian:: -is_closed() const { - return (_win == (GraphicsWindow *)NULL); +INLINE const FrameBufferProperties &GraphicsStateGuardian:: +get_properties() const { + return _properties; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_pipe +// Access: Public +// Description: Returns the graphics pipe on which this GSG was +// created. +//////////////////////////////////////////////////////////////////// +INLINE GraphicsPipe *GraphicsStateGuardian:: +get_pipe() const { + return _pipe; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_threading_model +// Access: Public +// Description: Returns the threading model that was used to create +// this GSG. +//////////////////////////////////////////////////////////////////// +INLINE const GraphicsThreadingModel &GraphicsStateGuardian:: +get_threading_model() const { + return _threading_model; } //////////////////////////////////////////////////////////////////// @@ -92,6 +114,19 @@ clear(DisplayRegion *dr) { pop_display_region(old_dr); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::reset_if_new +// Access: Public +// Description: Calls reset() to initialize the GSG, but only if it +// hasn't been called yet. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsStateGuardian:: +reset_if_new() { + if (_needs_reset) { + reset(); + } +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::modify_state // Access: Public diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 32048a9c49..22383c87fb 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -81,12 +81,13 @@ TypeHandle GraphicsStateGuardian::_type_handle; // Description: //////////////////////////////////////////////////////////////////// GraphicsStateGuardian:: -GraphicsStateGuardian(GraphicsWindow *win) { - _win = win; +GraphicsStateGuardian(const FrameBufferProperties &properties) { + _properties = properties; _coordinate_system = default_coordinate_system; _current_display_region = (DisplayRegion*)0L; _current_lens = (Lens *)NULL; - reset(); + _needs_reset = true; + _closing_gsg = false; } //////////////////////////////////////////////////////////////////// @@ -106,6 +107,8 @@ GraphicsStateGuardian:: //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: reset() { + _needs_reset = false; + _display_region_stack_level = 0; _frame_buffer_stack_level = 0; _lens_stack_level = 0; @@ -1374,11 +1377,10 @@ free_pointers() { //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: close_gsg() { + _closing_gsg = true; free_pointers(); release_all_textures(); release_all_geoms(); - - _win = (GraphicsWindow *)NULL; } #ifdef DO_PSTATS diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index d7143bcd94..7516cfda06 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -23,10 +23,13 @@ #include "savedFrameBuffer.h" #include "frameBufferStack.h" +#include "frameBufferProperties.h" #include "displayRegionStack.h" #include "lensStack.h" #include "graphicsStateGuardianBase.h" +#include "graphicsThreadingModel.h" +#include "graphicsPipe.h" #include "sceneSetup.h" #include "luse.h" #include "coordinateSystem.h" @@ -61,7 +64,7 @@ class EXPCL_PANDA GraphicsStateGuardian : public GraphicsStateGuardianBase { // Interfaces all GSGs should have // public: - GraphicsStateGuardian(GraphicsWindow *win); + GraphicsStateGuardian(const FrameBufferProperties &properties); virtual ~GraphicsStateGuardian(); PUBLISHED: @@ -69,7 +72,9 @@ PUBLISHED: void release_all_geoms(); public: - INLINE bool is_closed() const; + INLINE const FrameBufferProperties &get_properties() const; + INLINE GraphicsPipe *get_pipe() const; + INLINE const GraphicsThreadingModel &get_threading_model() const; INLINE void set_scene(SceneSetup *scene_setup); INLINE SceneSetup *get_scene() const; @@ -119,6 +124,7 @@ public: virtual CPT(RenderState) begin_decal_base_second(); virtual void finish_decal(); + INLINE void reset_if_new(); virtual void reset(); INLINE void modify_state(const RenderState *state); @@ -232,8 +238,6 @@ protected: int _frame_buffer_stack_level; int _lens_stack_level; - GraphicsWindow *_win; - CPT(DisplayRegion) _current_display_region; CPT(Lens) _current_lens; @@ -261,6 +265,9 @@ protected: ColorBlendAttrib::Mode _color_blend_mode; TransparencyAttrib::Mode _transparency_mode; + bool _needs_reset; + bool _closing_gsg; + public: // Statistics static PStatCollector _total_texusage_pcollector; @@ -324,11 +331,12 @@ private: typedef pset GeomNodes; GeomNodes _prepared_geom_nodes; -public: - void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg); + FrameBufferProperties _properties; + PT(GraphicsPipe) _pipe; + GraphicsThreadingModel _threading_model; public: - INLINE GraphicsWindow* get_window(void) const { return _win; } + void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg); public: static TypeHandle get_class_type() { @@ -351,6 +359,7 @@ private: friend class GraphicsPipe; friend class GraphicsWindow; + friend class GraphicsEngine; }; #include "graphicsStateGuardian.I" diff --git a/panda/src/display/graphicsWindow.cxx b/panda/src/display/graphicsWindow.cxx index 16399938e1..822c7c3bd2 100644 --- a/panda/src/display/graphicsWindow.cxx +++ b/panda/src/display/graphicsWindow.cxx @@ -37,11 +37,12 @@ TypeHandle GraphicsWindow::_type_handle; // GraphicsEngine::make_window() function. //////////////////////////////////////////////////////////////////// GraphicsWindow:: -GraphicsWindow(GraphicsPipe *pipe) { +GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) { #ifdef DO_MEMORY_USAGE MemoryUsage::update_type(this, this); #endif _pipe = pipe; + _gsg = gsg; // Some default properties for windows unless specified otherwise. // Other properties (size, title, etc.) must be explicitly @@ -51,11 +52,7 @@ GraphicsWindow(GraphicsPipe *pipe) { _properties.set_fullscreen(false); _properties.set_minimized(false); _properties.set_cursor_hidden(false); - _properties.set_depth_bits(1); - _properties.set_color_bits(1); - _properties.set_framebuffer_mode(WindowProperties::FM_rgba | - WindowProperties::FM_double_buffer | - WindowProperties::FM_depth); + _display_regions_stale = false; _window_event = "window-event"; @@ -581,32 +578,11 @@ make_scratch_display_region(int x_size, int y_size) const { bool GraphicsWindow:: begin_frame() { if (_gsg == (GraphicsStateGuardian *)NULL) { - MutexHolder holder(_lock); - // Oops, we don't have a GSG yet. - if (!_properties.get_open()) { - return false; - } - make_gsg(); - if (_gsg == (GraphicsStateGuardian *)NULL) { - // Still couldn't make the GSG for some reason. We should pass - // an appropriate diagnostic up to the application; for now, - // we'll just shut down the window. - - // WARNING: this is a non-thread-safe hack. This really should - // happen in the window thread, not here in the draw thread. - display_cat.info() - << "Could not open GSG, closing " << get_type() << ".\n"; - close_window(); - WindowProperties properties; - properties.set_open(false); - system_changed_properties(properties); - return false; - } - } else { - // Okay, we already have a GSG, so activate it. - make_current(); + return false; } + // Okay, we already have a GSG, so activate it. + make_current(); return _gsg->begin_frame(); } @@ -652,32 +628,6 @@ end_frame() { _gsg->end_frame(); } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsWindow::make_gsg -// Access: Public, Virtual -// Description: Creates a new GSG for the window and stores it in the -// _gsg pointer. This should only be called from within -// the draw thread. -//////////////////////////////////////////////////////////////////// -void GraphicsWindow:: -make_gsg() { -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsWindow::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. This should only -// be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void GraphicsWindow:: -release_gsg() { - if (_gsg != (GraphicsStateGuardian *)NULL) { - _gsg->close_gsg(); - _gsg.clear(); - } -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::make_current // Access: Public, Virtual @@ -689,6 +639,20 @@ void GraphicsWindow:: make_current() { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::release_gsg +// Access: Public +// Description: Releases the current GSG pointer, if it is currently +// held, and resets the GSG to NULL. The window will be +// permanently unable to render; this is normally called +// only just before destroying the window. This should +// only be called from within the draw thread. +//////////////////////////////////////////////////////////////////// +void GraphicsWindow:: +release_gsg() { + _gsg.clear(); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::begin_flip // Access: Public, Virtual diff --git a/panda/src/display/graphicsWindow.h b/panda/src/display/graphicsWindow.h index c2ece47f5f..72ab2d0a0f 100644 --- a/panda/src/display/graphicsWindow.h +++ b/panda/src/display/graphicsWindow.h @@ -58,7 +58,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GraphicsWindow : public TypedReferenceCount, public ClearableRegion { protected: - GraphicsWindow(GraphicsPipe *pipe); + GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); private: GraphicsWindow(const GraphicsWindow ©); @@ -119,12 +119,10 @@ public: void clear(); virtual void end_frame(); - virtual void make_gsg(); - virtual void release_gsg(); - // This method is called in the draw thread prior to issuing any // drawing commands for the window. virtual void make_current(); + virtual void release_gsg(); // These methods will be called within the app (main) thread. virtual void begin_flip(); diff --git a/panda/src/display/windowProperties.I b/panda/src/display/windowProperties.I index d3f8eaf915..ec0fb06ded 100644 --- a/panda/src/display/windowProperties.I +++ b/panda/src/display/windowProperties.I @@ -513,150 +513,6 @@ clear_cursor_hidden() { _flags &= ~F_cursor_hidden; } -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::set_framebuffer_mode -// Access: Published -// Description: Specifies the set of graphics properties that are -// required for the context associated with the window. -// This should be the union of the appropriate bits -// defined in FramebufferMode. -//////////////////////////////////////////////////////////////////// -INLINE void WindowProperties:: -set_framebuffer_mode(int framebuffer_mode) { - _framebuffer_mode = framebuffer_mode; - _specified |= S_framebuffer_mode; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::get_framebuffer_mode -// Access: Published -// Description: Returns the set of graphics properties that are -// in effect for the window. This will be the union of -// the corresponding bits from FramebufferMode. -//////////////////////////////////////////////////////////////////// -INLINE int WindowProperties:: -get_framebuffer_mode() const { - nassertr(has_framebuffer_mode(), false); - return _framebuffer_mode; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::has_framebuffer_mode -// Access: Published -// Description: Returns true if the framebuffer mode has been -// specified, false otherwise. -//////////////////////////////////////////////////////////////////// -INLINE bool WindowProperties:: -has_framebuffer_mode() const { - return ((_specified & S_framebuffer_mode) != 0); -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::clear_framebuffer_mode -// Access: Published -// Description: Removes the framebuffer_mode specification from the -// properties. -//////////////////////////////////////////////////////////////////// -INLINE void WindowProperties:: -clear_framebuffer_mode() { - _specified &= ~S_framebuffer_mode; - _framebuffer_mode = 0; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::set_depth_bits -// Access: Published -// Description: Specifies the minimum number of bits that are -// required for the depth buffer. -//////////////////////////////////////////////////////////////////// -INLINE void WindowProperties:: -set_depth_bits(int depth_bits) { - _depth_bits = depth_bits; - _specified |= S_depth_bits; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::get_depth_bits -// Access: Published -// Description: Returns the number of bits specified for the depth -// buffer. -//////////////////////////////////////////////////////////////////// -INLINE int WindowProperties:: -get_depth_bits() const { - return _depth_bits; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::has_depth_bits -// Access: Published -// Description: Returns true if the number of bits for the depth -// buffer has been specified, false otherwise. -//////////////////////////////////////////////////////////////////// -INLINE bool WindowProperties:: -has_depth_bits() const { - return ((_specified & S_depth_bits) != 0); -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::clear_depth_bits -// Access: Published -// Description: Removes the depth_bits specification from the -// properties. -//////////////////////////////////////////////////////////////////// -INLINE void WindowProperties:: -clear_depth_bits() { - _specified &= ~S_depth_bits; - _depth_bits = 0; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::set_color_bits -// Access: Published -// Description: Specifies the minimum number of bits that are -// required for all three channels of the color buffer. -// That is, this is the per-channel color requirement -// times three. -//////////////////////////////////////////////////////////////////// -INLINE void WindowProperties:: -set_color_bits(int color_bits) { - _color_bits = color_bits; - _specified |= S_color_bits; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::get_color_bits -// Access: Published -// Description: Returns the number of bits specified for the color -// buffer. -//////////////////////////////////////////////////////////////////// -INLINE int WindowProperties:: -get_color_bits() const { - return _color_bits; -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::has_color_bits -// Access: Published -// Description: Returns true if the number of bits for the color -// buffer has been specified, false otherwise. -//////////////////////////////////////////////////////////////////// -INLINE bool WindowProperties:: -has_color_bits() const { - return ((_specified & S_color_bits) != 0); -} - -//////////////////////////////////////////////////////////////////// -// Function: WindowProperties::clear_color_bits -// Access: Published -// Description: Removes the color_bits specification from the -// properties. -//////////////////////////////////////////////////////////////////// -INLINE void WindowProperties:: -clear_color_bits() { - _specified &= ~S_color_bits; - _color_bits = 0; -} - INLINE ostream & operator << (ostream &out, const WindowProperties &properties) { properties.output(out); diff --git a/panda/src/display/windowProperties.cxx b/panda/src/display/windowProperties.cxx index 3aa5483083..ce41548e1e 100644 --- a/panda/src/display/windowProperties.cxx +++ b/panda/src/display/windowProperties.cxx @@ -43,9 +43,6 @@ operator = (const WindowProperties ©) { _y_size = copy._y_size; _title = copy._title; _flags = copy._flags; - _framebuffer_mode = copy._framebuffer_mode; - _depth_bits = copy._depth_bits; - _color_bits = copy._color_bits; } //////////////////////////////////////////////////////////////////// @@ -61,10 +58,7 @@ operator == (const WindowProperties &other) const { _y_origin == other._y_origin && _x_size == other._x_size && _y_size == other._y_size && - _title == other._title && - _framebuffer_mode == other._framebuffer_mode && - _depth_bits == other._depth_bits && - _color_bits == other._color_bits); + _title == other._title); } //////////////////////////////////////////////////////////////////// @@ -83,9 +77,6 @@ clear() { _y_size = 0; _title = string(); _flags = 0; - _framebuffer_mode = 0; - _depth_bits = 0; - _color_bits = 0; } //////////////////////////////////////////////////////////////////// @@ -124,15 +115,6 @@ add_properties(const WindowProperties &other) { if (other.has_cursor_hidden()) { set_cursor_hidden(other.get_cursor_hidden()); } - if (other.has_framebuffer_mode()) { - set_framebuffer_mode(other.get_framebuffer_mode()); - } - if (other.has_depth_bits()) { - set_depth_bits(other.get_depth_bits()); - } - if (other.has_color_bits()) { - set_color_bits(other.get_color_bits()); - } } //////////////////////////////////////////////////////////////////// @@ -171,50 +153,4 @@ output(ostream &out) const { if (has_cursor_hidden()) { out << (get_cursor_hidden() ? "cursor_hidden " : "!cursor_hidden "); } - if (has_framebuffer_mode()) { - out << "framebuffer_mode="; - int framebuffer_mode = get_framebuffer_mode(); - if ((framebuffer_mode & FM_index) != 0) { - out << "FM_index"; - } else { - out << "FM_rgb"; - } - - if ((framebuffer_mode & FM_triple_buffer) != 0) { - out << "|FM_triple_buffer"; - } else if ((framebuffer_mode & FM_double_buffer) != 0) { - out << "|FM_double_buffer"; - } else { - out << "|FM_single_buffer"; - } - - if ((framebuffer_mode & FM_accum) != 0) { - out << "|FM_accum"; - } - if ((framebuffer_mode & FM_alpha) != 0) { - out << "|FM_alpha"; - } - if ((framebuffer_mode & FM_depth) != 0) { - out << "|FM_depth"; - } - if ((framebuffer_mode & FM_stencil) != 0) { - out << "|FM_stencil"; - } - if ((framebuffer_mode & FM_multisample) != 0) { - out << "|FM_multisample"; - } - if ((framebuffer_mode & FM_stereo) != 0) { - out << "|FM_stereo"; - } - if ((framebuffer_mode & FM_luminance) != 0) { - out << "|FM_luminance"; - } - out << " "; - } - if (has_depth_bits()) { - out << "depth_bits=" << get_depth_bits() << " "; - } - if (has_color_bits()) { - out << "color_bits=" << get_color_bits() << " "; - } } diff --git a/panda/src/display/windowProperties.h b/panda/src/display/windowProperties.h index 45bf274a87..0c133cff15 100644 --- a/panda/src/display/windowProperties.h +++ b/panda/src/display/windowProperties.h @@ -38,22 +38,6 @@ PUBLISHED: bool operator == (const WindowProperties &other) const; INLINE bool operator != (const WindowProperties &other) const; - enum FramebufferMode { - FM_rgba = 0x0000, - FM_rgb = 0x0000, - FM_index = 0x0001, - FM_single_buffer = 0x0000, - FM_double_buffer = 0x0002, - FM_triple_buffer = 0x0004, - FM_accum = 0x0008, - FM_alpha = 0x0010, - FM_depth = 0x0020, - FM_stencil = 0x0040, - FM_multisample = 0x0080, - FM_stereo = 0x0100, - FM_luminance = 0x0200, - }; - void clear(); INLINE bool is_any_specified() const; @@ -104,21 +88,6 @@ PUBLISHED: INLINE bool has_cursor_hidden() const; INLINE void clear_cursor_hidden(); - INLINE void set_framebuffer_mode(int framebuffer_mode); - INLINE int get_framebuffer_mode() const; - INLINE bool has_framebuffer_mode() const; - INLINE void clear_framebuffer_mode(); - - INLINE void set_depth_bits(int depth_bits); - INLINE int get_depth_bits() const; - INLINE bool has_depth_bits() const; - INLINE void clear_depth_bits(); - - INLINE void set_color_bits(int color_bits); - INLINE int get_color_bits() const; - INLINE bool has_color_bits() const; - INLINE void clear_color_bits(); - void add_properties(const WindowProperties &other); void output(ostream &out) const; @@ -137,9 +106,6 @@ private: S_minimized = 0x0040, S_open = 0x0080, S_cursor_hidden = 0x0100, - S_framebuffer_mode = 0x0200, - S_depth_bits = 0x0400, - S_color_bits = 0x0800, }; // This bitmask represents the true/false settings for various @@ -161,9 +127,6 @@ private: int _y_size; string _title; int _flags; - int _framebuffer_mode; - int _depth_bits; - int _color_bits; }; INLINE ostream &operator << (ostream &out, const WindowProperties &properties); diff --git a/panda/src/distort/nonlinearImager.cxx b/panda/src/distort/nonlinearImager.cxx index 54e93b614f..47b63cad84 100644 --- a/panda/src/distort/nonlinearImager.cxx +++ b/panda/src/distort/nonlinearImager.cxx @@ -259,8 +259,9 @@ int NonlinearImager:: add_viewer(DisplayRegion *dr) { GraphicsWindow *win = dr->get_window(); GraphicsStateGuardian *gsg = win->get_gsg(); - nassertr(_viewers.empty() || gsg == _gsg, -1); + nassertr(_viewers.empty() || (gsg == _gsg && win == _win), -1); _gsg = gsg; + _win = win; int previous_vi = find_viewer(dr); if (previous_vi >= 0) { @@ -601,7 +602,7 @@ render_screen(GraphicsEngine *engine, NonlinearImager::Screen &screen) { // Make a display region of the proper size and clear it to prepare for // rendering the scene. PT(DisplayRegion) scratch_region = - _gsg->get_window()->make_scratch_display_region(screen._tex_width, screen._tex_height); + _win->make_scratch_display_region(screen._tex_width, screen._tex_height); scratch_region->set_camera(screen._source_camera); engine->render_subframe(_gsg, scratch_region, true); diff --git a/panda/src/distort/nonlinearImager.h b/panda/src/distort/nonlinearImager.h index c761e17f28..e605a5e3bb 100644 --- a/panda/src/distort/nonlinearImager.h +++ b/panda/src/distort/nonlinearImager.h @@ -32,6 +32,7 @@ class GraphicsEngine; class GraphicsStateGuardian; +class GraphicsWindow; //////////////////////////////////////////////////////////////////// // Class : NonlinearImager @@ -162,6 +163,7 @@ private: Viewers _viewers; Screens _screens; GraphicsStateGuardian *_gsg; + GraphicsWindow *_win; bool _stale; }; diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.I b/panda/src/dxgsg7/dxGraphicsStateGuardian7.I index 71100e92ef..8836a45ef3 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.I +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.I @@ -30,12 +30,12 @@ enable_line_smooth(bool val) { _line_smooth_enabled = val; #ifdef NDEBUG { - if(val && (scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)) + if(val && (_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)) dxgsg7_cat.error() << "no HW support for line smoothing!!\n"; } #endif - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, (DWORD)val); } } @@ -50,14 +50,14 @@ enable_dither(bool val) { #ifdef _DEBUG { - if(val && !(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)) + if(val && !(_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)) dxgsg7_cat.error() << "no HW support for color dithering!!\n"; return; } #endif _dither_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, (DWORD)val); } } @@ -70,7 +70,7 @@ INLINE void DXGraphicsStateGuardian7:: enable_stencil_test(bool val) { if (_stencil_test_enabled != val) { _stencil_test_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, (DWORD)val); } } @@ -95,7 +95,7 @@ INLINE void DXGraphicsStateGuardian7:: enable_blend(bool val) { if (_blend_enabled != val) { _blend_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)val); } } @@ -108,7 +108,7 @@ INLINE void DXGraphicsStateGuardian7:: set_shademode(D3DSHADEMODE val) { if (_CurShadeMode != val) { _CurShadeMode = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, (DWORD)val); } } @@ -116,7 +116,7 @@ INLINE void DXGraphicsStateGuardian7:: enable_primitive_clipping(bool val) { if (_clipping_enabled != val) { _clipping_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, (DWORD)val); } } @@ -129,7 +129,7 @@ INLINE void DXGraphicsStateGuardian7:: enable_fog(bool val) { if ((_fog_enabled != val) && (_doFogType!=None)) { _fog_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, (DWORD)val); } } @@ -143,7 +143,7 @@ enable_alpha_test(bool val ) { if (_alpha_test_enabled != val) { _alpha_test_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, (DWORD)val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, (DWORD)val); } } @@ -160,7 +160,7 @@ call_dxLightModelAmbient( const Colorf& color) #ifdef GSG_VERBOSE dxgsg7_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl; #endif - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, + _pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, D3DRGBA(color[0], color[1], color[2], color[3])); } } @@ -208,12 +208,12 @@ call_dxAlphaFunc(D3DCMPFUNC func, float reference_alpha) { } dxgsg7_cat.debug() << " , " << reference_alpha << ")" << endl; #endif - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func); } if(_alpha_func_refval != reference_alpha) { _alpha_func_refval = reference_alpha; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float } } @@ -223,7 +223,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc ) if (_blend_source_func != sfunc) { _blend_source_func = sfunc; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc); #ifdef GSG_VERBOSE dxgsg7_cat.debug() << "dxSrcBlendFunc("; switch (sfunc) @@ -265,7 +265,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc ) if ( _blend_dest_func != dfunc) { _blend_dest_func = dfunc; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc); #ifdef GSG_VERBOSE dxgsg7_cat.debug() << "dxDstBlendFunc("; switch (dfunc) @@ -307,7 +307,7 @@ INLINE void DXGraphicsStateGuardian7:: enable_zwritemask(bool val) { if (_depth_write_enabled != val) { _depth_write_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, val); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, val); } } diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx index a074a645a6..3cb20fef02 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx @@ -228,21 +228,23 @@ set_color_clear_value(const Colorf& value) { // Description: //////////////////////////////////////////////////////////////////// DXGraphicsStateGuardian7:: -DXGraphicsStateGuardian7(GraphicsWindow *win) : GraphicsStateGuardian(win) { +DXGraphicsStateGuardian7(const FrameBufferProperties &properties) : + GraphicsStateGuardian(properties) +{ // allocate local buffers used during rendering GraphicsStateGuardian::reset(); - ZeroMemory(&scrn,sizeof(DXScreenData)); + _pScrn = NULL; _pCurFvfBufPtr = NULL; _pFvfBufBasePtr = new BYTE[VERT_BUFFER_SIZE]; // allocate storage for vertex info. _index_buf = new WORD[D3DMAXNUMVERTICES]; // allocate storage for vertex index info. _dx_ready = false; _overlay_windows_supported = false; -// scrn.pddsPrimary = scrn.pddsZBuf = scrn.pddsBack = NULL; +// _pScrn->pddsPrimary = _pScrn->pddsZBuf = _pScrn->pddsBack = NULL; // _pDD = NULL; -// scrn.pD3DDevice = NULL; +// _pScrn->pD3DDevice = NULL; // non-dx obj values inited here should not change if resize is // called and dx objects need to be recreated (otherwise they @@ -275,29 +277,48 @@ DXGraphicsStateGuardian7(GraphicsWindow *win) : GraphicsStateGuardian(win) { //////////////////////////////////////////////////////////////////// DXGraphicsStateGuardian7:: ~DXGraphicsStateGuardian7() { - if (scrn.pD3DDevice != NULL) - scrn.pD3DDevice->SetTexture(0, NULL); // this frees reference to the old texture +/* + if(IS_VALID_PTR(_pScrn)) { + assert((_pScrn->pD3DDevice==NULL) || IS_VALID_PTR(_pScrn->pD3DDevice)); + _pScrn->pD3DDevice->SetTexture(0, NULL); // this frees reference to the old texture + } +*/ _pCurTexContext = NULL; + // free_dxgsg_objects() ???????????? + free_pointers(); - delete [] _pFvfBufBasePtr; - delete [] _index_buf; + SAFE_DELETE_ARRAY(_pFvfBufBasePtr) + SAFE_DELETE_ARRAY(_index_buf); } //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian7::reset // Access: Public, Virtual // Description: Resets all internal state as if the gsg were newly -// created. +// created. The GraphicsWindow pointer represents a +// typical window that might be used for this context; +// it may be required to set up the frame buffer +// properly the first time. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: -reset(void) { +reset() { GraphicsStateGuardian::reset(); dxgsg7_cat.error() << "DXGSG reset() not implemented properly yet!\n"; // delete all the objs too, right? //dx_init(); } +void DXGraphicsStateGuardian7:: +set_context(DXScreenData *pNewContextData) { + // dont do copy from window since dx_init sets fields too. + // simpler to keep all of it in one place, so use ptr to window struct + + assert(pNewContextData!=NULL); + _pScrn = pNewContextData; + _pD3DDevice = _pScrn->pD3DDevice; //copy this one field for speed of deref +} + // recreate dx objects without modifying gsg state, other than clearing state cache void DXGraphicsStateGuardian7:: free_dxgsg_objects(void) { @@ -313,17 +334,17 @@ free_dxgsg_objects(void) { _dx_ready = false; - if (scrn.pD3DDevice!=NULL) { - scrn.pD3DDevice->SetTexture(0,NULL); // should release this stuff internally anyway - RELEASE(scrn.pD3DDevice,dxgsg7,"d3dDevice",RELEASE_DOWN_TO_ZERO); + if (_pScrn->pD3DDevice!=NULL) { + _pScrn->pD3DDevice->SetTexture(0,NULL); // should release this stuff internally anyway + RELEASE(_pScrn->pD3DDevice,dxgsg7,"d3dDevice",RELEASE_DOWN_TO_ZERO); } DeleteAllVideoSurfaces(); // Release the DDraw and D3D objects used by the app - RELEASE(scrn.pddsZBuf,dxgsg7,"zbuffer",false); - RELEASE(scrn.pddsBack,dxgsg7,"backbuffer",false); - RELEASE(scrn.pddsPrimary,dxgsg7,"primary surface",false); + RELEASE(_pScrn->pddsZBuf,dxgsg7,"zbuffer",false); + RELEASE(_pScrn->pddsBack,dxgsg7,"backbuffer",false); + RELEASE(_pScrn->pddsPrimary,dxgsg7,"primary surface",false); } HRESULT CALLBACK EnumTexFmtsCallback( LPDDPIXELFORMAT pddpf, VOID* param ) { @@ -356,38 +377,38 @@ dx_init( void) { LPDIRECT3D7 pD3D, LPDIRECT3DDEVICE7 pDevice, RECT viewrect) */ - assert(scrn.pDD!=NULL); - assert(scrn.pD3D!=NULL); - assert(scrn.pD3DDevice!=NULL); - assert(scrn.pddsPrimary!=NULL); - assert(scrn.pddsBack!=NULL); + assert(_pScrn->pDD!=NULL); + assert(_pScrn->pD3D!=NULL); + assert(_pScrn->pD3DDevice!=NULL); + assert(_pScrn->pddsPrimary!=NULL); + assert(_pScrn->pddsBack!=NULL); -// _pDD=scrn.pDD; // save for speed of access -// _pCurD3DDevice = scrn.pD3DDevice; +// _pDD=_pScrn->pDD; // save for speed of access +// _pCurD3DDevice = _pScrn->pD3DDevice; /* _pDD = context; - scrn.pddsPrimary = pri; - scrn.pddsBack = back; - scrn.pddsZBuf = zbuf; - scrn.pD3D = pD3D; - scrn.pD3DDevice = pDevice; + _pScrn->pddsPrimary = pri; + _pScrn->pddsBack = back; + _pScrn->pddsZBuf = zbuf; + _pScrn->pD3D = pD3D; + _pScrn->pD3DDevice = pDevice; _view_rect = viewrect; */ ZeroMemory(&_lmodel_ambient,sizeof(Colorf)); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0x0); + _pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0x0); _clip_plane_bits = 0; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE , 0x0); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE , 0x0); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, true); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, true); _clipping_enabled = true; _CurShadeMode = D3DSHADE_FLAT; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, _CurShadeMode); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, _CurShadeMode); _depth_write_enabled = true; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, _depth_write_enabled); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, _depth_write_enabled); // need to free these properly #ifndef USE_TEXFMTVEC @@ -401,22 +422,22 @@ dx_init( void) { //_point_smooth_enabled = false; _line_smooth_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, false); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, false); _color_material_enabled = false; _normals_enabled = false; _depth_test_enabled = D3DZB_FALSE; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); _blend_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)_blend_enabled); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)_blend_enabled); - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_SRCBLEND, (DWORD*)&_blend_source_func); - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_DESTBLEND, (DWORD*)&_blend_dest_func); + _pScrn->pD3DDevice->GetRenderState(D3DRENDERSTATE_SRCBLEND, (DWORD*)&_blend_source_func); + _pScrn->pD3DDevice->GetRenderState(D3DRENDERSTATE_DESTBLEND, (DWORD*)&_blend_dest_func); _fog_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, _fog_enabled); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, _fog_enabled); _current_projection_mat = LMatrix4f::ident_mat(); _projection_mat_stack_count = 0; @@ -429,7 +450,7 @@ dx_init( void) { // _line_width = 1.0f; // _point_size = 1.0f; - assert(scrn.pddsBack!=NULL); // dxgsg7 is always double-buffered right now + assert(_pScrn->pddsBack!=NULL); // dxgsg7 is always double-buffered right now #ifdef COUNT_DRAWPRIMS global_pD3DDevice = pDevice; @@ -440,20 +461,20 @@ dx_init( void) { _last_testcooplevel_result = S_OK; // only 1 channel on dx currently - _panda_gfx_channel = _win->get_channel(0); + //_panda_gfx_channel = _win->get_channel(0); HRESULT hr; #ifdef USE_TEXFMTVEC - assert(scrn.TexPixFmts.size()==0); + assert(_pScrn->TexPixFmts.size()==0); - if(FAILED(hr=scrn.pD3DDevice->EnumTextureFormats(EnumTexFmtsCallback, &scrn.TexPixFmts))) { + if(FAILED(hr=_pScrn->pD3DDevice->EnumTextureFormats(EnumTexFmtsCallback, &_pScrn->TexPixFmts))) { #else _pTexPixFmts = new DDPIXELFORMAT[MAX_DX_TEXPIXFMTS]; _cNumTexPixFmts = 0; assert(_pTexPixFmts!=NULL); - if(FAILED(hr=scrn.pD3DDevice->EnumTextureFormats(EnumTexFmtsCallback, this))) { + if(FAILED(hr=_pScrn->pD3DDevice->EnumTextureFormats(EnumTexFmtsCallback, this))) { #endif if(hr==D3DERR_TEXTURE_NO_SUPPORT) { dxgsg7_cat.error() << "EnumTextureFormats indicates No Texturing Support on this HW!, exiting...\n"; @@ -464,22 +485,22 @@ dx_init( void) { } DX_DECLARE_CLEAN(DDCAPS,ddCaps); - if (FAILED(hr = scrn.pDD->GetCaps(&ddCaps,NULL))) { + if (FAILED(hr = _pScrn->pDD->GetCaps(&ddCaps,NULL))) { dxgsg7_cat.fatal() << "GetCaps failed on DDraw! hr = " << ConvD3DErrorToString(hr) << "\n"; exit(1); } // s3 virge drivers sometimes give crap values for these - if(scrn.D3DDevDesc.dwMaxTextureWidth==0) - scrn.D3DDevDesc.dwMaxTextureWidth=256; + if(_pScrn->D3DDevDesc.dwMaxTextureWidth==0) + _pScrn->D3DDevDesc.dwMaxTextureWidth=256; - if(scrn.D3DDevDesc.dwMaxTextureHeight==0) - scrn.D3DDevDesc.dwMaxTextureHeight=256; + if(_pScrn->D3DDevDesc.dwMaxTextureHeight==0) + _pScrn->D3DDevDesc.dwMaxTextureHeight=256; // shouldve already been set -// sc_bIsTNLDevice = (IsEqualGUID(scrn.D3DDevDesc.deviceGUID,IID_IDirect3DTnLHalDevice)!=0); +// sc_bIsTNLDevice = (IsEqualGUID(_pScrn->D3DDevDesc.deviceGUID,IID_IDirect3DTnLHalDevice)!=0); - if ((dx_decal_type==GDT_offset) && !(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBIAS)) { + if ((dx_decal_type==GDT_offset) && !(_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBIAS)) { #ifdef _DEBUG // dx7 doesnt support PLANEMASK renderstate #if(DIRECT3D_VERSION < 0x700) @@ -507,14 +528,14 @@ dx_init( void) { #endif #endif - if ((dx_decal_type==GDT_mask) && !(scrn.D3DDevDesc.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKPLANES)) { + if ((dx_decal_type==GDT_mask) && !(_pScrn->D3DDevDesc.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKPLANES)) { #ifdef _DEBUG dxgsg7_cat.debug() << "No hardware support for colorwrite disabling, switching to dx-decal-type 'mask' to 'blend'\n"; #endif dx_decal_type = GDT_blend; } - if (((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(scrn.D3DDevDesc.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKZ)) { + if (((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(_pScrn->D3DDevDesc.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKZ)) { dxgsg7_cat.error() << "dx-decal-type mask impossible to implement, no hardware support for Z-masking, decals will not appear correctly!\n"; } @@ -525,41 +546,41 @@ dx_init( void) { #define REQUIRED_BLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| /*D3DPBLENDCAPS_SRCCOLOR|D3DPBLENDCAPS_INVSRCCOLOR| */ \ D3DPBLENDCAPS_SRCALPHA|D3DPBLENDCAPS_INVSRCALPHA /* | D3DPBLENDCAPS_DESTALPHA|D3DPBLENDCAPS_INVDESTALPHA|D3DPBLENDCAPS_DESTCOLOR|D3DPBLENDCAPS_INVDESTCOLOR*/) - if (((scrn.D3DDevDesc.dpcTriCaps.dwSrcBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS) || - ((scrn.D3DDevDesc.dpcTriCaps.dwDestBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS)) { - dxgsg7_cat.error() << "device is missing alpha blending capabilities, blending may not work correctly: SrcBlendCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwSrcBlendCaps << " DestBlendCaps: "<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwDestBlendCaps << endl; + if (((_pScrn->D3DDevDesc.dpcTriCaps.dwSrcBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS) || + ((_pScrn->D3DDevDesc.dpcTriCaps.dwDestBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS)) { + dxgsg7_cat.error() << "device is missing alpha blending capabilities, blending may not work correctly: SrcBlendCaps: 0x"<< (void*) _pScrn->D3DDevDesc.dpcTriCaps.dwSrcBlendCaps << " DestBlendCaps: "<< (void*) _pScrn->D3DDevDesc.dpcTriCaps.dwDestBlendCaps << endl; } - if (!(scrn.D3DDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_TRANSPARENCY)) { - dxgsg7_cat.error() << "device is missing texture transparency capability, transparency may not work correctly! TextureCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureCaps << endl; + if (!(_pScrn->D3DDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_TRANSPARENCY)) { + dxgsg7_cat.error() << "device is missing texture transparency capability, transparency may not work correctly! TextureCaps: 0x"<< (void*) _pScrn->D3DDevDesc.dpcTriCaps.dwTextureCaps << endl; } // just require trilinear. if it can do that, it can probably do all the lesser point-sampling variations too #define REQUIRED_TEXFILTERCAPS (D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_LINEAR) - if ((scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) { - dxgsg7_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky! TextureFilterCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; + if ((_pScrn->D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) { + dxgsg7_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky! TextureFilterCaps: 0x"<< (void*) _pScrn->D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; } #define REQUIRED_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR) if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) { - dxgsg7_cat.debug() << "device does not have mipmap texturing filtering capability! TextureFilterCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; + dxgsg7_cat.debug() << "device does not have mipmap texturing filtering capability! TextureFilterCaps: 0x"<< (void*) _pScrn->D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; dx_ignore_mipmaps = TRUE; - } else if ((scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_MIPMAP_TEXFILTERCAPS)!=REQUIRED_MIPMAP_TEXFILTERCAPS) { - dxgsg7_cat.debug() << "device is missing tri-linear mipmap filtering capability, texture mipmaps may not supported! TextureFilterCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; + } else if ((_pScrn->D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_MIPMAP_TEXFILTERCAPS)!=REQUIRED_MIPMAP_TEXFILTERCAPS) { + dxgsg7_cat.debug() << "device is missing tri-linear mipmap filtering capability, texture mipmaps may not supported! TextureFilterCaps: 0x"<< (void*) _pScrn->D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; } #define REQUIRED_TEXBLENDCAPS (D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2) - if ((scrn.D3DDevDesc.dwTextureOpCaps & REQUIRED_TEXBLENDCAPS)!=REQUIRED_TEXBLENDCAPS) { - dxgsg7_cat.error() << "device is missing some required texture blending capabilities, texture blending may not work properly! TextureOpCaps: 0x"<< (void*) scrn.D3DDevDesc.dwTextureOpCaps << endl; + if ((_pScrn->D3DDevDesc.dwTextureOpCaps & REQUIRED_TEXBLENDCAPS)!=REQUIRED_TEXBLENDCAPS) { + dxgsg7_cat.error() << "device is missing some required texture blending capabilities, texture blending may not work properly! TextureOpCaps: 0x"<< (void*) _pScrn->D3DDevDesc.dwTextureOpCaps << endl; } - if(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) { + if(_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) { // watch out for drivers that emulate per-pixel fog with per-vertex fog (Riva128, Matrox Millen G200) // some of these require gouraud-shading to be set to work, as if you were using vertex fog _doFogType=PerPixelFog; } else { // every card is going to have vertex fog, since it's implemented in d3d runtime - assert((scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX )!=0); + assert((_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX )!=0); // vtx fog may look crappy if you have large polygons in the foreground and they get clipped, // so you may want to disable it @@ -570,44 +591,44 @@ dx_init( void) { _doFogType = PerVertexFog; // range-based fog only works with vertex fog in dx7/8 - if(dx_use_rangebased_fog && (scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGRANGE)) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_RANGEFOGENABLE, true); + if(dx_use_rangebased_fog && (_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGRANGE)) + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_RANGEFOGENABLE, true); } } - SetRect(&scrn.clip_rect, 0,0,0,0); // no clip rect set + SetRect(&_pScrn->clip_rect, 0,0,0,0); // no clip rect set // Lighting, let's turn it off by default _lighting_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, _lighting_enabled); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, _lighting_enabled); // turn on dithering if the rendertarget is < 8bits/color channel DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_back); - scrn.pddsBack->GetSurfaceDesc(&ddsd_back); + _pScrn->pddsBack->GetSurfaceDesc(&ddsd_back); _dither_enabled = (!dx_no_dithering) && ((ddsd_back.ddpfPixelFormat.dwRGBBitCount < 24) && - (scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, _dither_enabled); + (_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, _dither_enabled); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING,true); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING,true); // Stencil test is off by default _stencil_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, _stencil_test_enabled); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, _stencil_test_enabled); // Antialiasing. enable_line_smooth(false); // enable_multisample(true); _current_fill_mode = RenderModeAttrib::M_filled; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); if(dx_auto_normalize_lighting) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true); // initial clip rect - SetRect(&scrn.clip_rect, 0,0,0,0); // no clip rect set + SetRect(&_pScrn->clip_rect, 0,0,0,0); // no clip rect set // must do SetTSS here because redundant states are filtered out by our code based on current values above, so // initial conditions must be correct @@ -615,7 +636,7 @@ dx_init( void) { _CurTexBlendMode = TextureApplyAttrib::M_modulate; SetTextureBlendMode(_CurTexBlendMode,FALSE); _texturing_enabled = false; - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); // disables texturing + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); // disables texturing // Init more Texture State _CurTexMagFilter=(D3DTEXTUREMAGFILTER) 0x0; @@ -627,23 +648,23 @@ dx_init( void) { // this code must match apply_texture() code for states above // so DX TSS renderstate matches dxgsg7 state - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFP_POINT); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_NONE); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MAXANISOTROPY,_CurTexAnisoDegree); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU,get_texture_wrap_mode(_CurTexWrapModeU)); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV,get_texture_wrap_mode(_CurTexWrapModeV)); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFP_POINT); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_NONE); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MAXANISOTROPY,_CurTexAnisoDegree); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU,get_texture_wrap_mode(_CurTexWrapModeU)); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV,get_texture_wrap_mode(_CurTexWrapModeV)); #ifdef _DEBUG - if ((scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) && + if ((_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) && (dx_global_miplevel_bias!=0.0f)) { - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&dx_global_miplevel_bias)) ); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&dx_global_miplevel_bias)) ); } #endif if (dx_full_screen_antialiasing) { - if(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ANTIALIAS,D3DANTIALIAS_SORTINDEPENDENT); + if(_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT) { + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ANTIALIAS,D3DANTIALIAS_SORTINDEPENDENT); if(dxgsg7_cat.is_debug()) dxgsg7_cat.debug() << "enabling full-screen anti-aliasing\n"; } else { @@ -656,24 +677,24 @@ dx_init( void) { if(dx_force_backface_culling!=0) { if((dx_force_backface_culling > 0) && (dx_force_backface_culling < D3DCULL_FORCE_DWORD)) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling); } else { dx_force_backface_culling=0; if(dxgsg7_cat.is_debug()) dxgsg7_cat.debug() << "error, invalid value for dx-force-backface-culling\n"; } } - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling); #else - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); #endif _alpha_func = D3DCMP_ALWAYS; _alpha_func_refval = 1.0f; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, _alpha_func); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (_alpha_func_refval*255.0f)); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, _alpha_func); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (_alpha_func_refval*255.0f)); _alpha_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, _alpha_test_enabled); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, _alpha_test_enabled); // Make sure the DX state matches all of our initial attribute states. CPT(RenderAttrib) dta = DepthTestAttrib::make(DepthTestAttrib::M_less); @@ -702,14 +723,14 @@ do_clear(const RenderBuffer &buffer) { if (buffer_type & RenderBuffer::T_depth) { flags |= D3DCLEAR_ZBUFFER; - assert(scrn.pddsZBuf!=NULL); + assert(_pScrn->pddsZBuf!=NULL); } if (buffer_type & RenderBuffer::T_back) //set appropriate flags flags |= D3DCLEAR_TARGET; if (buffer_type & RenderBuffer::T_stencil) flags |= D3DCLEAR_STENCIL; - HRESULT hr = scrn.pD3DDevice->Clear(0, NULL, flags, _d3dcolor_clear_value, + HRESULT hr = _pScrn->pD3DDevice->Clear(0, NULL, flags, _d3dcolor_clear_value, (D3DVALUE) _depth_clear_value, (DWORD)_stencil_clear_value); if (hr != DD_OK) dxgsg7_cat.error() << "clear_buffer failed: Clear returned " << ConvD3DErrorToString(hr) << endl; @@ -745,7 +766,7 @@ prepare_display_region() { w, h, 0.0f, 1.0f }; - HRESULT hr = scrn.pD3DDevice->SetViewport(&vp); + HRESULT hr = _pScrn->pD3DDevice->SetViewport(&vp); if (FAILED(hr)) { dxgsg7_cat.error() << "SetViewport(" << l << ", " << b << ", " << w << ", " << h @@ -789,7 +810,7 @@ prepare_lens() { projection_mat; HRESULT hr; - hr = scrn.pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, + hr = _pScrn->pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, (LPD3DMATRIX)new_projection_mat.get_data()); return SUCCEEDED(hr); } @@ -824,17 +845,17 @@ void DXGraphicsStateGuardian7::set_clipper(RECT cliprect) { HRGN hrgn = CreateRectRgn(cliprect.left, cliprect.top, cliprect.right, cliprect.bottom); GetRegionData(hrgn, sizeof(RGNDATAHEADER) + sizeof(RECT), rgn_data); - if (scrn.pddsPrimary->GetClipper(&Clipper) != DD_OK) { - result = scrn.pDD->CreateClipper(0, &Clipper, NULL); + if (_pScrn->pddsPrimary->GetClipper(&Clipper) != DD_OK) { + result = _pScrn->pDD->CreateClipper(0, &Clipper, NULL); result = Clipper->SetClipList(rgn_data, 0); - result = scrn.pddsPrimary->SetClipper(Clipper); + result = _pScrn->pddsPrimary->SetClipper(Clipper); } else { result = Clipper->SetClipList(rgn_data, 0 ); if (result == DDERR_CLIPPERISUSINGHWND) { - result = scrn.pddsPrimary->SetClipper(NULL); - result = scrn.pDD->CreateClipper(0, &Clipper, NULL); + result = _pScrn->pddsPrimary->SetClipper(NULL); + result = _pScrn->pDD->CreateClipper(0, &Clipper, NULL); result = Clipper->SetClipList(rgn_data, 0 ) ; - result = scrn.pddsPrimary->SetClipper(Clipper); + result = _pScrn->pddsPrimary->SetClipper(Clipper); } } free(rgn_data); @@ -884,13 +905,13 @@ report_texmgr_stats() { ZeroMemory(&ddsCaps,sizeof(ddsCaps)); ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; - if(FAILED( hr = scrn.pDD->GetAvailableVidMem(&ddsCaps,&dwVidTotal,&dwVidFree))) { + if(FAILED( hr = _pScrn->pDD->GetAvailableVidMem(&ddsCaps,&dwVidTotal,&dwVidFree))) { dxgsg7_cat.debug() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } ddsCaps.dwCaps = DDSCAPS_TEXTURE; - if(FAILED( hr = scrn.pDD->GetAvailableVidMem(&ddsCaps,&dwTexTotal,&dwTexFree))) { + if(FAILED( hr = _pScrn->pDD->GetAvailableVidMem(&ddsCaps,&dwTexTotal,&dwTexFree))) { dxgsg7_cat.debug() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } @@ -900,7 +921,7 @@ report_texmgr_stats() { ZeroMemory(&tminfo,sizeof(D3DDEVINFO_TEXTUREMANAGER)); if(!bTexStatsRetrievalImpossible) { - hr = scrn.pD3DDevice->GetInfo(D3DDEVINFOID_TEXTUREMANAGER,&tminfo,sizeof(D3DDEVINFO_TEXTUREMANAGER)); + hr = _pScrn->pD3DDevice->GetInfo(D3DDEVINFOID_TEXTUREMANAGER,&tminfo,sizeof(D3DDEVINFO_TEXTUREMANAGER)); if (hr!=D3D_OK) { if (hr==S_FALSE) { static int PrintedMsg=2; @@ -941,7 +962,7 @@ report_texmgr_stats() { D3DDEVINFO_TEXTURING texappinfo; ZeroMemory(&texappinfo,sizeof(D3DDEVINFO_TEXTURING)); - hr = scrn.pD3DDevice->GetInfo(D3DDEVINFOID_TEXTURING,&texappinfo,sizeof(D3DDEVINFO_TEXTURING)); + hr = _pScrn->pD3DDevice->GetInfo(D3DDEVINFOID_TEXTURING,&texappinfo,sizeof(D3DDEVINFO_TEXTURING)); if (hr!=D3D_OK) { dxgsg7_cat.error() << "GetInfo(TEXTURING) failed : result = " << ConvD3DErrorToString(hr) << endl; return; @@ -1347,8 +1368,8 @@ draw_point(GeomPoint *geom, GeomContext *gc) { nassertv((nPrims*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); if(!_bDrawPrimDoSetupVertexBuffer) { - HRESULT hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_POINTLIST, _curFVFflags, _pFvfBufBasePtr, nPrims, NULL); - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nPrims,0); + HRESULT hr = _pScrn->pD3DDevice->DrawPrimitive(D3DPT_POINTLIST, _curFVFflags, _pFvfBufBasePtr, nPrims, NULL); + TestDrawPrimFailure(DrawPrim,hr,_pScrn->pDD,nPrims,0); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_POINTLIST,nPrims); } @@ -1399,8 +1420,8 @@ draw_point(GeomPoint *geom, GeomContext *gc) { dps_data.textureCoords[0].dwStride = sizeof(TexCoordf); } - HRESULT hr = scrn.pD3DDevice->DrawPrimitiveStrided(D3DPT_POINTLIST, _curFVFflags, &dps_data, nPrims, NULL); - TestDrawPrimFailure(DrawPrimStrided,hr,scrn.pDD,nPrims,0); + HRESULT hr = _pScrn->pD3DDevice->DrawPrimitiveStrided(D3DPT_POINTLIST, _curFVFflags, &dps_data, nPrims, NULL); + TestDrawPrimFailure(DrawPrimStrided,hr,_pScrn->pDD,nPrims,0); } _pCurFvfBufPtr = NULL; @@ -1493,13 +1514,13 @@ draw_line(GeomLine* geom, GeomContext *gc) { if(!_bDrawPrimDoSetupVertexBuffer) { if (_tmp_fvfOverrunBuf == NULL) { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); - hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); + hr = _pScrn->pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); } else { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_tmp_fvfOverrunBuf)); - hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _tmp_fvfOverrunBuf, nVerts, NULL); + hr = _pScrn->pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _tmp_fvfOverrunBuf, nVerts, NULL); delete [] _tmp_fvfOverrunBuf; } - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,0); + TestDrawPrimFailure(DrawPrim,hr,_pScrn->pDD,nVerts,0); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINELIST,nVerts); } @@ -1615,8 +1636,8 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); if(!_bDrawPrimDoSetupVertexBuffer) { - HRESULT hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINESTRIP, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,0); + HRESULT hr = _pScrn->pD3DDevice->DrawPrimitive(D3DPT_LINESTRIP, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); + TestDrawPrimFailure(DrawPrim,hr,_pScrn->pDD,nVerts,0); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINESTRIP,nVerts); } @@ -1719,7 +1740,7 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { // ratio built in. // null the world xform, so sprites are orthog to scrn - scrn.pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matIdentity); + _pScrn->pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matIdentity); // only need to change _WORLD xform, _VIEW xform is Identity // precomputation stuff @@ -2018,14 +2039,14 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { // cant do tristrip/fan since it would require 1 call want to make 1 call for multiple quads which arent connected // best we can do is indexed primitive, which sends 2 redundant indices instead of sending 2 redundant full verts - HRESULT hr = scrn.pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, 4*nprims, _index_buf,QUADVERTLISTLEN*nprims,NULL); - TestDrawPrimFailure(DrawIndexedPrim,hr,scrn.pDD,QUADVERTLISTLEN*nprims,nprims); + HRESULT hr = _pScrn->pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, 4*nprims, _index_buf,QUADVERTLISTLEN*nprims,NULL); + TestDrawPrimFailure(DrawIndexedPrim,hr,_pScrn->pDD,QUADVERTLISTLEN*nprims,nprims); _pCurFvfBufPtr = NULL; delete [] SpriteArray; // restore the matrices - scrn.pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, + _pScrn->pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, (LPD3DMATRIX)modelview_mat.get_data()); if(bReEnableDither) enable_dither(true); @@ -2047,7 +2068,7 @@ draw_polygon(GeomPolygon *geom, GeomContext *gc) { // wireframe polygon will be drawn as linestrip, otherwise draw as multi-tri trifan DWORD rstate; - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate); + _pScrn->pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate); if(rstate!=D3DFILL_WIREFRAME) { draw_multitri(geom, D3DPT_TRIANGLEFAN); } else { @@ -2071,7 +2092,7 @@ draw_quad(GeomQuad *geom, GeomContext *gc) { // wireframe quad will be drawn as linestrip, otherwise draw as multi-tri trifan DWORD rstate; - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate); + _pScrn->pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate); if(rstate!=D3DFILL_WIREFRAME) { draw_multitri(geom, D3DPT_TRIANGLEFAN); } else { @@ -2233,8 +2254,8 @@ draw_tri(GeomTri *geom, GeomContext *gc) { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); if(!_bDrawPrimDoSetupVertexBuffer) { - hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,nPrims); + hr = _pScrn->pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); + TestDrawPrimFailure(DrawPrim,hr,_pScrn->pDD,nVerts,nPrims); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_TRIANGLELIST,nVerts); } @@ -2425,8 +2446,8 @@ draw_tri(GeomTri *geom, GeomContext *gc) { DWORD nVerts = nPrims*dwVertsperPrim; - hr = scrn.pD3DDevice->DrawPrimitiveStrided(primtype, fvf_flags, &dps_data, nVerts, NULL); - TestDrawPrimFailure(DrawPrimStrided,hr,scrn.pDD,nVerts,nPrims); + hr = _pScrn->pD3DDevice->DrawPrimitiveStrided(primtype, fvf_flags, &dps_data, nVerts, NULL); + TestDrawPrimFailure(DrawPrimStrided,hr,_pScrn->pDD,nVerts,nPrims); _pCurFvfBufPtr = NULL; } @@ -2442,13 +2463,13 @@ draw_tri(GeomTri *geom, GeomContext *gc) { 0.0f, 0.0f, 33.0, 2.0, 0.0f }; - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_BORDER); - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_BORDER); - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_BORDERCOLOR,MY_D3DRGBA(0,0,0,0)); + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_BORDER); + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_BORDER); + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_BORDERCOLOR,MY_D3DRGBA(0,0,0,0)); _curFVFflags = D3DFVF_XYZ | (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)) ; - HRESULT hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, vert_buf, nPrims*3, NULL); - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nPrims*3,nPrims); + HRESULT hr = _pScrn->pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, vert_buf, nPrims*3, NULL); + TestDrawPrimFailure(DrawPrim,hr,_pScrn->pDD,nPrims*3,nPrims); #endif */ } @@ -2690,8 +2711,8 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { assert((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); if(!_bDrawPrimDoSetupVertexBuffer) { - hr = scrn.pD3DDevice->DrawPrimitive(trilisttype, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,nVerts-2); + hr = _pScrn->pD3DDevice->DrawPrimitive(trilisttype, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); + TestDrawPrimFailure(DrawPrim,hr,_pScrn->pDD,nVerts,nVerts-2); } else { COPYVERTDATA_2_VERTEXBUFFER(trilisttype,nVerts); } @@ -2931,8 +2952,8 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { for (uint j=0;jDrawPrimitiveStrided(trilisttype, fvf_flags, &dps_data, cCurNumStripVerts, NULL); - TestDrawPrimFailure(DrawPrimStrided,hr,scrn.pDD,cCurNumStripVerts,cCurNumStripVerts-2); + hr = _pScrn->pD3DDevice->DrawPrimitiveStrided(trilisttype, fvf_flags, &dps_data, cCurNumStripVerts, NULL); + TestDrawPrimFailure(DrawPrimStrided,hr,_pScrn->pDD,cCurNumStripVerts,cCurNumStripVerts-2); dps_data.position.lpvData = (VOID*)(((char*) dps_data.position.lpvData) + cCurNumStripVerts*dps_data.position.dwStride); dps_data.diffuse.lpvData = (VOID*)(((char*) dps_data.diffuse.lpvData) + cCurNumStripVerts*dps_data.diffuse.dwStride); @@ -3243,8 +3264,8 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) { // possible optimization: make DP 1 for all spheres call here, since trilist is independent tris. // indexes couldnt start w/0 tho, need to pass offset to gensph - HRESULT hr = scrn.pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, _index_buf,nIndices,NULL); - TestDrawPrimFailure(DrawIndexedPrim,hr,scrn.pDD,nVerts,(nIndices>>2)); + HRESULT hr = _pScrn->pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, _index_buf,nIndices,NULL); + TestDrawPrimFailure(DrawIndexedPrim,hr,_pScrn->pDD,nVerts,(nIndices>>2)); } _pCurFvfBufPtr = NULL; @@ -3274,9 +3295,9 @@ prepare_texture(Texture *tex) { #else #ifdef USE_TEXFMTVEC - if (dtc->CreateTexture(scrn.pD3DDevice,scrn.TexPixFmts,&scrn.D3DDevDesc) == NULL) { + if (dtc->CreateTexture(_pScrn->pD3DDevice,_pScrn->TexPixFmts,&_pScrn->D3DDevDesc) == NULL) { #else - if (dtc->CreateTexture(scrn.pD3DDevice,_cNumTexPixFmts,_pTexPixFmts,&scrn.D3DDevDesc) == NULL) { + if (dtc->CreateTexture(_pScrn->pD3DDevice,_cNumTexPixFmts,_pTexPixFmts,&_pScrn->D3DDevDesc) == NULL) { #endif delete dtc; return NULL; @@ -3334,9 +3355,9 @@ apply_texture(TextureContext *tc) { dtc->DeleteTexture(); #ifdef USE_TEXFMTVEC - if (dtc->CreateTexture(scrn.pD3DDevice,scrn.TexPixFmts,&scrn.D3DDevDesc) == NULL) { + if (dtc->CreateTexture(_pScrn->pD3DDevice,_pScrn->TexPixFmts,&_pScrn->D3DDevDesc) == NULL) { #else - if (dtc->CreateTexture(scrn.pD3DDevice,_cNumTexPixFmts,_pTexPixFmts,&scrn.D3DDevDesc) == NULL) { + if (dtc->CreateTexture(_pScrn->pD3DDevice,_cNumTexPixFmts,_pTexPixFmts,&_pScrn->D3DDevDesc) == NULL) { #endif // Oops, we can't re-create the texture for some reason. dxgsg7_cat.error() << "Unable to re-create texture " << *dtc->_texture << endl; @@ -3359,17 +3380,17 @@ apply_texture(TextureContext *tc) { wrapV=tex->get_wrapv(); if (wrapU!=_CurTexWrapModeU) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,get_texture_wrap_mode(wrapU)); + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,get_texture_wrap_mode(wrapU)); _CurTexWrapModeU = wrapU; } if (wrapV!=_CurTexWrapModeV) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,get_texture_wrap_mode(wrapV)); + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,get_texture_wrap_mode(wrapV)); _CurTexWrapModeV = wrapV; } uint aniso_degree=tex->get_anisotropic_degree(); if(_CurTexAnisoDegree != aniso_degree) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_MAXANISOTROPY,aniso_degree); + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_MAXANISOTROPY,aniso_degree); _CurTexAnisoDegree = aniso_degree; } @@ -3390,7 +3411,7 @@ apply_texture(TextureContext *tc) { if(_CurTexMagFilter!=newMagFilter) { _CurTexMagFilter=newMagFilter; - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, newMagFilter); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, newMagFilter); } #ifdef _DEBUG @@ -3428,17 +3449,17 @@ apply_texture(TextureContext *tc) { if(newMinFilter!=_CurTexMinFilter) { _CurTexMinFilter = newMinFilter; - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, newMinFilter); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, newMinFilter); } if(newMipFilter!=_CurTexMipFilter) { _CurTexMipFilter = newMipFilter; - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, newMipFilter); + _pScrn->pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, newMipFilter); } // bugbug: does this handle the case of untextured geometry? // we dont see this bug cause we never mix textured/untextured - scrn.pD3DDevice->SetTexture(0,dtc->_surface); + _pScrn->pD3DDevice->SetTexture(0,dtc->_surface); #if 0 if (dtc!=NULL) { @@ -3556,6 +3577,10 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { +#if 1 + dxgsg7_cat.error() + << "texture_to_pixel_buffer unimplemented!\n"; +#else nassertv(tc != NULL && pb != NULL); Texture *tex = tc->_texture; @@ -3572,6 +3597,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { texture_to_pixel_buffer(tc, pb, dr); pop_frame_buffer(old_fb); +#endif } //////////////////////////////////////////////////////////////////// @@ -3617,7 +3643,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { */ - (void) ConvertDDSurftoPixBuf(pb,((_cur_read_pixel_buffer & RenderBuffer::T_back) ? scrn.pddsBack : scrn.pddsPrimary)); + (void) ConvertDDSurftoPixBuf(pb,((_cur_read_pixel_buffer & RenderBuffer::T_back) ? _pScrn->pddsBack : _pScrn->pddsPrimary)); nassertv(!pb->_image.empty()); } @@ -3646,7 +3672,7 @@ void DXGraphicsStateGuardian7::apply_material( const Material* material ) { cur_material.dcvSpecular = *(D3DCOLORVALUE *)(material->get_specular().get_data()); cur_material.dcvEmissive = *(D3DCOLORVALUE *)(material->get_emission().get_data()); cur_material.dvPower = material->get_shininess(); - scrn.pD3DDevice->SetMaterial(&cur_material); + _pScrn->pD3DDevice->SetMaterial(&cur_material); } //////////////////////////////////////////////////////////////////// @@ -3664,10 +3690,10 @@ apply_fog(Fog *fog) { // should probably avoid doing redundant SetRenderStates, but whatever - scrn.pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)_doFogType, d3dfogmode); + _pScrn->pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)_doFogType, d3dfogmode); const Colorf &fog_colr = fog->get_color(); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f)); // Alpha bits are not used // do we need to adjust fog start/end values based on D3DPRASTERCAPS_WFOG/D3DPRASTERCAPS_ZFOG ? @@ -3679,9 +3705,9 @@ apply_fog(Fog *fog) { float onset, opaque; fog->get_linear_range(onset, opaque); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGSTART, + _pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGSTART, *((LPDWORD) (&onset)) ); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGEND, + _pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGEND, *((LPDWORD) (&opaque)) ); } break; @@ -3690,7 +3716,7 @@ apply_fog(Fog *fog) { { // Exponential fog is always camera-relative. float fog_density = fog->get_exp_density(); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGDENSITY, + _pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGDENSITY, *((LPDWORD) (&fog_density)) ); } break; @@ -3709,47 +3735,47 @@ void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexB //if bCanJustEnable, then we only need to make sure ColorOp is turned on and set properly if (bCanJustEnable && (TexBlendMode==_CurTexBlendMode)) { // just reset COLOROP 0 to enable pipeline, rest is already set properly - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); return; } - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); switch (TexBlendMode) { case TextureApplyAttrib::M_modulate: // emulates GL_MODULATE glTexEnv mode // want to multiply tex-color*pixel color to emulate GL modulate blend (see glTexEnv) - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; case TextureApplyAttrib::M_decal: // emulates GL_DECAL glTexEnv mode - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); break; case TextureApplyAttrib::M_replace: - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); break; case TextureApplyAttrib::M_add: - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); // since I'm making up 'add' mode, use modulate. "adding" alpha never makes sense right? - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; case TextureApplyAttrib::M_blend: @@ -3761,21 +3787,21 @@ void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexB GL requires 2 independent operations on 3 input vars for this mode DX texture pipeline requires re-using input of last stage on each new op, so I dont think exact emulation is possible - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); need to SetTexture(1,tex) also - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE ); wrong - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR ); + _pScrn->pD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE ); wrong + _pScrn->pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pScrn->pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR ); - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT ); + _pScrn->pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + _pScrn->pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT ); */ @@ -3804,7 +3830,7 @@ enable_texturing(bool val) { // I'm going to allow enabling texturing even if no tex has been set yet, seems to cause no probs if (val == FALSE) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); + _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); } else { SetTextureBlendMode(_CurTexBlendMode,TRUE); } @@ -3818,7 +3844,7 @@ enable_texturing(bool val) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: issue_transform(const TransformState *transform) { - scrn.pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, + _pScrn->pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, (LPD3DMATRIX)transform->get_mat().get_data()); } @@ -3877,11 +3903,11 @@ issue_render_mode(const RenderModeAttrib *attrib) { switch (mode) { case RenderModeAttrib::M_filled: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); break; case RenderModeAttrib::M_wireframe: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME); break; default: @@ -3911,11 +3937,11 @@ issue_depth_test(const DepthTestAttrib *attrib) { DepthTestAttrib::PandaCompareFunc mode = attrib->get_mode(); if (mode == DepthTestAttrib::M_none) { _depth_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); } else { _depth_test_enabled = true; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, (D3DCMPFUNC) mode); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, (D3DCMPFUNC) mode); } } @@ -3957,13 +3983,13 @@ issue_cull_face(const CullFaceAttrib *attrib) { switch (mode) { case CullFaceAttrib::M_cull_none: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); break; case CullFaceAttrib::M_cull_clockwise: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW); break; case CullFaceAttrib::M_cull_counter_clockwise: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); break; default: dxgsg7_cat.error() @@ -3997,7 +4023,7 @@ issue_fog(const FogAttrib *attrib) { void DXGraphicsStateGuardian7:: issue_depth_offset(const DepthOffsetAttrib *attrib) { int offset = attrib->get_offset(); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, offset); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, offset); } //////////////////////////////////////////////////////////////////// @@ -4038,7 +4064,7 @@ bind_light(PointLight *light, int light_id) { alight.dvAttenuation1 = (D3DVALUE)att[1]; alight.dvAttenuation2 = (D3DVALUE)att[2]; - HRESULT res = scrn.pD3DDevice->SetLight(light_id, &alight); + HRESULT res = _pScrn->pD3DDevice->SetLight(light_id, &alight); } //////////////////////////////////////////////////////////////////// @@ -4079,7 +4105,7 @@ bind_light(DirectionalLight *light, int light_id) { alight.dvAttenuation1 = 0.0f; // linear alight.dvAttenuation2 = 0.0f; // quadratic - HRESULT res = scrn.pD3DDevice->SetLight(light_id, &alight); + HRESULT res = _pScrn->pD3DDevice->SetLight(light_id, &alight); } //////////////////////////////////////////////////////////////////// @@ -4129,9 +4155,10 @@ bind_light(Spotlight *light, int light_id) { alight.dvAttenuation1 = (D3DVALUE)att[1]; alight.dvAttenuation2 = (D3DVALUE)att[2]; - HRESULT res = scrn.pD3DDevice->SetLight(light_id, &alight); + HRESULT res = _pScrn->pD3DDevice->SetLight(light_id, &alight); } +#if 0 //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian7::begin_frame // Access: Public, Virtual @@ -4149,6 +4176,7 @@ bool DXGraphicsStateGuardian7:: begin_frame() { return GraphicsStateGuardian::begin_frame(); } +#endif //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian7::begin_scene @@ -4171,7 +4199,7 @@ begin_scene() { return false; } - HRESULT hr = scrn.pD3DDevice->BeginScene(); + HRESULT hr = _pScrn->pD3DDevice->BeginScene(); if (FAILED(hr)) { if ((hr == DDERR_SURFACELOST) || (hr == DDERR_SURFACEBUSY)) { @@ -4205,7 +4233,7 @@ begin_scene() { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: end_scene() { - HRESULT hr = scrn.pD3DDevice->EndScene(); + HRESULT hr = _pScrn->pD3DDevice->EndScene(); if (FAILED(hr)) { if ((hr == DDERR_SURFACELOST) || (hr == DDERR_SURFACEBUSY)) { @@ -4491,7 +4519,7 @@ get_fog_mode_type(Fog::Mode m) const { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: enable_lighting(bool enable) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, (DWORD)enable); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, (DWORD)enable); } //////////////////////////////////////////////////////////////////// @@ -4504,7 +4532,7 @@ enable_lighting(bool enable) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: set_ambient_light(const Colorf &color) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, Colorf_to_D3DCOLOR(color)); } @@ -4517,7 +4545,7 @@ set_ambient_light(const Colorf &color) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: enable_light(int light_id, bool enable) { - HRESULT res = scrn.pD3DDevice->LightEnable(light_id, enable); + HRESULT res = _pScrn->pD3DDevice->LightEnable(light_id, enable); #ifdef GSG_VERBOSE dxgsg7_cat.debug() @@ -4563,7 +4591,7 @@ enable_clip_plane(int plane_id, bool enable) { _clip_plane_bits &= ~bitflag; } - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, _clip_plane_bits); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, _clip_plane_bits); } //////////////////////////////////////////////////////////////////// @@ -4584,7 +4612,7 @@ bind_clip_plane(PlaneNode *plane, int plane_id) { LMatrix4f rel_mat = plane_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default); Planef world_plane = plane->get_plane() * rel_mat; - scrn.pD3DDevice->SetClipPlane(plane_id, (float *)world_plane.get_data()); + _pScrn->pD3DDevice->SetClipPlane(plane_id, (float *)world_plane.get_data()); } //////////////////////////////////////////////////////////////////// @@ -4668,12 +4696,9 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, void DXGraphicsStateGuardian7:: free_pointers() { #ifdef USE_TEXFMTVEC - scrn.TexPixFmts.clear(); + _pScrn->TexPixFmts.clear(); #else - if (_pTexPixFmts != NULL) { - delete [] _pTexPixFmts; - _pTexPixFmts = NULL; - } + SAFE_DELETE_ARRAY(_pTexPixFmts); #endif } @@ -4766,46 +4791,46 @@ dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) { // msg already delivered to d3d.dll and it's unloaded itself if(!bAtExitFnEverCalled) { - PRINTREFCNT(scrn.pDD,"exit start IDirectDraw7"); + PRINTREFCNT(_pScrn->pDD,"exit start IDirectDraw7"); // these 2 calls release ddraw surfaces and vbuffers. unsafe unless not on exit release_all_textures(); release_all_geoms(); - PRINTREFCNT(scrn.pDD,"after release_all_textures IDirectDraw7"); + PRINTREFCNT(_pScrn->pDD,"after release_all_textures IDirectDraw7"); // Do a safe check for releasing the D3DDEVICE. RefCount should be zero. - // if we're called from exit(), scrn.pD3DDevice may already have been released - if (scrn.pD3DDevice!=NULL) { - scrn.pD3DDevice->SetTexture(0,NULL); // should release this stuff internally anyway - RELEASE(scrn.pD3DDevice,dxgsg7,"d3dDevice",RELEASE_DOWN_TO_ZERO); + // if we're called from exit(), _pScrn->pD3DDevice may already have been released + if (_pScrn->pD3DDevice!=NULL) { + _pScrn->pD3DDevice->SetTexture(0,NULL); // should release this stuff internally anyway + RELEASE(_pScrn->pD3DDevice,dxgsg7,"d3dDevice",RELEASE_DOWN_TO_ZERO); } - PRINTREFCNT(scrn.pDD,"after d3ddevice release IDirectDraw7"); + PRINTREFCNT(_pScrn->pDD,"after d3ddevice release IDirectDraw7"); - if((scrn.pddsBack!=NULL)&&(scrn.pddsZBuf!=NULL)) - scrn.pddsBack->DeleteAttachedSurface(0x0,scrn.pddsZBuf); + if((_pScrn->pddsBack!=NULL)&&(_pScrn->pddsZBuf!=NULL)) + _pScrn->pddsBack->DeleteAttachedSurface(0x0,_pScrn->pddsZBuf); // Release the DDraw and D3D objects used by the app - RELEASE(scrn.pddsZBuf,dxgsg7,"zbuffer",false); + RELEASE(_pScrn->pddsZBuf,dxgsg7,"zbuffer",false); - PRINTREFCNT(scrn.pDD,"before releasing d3d obj, IDirectDraw7"); - RELEASE(scrn.pD3D,dxgsg7,"IDirect3D7 scrn.pD3D",false); //RELEASE_DOWN_TO_ZERO); - PRINTREFCNT(scrn.pDD,"after releasing d3d obj, IDirectDraw7"); + PRINTREFCNT(_pScrn->pDD,"before releasing d3d obj, IDirectDraw7"); + RELEASE(_pScrn->pD3D,dxgsg7,"IDirect3D7 _pScrn->pD3D",false); //RELEASE_DOWN_TO_ZERO); + PRINTREFCNT(_pScrn->pDD,"after releasing d3d obj, IDirectDraw7"); - // is it wrong to explictly release scrn.pddsBack if it is part of complex surface chain (as in fullscrn mode)? - RELEASE(scrn.pddsBack,dxgsg7,"backbuffer",false); - RELEASE(scrn.pddsPrimary,dxgsg7,"primary surface",false); + // is it wrong to explictly release _pScrn->pddsBack if it is part of complex surface chain (as in full_pScrn->mode)? + RELEASE(_pScrn->pddsBack,dxgsg7,"backbuffer",false); + RELEASE(_pScrn->pddsPrimary,dxgsg7,"primary surface",false); - PRINTREFCNT(scrn.pDD,"after releasing all surfs, IDirectDraw7"); + PRINTREFCNT(_pScrn->pDD,"after releasing all surfs, IDirectDraw7"); } // 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 (scrn.pDD!=NULL) { + if (_pScrn->pDD!=NULL) { if(bRestoreDisplayMode) { - HRESULT hr = scrn.pDD->RestoreDisplayMode(); + HRESULT hr = _pScrn->pDD->RestoreDisplayMode(); if(dxgsg7_cat.is_spam()) dxgsg7_cat.spam() << "dx_cleanup - Restoring original desktop DisplayMode\n"; if(FAILED(hr)) { @@ -4817,11 +4842,11 @@ dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) { // if exit() called, there is definitely no more need for the IDDraw object, // so we can make sure it's fully released // note currently this is never called - RELEASE(scrn.pDD,dxgsg7,"IDirectDraw7 scrn.pDD", RELEASE_DOWN_TO_ZERO); + RELEASE(_pScrn->pDD,dxgsg7,"IDirectDraw7 _pScrn->pDD", RELEASE_DOWN_TO_ZERO); } else { // seems wrong to release to zero, since it might be being used somewhere else? - RELEASE(scrn.pDD,dxgsg7,"IDirectDraw7 scrn.pDD", false); + RELEASE(_pScrn->pDD,dxgsg7,"IDirectDraw7 _pScrn->pDD", false); if(refcnt>0) { if(dxgsg7_cat.is_spam()) dxgsg7_cat.debug() << "dx_cleanup - warning IDDraw7 refcnt = " << refcnt << ", should be zero!\n"; @@ -4835,33 +4860,33 @@ dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) { // Description: Recreate the back buffer and zbuffers at the new size //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: -dx_setup_after_resize(RECT viewrect, HWND mwindow) { - if (scrn.pddsBack == NULL) // nothing created yet +dx_setup_after_resize(RECT *pViewRect) { + if (_pScrn->pddsBack == NULL) // nothing created yet return; // for safety, need some better error-cleanup here - assert((scrn.pddsPrimary!=NULL) && (scrn.pddsBack!=NULL) && (scrn.pddsZBuf!=NULL)); + assert((_pScrn->pddsPrimary!=NULL) && (_pScrn->pddsBack!=NULL) && (_pScrn->pddsZBuf!=NULL)); DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_back); DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_zbuf); - scrn.pddsBack->GetSurfaceDesc(&ddsd_back); - scrn.pddsZBuf->GetSurfaceDesc(&ddsd_zbuf); + _pScrn->pddsBack->GetSurfaceDesc(&ddsd_back); + _pScrn->pddsZBuf->GetSurfaceDesc(&ddsd_zbuf); ULONG refcnt; - if((scrn.pddsBack!=NULL)&&(scrn.pddsZBuf!=NULL)) - scrn.pddsBack->DeleteAttachedSurface(0x0,scrn.pddsZBuf); + if((_pScrn->pddsBack!=NULL)&&(_pScrn->pddsZBuf!=NULL)) + _pScrn->pddsBack->DeleteAttachedSurface(0x0,_pScrn->pddsZBuf); - RELEASE(scrn.pddsZBuf,dxgsg7,"zbuffer",false); - RELEASE(scrn.pddsBack,dxgsg7,"backbuffer",false); - RELEASE(scrn.pddsPrimary,dxgsg7,"primary surface",false); + RELEASE(_pScrn->pddsZBuf,dxgsg7,"zbuffer",false); + RELEASE(_pScrn->pddsBack,dxgsg7,"backbuffer",false); + RELEASE(_pScrn->pddsPrimary,dxgsg7,"primary surface",false); - assert((scrn.pddsPrimary == NULL) && (scrn.pddsBack == NULL) && (scrn.pddsZBuf == NULL)); - scrn.view_rect = viewrect; + assert((_pScrn->pddsPrimary == NULL) && (_pScrn->pddsBack == NULL) && (_pScrn->pddsZBuf == NULL)); + _pScrn->view_rect = *pViewRect; - DWORD renderWid = scrn.view_rect.right - scrn.view_rect.left; - DWORD renderHt = scrn.view_rect.bottom - scrn.view_rect.top; + DWORD renderWid = _pScrn->view_rect.right - _pScrn->view_rect.left; + DWORD renderHt = _pScrn->view_rect.bottom - _pScrn->view_rect.top; ddsd_back.dwWidth = ddsd_zbuf.dwWidth = renderWid; ddsd_back.dwHeight = ddsd_zbuf.dwHeight = renderHt; @@ -4871,20 +4896,20 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; ddsd.dwFlags = DDSD_CAPS; - PRINTVIDMEM(scrn.pDD,&ddsd.ddsCaps,"resize primary surf"); + PRINTVIDMEM(_pScrn->pDD,&ddsd.ddsCaps,"resize primary surf"); HRESULT hr; - if (FAILED(hr = scrn.pDD->CreateSurface( &ddsd, &scrn.pddsPrimary, NULL ))) { + if (FAILED(hr = _pScrn->pDD->CreateSurface( &ddsd, &_pScrn->pddsPrimary, NULL ))) { dxgsg7_cat.fatal() << "resize() - CreateSurface failed for primary : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } - if (!_win->is_fullscreen()) { + if (!_pScrn->bIsFullScreen) { // Create a clipper object which handles all our clipping for cases when // our window is partially obscured by other windows. LPDIRECTDRAWCLIPPER Clipper; - if (FAILED(hr = scrn.pDD->CreateClipper( 0, &Clipper, NULL ))) { + if (FAILED(hr = _pScrn->pDD->CreateClipper( 0, &Clipper, NULL ))) { dxgsg7_cat.fatal() << "CreateClipper after resize failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); @@ -4892,8 +4917,8 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { // Associate the clipper with our window. Note that, afterwards, the // clipper is internally referenced by the primary surface, so it is safe // to release our local reference to it. - Clipper->SetHWnd( 0, mwindow ); - scrn.pddsPrimary->SetClipper( Clipper ); + Clipper->SetHWnd( 0, _pScrn->hWnd ); + _pScrn->pddsPrimary->SetClipper( Clipper ); Clipper->Release(); } @@ -4903,28 +4928,28 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { ddsd_back.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; // just to make sure ddsd_back.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; - PRINTVIDMEM(scrn.pDD,&ddsd_back.ddsCaps,"resize backbuffer surf"); + PRINTVIDMEM(_pScrn->pDD,&ddsd_back.ddsCaps,"resize backbuffer surf"); - if (FAILED(hr = scrn.pDD->CreateSurface( &ddsd_back, &scrn.pddsBack, NULL ))) { + if (FAILED(hr = _pScrn->pDD->CreateSurface( &ddsd_back, &_pScrn->pddsBack, NULL ))) { dxgsg7_cat.fatal() << "resize() - CreateSurface failed for backbuffer : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } - PRINTVIDMEM(scrn.pDD,&ddsd_back.ddsCaps,"resize zbuffer surf"); + PRINTVIDMEM(_pScrn->pDD,&ddsd_back.ddsCaps,"resize zbuffer surf"); // Recreate and attach a z-buffer. - if (FAILED(hr = scrn.pDD->CreateSurface( &ddsd_zbuf, &scrn.pddsZBuf, NULL ))) { + if (FAILED(hr = _pScrn->pDD->CreateSurface( &ddsd_zbuf, &_pScrn->pddsZBuf, NULL ))) { dxgsg7_cat.fatal() << "resize() - CreateSurface failed for Z buffer: result = " << ConvD3DErrorToString(hr) << endl; exit(1); } // Attach the z-buffer to the back buffer. - if ((hr = scrn.pddsBack->AddAttachedSurface( scrn.pddsZBuf ) ) != DD_OK) { + if ((hr = _pScrn->pddsBack->AddAttachedSurface( _pScrn->pddsZBuf ) ) != DD_OK) { dxgsg7_cat.fatal() << "resize() - AddAttachedSurface failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } - if ((hr = scrn.pD3DDevice->SetRenderTarget(scrn.pddsBack,0x0) ) != DD_OK) { + if ((hr = _pScrn->pD3DDevice->SetRenderTarget(_pScrn->pddsBack,0x0) ) != DD_OK) { dxgsg7_cat.fatal() << "resize() - SetRenderTarget failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } @@ -4940,13 +4965,15 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { renderWid, renderHt, 0.0f, 1.0f }; - hr = scrn.pD3DDevice->SetViewport( &vp ); + hr = _pScrn->pD3DDevice->SetViewport( &vp ); if (hr != DD_OK) { dxgsg7_cat.fatal() << "SetViewport failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } */ + +// _dxgsg->set_context(&_wcontext); } bool refill_tex_callback(TextureContext *tc,void *void_dxgsg7_ptr) { @@ -4976,9 +5003,9 @@ bool recreate_tex_callback(TextureContext *tc,void *void_dxgsg7_ptr) { LPDIRECTDRAWSURFACE7 ddtex = #ifdef USE_TEXFMTVEC - dtc->CreateTexture(dxgsg7->scrn.pD3DDevice,scrn.TexPixFmts,&dxgsg7->scrn.D3DDevDesc); + dtc->CreateTexture(dxgsg7->_pScrn->pD3DDevice,_pScrn->TexPixFmts,&dxgsg7->_pScrn->D3DDevDesc); #else - dtc->CreateTexture(dxgsg7->scrn.pD3DDevice,dxgsg7->_cNumTexPixFmts,dxgsg7->_pTexPixFmts,&dxgsg7->scrn.D3DDevDesc); + dtc->CreateTexture(dxgsg7->_pScrn->pD3DDevice,dxgsg7->_cNumTexPixFmts,dxgsg7->_pTexPixFmts,&dxgsg7->_pScrn->D3DDevDesc); #endif return ddtex!=NULL; } @@ -5016,7 +5043,7 @@ HRESULT DXGraphicsStateGuardian7::RestoreAllVideoSurfaces(void) { // note: could go through and just restore surfs that return IsLost() true // apparently that isnt as reliable w/some drivers tho - if (FAILED(hr = scrn.pDD->RestoreAllSurfaces() )) { + if (FAILED(hr = _pScrn->pDD->RestoreAllSurfaces() )) { dxgsg7_cat.fatal() << "RestoreAllSurfs failed : result = " << ConvD3DErrorToString(hr) << endl; exit(1); } @@ -5036,12 +5063,12 @@ HRESULT DXGraphicsStateGuardian7::RestoreAllVideoSurfaces(void) { // Description: Repaint primary buffer from back buffer //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7::show_frame(void) { - if(scrn.pddsPrimary==NULL) + if(_pScrn->pddsPrimary==NULL) return; // DO_PSTATS_STUFF(PStatTimer timer(_win->_swap_pcollector)); // this times just the flip, so it must go here in dxgsg7, instead of wdxdisplay, which would time the whole frame - if (_win->is_fullscreen()) { + if (_pScrn->bIsFullScreen) { show_full_screen_frame(); } else { show_windowed_frame(); @@ -5069,23 +5096,23 @@ support_overlay_window(bool flag) { // Disable support for overlay windows. _overlay_windows_supported = false; - if (_win->is_fullscreen()) { - scrn.pddsPrimary->SetClipper(NULL); + if (_pScrn->bIsFullScreen) { + _pScrn->pddsPrimary->SetClipper(NULL); } } else if (!_overlay_windows_supported && flag) { // Enable support for overlay windows. _overlay_windows_supported = true; - if (_win->is_fullscreen()) { + if (_pScrn->bIsFullScreen) { // Create a Clipper object to blt the whole screen. LPDIRECTDRAWCLIPPER Clipper; - if (scrn.pDD->CreateClipper(0, &Clipper, NULL) == DD_OK) { - Clipper->SetHWnd(0, scrn.hWnd); - scrn.pddsPrimary->SetClipper(Clipper); + if (_pScrn->pDD->CreateClipper(0, &Clipper, NULL) == DD_OK) { + Clipper->SetHWnd(0, _pScrn->hWnd); + _pScrn->pddsPrimary->SetClipper(Clipper); } - scrn.pDD->FlipToGDISurface(); + _pScrn->pDD->FlipToGDISurface(); Clipper->Release(); } } @@ -5119,11 +5146,11 @@ void DXGraphicsStateGuardian7::show_full_screen_frame(void) { // bugbug: dont we want triple buffering instead of wasting time // waiting for vsync? - hr = scrn.pddsPrimary->Flip( NULL, dwFlipFlags); + hr = _pScrn->pddsPrimary->Flip( NULL, dwFlipFlags); } else { // If we're asking for overlay windows, we have to blt instead of // flip, so we don't lose the window. - hr = scrn.pddsPrimary->Blt( NULL, scrn.pddsBack, NULL, DDBLT_WAIT, NULL ); + hr = _pScrn->pddsPrimary->Blt( NULL, _pScrn->pddsBack, NULL, DDBLT_WAIT, NULL ); } if(FAILED(hr)) { @@ -5166,10 +5193,10 @@ void DXGraphicsStateGuardian7::show_windowed_frame(void) { bltfx.dwDDFX |= DDBLTFX_NOTEARING; // hmm, does any driver actually recognize this flag? } - hr = scrn.pddsPrimary->Blt( &scrn.view_rect, scrn.pddsBack, NULL, DDBLT_DDFX | DDBLT_WAIT, &bltfx ); + hr = _pScrn->pddsPrimary->Blt( &_pScrn->view_rect, _pScrn->pddsBack, NULL, DDBLT_DDFX | DDBLT_WAIT, &bltfx ); if (dx_sync_video) { - HRESULT hr = scrn.pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL); + HRESULT hr = _pScrn->pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL); if(hr != DD_OK) { dxgsg7_cat.error() << "WaitForVerticalBlank() failed : " << ConvD3DErrorToString(hr) << endl; exit(1); @@ -5189,7 +5216,7 @@ void DXGraphicsStateGuardian7::show_windowed_frame(void) { bool DXGraphicsStateGuardian7:: CheckCooperativeLevel(bool bDoReactivateWindow) { - HRESULT hr = scrn.pDD->TestCooperativeLevel(); + HRESULT hr = _pScrn->pDD->TestCooperativeLevel(); if (SUCCEEDED(_last_testcooplevel_result)) { if (SUCCEEDED(hr)) { @@ -5278,11 +5305,11 @@ CheckCooperativeLevel(bool bDoReactivateWindow) { // Description: we receive the new x and y position of the client //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7::adjust_view_rect(int x, int y) { - if (scrn.view_rect.left != x || scrn.view_rect.top != y) { - scrn.view_rect.right = x + scrn.view_rect.right - scrn.view_rect.left; - scrn.view_rect.left = x; - scrn.view_rect.bottom = y + scrn.view_rect.bottom - scrn.view_rect.top; - scrn.view_rect.top = y; + if (_pScrn->view_rect.left != x || _pScrn->view_rect.top != y) { + _pScrn->view_rect.right = x + _pScrn->view_rect.right - _pScrn->view_rect.left; + _pScrn->view_rect.left = x; + _pScrn->view_rect.bottom = y + _pScrn->view_rect.bottom - _pScrn->view_rect.top; + _pScrn->view_rect.top = y; // set_clipper(clip_rect); } @@ -5756,14 +5783,14 @@ prepare_geom_node(GeomNode *node) { HRESULT hr; LPDIRECT3D7 pD3D; - assert(scrn.pD3DDevice!=NULL); - hr=scrn.pD3DDevice->GetDirect3D(&pD3D); + assert(_pScrn->pD3DDevice!=NULL); + hr=_pScrn->pD3DDevice->GetDirect3D(&pD3D); assert(!FAILED(hr)); LPDIRECT3DVERTEXBUFFER7 pD3DVertexBuffer; DX_DECLARE_CLEAN(D3DVERTEXBUFFERDESC, VBdesc); VBdesc.dwCaps = D3DVBCAPS_WRITEONLY; - VBdesc.dwCaps |= scrn.bIsTNLDevice ? 0x0 : D3DVBCAPS_SYSTEMMEMORY; + VBdesc.dwCaps |= _pScrn->bIsTNLDevice ? 0x0 : D3DVBCAPS_SYSTEMMEMORY; VBdesc.dwFVF=fvfFlags; VBdesc.dwNumVertices=cNumVerts; @@ -5776,7 +5803,7 @@ prepare_geom_node(GeomNode *node) { dx_gnc->_pVB = pD3DVertexBuffer; - if(!scrn.bIsTNLDevice) { + if(!_pScrn->bIsTNLDevice) { // create VB for ProcessVerts to xform to fvfFlags&=~D3DFVF_XYZ; // switch to xformed vert type @@ -5845,7 +5872,7 @@ prepare_geom_node(GeomNode *node) { assert(cNumVerts==dx_gnc->_num_verts); - hr=dx_gnc->_pVB->Optimize(scrn.pD3DDevice,0x0); + hr=dx_gnc->_pVB->Optimize(_pScrn->pD3DDevice,0x0); if(FAILED(hr)) { dxgsg7_cat.error() << "error optimizing vertex buffer: " << ConvD3DErrorToString(hr) << endl; delete dx_gnc; @@ -5905,10 +5932,10 @@ draw_geom_node(GeomNode *node, const RenderState *state, GeomNodeContext *gnc) { #ifdef _DEBUG assert(dx_gnc->_pVB!=NULL); - assert((!scrn.bIsTNLDevice)==(dx_gnc->_pXformed_VB!=NULL)); + assert((!_pScrn->bIsTNLDevice)==(dx_gnc->_pXformed_VB!=NULL)); #endif - if(!scrn.bIsTNLDevice) { + if(!_pScrn->bIsTNLDevice) { HRESULT hr; DWORD PVOp=D3DVOP_CLIP | D3DVOP_TRANSFORM | D3DVOP_EXTENTS; @@ -5925,7 +5952,7 @@ draw_geom_node(GeomNode *node, const RenderState *state, GeomNodeContext *gnc) { PVOp|=D3DVOP_LIGHT; } - hr=dx_gnc->_pXformed_VB->ProcessVertices(PVOp,0,dx_gnc->_num_verts,dx_gnc->_pVB,0,scrn.pD3DDevice,0x0); + hr=dx_gnc->_pXformed_VB->ProcessVertices(PVOp,0,dx_gnc->_num_verts,dx_gnc->_pVB,0,_pScrn->pD3DDevice,0x0); if(FAILED(hr)) { dxgsg7_cat.error() << "error in ProcessVertices: " << ConvD3DErrorToString(hr) << endl; exit(1); @@ -5933,7 +5960,7 @@ draw_geom_node(GeomNode *node, const RenderState *state, GeomNodeContext *gnc) { // disable clipping, since VB is already xformed and clipped if(_clipping_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, false); + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, false); } // assume we need gouraud for now. we can make this more complex to select flat conditionally later @@ -5948,20 +5975,20 @@ draw_geom_node(GeomNode *node, const RenderState *state, GeomNodeContext *gnc) { DPInfo *dpi=&dx_gnc->_PrimInfo[i]; LPDIRECT3DVERTEXBUFFER7 pVB; - if(scrn.bIsTNLDevice) { + if(_pScrn->bIsTNLDevice) { pVB=dx_gnc->_pVB; } else { pVB=dx_gnc->_pXformed_VB; } - HRESULT hr = scrn.pD3DDevice->DrawPrimitiveVB(dpi->primtype,pVB,cur_startvert,dpi->nVerts,0x0); - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,dpi->nVerts,0); + HRESULT hr = _pScrn->pD3DDevice->DrawPrimitiveVB(dpi->primtype,pVB,cur_startvert,dpi->nVerts,0x0); + TestDrawPrimFailure(DrawPrim,hr,_pScrn->pDD,dpi->nVerts,0); cur_startvert+=dpi->nVerts; } - if((!scrn.bIsTNLDevice) && _clipping_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, true); + if((!_pScrn->bIsTNLDevice) && _clipping_enabled) + _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, true); // Also draw all the dynamic Geoms. for (i = 0; i < dx_gnc->_other_geoms.size(); i++) { diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h index a0f11b32e8..a029806a7e 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h @@ -65,7 +65,7 @@ class EXPCL_PANDADX DXGraphicsStateGuardian7 : public GraphicsStateGuardian { friend class DXTextureContext7; public: - DXGraphicsStateGuardian7(GraphicsWindow *win); + DXGraphicsStateGuardian7(const FrameBufferProperties &properties); ~DXGraphicsStateGuardian7(); virtual void reset(); @@ -128,7 +128,7 @@ public: virtual void bind_light(DirectionalLight *light, int light_id); virtual void bind_light(Spotlight *light, int light_id); - virtual bool begin_frame(); + //virtual bool begin_frame(); virtual bool begin_scene(); virtual void end_scene(); virtual void end_frame(); @@ -144,7 +144,8 @@ public: public: // recreate_tex_callback needs pDD,pD3DDevice to be public - DXScreenData scrn; + DXScreenData *_pScrn; + LPDIRECT3DDEVICE7 _pD3DDevice; // cache copy of _pScrn->pD3DDevice, just for speedier access #ifndef USE_TEXFMTVEC LPDDPIXELFORMAT _pTexPixFmts; @@ -225,6 +226,7 @@ protected: INLINE void enable_stencil_test(bool val); void report_texmgr_stats(); void draw_multitri(Geom *geom, D3DPRIMITIVETYPE tri_id); + void set_context(DXScreenData *pNewContextData); void draw_prim_inner_loop(int nVerts, const Geom *geom, ushort perFlags); void draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom); @@ -301,7 +303,7 @@ protected: DWORD _clip_plane_bits; RenderModeAttrib::Mode _current_fill_mode; //poinr/wireframe/solid - GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports + // GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports // Cur Texture State TextureApplyAttrib::Mode _CurTexBlendMode; @@ -321,6 +323,16 @@ protected: bool _overlay_windows_supported; +#if 0 + // This is here just as a temporary hack so this file will still + // compile. However, it is never initialized and will certainly + // cause the code to crash when it is referenced. (This used to be + // inherited from the base class, but the new design requires that a + // GSG may be used for multiple windows, so it doesn't make sense to + // store a window pointer any more.) + GraphicsWindow *_win; +#endif + public: static GraphicsStateGuardian* make_DXGraphicsStateGuardian(const FactoryParams ¶ms); @@ -329,12 +341,6 @@ public: static void init_type(void); virtual TypeHandle get_type(void) const; virtual TypeHandle force_init_type() {init_type(); return get_class_type();} -/* - LPDIRECT3DDEVICE7 GetD3DDevice() { return scrn.pD3DDevice; } - LPDIRECTDRAW7 GetDDInterface() { return scrn.pDD; } - LPDIRECTDRAWSURFACE7 GetBackBuffer() { return scrn.pddsBackBuffer; } - LPDIRECTDRAWSURFACE7 GetZBuffer() { return _zbuf; } -*/ // INLINE void Set_HDC(HDC hdc) { _front_hdc = hdc; } void adjust_view_rect(int x, int y); INLINE void SetDXReady(bool stat) { _dx_ready = stat; } @@ -346,7 +352,7 @@ public: #define DO_REACTIVATE_WINDOW true bool CheckCooperativeLevel(bool bDoReactivateWindow = false); - void dx_setup_after_resize(RECT viewrect,HWND mwindow) ; + void dx_setup_after_resize(RECT *pViewRect); void show_frame(); void show_full_screen_frame(); void show_windowed_frame(); diff --git a/panda/src/dxgsg7/dxgsg7base.h b/panda/src/dxgsg7/dxgsg7base.h index 34c0773c6a..5f903f90d3 100644 --- a/panda/src/dxgsg7/dxgsg7base.h +++ b/panda/src/dxgsg7/dxgsg7base.h @@ -40,7 +40,7 @@ #error DX7 headers not available, you need to install MS Platform SDK or DirectX 8+ SDK! #endif -#include +#include "pandabase.h" // disable nameless struct 'warning' #pragma warning (disable : 4201) @@ -63,12 +63,14 @@ typedef pvector DDPixelFormatVec; #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_FREELIB(hDLL) { if(hDLL!=NULL) { FreeLibrary(hDLL); hDLL = NULL; } } +#define IS_VALID_PTR(PTR) (!IsBadWritePtr(PTR,sizeof(void*))) // this is bDoDownToZero argument to RELEASE() #define RELEASE_DOWN_TO_ZERO true #define RELEASE_ONCE false -// #define DEBUG_RELEASES +#define DEBUG_RELEASES #ifdef DEBUG_RELEASES #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) \ @@ -124,6 +126,7 @@ typedef struct { bool bIsLowVidMemCard; bool bIsTNLDevice; bool bIsSWRast; + bool bIsFullScreen; WORD depth_buffer_bitdepth; //GetSurfaceDesc is not reliable so must store this explicitly WORD CardIDNum; // its posn in DisplayArray, for dbgprint purposes DDDEVICEIDENTIFIER2 DXDeviceID; diff --git a/panda/src/dxgsg7/wdxGraphicsPipe7.cxx b/panda/src/dxgsg7/wdxGraphicsPipe7.cxx index 4cdd01d6cd..018f0fea0f 100644 --- a/panda/src/dxgsg7/wdxGraphicsPipe7.cxx +++ b/panda/src/dxgsg7/wdxGraphicsPipe7.cxx @@ -40,10 +40,7 @@ wdxGraphicsPipe7() { //////////////////////////////////////////////////////////////////// wdxGraphicsPipe7:: ~wdxGraphicsPipe7() { - if (_hDDrawDLL != NULL) { - FreeLibrary(_hDDrawDLL); - _hDDrawDLL = NULL; - } + SAFE_FREELIB(_hDDrawDLL); } //////////////////////////////////////////////////////////////////// @@ -79,8 +76,21 @@ pipe_constructor() { // Description: Creates a new window on the pipe, if possible. //////////////////////////////////////////////////////////////////// PT(GraphicsWindow) wdxGraphicsPipe7:: -make_window() { - return new wdxGraphicsWindow7(this); +make_window(GraphicsStateGuardian *gsg) { + // thanks to the dumb threading requirements this constructor actually does nothing but create an empty c++ object + // no windows are really opened until wdxGraphicsWindow8->open_window() is called + + return new wdxGraphicsWindow7(this, gsg); +} + + +PT(GraphicsStateGuardian) wdxGraphicsPipe7:: +make_gsg(const FrameBufferProperties &properties) { + + // FrameBufferProperties really belongs as part of the window/renderbuffer specification + // put here because of GLX multithreading requirement + PT(DXGraphicsStateGuardian7) gsg = new DXGraphicsStateGuardian7(properties); + return gsg.p(); } //////////////////////////////////////////////////////////////////// @@ -94,21 +104,17 @@ make_window() { //////////////////////////////////////////////////////////////////// bool wdxGraphicsPipe7:: init() { - static const char * const ddraw_name = "ddraw.dll"; - _hDDrawDLL = LoadLibrary(ddraw_name); - if(_hDDrawDLL == 0) { - wdxdisplay7_cat.error() - << "can't locate " << ddraw_name << "!\n"; - return false; + + if(!MyLoadLib(_hDDrawDLL,"ddraw.dll")) { + goto error; } - _DirectDrawCreateEx = - (LPDIRECTDRAWCREATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawCreateEx"); - if (_DirectDrawCreateEx == NULL) { - wdxdisplay7_cat.error() - << "GetProcAddr failed for DDCreateEx" << endl; - return false; + if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawCreateEx, "DirectDrawCreateEx")) { + goto error; } return true; + +error: + return false; } diff --git a/panda/src/dxgsg7/wdxGraphicsPipe7.h b/panda/src/dxgsg7/wdxGraphicsPipe7.h index ffef40e627..8d47ddd0a5 100644 --- a/panda/src/dxgsg7/wdxGraphicsPipe7.h +++ b/panda/src/dxgsg7/wdxGraphicsPipe7.h @@ -34,9 +34,10 @@ public: virtual string get_interface_name() const; static PT(GraphicsPipe) pipe_constructor(); + virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties); protected: - virtual PT(GraphicsWindow) make_window(); + virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg); private: bool init(); @@ -61,6 +62,7 @@ public: } virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + private: static TypeHandle _type_handle; diff --git a/panda/src/dxgsg7/wdxGraphicsWindow7.cxx b/panda/src/dxgsg7/wdxGraphicsWindow7.cxx index 8725fc706d..9f6eaaeb03 100644 --- a/panda/src/dxgsg7/wdxGraphicsWindow7.cxx +++ b/panda/src/dxgsg7/wdxGraphicsWindow7.cxx @@ -116,10 +116,11 @@ TypeHandle wdxGraphicsWindow7::_type_handle; // Description: //////////////////////////////////////////////////////////////////// wdxGraphicsWindow7:: -wdxGraphicsWindow7(GraphicsPipe *pipe) : - WinGraphicsWindow(pipe) +wdxGraphicsWindow7(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) : + WinGraphicsWindow(pipe, gsg) { - _dxgsg = (DXGraphicsStateGuardian7 *)NULL; + _dxgsg = DCAST(DXGraphicsStateGuardian7, gsg); + ZeroMemory(&_wcontext,sizeof(_wcontext)); } //////////////////////////////////////////////////////////////////// @@ -131,6 +132,47 @@ wdxGraphicsWindow7:: ~wdxGraphicsWindow7() { } +void wdxGraphicsWindow7:: +make_current(void) { + DXGraphicsStateGuardian7 *dxgsg; + DCAST_INTO_V(dxgsg, _gsg); + //wglMakeCurrent(_hdc, wdxgsg->_context); + dxgsg->set_context(&_wcontext); + + // Now that we have made the context current to a window, we can + // reset the GSG state if this is the first time it has been used. + // (We can't just call reset() when we construct the GSG, because + // reset() requires having a current context.) + dxgsg->reset_if_new(); +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsWindow7::open_window +// Access: Protected, Virtual +// Description: Opens the window right now. Called from the window +// thread. Returns true if the window is successfully +// opened, or false if there was a problem. +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsWindow7:: +open_window(void) { + + if (!choose_device(0, NULL)) { + wdxdisplay7_cat.error() << "Unable to find suitable rendering device.\n"; + return false; + } + + if (!WinGraphicsWindow::open_window()) { + return false; + } + + _wcontext.hWnd = _hWnd; + set_coop_levels_and_display_modes(); + create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer); + + return true; +} + +/* //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsWindow7::make_gsg // Access: Public, Virtual @@ -144,9 +186,9 @@ make_gsg() { _dxgsg = new DXGraphicsStateGuardian7(this); _gsg = _dxgsg; // Tell the associated dxGSG about the window handle. - _dxgsg->scrn.hWnd = _mwindow; + _wcontext.hWnd = _hWnd; - if (!search_for_device(0, NULL)) { + if (!choose_device(0, NULL)) { wdxdisplay7_cat.error() << "Unable to find suitable rendering device.\n"; release_gsg(); @@ -156,30 +198,7 @@ make_gsg() { set_coop_levels_and_display_modes(); create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer); } - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow7::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. This should only -// be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow7:: -release_gsg() { - if (_gsg != (GraphicsStateGuardian *)NULL) { - if (is_fullscreen()) { - // Release the cooperative level we grabbed when we created the - // GSG. - DXScreenData *pScrn = &_dxgsg->scrn; - nassertv(pScrn != (DXScreenData *)NULL); - if (pScrn->pDD != (LPDIRECTDRAW7)NULL) { - pScrn->pDD->SetCooperativeLevel(_mwindow, DDSCL_NORMAL); - } - } - - GraphicsWindow::release_gsg(); - } -} +*/ //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsWindow7::end_flip @@ -234,15 +253,15 @@ handle_reshape() { if (_dxgsg!=NULL) { HRESULT hr; - if (_dxgsg->scrn.pddsBack == NULL) { + if (_wcontext.pddsBack == NULL) { // assume this is initial creation reshape and ignore this call return; } - // Clear the back/primary surface to black + // Clear the back/primary surface to black using ddraw DX_DECLARE_CLEAN(DDBLTFX, bltfx); bltfx.dwDDFX |= DDBLTFX_NOTEARING; - hr = _dxgsg->scrn.pddsPrimary->Blt + hr = _wcontext.pddsPrimary->Blt (NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx); if (FAILED(hr)) { wdxdisplay7_cat.fatal() @@ -251,7 +270,7 @@ handle_reshape() { exit(1); } - hr = _dxgsg->scrn.pDD->TestCooperativeLevel(); + hr = _wcontext.pDD->TestCooperativeLevel(); if (FAILED(hr)) { wdxdisplay7_cat.error() << "TestCooperativeLevel failed : result = " @@ -264,10 +283,13 @@ handle_reshape() { set_to_temp_rendertarget(); // create the new resized rendertargets + //RECT view_rect; + //get_client_rect_screen(hWnd, &view_rect); + //_dxgsg->dx_setup_after_resize(view_rect, &_wcontext); + RECT view_rect; - HWND hWnd = _dxgsg->scrn.hWnd; - get_client_rect_screen(hWnd, &view_rect); - _dxgsg->dx_setup_after_resize(view_rect, hWnd); + get_client_rect_screen(_wcontext.hWnd, &view_rect); + _dxgsg->dx_setup_after_resize(&view_rect); } } @@ -285,7 +307,7 @@ do_fullscreen_resize(int x_size, int y_size) { DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_curmode); - hr = _dxgsg->scrn.pDD->GetDisplayMode(&ddsd_curmode); + hr = _wcontext.pDD->GetDisplayMode(&ddsd_curmode); if (FAILED(hr)) { wdxdisplay7_cat.fatal() << "resize() - GetDisplayMode failed, result = " @@ -310,7 +332,7 @@ do_fullscreen_resize(int x_size, int y_size) { DMI.maxHeight = y_size; DMI.pDDSD_Arr = DDSD_Arr; - hr = _dxgsg->scrn.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search, + hr = _wcontext.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search, &DMI, EnumDisplayModesCallBack); if (FAILED(hr)) { wdxdisplay7_cat.fatal() @@ -319,7 +341,7 @@ do_fullscreen_resize(int x_size, int y_size) { return false; } - DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth; + DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth; DWORD dwFullScreenBitDepth; DWORD requested_bpp = ddsd_curmode.ddpfPixelFormat.dwRGBBitCount; @@ -341,7 +363,7 @@ do_fullscreen_resize(int x_size, int y_size) { return false; } - hr = _dxgsg->scrn.pDD->TestCooperativeLevel(); + hr = _wcontext.pDD->TestCooperativeLevel(); if (FAILED(hr)) { wdxdisplay7_cat.error() << "TestCooperativeLevel failed : result = " @@ -354,7 +376,7 @@ do_fullscreen_resize(int x_size, int y_size) { _dxgsg->free_dxgsg_objects(); // let driver choose default refresh rate (hopefully its >=60Hz) - hr = _dxgsg->scrn.pDD->SetDisplayMode(x_size, y_size, dwFullScreenBitDepth, + hr = _wcontext.pDD->SetDisplayMode(x_size, y_size, dwFullScreenBitDepth, 0L, 0L); if (FAILED(hr)) { wdxdisplay7_cat.error() @@ -366,17 +388,17 @@ do_fullscreen_resize(int x_size, int y_size) { if (wdxdisplay7_cat.is_debug()) { DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34); - _dxgsg->scrn.pDD->GetDisplayMode(&ddsd34); + _wcontext.pDD->GetDisplayMode(&ddsd34); wdxdisplay7_cat.debug() << "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight << " at "<< ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, " << ddsd34.dwRefreshRate << "Hz\n"; } - _dxgsg->scrn.dwRenderWidth = x_size; - _dxgsg->scrn.dwRenderHeight = y_size; + _wcontext.dwRenderWidth = x_size; + _wcontext.dwRenderHeight = y_size; - create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer); + create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer); _dxgsg->RecreateAllVideoSurfaces(); _dxgsg->SetDXReady(true); return true; @@ -400,8 +422,8 @@ set_to_temp_rendertarget() { DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); - _dxgsg->scrn.pddsBack->GetSurfaceDesc(&ddsd); - LPDIRECTDRAW7 pDD = _dxgsg->scrn.pDD; + _wcontext.pddsBack->GetSurfaceDesc(&ddsd); + LPDIRECTDRAW7 pDD = _wcontext.pDD; ddsd.dwFlags &= ~DDSD_PITCH; ddsd.dwWidth = 1; @@ -418,9 +440,9 @@ set_to_temp_rendertarget() { return false; } - if (_dxgsg->scrn.pddsZBuf != NULL) { + if (_wcontext.pddsZBuf != NULL) { DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsdZ); - _dxgsg->scrn.pddsZBuf->GetSurfaceDesc(&ddsdZ); + _wcontext.pddsZBuf->GetSurfaceDesc(&ddsdZ); ddsdZ.dwFlags &= ~DDSD_PITCH; ddsdZ.dwWidth = 1; ddsdZ.dwHeight = 1; @@ -444,7 +466,7 @@ set_to_temp_rendertarget() { } } - hr = _dxgsg->scrn.pD3DDevice->SetRenderTarget(pddsDummy, 0x0); + hr = _wcontext.pD3DDevice->SetRenderTarget(pddsDummy, 0x0); if (FAILED(hr)) { wdxdisplay7_cat.error() << "Resize failed to set render target to temporary surface, result = " @@ -499,6 +521,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; + Display.bIsFullScreen=true; if (dx_full_screen_antialiasing) { // cant check that d3ddevice has this capability yet, so got to @@ -704,10 +727,10 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer // resized(dwRenderWidth, dwRenderHeight); // update panda channel/display rgn info - int framebuffer_mode = get_properties().get_framebuffer_mode(); + int frame_buffer_mode = _gsg->get_properties().get_frame_buffer_mode(); #ifndef NDEBUG - if ((framebuffer_mode & WindowProperties::FM_depth) == 0) { + if ((frame_buffer_mode & FrameBufferProperties::FM_depth) == 0) { wdxdisplay7_cat.info() << "no zbuffer requested, skipping zbuffer creation\n"; } @@ -716,7 +739,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer // Check if the device supports z-bufferless hidden surface // removal. If so, we don't really need a z-buffer if ((!(pD3DDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) && - ((framebuffer_mode & WindowProperties::FM_depth) != 0)) { + ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0)) { // Get z-buffer dimensions from the render target DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd); @@ -724,7 +747,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer // Setup the surface desc for the z-buffer. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT; - ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | ((_dxgsg->scrn.bIsSWRast) ? DDSCAPS_SYSTEMMEMORY : DDSCAPS_VIDEOMEMORY); + ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | ((_wcontext.bIsSWRast) ? DDSCAPS_SYSTEMMEMORY : DDSCAPS_VIDEOMEMORY); DDPIXELFORMAT ZBufPixFmts[MAX_DX_ZBUF_FMTS]; cNumZBufFmts=0; @@ -756,7 +779,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer // should we pay attn to these at some point? //int want_depth_bits = _props._want_depth_bits; //int want_color_bits = _props._want_color_bits; - bool bWantStencil = ((framebuffer_mode & WindowProperties::FM_stencil) != 0); + bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0); LPDDPIXELFORMAT pCurPixFmt, pz16 = NULL, pz24 = NULL, pz32 = NULL; for (i = 0, pCurPixFmt = ZBufPixFmts; @@ -790,7 +813,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer #define SET_ZBUF_DEPTH(DEPTH) { assert(pz##DEPTH != NULL); Display.depth_buffer_bitdepth=DEPTH; ddsd.ddpfPixelFormat = *pz##DEPTH;} - if (_dxgsg->scrn.bIsSWRast) { + if (_wcontext.bIsSWRast) { SET_ZBUF_DEPTH(16); // need this for fast path rasterizers } else { if (IS_NVIDIA(Display.DXDeviceID)) { @@ -945,6 +968,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer Display.pddsZBuf = pZDDSurf; Display.view_rect = view_rect; + _dxgsg->set_context(&Display); //pDD, pPrimaryDDSurf, pBackDDSurf, pZDDSurf, pD3DI, pD3DDevice, view_rect); _dxgsg->dx_init(); @@ -956,13 +980,13 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer } //////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow7::search_for_device +// Function: wdxGraphicsWindow7::choose_device // Access: Private // Description: Searches for a suitable hardware device for // rendering. //////////////////////////////////////////////////////////////////// bool wdxGraphicsWindow7:: -search_for_device(int devnum, DXDeviceInfo *pDevinfo) { +choose_device(int devnum, DXDeviceInfo *pDevinfo) { wdxGraphicsPipe7 *dxpipe; DCAST_INTO_R(dxpipe, _pipe, false); @@ -992,16 +1016,16 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { return false; } - _dxgsg->scrn.pDD = pDD; + _wcontext.pDD = pDD; // GetDeviceID bug writes an extra 4 bytes, so need xtra space BYTE id_arr[sizeof(DDDEVICEIDENTIFIER2) + 4]; pDD->GetDeviceIdentifier((DDDEVICEIDENTIFIER2 *)&id_arr, 0x0); - memcpy(&_dxgsg->scrn.DXDeviceID, id_arr, sizeof(DDDEVICEIDENTIFIER2)); + memcpy(&_wcontext.DXDeviceID, id_arr, sizeof(DDDEVICEIDENTIFIER2)); if (wdxdisplay7_cat.is_info()) { - DDDEVICEIDENTIFIER2 *pDevID = &_dxgsg->scrn.DXDeviceID; + DDDEVICEIDENTIFIER2 *pDevID = &_wcontext.DXDeviceID; wdxdisplay7_cat.info() << "GfxCard: " << pDevID->szDescription << "; DriverFile: '" << pDevID->szDriver @@ -1015,7 +1039,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { } // Query DirectDraw for access to Direct3D - hr = pDD->QueryInterface(IID_IDirect3D7, (VOID**)&_dxgsg->scrn.pD3D); + hr = pDD->QueryInterface(IID_IDirect3D7, (VOID**)&_wcontext.pD3D); if(hr != DD_OK) { wdxdisplay7_cat.fatal() << "QI for D3D failed : result = " << ConvD3DErrorToString(hr) << endl; @@ -1029,7 +1053,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { ZeroMemory(d3ddevs,3*sizeof(D3DDEVICEDESC7)); - hr = _dxgsg->scrn.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs); + hr = _wcontext.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs); if(hr != DD_OK) { wdxdisplay7_cat.fatal() << "EnumDevices failed : result = " << ConvD3DErrorToString(hr) << endl; @@ -1048,7 +1072,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { } else { wdxdisplay7_cat.error() << "No 3D HW present on device #" << devnum << ", skipping it... (" - << _dxgsg->scrn.DXDeviceID.szDescription<<")\n"; + << _wcontext.DXDeviceID.szDescription<<")\n"; goto error_exit; } @@ -1056,10 +1080,10 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { DeviceIdx = SWRASTIDX; } - memcpy(&_dxgsg->scrn.D3DDevDesc, &d3ddevs[DeviceIdx], + memcpy(&_wcontext.D3DDevDesc, &d3ddevs[DeviceIdx], sizeof(D3DDEVICEDESC7)); - _dxgsg->scrn.bIsTNLDevice = (DeviceIdx == TNLHALIDX); + _wcontext.bIsTNLDevice = (DeviceIdx == TNLHALIDX); // Get Current VidMem avail. Note this is only an estimate, when we // switch to fullscreen mode from desktop, more vidmem will be @@ -1084,25 +1108,25 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { // 1.2 meg (contradicting above comment and what I think would be // correct behavior (shouldnt FS mode release the desktop vidmem?), // so this is the true value - _dxgsg->scrn.MaxAvailVidMem = dwVidMemTotal; + _wcontext.MaxAvailVidMem = dwVidMemTotal; #define LOWVIDMEMTHRESHOLD 5500000 #define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 // every vidcard we deal with should have at least 1MB // 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 = + _wcontext.bIsLowVidMemCard = ((dwVidMemTotal>CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) && (dwVidMemTotal< LOWVIDMEMTHRESHOLD)); if (!dx_do_vidmemsize_check) { - _dxgsg->scrn.MaxAvailVidMem = 0xFFFFFFFF; - _dxgsg->scrn.bIsLowVidMemCard = false; + _wcontext.MaxAvailVidMem = 0xFFFFFFFF; + _wcontext.bIsLowVidMemCard = false; } if (DeviceIdx == SWRASTIDX) { // this will force 640x480x16, is this what we want for all sw rast? - _dxgsg->scrn.bIsLowVidMemCard = true; - _dxgsg->scrn.bIsSWRast = true; + _wcontext.bIsLowVidMemCard = true; + _wcontext.bIsSWRast = true; dx_force_16bpp_zbuffer = true; } @@ -1125,7 +1149,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { if (FAILED(hr)) { wdxdisplay7_cat.fatal() << "EnumDisplayModes failed for device #" << devnum - << " (" << _dxgsg->scrn.DXDeviceID.szDescription + << " (" << _wcontext.DXDeviceID.szDescription << "), result = " << ConvD3DErrorToString(hr) << endl; // goto skip_device; exit(1); // probably want to exit, since it may be my fault @@ -1142,7 +1166,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { // resolution and best rendertarget bpp and still have at least 2 // meg of texture vidmem - DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth; + DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth; DWORD dwFullScreenBitDepth; @@ -1158,12 +1182,12 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { wdxdisplay7_cat.fatal() << "No Supported FullScreen resolutions at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << devnum - << " (" << _dxgsg->scrn.DXDeviceID.szDescription + << " (" << _wcontext.DXDeviceID.szDescription << "), skipping device...\n"; goto error_exit; } - if (_dxgsg->scrn.bIsLowVidMemCard) { + if (_wcontext.bIsLowVidMemCard) { { // hack: figuring out exactly what res to use is tricky, // instead I will just use 640x480 if we have < 3 meg avail @@ -1181,28 +1205,28 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) { } } - _dxgsg->scrn.dwFullScreenBitDepth = dwFullScreenBitDepth; + _wcontext.dwFullScreenBitDepth = dwFullScreenBitDepth; } - _dxgsg->scrn.dwRenderWidth = dwRenderWidth; - _dxgsg->scrn.dwRenderHeight = dwRenderHeight; + _wcontext.dwRenderWidth = dwRenderWidth; + _wcontext.dwRenderHeight = dwRenderHeight; if (pDevinfo) { - _dxgsg->scrn.hMon = pDevinfo->hMon; + _wcontext.hMon = pDevinfo->hMon; } - _dxgsg->scrn.CardIDNum = devnum; // add ID tag for dbgprint purposes + _wcontext.CardIDNum = devnum; // add ID tag for dbgprint purposes return true; // handle errors within this for device loop error_exit: - if (_dxgsg->scrn.pD3D != NULL) - _dxgsg->scrn.pD3D->Release(); - if (_dxgsg->scrn.pDD != NULL) - _dxgsg->scrn.pDD->Release(); + if (_wcontext.pD3D != NULL) + _wcontext.pD3D->Release(); + if (_wcontext.pDD != NULL) + _wcontext.pDD->Release(); - _dxgsg->scrn.pDD = NULL; - _dxgsg->scrn.pD3D = NULL; + _wcontext.pDD = NULL; + _wcontext.pD3D = NULL; return false; } @@ -1220,16 +1244,15 @@ set_coop_levels_and_display_modes() { // tell d3d to preserve the fpu state across calls. this hurts // perf, but is good for dbgging SCL_FPUFlag = DDSCL_FPUPRESERVE; - } else { SCL_FPUFlag = DDSCL_FPUSETUP; } - DXScreenData *pScrn = &_dxgsg->scrn; + // DXScreenData *pScrn = &_dxgsg->scrn; if (!is_fullscreen()) { - hr = pScrn->pDD->SetCooperativeLevel(_mwindow, - SCL_FPUFlag | DDSCL_NORMAL); + hr = _wcontext.pDD->SetCooperativeLevel(_hWnd, + SCL_FPUFlag | DDSCL_NORMAL); if (FAILED(hr)) { wdxdisplay7_cat.fatal() << "SetCooperativeLevel failed : result = " @@ -1246,7 +1269,7 @@ set_coop_levels_and_display_modes() { // restore that functionality. DWORD devnum = 0; { - DXScreenData *pScrn = &_dxgsg->scrn; + // DXScreenData *pScrn = &_dxgsg->scrn; // need to set focus/device windows for multimon // focus window is primary monitor that will receive keybd input @@ -1264,7 +1287,7 @@ set_coop_levels_and_display_modes() { // SetCoopLevel twice. so we do it, it really shouldnt be necessary // if drivers werent buggy for (int jj=0; jj<2; jj++) { - hr = pScrn->pDD->SetCooperativeLevel(pScrn->hWnd, SCL_FLAGS); + hr = _wcontext.pDD->SetCooperativeLevel(_wcontext.hWnd, SCL_FLAGS); if (FAILED(hr)) { wdxdisplay7_cat.fatal() << "SetCooperativeLevel failed for device #" << devnum @@ -1273,7 +1296,7 @@ set_coop_levels_and_display_modes() { } } - hr = pScrn->pDD->TestCooperativeLevel(); + hr = _wcontext.pDD->TestCooperativeLevel(); if (FAILED(hr)) { wdxdisplay7_cat.fatal() << "TestCooperativeLevel failed: result = " << ConvD3DErrorToString(hr) @@ -1282,31 +1305,59 @@ set_coop_levels_and_display_modes() { << "Full screen app failed to get exclusive mode on init, exiting..\n"; exit(1); } - + // note: its important we call SetDisplayMode on all cards before // creating surfaces on any of them to let driver choose default // refresh rate (hopefully its >=60Hz) - hr = pScrn->pDD->SetDisplayMode(pScrn->dwRenderWidth, - pScrn->dwRenderHeight, - pScrn->dwFullScreenBitDepth, 0, 0); + hr = _wcontext.pDD->SetDisplayMode(_wcontext.dwRenderWidth, + _wcontext.dwRenderHeight, + _wcontext.dwFullScreenBitDepth, 0, 0); if (FAILED(hr)) { wdxdisplay7_cat.fatal() - << "SetDisplayMode failed to set (" << pScrn->dwRenderWidth - << "x" <dwRenderHeight << "x" << pScrn->dwFullScreenBitDepth - << ") on device #" << pScrn->CardIDNum << ": result = " + << "SetDisplayMode failed to set (" << _wcontext.dwRenderWidth + << "x" <<_wcontext.dwRenderHeight << "x" << _wcontext.dwFullScreenBitDepth + << ") on device #" << _wcontext.CardIDNum << ": result = " << ConvD3DErrorToString(hr) << endl; exit(1); } if(wdxdisplay7_cat.is_debug()) { - DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34); - pScrn->pDD->GetDisplayMode(&ddsd34); + DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_temp); + _wcontext.pDD->GetDisplayMode(&ddsd_temp); wdxdisplay7_cat.debug() - << "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight - << " at " << ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, " - << ddsd34.dwRefreshRate<< "Hz\n"; + << "set displaymode to " << ddsd_temp.dwWidth << "x" << ddsd_temp.dwHeight + << " at " << ddsd_temp.ddpfPixelFormat.dwRGBBitCount << "bpp, " + << ddsd_temp.dwRefreshRate<< "Hz\n"; } } } +#if 0 +// probably need this here similar to dx8 +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsWindow8::begin_frame +// Access: Public, Virtual +// Description: This function will be called within the draw thread +// before beginning rendering for a given frame. It +// should do whatever setup is required, and return true +// if the frame should be rendered, or false if it +// should be skipped. +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsWindow7:: +begin_frame() { + if (_awaiting_restore) { + // The fullscreen window was recently restored; we can't continue + // until the GSG says we can. + if (!_dxgsg->CheckCooperativeLevel()) { + // Keep waiting. + return false; + } + _awaiting_restore = false; + + init_resized_window(); + } + + return WinGraphicsWindow::begin_frame(); +} +#endif diff --git a/panda/src/dxgsg7/wdxGraphicsWindow7.h b/panda/src/dxgsg7/wdxGraphicsWindow7.h index 2936baeeca..02d79f7249 100644 --- a/panda/src/dxgsg7/wdxGraphicsWindow7.h +++ b/panda/src/dxgsg7/wdxGraphicsWindow7.h @@ -42,13 +42,12 @@ typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplp //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX wdxGraphicsWindow7 : public WinGraphicsWindow { public: - wdxGraphicsWindow7(GraphicsPipe *pipe); + wdxGraphicsWindow7(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); virtual ~wdxGraphicsWindow7(); - - virtual void make_gsg(); - virtual void release_gsg(); - virtual void end_flip(); + //virtual bool begin_frame(); + virtual void make_current(void); + virtual bool open_window(void); protected: virtual void fullscreen_restored(WindowProperties &properties); @@ -59,10 +58,11 @@ private: bool set_to_temp_rendertarget(); void create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer); - bool search_for_device(int devnum, DXDeviceInfo *pDevinfo); + bool choose_device(int devnum, DXDeviceInfo *pDevinfo); void set_coop_levels_and_display_modes(); DXGraphicsStateGuardian7 *_dxgsg; + DXScreenData _wcontext; public: static TypeHandle get_class_type() { diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx index f28cb74c7e..cd1fe17687 100644 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ b/panda/src/dxgsg8/config_dxgsg8.cxx @@ -27,7 +27,8 @@ #include Configure(config_dxgsg8); -NotifyCategoryDef(dxgsg8, ":display:gsg"); +//NotifyCategoryDef(dxgsg8, ":display:gsg"); dont want to merge this with the regular parent class dbg output +NotifyCategoryDef(dxgsg8, "dxgsg"); NotifyCategoryDef(wdxdisplay8, "windisplay"); // Configure this variable true to cause the DXGSG to show each @@ -196,58 +197,5 @@ init_libdxgsg8() { GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); selection->add_pipe_type(wdxGraphicsPipe8::get_class_type(), wdxGraphicsPipe8::pipe_constructor); + } - -const char *D3DFormatStr(D3DFORMAT fmt) { - -#define CASESTR(XX) case XX: return #XX; - - switch(fmt) { - CASESTR(D3DFMT_UNKNOWN); - CASESTR(D3DFMT_R8G8B8); - CASESTR(D3DFMT_A8R8G8B8); - CASESTR(D3DFMT_X8R8G8B8); - CASESTR(D3DFMT_R5G6B5); - CASESTR(D3DFMT_X1R5G5B5); - CASESTR(D3DFMT_A1R5G5B5); - CASESTR(D3DFMT_A4R4G4B4); - CASESTR(D3DFMT_R3G3B2); - CASESTR(D3DFMT_A8); - CASESTR(D3DFMT_A8R3G3B2); - CASESTR(D3DFMT_X4R4G4B4); - CASESTR(D3DFMT_A2B10G10R10); - CASESTR(D3DFMT_G16R16); - CASESTR(D3DFMT_A8P8); - CASESTR(D3DFMT_P8); - CASESTR(D3DFMT_L8); - CASESTR(D3DFMT_A8L8); - CASESTR(D3DFMT_A4L4); - CASESTR(D3DFMT_V8U8); - CASESTR(D3DFMT_L6V5U5); - CASESTR(D3DFMT_X8L8V8U8); - CASESTR(D3DFMT_Q8W8V8U8); - CASESTR(D3DFMT_V16U16); - CASESTR(D3DFMT_W11V11U10); - CASESTR(D3DFMT_A2W10V10U10); - CASESTR(D3DFMT_UYVY); - CASESTR(D3DFMT_YUY2); - CASESTR(D3DFMT_DXT1); - CASESTR(D3DFMT_DXT2); - CASESTR(D3DFMT_DXT3); - CASESTR(D3DFMT_DXT4); - CASESTR(D3DFMT_DXT5); - CASESTR(D3DFMT_D16_LOCKABLE); - CASESTR(D3DFMT_D32); - CASESTR(D3DFMT_D15S1); - CASESTR(D3DFMT_D24S8); - CASESTR(D3DFMT_D16); - CASESTR(D3DFMT_D24X8); - CASESTR(D3DFMT_D24X4S4); - CASESTR(D3DFMT_VERTEXDATA); - CASESTR(D3DFMT_INDEX16); - CASESTR(D3DFMT_INDEX32); - } - - return "Invalid D3DFORMAT"; -} - diff --git a/panda/src/dxgsg8/config_dxgsg8.h b/panda/src/dxgsg8/config_dxgsg8.h index 48ebcfc469..c67b939122 100644 --- a/panda/src/dxgsg8/config_dxgsg8.h +++ b/panda/src/dxgsg8/config_dxgsg8.h @@ -21,7 +21,7 @@ #include "pandabase.h" #include "notifyCategoryProxy.h" -#include +#include "dxgsg8base.h" NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX); NotifyCategoryDecl(wdxdisplay8, EXPCL_PANDADX, EXPTP_PANDADX); @@ -39,9 +39,9 @@ extern bool dx_use_rangebased_fog; extern const bool link_tristrips; extern DWORD dx_multisample_antialiasing_level; extern bool dx_use_triangle_mipgen_filter; -extern const char *D3DFormatStr(D3DFORMAT fmt); extern bool dx_use_dx_cursor; + // debug flags we might want to use in full optimized build extern bool dx_ignore_mipmaps; extern bool dx_mipmap_everything; diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.I b/panda/src/dxgsg8/dxGraphicsStateGuardian8.I index a3448cb8a6..d27686fa6c 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.I +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.I @@ -30,12 +30,12 @@ enable_line_smooth(bool val) { _line_smooth_enabled = val; #ifdef NDEBUG { - if(val && (scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)) + if(val && (_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)) dxgsg8_cat.error() << "no HW support for line smoothing!!\n"; } #endif - scrn.pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val); + _pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val); } } @@ -50,14 +50,14 @@ enable_dither(bool val) { #ifdef _DEBUG { - if(val && !(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)) + if(val && !(_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)) dxgsg8_cat.error() << "no HW support for color dithering!!\n"; return; } #endif _dither_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, (DWORD)val); + _pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, (DWORD)val); } } @@ -70,7 +70,7 @@ INLINE void DXGraphicsStateGuardian8:: enable_stencil_test(bool val) { if (_stencil_test_enabled != val) { _stencil_test_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, (DWORD)val); + _pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, (DWORD)val); } } @@ -96,7 +96,7 @@ INLINE void DXGraphicsStateGuardian8:: enable_blend(bool val) { if (_blend_enabled != val) { _blend_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)val); + _pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)val); } } @@ -109,9 +109,9 @@ INLINE void DXGraphicsStateGuardian8:: set_color_writemask(UINT color_writemask) { if (_color_writemask != color_writemask) { _color_writemask = color_writemask; - if(scrn.bCanDirectDisableColorWrites) { + if(_pScrn->bCanDirectDisableColorWrites) { // only newer HW supports this rstate - scrn.pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask); + _pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask); } else { // blending can only handle on/off assert((color_writemask==0x0)||(color_writemask==0xFFFFFFFF)); @@ -129,7 +129,7 @@ INLINE void DXGraphicsStateGuardian8:: enable_gouraud_shading(bool val) { if (_bGouraudShadingOn != val) { _bGouraudShadingOn = val; - scrn.pD3DDevice->SetRenderState(D3DRS_SHADEMODE, (val ? D3DSHADE_GOURAUD : D3DSHADE_FLAT)); + _pD3DDevice->SetRenderState(D3DRS_SHADEMODE, (val ? D3DSHADE_GOURAUD : D3DSHADE_FLAT)); } } @@ -137,7 +137,7 @@ INLINE void DXGraphicsStateGuardian8:: enable_primitive_clipping(bool val) { if (_clipping_enabled != val) { _clipping_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, (DWORD)val); + _pD3DDevice->SetRenderState(D3DRS_CLIPPING, (DWORD)val); } } @@ -150,7 +150,7 @@ INLINE void DXGraphicsStateGuardian8:: enable_fog(bool val) { if ((_fog_enabled != val) && (_doFogType!=None)) { _fog_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRS_FOGENABLE, (DWORD)val); + _pD3DDevice->SetRenderState(D3DRS_FOGENABLE, (DWORD)val); } } @@ -164,7 +164,7 @@ set_vertex_format(DWORD NewFvfType) { #ifdef USE_VERTEX_SHADERS if(_CurVertexShader!=NULL) { // this needs optimization - HRESULT hr = scrn.pD3DDevice->SetVertexShader(_CurVertexShader); + HRESULT hr = _pD3DDevice->SetVertexShader(_CurVertexShader); #ifndef NDEBUG if(FAILED(hr)) { dxgsg8_cat.error() << "SetVertexShader for custom vtx shader failed" << D3DERRORSTRING(hr); @@ -179,7 +179,7 @@ set_vertex_format(DWORD NewFvfType) { if (_CurFVFType != NewFvfType) { _CurFVFType = NewFvfType; - HRESULT hr = scrn.pD3DDevice->SetVertexShader(NewFvfType); + HRESULT hr = _pD3DDevice->SetVertexShader(NewFvfType); #ifndef NDEBUG if(FAILED(hr)) { dxgsg8_cat.error() << "SetVertexShader(0x" << (void*)NewFvfType<<") failed" << D3DERRORSTRING(hr); @@ -199,7 +199,7 @@ enable_alpha_test(bool val ) { if (_alpha_test_enabled != val) { _alpha_test_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, (DWORD)val); + _pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, (DWORD)val); } } @@ -216,7 +216,7 @@ call_dxLightModelAmbient( const Colorf& color) #ifdef GSG_VERBOSE dxgsg8_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl; #endif - scrn.pD3DDevice->SetRenderState( D3DRS_AMBIENT, + _pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(color[0], color[1], color[2], color[3])); } } @@ -265,12 +265,12 @@ call_dxAlphaFunc(D3DCMPFUNC func, float reference_alpha) { } dxgsg8_cat.debug() << " , " << reference_alpha << ")" << endl; #endif - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func); + _pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func); } if(_alpha_func_refval != reference_alpha) { _alpha_func_refval = reference_alpha; - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float + _pD3DDevice->SetRenderState(D3DRS_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float } } @@ -281,7 +281,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc ) if (_blend_source_func != sfunc) { _blend_source_func = sfunc; - scrn.pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc); + _pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc); #ifdef GSG_VERBOSE dxgsg8_cat.debug() << "dxSrcBlendFunc("; switch (sfunc) @@ -323,7 +323,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc ) if ( _blend_dest_func != dfunc) { _blend_dest_func = dfunc; - scrn.pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc); + _pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc); #ifdef GSG_VERBOSE dxgsg8_cat.debug() << "dxDstBlendFunc("; switch (dfunc) @@ -365,7 +365,7 @@ INLINE void DXGraphicsStateGuardian8:: enable_zwritemask(bool val) { if (_depth_write_enabled != val) { _depth_write_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, val); + _pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, val); } } diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index de3047cc93..954df33ecc 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -126,8 +126,6 @@ static void CountDPs(DWORD nVerts,DWORD nTris) { static bool bTexStatsRetrievalImpossible=false; #endif -HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark); - //#define Colorf_to_D3DCOLOR(out_color) (MY_D3DRGBA((out_color)[0], (out_color)[1], (out_color)[2], (out_color)[3])) INLINE DWORD @@ -183,48 +181,6 @@ Colorf_to_D3DCOLOR(const Colorf &cColorf) { #endif //!_X86_ } -map g_D3DFORMATmap; - -void make_D3DFORMAT_map(void) { - if(g_D3DFORMATmap.size()!=0) - return; - -#define INSERT_ELEM(XX) g_D3DFORMATmap[XX##_FLAG] = D3DFMT_##XX; - - INSERT_ELEM(R8G8B8); - INSERT_ELEM(A8R8G8B8); - INSERT_ELEM(X8R8G8B8); - INSERT_ELEM(R5G6B5); - INSERT_ELEM(X1R5G5B5); - INSERT_ELEM(A1R5G5B5); - INSERT_ELEM(A4R4G4B4); - INSERT_ELEM(R3G3B2); - INSERT_ELEM(A8); - INSERT_ELEM(A8R3G3B2); - INSERT_ELEM(X4R4G4B4); - INSERT_ELEM(A2B10G10R10); - INSERT_ELEM(G16R16); - INSERT_ELEM(A8P8); - INSERT_ELEM(P8); - INSERT_ELEM(L8); - INSERT_ELEM(A8L8); - INSERT_ELEM(A4L4); - INSERT_ELEM(V8U8); - INSERT_ELEM(L6V5U5); - INSERT_ELEM(X8L8V8U8); - INSERT_ELEM(Q8W8V8U8); - INSERT_ELEM(V16U16); - INSERT_ELEM(W11V11U10); - INSERT_ELEM(A2W10V10U10); - INSERT_ELEM(UYVY); - INSERT_ELEM(YUY2); - INSERT_ELEM(DXT1); - INSERT_ELEM(DXT2); - INSERT_ELEM(DXT3); - INSERT_ELEM(DXT4); - INSERT_ELEM(DXT5); -} - void DXGraphicsStateGuardian8:: set_color_clear_value(const Colorf& value) { _color_clear_value = value; @@ -239,8 +195,8 @@ read_pixel_shader(string &filename) { BYTE *pShaderBytes=NULL; LPD3DXBUFFER pD3DXBuf_Constants=NULL,pD3DXBuf_CompiledShader=NULL,pD3DXBuf_CompilationErrors=NULL; - assert(scrn.pD3DDevice!=NULL); - assert(scrn.bCanUsePixelShaders); + assert(_pD3DDevice!=NULL); + assert(_pScrn->bCanUsePixelShaders); bool bIsCompiledShader=(filename.find(".pso")!=string::npos); if(bIsCompiledShader) { @@ -287,7 +243,7 @@ read_pixel_shader(string &filename) { #endif } - hr = scrn.pD3DDevice->CreatePixelShader((DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes), + hr = _pD3DDevice->CreatePixelShader((DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes), &hShader); if (FAILED(hr)) { dxgsg8_cat.error() << "CreatePixelShader failed for '"<< filename << "' " << D3DERRORSTRING(hr); @@ -336,7 +292,7 @@ read_vertex_shader(string &filename) { // need to append any compiled constants to instr array UINT ShaderDeclHeader_UINTSize=sizeof(Predefined_DeclArray)/sizeof(UINT); - assert(scrn.pD3DDevice!=NULL); + assert(_pD3DDevice!=NULL); bool bIsCompiledShader=(filename.find(".vso")!=string::npos); if(bIsCompiledShader) { @@ -393,8 +349,8 @@ read_vertex_shader(string &filename) { assert(VSDDECL_BUFSIZE >= (ShaderDeclHeader_UINTSize+1)); ShaderDeclHeader[ShaderDeclHeader_UINTSize]=D3DVSD_END(); - UINT UsageFlags = (scrn.bCanUseHWVertexShaders ? 0x0 : D3DUSAGE_SOFTWAREPROCESSING); - hr = scrn.pD3DDevice->CreateVertexShader((DWORD*)ShaderDeclHeader, + UINT UsageFlags = (_pScrn->bCanUseHWVertexShaders ? 0x0 : D3DUSAGE_SOFTWAREPROCESSING); + hr = _pD3DDevice->CreateVertexShader((DWORD*)ShaderDeclHeader, (DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes), &hShader, UsageFlags); if(FAILED(hr)) { @@ -442,12 +398,13 @@ reset_panda_gsg(void) { // Description: //////////////////////////////////////////////////////////////////// DXGraphicsStateGuardian8:: -DXGraphicsStateGuardian8(GraphicsWindow *win) : GraphicsStateGuardian(win) { +DXGraphicsStateGuardian8(const FrameBufferProperties &properties) : + GraphicsStateGuardian(properties) { + reset_panda_gsg(); - // allocate local buffers used during rendering - - ZeroMemory(&scrn,sizeof(DXScreenData)); + _pScrn = NULL; + _bDXisReady = false; _overlay_windows_supported = false; @@ -464,8 +421,6 @@ DXGraphicsStateGuardian8(GraphicsWindow *win) : GraphicsStateGuardian(win) { // called and dx objects need to be recreated (otherwise they // belong in dx_init, with other renderstate - make_D3DFORMAT_map(); - ZeroMemory(&matIdentity,sizeof(D3DMATRIX)); matIdentity._11 = matIdentity._22 = matIdentity._33 = matIdentity._44 = 1.0f; @@ -480,10 +435,12 @@ DXGraphicsStateGuardian8(GraphicsWindow *win) : GraphicsStateGuardian(win) { //////////////////////////////////////////////////////////////////// DXGraphicsStateGuardian8:: ~DXGraphicsStateGuardian8() { - if (scrn.pD3DDevice != NULL) - scrn.pD3DDevice->SetTexture(0, NULL); // this frees reference to the old texture + if (IS_VALID_PTR(_pD3DDevice)) + _pD3DDevice->SetTexture(0, NULL); // this frees reference to the old texture _pCurTexContext = NULL; + //free_d3d_device(); ??? + free_nondx_resources(); } @@ -491,10 +448,13 @@ DXGraphicsStateGuardian8:: // Function: DXGraphicsStateGuardian8::reset // Access: Public, Virtual // Description: Resets all internal state as if the gsg were newly -// created. +// created. The GraphicsWindow pointer represents a +// typical window that might be used for this context; +// it may be required to set up the frame buffer +// properly the first time. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: -reset(void) { +reset() { reset_panda_gsg(); dxgsg8_cat.error() << "DXGSG reset() not implemented properly yet!\n"; // what else do we need to do? @@ -512,14 +472,14 @@ free_d3d_device(void) { _bDXisReady = false; - if(scrn.pD3DDevice!=NULL) + if(_pD3DDevice!=NULL) for(int i=0;iSetTexture(i,NULL); // d3d should release this stuff internally anyway, but whatever + _pD3DDevice->SetTexture(i,NULL); // d3d should release this stuff internally anyway, but whatever DeleteAllDeviceObjects(); - if (scrn.pD3DDevice!=NULL) - RELEASE(scrn.pD3DDevice,dxgsg8,"d3dDevice",RELEASE_DOWN_TO_ZERO); + if (_pD3DDevice!=NULL) + RELEASE(_pD3DDevice,dxgsg8,"d3dDevice",RELEASE_DOWN_TO_ZERO); free_nondx_resources(); @@ -547,18 +507,18 @@ free_nondx_resources() { // set up. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: -dx_init(HCURSOR hMouseCursor) { +dx_init(void) { HRESULT hr; // make sure gsg passes all current state down to us set_state(RenderState::make_empty()); // want gsg to pass all state settings down so any non-matching defaults we set here get overwritten - assert(scrn.pD3D8!=NULL); - assert(scrn.pD3DDevice!=NULL); + assert(_pScrn->pD3D8!=NULL); + assert(_pD3DDevice!=NULL); ZeroMemory(&_lmodel_ambient,sizeof(Colorf)); - scrn.pD3DDevice->SetRenderState(D3DRS_AMBIENT, 0x0); + _pD3DDevice->SetRenderState(D3DRS_AMBIENT, 0x0); if(_pFvfBufBasePtr==NULL) _pFvfBufBasePtr = new BYTE[VERT_BUFFER_SIZE]; // allocate storage for vertex info. @@ -568,9 +528,9 @@ dx_init(HCURSOR hMouseCursor) { _pCurFvfBufPtr = NULL; _clip_plane_bits = 0; - scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE , 0x0); + _pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE , 0x0); - scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, true); + _pD3DDevice->SetRenderState(D3DRS_CLIPPING, true); _clipping_enabled = true; // these both reflect d3d defaults @@ -578,35 +538,35 @@ dx_init(HCURSOR hMouseCursor) { _CurFVFType = 0x0; // guards SetVertexShader fmt _bGouraudShadingOn = false; - scrn.pD3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); + _pD3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); // this specifies if lighting model uses material color or vertex color // (not related to gouraud/flat shading) -// scrn.pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, true); +// _pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, true); _depth_test_enabled = true; - scrn.pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, _depth_test_enabled); + _pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, _depth_test_enabled); _pCurTexContext = NULL; _line_smooth_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, false); + _pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, false); _color_material_enabled = false; _normals_enabled = false; _depth_test_enabled = D3DZB_FALSE; - scrn.pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + _pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); _blend_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)_blend_enabled); + _pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)_blend_enabled); // just use whatever d3d defaults to here - scrn.pD3DDevice->GetRenderState(D3DRS_SRCBLEND, (DWORD*)&_blend_source_func); - scrn.pD3DDevice->GetRenderState(D3DRS_DESTBLEND, (DWORD*)&_blend_dest_func); + _pD3DDevice->GetRenderState(D3DRS_SRCBLEND, (DWORD*)&_blend_source_func); + _pD3DDevice->GetRenderState(D3DRS_DESTBLEND, (DWORD*)&_blend_dest_func); _fog_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRS_FOGENABLE, _fog_enabled); + _pD3DDevice->SetRenderState(D3DRS_FOGENABLE, _fog_enabled); _current_projection_mat = LMatrix4f::ident_mat(); _projection_mat_stack_count = 0; @@ -631,28 +591,31 @@ dx_init(HCURSOR hMouseCursor) { _last_testcooplevel_result = D3D_OK; +#if 0 + // unused now // only 1 channel on dx currently _panda_gfx_channel = _win->get_channel(0); +#endif for(int i=0;iCheckDeviceFormat(scrn.CardIDNum,D3DDEVTYPE_HAL,scrn.DisplayMode.Format, + hr = _pScrn->pD3D8->CheckDeviceFormat(_pScrn->CardIDNum,D3DDEVTYPE_HAL,_pScrn->DisplayMode.Format, 0x0,D3DRTYPE_TEXTURE,g_D3DFORMATmap[fmtflag]); if(SUCCEEDED(hr)){ - scrn.SupportedTexFmtsMask|=fmtflag; + _pScrn->SupportedTexFmtsMask|=fmtflag; } } // s3 virge drivers sometimes give crap values for these - if(scrn.d3dcaps.MaxTextureWidth==0) - scrn.d3dcaps.MaxTextureWidth=256; + if(_pScrn->d3dcaps.MaxTextureWidth==0) + _pScrn->d3dcaps.MaxTextureWidth=256; - if(scrn.d3dcaps.MaxTextureHeight==0) - scrn.d3dcaps.MaxTextureHeight=256; + if(_pScrn->d3dcaps.MaxTextureHeight==0) + _pScrn->d3dcaps.MaxTextureHeight=256; - if ((dx_decal_type==GDT_offset) && !(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBIAS)) { - if(scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) { + if ((dx_decal_type==GDT_offset) && !(_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBIAS)) { + if(_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) { if(dxgsg8_cat.is_debug()) dxgsg8_cat.debug() << "dx-decal-type 'offset' not supported by hardware, switching to mask-type decals\n"; dx_decal_type = GDT_mask; @@ -668,7 +631,7 @@ dx_init(HCURSOR hMouseCursor) { if(dxgsg8_cat.is_spam()) dxgsg8_cat.spam() << "polygon-offset decaling disabled in dxgsg, switching to double-draw decaling\n"; - if(scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) { + if(_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) { if(dxgsg8_cat.is_debug()) dxgsg8_cat.debug() << "using dx-decal-type 'GDT_mask'\n"; dx_decal_type = GDT_mask; @@ -680,53 +643,53 @@ dx_init(HCURSOR hMouseCursor) { } #endif - if (((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_MASKZ)) { + if (((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_MASKZ)) { dxgsg8_cat.error() << "dx-decal-types mask&blend impossible to implement, no hardware support for Z-masking, decals will not appear correctly!\n"; } #define REQUIRED_DESTBLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| D3DPBLENDCAPS_SRCALPHA) #define REQUIRED_SRCBLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| D3DPBLENDCAPS_INVSRCALPHA) - if (((scrn.d3dcaps.SrcBlendCaps & REQUIRED_SRCBLENDCAPS)!=REQUIRED_SRCBLENDCAPS) || - ((scrn.d3dcaps.DestBlendCaps & REQUIRED_DESTBLENDCAPS)!=REQUIRED_DESTBLENDCAPS)) { - dxgsg8_cat.error() << "device is missing alpha blending capabilities, blending may not work correctly: SrcBlendCaps: 0x"<< (void*) scrn.d3dcaps.SrcBlendCaps << " DestBlendCaps: "<< (void*) scrn.d3dcaps.DestBlendCaps << endl; + if (((_pScrn->d3dcaps.SrcBlendCaps & REQUIRED_SRCBLENDCAPS)!=REQUIRED_SRCBLENDCAPS) || + ((_pScrn->d3dcaps.DestBlendCaps & REQUIRED_DESTBLENDCAPS)!=REQUIRED_DESTBLENDCAPS)) { + dxgsg8_cat.error() << "device is missing alpha blending capabilities, blending may not work correctly: SrcBlendCaps: 0x"<< (void*) _pScrn->d3dcaps.SrcBlendCaps << " DestBlendCaps: "<< (void*) _pScrn->d3dcaps.DestBlendCaps << endl; } // just 'require' bilinear with mip nearest. #define REQUIRED_TEXFILTERCAPS (D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MINFLINEAR) - if ((scrn.d3dcaps.TextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) { - dxgsg8_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky! TextureFilterCaps: 0x"<< (void*) scrn.d3dcaps.TextureFilterCaps << endl; + if ((_pScrn->d3dcaps.TextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) { + dxgsg8_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky! TextureFilterCaps: 0x"<< (void*) _pScrn->d3dcaps.TextureFilterCaps << endl; } #define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR) // give a warning if we dont at least have bilinear + nearest mip filtering - if (!(scrn.d3dcaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)) { + if (!(_pScrn->d3dcaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)) { if(dxgsg8_cat.is_debug()) - dxgsg8_cat.debug() << "device does not have mipmap texturing filtering capability! TextureFilterCaps: 0x"<< (void*) scrn.d3dcaps.TextureFilterCaps << endl; + dxgsg8_cat.debug() << "device does not have mipmap texturing filtering capability! TextureFilterCaps: 0x"<< (void*) _pScrn->d3dcaps.TextureFilterCaps << endl; dx_ignore_mipmaps = TRUE; - } else if ((scrn.d3dcaps.TextureFilterCaps & TRILINEAR_MIPMAP_TEXFILTERCAPS)!=TRILINEAR_MIPMAP_TEXFILTERCAPS) { + } else if ((_pScrn->d3dcaps.TextureFilterCaps & TRILINEAR_MIPMAP_TEXFILTERCAPS)!=TRILINEAR_MIPMAP_TEXFILTERCAPS) { if(dxgsg8_cat.is_debug()) dxgsg8_cat.debug() << "device is missing tri-linear mipmap filtering capability, textures may look crappy\n"; - } else if(scrn.d3dcaps.DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) { + } else if(_pScrn->d3dcaps.DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) { // this cap is pretty much voodoo2-specific // turn off trilinear filtering on voodoo2 since it doubles the reqd texture memory, degrade to mip point filtering - scrn.d3dcaps.TextureFilterCaps &= (~D3DPTFILTERCAPS_MIPFLINEAR); + _pScrn->d3dcaps.TextureFilterCaps &= (~D3DPTFILTERCAPS_MIPFLINEAR); } #define REQUIRED_TEXBLENDCAPS (D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2) - if ((scrn.d3dcaps.TextureOpCaps & REQUIRED_TEXBLENDCAPS)!=REQUIRED_TEXBLENDCAPS) { - dxgsg8_cat.error() << "device is missing some required texture blending capabilities, texture blending may not work properly! TextureOpCaps: 0x"<< (void*) scrn.d3dcaps.TextureOpCaps << endl; + if ((_pScrn->d3dcaps.TextureOpCaps & REQUIRED_TEXBLENDCAPS)!=REQUIRED_TEXBLENDCAPS) { + dxgsg8_cat.error() << "device is missing some required texture blending capabilities, texture blending may not work properly! TextureOpCaps: 0x"<< (void*) _pScrn->d3dcaps.TextureOpCaps << endl; } - if(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) { + if(_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) { // watch out for drivers that emulate per-pixel fog with per-vertex fog (Riva128, Matrox Millen G200) // some of these require gouraud-shading to be set to work, as if you were using vertex fog _doFogType=PerPixelFog; } else { // every card is going to have vertex fog, since it's implemented in d3d runtime - assert((scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX )!=0); + assert((_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX )!=0); // vtx fog may look crappy if you have large polygons in the foreground and they get clipped, // so you may want to disable it @@ -737,35 +700,35 @@ dx_init(HCURSOR hMouseCursor) { _doFogType = PerVertexFog; // range-based fog only works with vertex fog in dx7/8 - if(dx_use_rangebased_fog && (scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)) - scrn.pD3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, true); + if(dx_use_rangebased_fog && (_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)) + _pD3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, true); } } - scrn.bCanDirectDisableColorWrites=((scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE)!=0); + _pScrn->bCanDirectDisableColorWrites=((_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE)!=0); // Lighting, let's turn it off by default - scrn.pD3DDevice->SetRenderState(D3DRS_LIGHTING, false); + _pD3DDevice->SetRenderState(D3DRS_LIGHTING, false); // turn on dithering if the rendertarget is < 8bits/color channel - _dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(scrn.PresParams.BackBufferFormat) - && (scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)); - scrn.pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, _dither_enabled); + _dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(_pScrn->PresParams.BackBufferFormat) + && (_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)); + _pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, _dither_enabled); - scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING,true); + _pD3DDevice->SetRenderState(D3DRS_CLIPPING,true); // Stencil test is off by default _stencil_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, _stencil_test_enabled); + _pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, _stencil_test_enabled); // Antialiasing. enable_line_smooth(false); // enable_multisample(true); _current_fill_mode = RenderModeAttrib::M_filled; - scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + _pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - scrn.pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); // Use the diffuse vertex color. + _pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); // Use the diffuse vertex color. /* Panda no longer requires us to specify the maximum number of @@ -774,16 +737,16 @@ dx_init(HCURSOR hMouseCursor) { limit or not. Until we override this function, there is no limit. - if(scrn.d3dcaps.MaxActiveLights==0) { + if(_pScrn->d3dcaps.MaxActiveLights==0) { // 0 indicates no limit on # of lights, but we use DXGSG_MAX_LIGHTS anyway for now init_lights(DXGSG_MAX_LIGHTS); } else { - init_lights(min(DXGSG_MAX_LIGHTS,scrn.d3dcaps.MaxActiveLights)); + init_lights(min(DXGSG_MAX_LIGHTS,_pScrn->d3dcaps.MaxActiveLights)); } */ if(dx_auto_normalize_lighting) - scrn.pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true); + _pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true); // must do SetTSS here because redundant states are filtered out by our code based on current values above, so // initial conditions must be correct @@ -791,7 +754,7 @@ dx_init(HCURSOR hMouseCursor) { _CurTexBlendMode = TextureApplyAttrib::M_modulate; SetTextureBlendMode(_CurTexBlendMode,false); _texturing_enabled = false; - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); // disables texturing + _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); // disables texturing // Init more Texture State _CurTexMagFilter=_CurTexMinFilter=_CurTexMipFilter=D3DTEXF_NONE; @@ -801,17 +764,17 @@ dx_init(HCURSOR hMouseCursor) { // this code must match apply_texture() code for states above // so DX TSS renderstate matches dxgsg state - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MAXANISOTROPY,_CurTexAnisoDegree); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU,get_texture_wrap_mode(_CurTexWrapModeU)); - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV,get_texture_wrap_mode(_CurTexWrapModeV)); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MAXANISOTROPY,_CurTexAnisoDegree); + _pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU,get_texture_wrap_mode(_CurTexWrapModeU)); + _pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV,get_texture_wrap_mode(_CurTexWrapModeV)); #ifdef _DEBUG - if ((scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) && + if ((_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) && (dx_global_miplevel_bias!=0.0f)) { - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&dx_global_miplevel_bias)) ); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&dx_global_miplevel_bias)) ); } #endif @@ -819,35 +782,30 @@ dx_init(HCURSOR hMouseCursor) { if(dx_force_backface_culling!=0) { if((dx_force_backface_culling > 0) && (dx_force_backface_culling < D3DCULL_FORCE_DWORD)) { - scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling); + _pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling); } else { dx_force_backface_culling=0; if(dxgsg8_cat.is_debug()) dxgsg8_cat.debug() << "error, invalid value for dx-force-backface-culling\n"; } } - scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling); + _pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling); #else - scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); #endif _alpha_func = D3DCMP_ALWAYS; _alpha_func_refval = 1.0f; - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, _alpha_func); - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAREF, (UINT)(_alpha_func_refval*255.0f)); + _pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, _alpha_func); + _pD3DDevice->SetRenderState(D3DRS_ALPHAREF, (UINT)(_alpha_func_refval*255.0f)); _alpha_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, _alpha_test_enabled); + _pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, _alpha_test_enabled); // this is a new DX8 state that lets you do additional operations other than ADD (e.g. subtract/max/min) - // must check (scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon8500, no on TNT) - scrn.pD3DDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD); + // must check (_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon8500, no on TNT) + _pD3DDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD); - if((_win->is_fullscreen()) && dx_use_dx_cursor) { - hr = CreateDX8Cursor(scrn.pD3DDevice,hMouseCursor,dx_show_cursor_watermark); - if(FAILED(hr)) - dxgsg8_cat.error() << "CreateDX8Cursor failed!\n"; - } - PRINT_REFCNT(dxgsg,scrn.pD3DDevice); + PRINT_REFCNT(dxgsg8,_pD3DDevice); // Make sure the DX state matches all of our initial attribute states. CPT(RenderAttrib) dta = DepthTestAttrib::make(DepthTestAttrib::M_less); @@ -864,20 +822,20 @@ dx_init(HCURSOR hMouseCursor) { if(pdx_globaltexture_filename!=NULL) { // bypasses panda tex mechanism - hr = D3DXCreateTextureFromFile(scrn.pD3DDevice,pdx_globaltexture_filename->c_str(),&_pGlobalTexture); + hr = D3DXCreateTextureFromFile(_pD3DDevice,pdx_globaltexture_filename->c_str(),&_pGlobalTexture); if(FAILED(hr)) { dxgsg8_cat.fatal() << "CreateTexFromFile failed" << D3DERRORSTRING(hr); exit(1); } - hr=scrn.pD3DDevice->SetTexture(dx_globaltexture_stagenum,_pGlobalTexture); + hr=_pD3DDevice->SetTexture(dx_globaltexture_stagenum,_pGlobalTexture); if(FAILED(hr)) { dxgsg8_cat.fatal() << "SetTexture failed" << D3DERRORSTRING(hr); exit(1); } } - PRINT_REFCNT(dxgsg,scrn.pD3DDevice); + PRINT_REFCNT(dxgsg8,_pD3DDevice); } void DXGraphicsStateGuardian8:: @@ -895,16 +853,16 @@ init_shader(ShaderType stype,DXShaderHandle &hShader,string *pFname) { sh_typename="Vertex"; else sh_typename="Pixel"; - if((stype==PixelShader) && (!scrn.bCanUsePixelShaders)) { + if((stype==PixelShader) && (!_pScrn->bCanUsePixelShaders)) { dxgsg8_cat.error() << "HW doesnt support pixel shaders!\n"; exit(1); } - if((hShader!=NULL)&&(!scrn.bIsDX81)) { + if((hShader!=NULL)&&(!_pScrn->bIsDX81)) { // for dx8.0, need to release and recreate shaders after Reset() has been called if(stype==VertexShader) - hr = scrn.pD3DDevice->DeleteVertexShader(hShader); - else hr = scrn.pD3DDevice->DeletePixelShader(hShader); + hr = _pD3DDevice->DeleteVertexShader(hShader); + else hr = _pD3DDevice->DeletePixelShader(hShader); if(FAILED(hr)) dxgsg8_cat.error() << "Delete"<< sh_typename<<"Shader failed!" << D3DERRORSTRING(hr); hShader=NULL; @@ -916,10 +874,10 @@ init_shader(ShaderType stype,DXShaderHandle &hShader,string *pFname) { if(stype==VertexShader) { hShader=read_vertex_shader(*pFname); - hr = scrn.pD3DDevice->SetVertexShader(hShader); + hr = _pD3DDevice->SetVertexShader(hShader); } else { hShader=read_pixel_shader(*pFname); - hr = scrn.pD3DDevice->SetPixelShader(hShader); + hr = _pD3DDevice->SetPixelShader(hShader); } if(FAILED(hr)) @@ -952,7 +910,7 @@ support_overlay_window(bool flag) { _overlay_windows_supported = false; if (dx_full_screen) { - scrn.pddsPrimary->SetClipper(NULL); + _pScrn->pddsPrimary->SetClipper(NULL); } } else if (!_overlay_windows_supported && flag) { @@ -963,11 +921,11 @@ support_overlay_window(bool flag) { // Create a Clipper object to blt the whole screen. LPDIRECTDRAWCLIPPER Clipper; - if (scrn.pDD->CreateClipper(0, &Clipper, NULL) == DD_OK) { - Clipper->SetHWnd(0, scrn.hWnd); - scrn.pddsPrimary->SetClipper(Clipper); + if (_pScrn->pDD->CreateClipper(0, &Clipper, NULL) == DD_OK) { + Clipper->SetHWnd(0, _pScrn->hWnd); + _pScrn->pddsPrimary->SetClipper(Clipper); } - scrn.pDD->FlipToGDISurface(); + _pScrn->pDD->FlipToGDISurface(); Clipper->Release(); } } @@ -991,7 +949,7 @@ do_clear(const RenderBuffer &buffer) { if(buffer_type & RenderBuffer::T_depth) { flags |= D3DCLEAR_ZBUFFER; - assert(scrn.PresParams.EnableAutoDepthStencil); + assert(_pScrn->PresParams.EnableAutoDepthStencil); } if(buffer_type & RenderBuffer::T_back) //set appropriate flags @@ -999,10 +957,10 @@ do_clear(const RenderBuffer &buffer) { if(buffer_type & RenderBuffer::T_stencil) { flags |= D3DCLEAR_STENCIL; - assert(scrn.PresParams.EnableAutoDepthStencil && IS_STENCIL_FORMAT(scrn.PresParams.AutoDepthStencilFormat)); + assert(_pScrn->PresParams.EnableAutoDepthStencil && IS_STENCIL_FORMAT(_pScrn->PresParams.AutoDepthStencilFormat)); } - HRESULT hr = scrn.pD3DDevice->Clear(0, NULL, flags, _d3dcolor_clear_value, + HRESULT hr = _pD3DDevice->Clear(0, NULL, flags, _d3dcolor_clear_value, _depth_clear_value, (DWORD)_stencil_clear_value); if(FAILED(hr)) dxgsg8_cat.error() << "clear_buffer failed: Clear returned " << D3DERRORSTRING(hr); @@ -1033,7 +991,7 @@ prepare_display_region() { // Create the viewport D3DVIEWPORT8 vp = {l,b,w,h,0.0f,1.0f}; - HRESULT hr = scrn.pD3DDevice->SetViewport( &vp ); + HRESULT hr = _pD3DDevice->SetViewport( &vp ); if (FAILED(hr)) { dxgsg8_cat.error() << "SetViewport(" << l << ", " << b << ", " << w << ", " << h @@ -1075,7 +1033,7 @@ prepare_lens() { projection_mat; HRESULT hr; - hr = scrn.pD3DDevice->SetTransform(D3DTS_PROJECTION, + hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)new_projection_mat.get_data()); return SUCCEEDED(hr); } @@ -1110,17 +1068,17 @@ void DXGraphicsStateGuardian8::set_clipper(RECT cliprect) { HRGN hrgn = CreateRectRgn(cliprect.left, cliprect.top, cliprect.right, cliprect.bottom); GetRegionData(hrgn, sizeof(RGNDATAHEADER) + sizeof(RECT), rgn_data); - if (scrn.pD3DDevicesPrimary->GetClipper(&Clipper) != DD_OK) { - result = scrn.pD3DDevice->CreateClipper(0, &Clipper, NULL); + if (_pD3DDevicesPrimary->GetClipper(&Clipper) != DD_OK) { + result = _pD3DDevice->CreateClipper(0, &Clipper, NULL); result = Clipper->SetClipList(rgn_data, 0); - result = scrn.pD3DDevicesPrimary->SetClipper(Clipper); + result = _pD3DDevicesPrimary->SetClipper(Clipper); } else { result = Clipper->SetClipList(rgn_data, 0 ); if (result == DDERR_CLIPPERISUSINGHWND) { - result = scrn.pD3DDevicesPrimary->SetClipper(NULL); - result = scrn.pD3DDevice->CreateClipper(0, &Clipper, NULL); + result = _pD3DDevicesPrimary->SetClipper(NULL); + result = _pD3DDevice->CreateClipper(0, &Clipper, NULL); result = Clipper->SetClipList(rgn_data, 0 ) ; - result = scrn.pD3DDevicesPrimary->SetClipper(Clipper); + result = _pD3DDevicesPrimary->SetClipper(Clipper); } } free(rgn_data); @@ -1171,13 +1129,13 @@ report_texmgr_stats() { ZeroMemory(&ddsCaps,sizeof(ddsCaps)); ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; - if(FAILED( hr = scrn.pD3DDevice->GetAvailableVidMem(&ddsCaps,&dwVidTotal,&dwVidFree))) { + if(FAILED( hr = _pD3DDevice->GetAvailableVidMem(&ddsCaps,&dwVidTotal,&dwVidFree))) { dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << D3DERRORSTRING(hr); exit(1); } ddsCaps.dwCaps = DDSCAPS_TEXTURE; - if(FAILED( hr = scrn.pD3DDevice->GetAvailableVidMem(&ddsCaps,&dwTexTotal,&dwTexFree))) { + if(FAILED( hr = _pD3DDevice->GetAvailableVidMem(&ddsCaps,&dwTexTotal,&dwTexFree))) { dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << D3DERRORSTRING(hr); exit(1); } @@ -1188,7 +1146,7 @@ report_texmgr_stats() { ZeroMemory(&all_resource_stats,sizeof(D3DDEVINFO_RESOURCEMANAGER)); if(!bTexStatsRetrievalImpossible) { - hr = scrn.pD3DDevice->GetInfo(D3DDEVINFOID_RESOURCEMANAGER,&all_resource_stats,sizeof(D3DDEVINFO_RESOURCEMANAGER)); + hr = _pD3DDevice->GetInfo(D3DDEVINFOID_RESOURCEMANAGER,&all_resource_stats,sizeof(D3DDEVINFO_RESOURCEMANAGER)); if (hr!=D3D_OK) { if (hr==S_FALSE) { static int PrintedMsg=2; @@ -1254,7 +1212,7 @@ report_texmgr_stats() { D3DDEVINFO_D3DVERTEXSTATS vtxstats; ZeroMemory(&vtxstats,sizeof(D3DDEVINFO_D3DVERTEXSTATS)); - hr = scrn.pD3DDevice->GetInfo(D3DDEVINFOID_VERTEXSTATS,&vtxstats,sizeof(D3DDEVINFO_D3DVERTEXSTATS)); + hr = _pD3DDevice->GetInfo(D3DDEVINFOID_VERTEXSTATS,&vtxstats,sizeof(D3DDEVINFO_D3DVERTEXSTATS)); if (hr!=D3D_OK) { dxgsg8_cat.error() << "GetInfo(D3DVERTEXSTATS) failed : result = " << D3DERRORSTRING(hr); return; @@ -1633,8 +1591,8 @@ draw_point(GeomPoint *geom, GeomContext *gc) { draw_prim_inner_loop(nPrims, geom, _perVertex | _perPrim); if(!_bDrawPrimDoSetupVertexBuffer) { - HRESULT hr = scrn.pD3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nPrims, _pFvfBufBasePtr, vertex_size); - TestDrawPrimFailure(DrawPrim,hr,scrn.pD3DDevice,nPrims,0); + HRESULT hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nPrims, _pFvfBufBasePtr, vertex_size); + TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nPrims,0); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_POINTLIST,nPrims); } @@ -1731,13 +1689,13 @@ draw_line(GeomLine* geom, GeomContext *gc) { if(!_bDrawPrimDoSetupVertexBuffer) { if (_tmp_fvfOverrunBuf == NULL) { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); - hr = scrn.pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, nPrims, _pFvfBufBasePtr, vertex_size); + hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, nPrims, _pFvfBufBasePtr, vertex_size); } else { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_tmp_fvfOverrunBuf)); - hr = scrn.pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, nPrims, _tmp_fvfOverrunBuf, vertex_size); + hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, nPrims, _tmp_fvfOverrunBuf, vertex_size); delete [] _tmp_fvfOverrunBuf; } - TestDrawPrimFailure(DrawPrim,hr,scrn.pD3DDevice,nVerts,0); + TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,0); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINELIST,nVerts); } @@ -1852,8 +1810,8 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); if(!_bDrawPrimDoSetupVertexBuffer) { - HRESULT hr = scrn.pD3DDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts-1, _pFvfBufBasePtr, vertex_size); - TestDrawPrimFailure(DrawPrim,hr,scrn.pD3DDevice,nVerts,0); + HRESULT hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts-1, _pFvfBufBasePtr, vertex_size); + TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,0); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINESTRIP,nVerts); } @@ -1927,11 +1885,11 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(nPrims)); D3DMATRIX OldD3DWorldMatrix; - scrn.pD3DDevice->GetTransform(D3DTS_WORLD, &OldD3DWorldMatrix); + _pD3DDevice->GetTransform(D3DTS_WORLD, &OldD3DWorldMatrix); bool bReEnableDither=false; - scrn.pD3DDevice->GetTransform(D3DTS_WORLD, &OldD3DWorldMatrix); + _pD3DDevice->GetTransform(D3DTS_WORLD, &OldD3DWorldMatrix); Geom::VertexIterator vi = geom->make_vertex_iterator(); Geom::ColorIterator ci = geom->make_color_iterator(); @@ -1961,7 +1919,7 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { // ratio built in. // null the world xform, so sprites are orthog to scrn - scrn.pD3DDevice->SetTransform(D3DTS_WORLD, &matIdentity); + _pD3DDevice->SetTransform(D3DTS_WORLD, &matIdentity); // only need to change _WORLD xform, _VIEW xform is Identity // precomputation stuff @@ -2239,17 +2197,17 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { // cant do tristrip/fan since multiple quads arent connected // best we can do is indexed primitive, which sends 2 redundant indices instead of sending 2 redundant full verts - HRESULT hr = scrn.pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, // start index in array + HRESULT hr = _pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, // start index in array nVerts, numTris, _index_buf, D3DFMT_INDEX16, _pFvfBufBasePtr, vertex_size); - TestDrawPrimFailure(DrawIndexedPrim,hr,scrn.pD3DDevice,QUADVERTLISTLEN*nPrims,numTris); + TestDrawPrimFailure(DrawIndexedPrim,hr,_pD3DDevice,QUADVERTLISTLEN*nPrims,numTris); _pCurFvfBufPtr = NULL; delete [] SpriteArray; // restore the matrices - scrn.pD3DDevice->SetTransform(D3DTS_WORLD, + _pD3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)modelview_mat.get_data()); if(bReEnableDither) @@ -2272,7 +2230,7 @@ draw_polygon(GeomPolygon *geom, GeomContext *gc) { // wireframe polygon will be drawn as linestrip, otherwise draw as multi-tri trifan DWORD rstate; - scrn.pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate); + _pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate); if(rstate==D3DFILL_WIREFRAME) { draw_linestrip_base(geom,gc,true); } else { @@ -2296,7 +2254,7 @@ draw_quad(GeomQuad *geom, GeomContext *gc) { // wireframe quad will be drawn as linestrip, otherwise draw as multi-tri trifan DWORD rstate; - scrn.pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate); + _pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate); if(rstate==D3DFILL_WIREFRAME) { draw_linestrip_base(geom,gc,true); } else { @@ -2425,8 +2383,8 @@ draw_tri(GeomTri *geom, GeomContext *gc) { nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); if(!_bDrawPrimDoSetupVertexBuffer) { - hr = scrn.pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nPrims, _pFvfBufBasePtr, vertex_size); - TestDrawPrimFailure(DrawPrim,hr,scrn.pD3DDevice,nVerts,nPrims); + hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nPrims, _pFvfBufBasePtr, vertex_size); + TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,nPrims); } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_TRIANGLELIST,nVerts); } @@ -2443,14 +2401,14 @@ draw_tri(GeomTri *geom, GeomContext *gc) { 0.0f, 0.0f, 33.0, 2.0, 0.0f }; - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_BORDER); - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_BORDER); - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_BORDERCOLOR,MY_D3DRGBA(0,0,0,0)); + _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_BORDER); + _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_BORDER); + _pD3DDevice->SetTextureStageState(0,D3DTSS_BORDERCOLOR,MY_D3DRGBA(0,0,0,0)); DWORD FVFType = D3DFVF_XYZ | (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)) ; set_vertex_format(FVFType); - HRESULT hr = scrn.pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, vert_buf, 1, 5*sizeof(float)); - TestDrawPrimFailure(DrawPrim,hr,scrn.pD3DDevice,3,1); + HRESULT hr = _pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, vert_buf, 1, 5*sizeof(float)); + TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,3,1); #endif } @@ -2661,8 +2619,8 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { DWORD numTris=nVerts-2; if(!_bDrawPrimDoSetupVertexBuffer) { - hr = scrn.pD3DDevice->DrawPrimitiveUP(trilisttype, numTris, _pFvfBufBasePtr, vertex_size); - TestDrawPrimFailure(DrawPrim,hr,scrn.pD3DDevice,nVerts,numTris); + hr = _pD3DDevice->DrawPrimitiveUP(trilisttype, numTris, _pFvfBufBasePtr, vertex_size); + TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nVerts,numTris); } else { COPYVERTDATA_2_VERTEXBUFFER(trilisttype,nVerts); } @@ -2976,10 +2934,10 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) { // possible optimization: make DP 1 for all spheres call here, since trilist is independent tris. // indexes couldnt start w/0 tho, need to pass offset to gensph - HRESULT hr = scrn.pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, // start index in array + HRESULT hr = _pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, // start index in array nVerts, nTris, _index_buf, D3DFMT_INDEX16, _pFvfBufBasePtr, vertex_size); - TestDrawPrimFailure(DrawIndexedPrim,hr,scrn.pD3DDevice,nVerts,nTris); + TestDrawPrimFailure(DrawIndexedPrim,hr,_pD3DDevice,nVerts,nTris); } _pCurFvfBufPtr = NULL; @@ -3008,7 +2966,7 @@ prepare_texture(Texture *tex) { apply_texture_immediate(tex); #else - if (dtc->CreateTexture(scrn) == NULL) { + if (dtc->CreateTexture(*_pScrn) == NULL) { delete dtc; return NULL; } @@ -3064,7 +3022,7 @@ apply_texture(TextureContext *tc) { } dtc->DeleteTexture(); - if (dtc->CreateTexture(scrn) == NULL) { + if (dtc->CreateTexture(*_pScrn) == NULL) { // Oops, we can't re-create the texture for some reason. dxgsg8_cat.error() << "Unable to re-create texture " << *dtc->_texture << endl; @@ -3087,11 +3045,11 @@ apply_texture(TextureContext *tc) { wrapV=tex->get_wrapv(); if (wrapU!=_CurTexWrapModeU) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,get_texture_wrap_mode(wrapU)); + _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,get_texture_wrap_mode(wrapU)); _CurTexWrapModeU = wrapU; } if (wrapV!=_CurTexWrapModeV) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,get_texture_wrap_mode(wrapV)); + _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,get_texture_wrap_mode(wrapV)); _CurTexWrapModeV = wrapV; } @@ -3099,7 +3057,7 @@ apply_texture(TextureContext *tc) { Texture::FilterType ft=tex->get_magfilter(); if(_CurTexAnisoDegree != aniso_degree) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_MAXANISOTROPY,aniso_degree); + _pD3DDevice->SetTextureStageState(0,D3DTSS_MAXANISOTROPY,aniso_degree); _CurTexAnisoDegree = aniso_degree; } @@ -3118,7 +3076,7 @@ apply_texture(TextureContext *tc) { if(_CurTexMagFilter!=newMagFilter) { _CurTexMagFilter=newMagFilter; - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, newMagFilter); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, newMagFilter); } #ifdef _DEBUG @@ -3164,17 +3122,17 @@ apply_texture(TextureContext *tc) { if(newMinFilter!=_CurTexMinFilter) { _CurTexMinFilter = newMinFilter; - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, newMinFilter); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, newMinFilter); } if(newMipFilter!=_CurTexMipFilter) { _CurTexMipFilter = newMipFilter; - scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, newMipFilter); + _pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, newMipFilter); } // bugbug: does this handle the case of untextured geometry? // we dont see this bug cause we never mix textured/untextured - scrn.pD3DDevice->SetTexture(0,dtc->_pD3DTexture8); + _pD3DDevice->SetTexture(0,dtc->_pD3DTexture8); #if 0 if (dtc!=NULL) { @@ -3228,7 +3186,7 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) { exit(1); } - hr = scrn.pD3DDevice->GetRenderTarget(&pCurRenderTarget); + hr = _pD3DDevice->GetRenderTarget(&pCurRenderTarget); if(FAILED(hr)) { dxgsg8_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr); exit(1); @@ -3243,7 +3201,7 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) { SrcRect.bottom = yo+h; // now copy from fb to tex - hr = scrn.pD3DDevice->CopyRects(pCurRenderTarget,&SrcRect,1,pTexSurfaceLev0,NULL); + hr = _pD3DDevice->CopyRects(pCurRenderTarget,&SrcRect,1,pTexSurfaceLev0,NULL); if(FAILED(hr)) { dxgsg8_cat.error() << "CopyRects failed in copy_texture" << D3DERRORSTRING(hr); exit(1); @@ -3272,6 +3230,10 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { + // This code is now invalidated by the new design; perhaps the + // interface is not needed anyway. +#if 0 + nassertv(tc != NULL && pb != NULL); Texture *tex = tc->_texture; @@ -3288,6 +3250,9 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { texture_to_pixel_buffer(tc, pb, dr); pop_frame_buffer(old_fb); +#else + dxgsg8_cat.error() << "texture_to_pixel_buffer unimplemented for DX!\n"; +#endif } //////////////////////////////////////////////////////////////////// @@ -3326,11 +3291,11 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { HRESULT hr; RECT WindRect; - GetWindowRect(scrn.hWnd,&WindRect); + GetWindowRect(_pScrn->hWnd,&WindRect); // just handling front and backbuf for now, not textures yet if(_cur_read_pixel_buffer & RenderBuffer::T_back) { - hr=scrn.pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf); + hr=_pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf); if(FAILED(hr)) { dxgsg8_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); @@ -3352,20 +3317,20 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { DWORD TmpSurfXsize,TmpSurfYsize; - if(scrn.PresParams.Windowed) { + if(_pScrn->PresParams.Windowed) { // GetFrontBuffer retrieves the entire desktop for a monitor, so need space for that MONITORINFO minfo; minfo.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(scrn.hMon, &minfo); // have to use GetMonitorInfo, since this gsg may not be for primary monitor + GetMonitorInfo(_pScrn->hMon, &minfo); // have to use GetMonitorInfo, since this gsg may not be for primary monitor TmpSurfXsize=RECT_XSIZE(minfo.rcMonitor); TmpSurfYsize=RECT_YSIZE(minfo.rcMonitor); // set SrcCopyRect to client area of window in scrn coords - GetClientRect( scrn.hWnd, &SrcCopyRect); - ClientToScreen( scrn.hWnd, (POINT*)&SrcCopyRect.left ); - ClientToScreen( scrn.hWnd, (POINT*)&SrcCopyRect.right ); + GetClientRect( _pScrn->hWnd, &SrcCopyRect); + ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.left ); + ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.right ); } else { TmpSurfXsize=RECT_XSIZE(WindRect); TmpSurfYsize=RECT_YSIZE(WindRect); @@ -3375,13 +3340,13 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { SrcCopyRect.bottom=TmpSurfYsize; } - hr=scrn.pD3DDevice->CreateImageSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,&pD3DSurf); + hr=_pD3DDevice->CreateImageSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,&pD3DSurf); if(FAILED(hr)) { dxgsg8_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); exit(1); } - hr=scrn.pD3DDevice->GetFrontBuffer(pD3DSurf); + hr=_pD3DDevice->GetFrontBuffer(pD3DSurf); if(hr==D3DERR_DEVICELOST) { // dont necessary want to exit in this case @@ -3429,7 +3394,7 @@ void DXGraphicsStateGuardian8::apply_material( const Material* material ) { cur_material.Specular = *(D3DCOLORVALUE *)(material->get_specular().get_data()); cur_material.Emissive = *(D3DCOLORVALUE *)(material->get_emission().get_data()); cur_material.Power = material->get_shininess(); - scrn.pD3DDevice->SetMaterial(&cur_material); + _pD3DDevice->SetMaterial(&cur_material); } //////////////////////////////////////////////////////////////////// @@ -3448,10 +3413,10 @@ apply_fog(Fog *fog) { // should probably avoid doing redundant SetRenderStates, but whatever - scrn.pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)_doFogType, d3dfogmode); + _pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)_doFogType, d3dfogmode); const Colorf &fog_colr = fog->get_color(); - scrn.pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, + _pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f)); // Alpha bits are not used // do we need to adjust fog start/end values based on D3DPRASTERCAPS_WFOG/D3DPRASTERCAPS_ZFOG ? @@ -3463,9 +3428,9 @@ apply_fog(Fog *fog) { float onset, opaque; fog->get_linear_range(onset, opaque); - scrn.pD3DDevice->SetRenderState( D3DRS_FOGSTART, + _pD3DDevice->SetRenderState( D3DRS_FOGSTART, *((LPDWORD) (&onset)) ); - scrn.pD3DDevice->SetRenderState( D3DRS_FOGEND, + _pD3DDevice->SetRenderState( D3DRS_FOGEND, *((LPDWORD) (&opaque)) ); } break; @@ -3474,7 +3439,7 @@ apply_fog(Fog *fog) { { // Exponential fog is always camera-relative. float fog_density = fog->get_exp_density(); - scrn.pD3DDevice->SetRenderState( D3DRS_FOGDENSITY, + _pD3DDevice->SetRenderState( D3DRS_FOGDENSITY, *((LPDWORD) (&fog_density)) ); } break; @@ -3493,47 +3458,47 @@ void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexB //if bCanJustEnable, then we only need to make sure ColorOp is turned on and set properly if (bCanJustEnable && (TexBlendMode==_CurTexBlendMode)) { // just reset COLOROP 0 to enable pipeline, rest is already set properly - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); return; } - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, TexBlendColorOp1[TexBlendMode] ); switch (TexBlendMode) { case TextureApplyAttrib::M_modulate: // emulates GL_MODULATE glTexEnv mode // want to multiply tex-color*pixel color to emulate GL modulate blend (see glTexEnv) - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; case TextureApplyAttrib::M_decal: // emulates GL_DECAL glTexEnv mode - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); break; case TextureApplyAttrib::M_replace: - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); break; case TextureApplyAttrib::M_add: - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); // since I'm making up 'add' mode, use modulate. "adding" alpha never makes sense right? - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; case TextureApplyAttrib::M_blend: @@ -3545,21 +3510,21 @@ void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexB GL requires 2 independent operations on 3 input vars for this mode DX texture pipeline requires re-using input of last stage on each new op, so I dont think exact emulation is possible - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); need to SetTexture(1,tex) also - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE ); wrong - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR ); + _pD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE ); wrong + _pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + _pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR ); - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); - scrn.pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT ); + _pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + _pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT ); */ @@ -3588,7 +3553,7 @@ enable_texturing(bool val) { // I'm going to allow enabling texturing even if no tex has been set yet, seems to cause no probs if (val == false) { - scrn.pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); + _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); } else { SetTextureBlendMode(_CurTexBlendMode,true); } @@ -3604,13 +3569,13 @@ void DXGraphicsStateGuardian8:: issue_transform(const TransformState *transform) { // if we're using ONLY vertex shaders, could get avoid calling SetTrans D3DMATRIX *pMat = (D3DMATRIX*)transform->get_mat().get_data(); - scrn.pD3DDevice->SetTransform(D3DTS_WORLD,pMat); + _pD3DDevice->SetTransform(D3DTS_WORLD,pMat); #ifdef USE_VERTEX_SHADERS if(_CurVertexShader!=NULL) { // vertex shaders need access to the current xform matrix, // so need to reset this vshader 'constant' every time view matrix changes - HRESULT hr = scrn.pD3DDevice->SetVertexShaderConstant(VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART, pMat, 4); + HRESULT hr = _pD3DDevice->SetVertexShaderConstant(VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART, pMat, 4); #ifdef _DEBUG if(FAILED(hr)) { dxgsg8_cat.error() << "SetVertexShader failed" << D3DERRORSTRING(hr); @@ -3676,11 +3641,11 @@ issue_render_mode(const RenderModeAttrib *attrib) { switch (mode) { case RenderModeAttrib::M_filled: - scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + _pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); break; case RenderModeAttrib::M_wireframe: - scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); + _pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); break; default: @@ -3710,11 +3675,11 @@ issue_depth_test(const DepthTestAttrib *attrib) { DepthTestAttrib::PandaCompareFunc mode = attrib->get_mode(); if (mode == DepthTestAttrib::M_none) { _depth_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + _pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); } else { _depth_test_enabled = true; - scrn.pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - scrn.pD3DDevice->SetRenderState(D3DRS_ZFUNC, (D3DCMPFUNC) mode); + _pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + _pD3DDevice->SetRenderState(D3DRS_ZFUNC, (D3DCMPFUNC) mode); } } @@ -3756,13 +3721,13 @@ issue_cull_face(const CullFaceAttrib *attrib) { switch (mode) { case CullFaceAttrib::M_cull_none: - scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); break; case CullFaceAttrib::M_cull_clockwise: - scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); + _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); break; case CullFaceAttrib::M_cull_counter_clockwise: - scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); + _pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); break; default: dxgsg8_cat.error() @@ -3796,7 +3761,7 @@ issue_fog(const FogAttrib *attrib) { void DXGraphicsStateGuardian8:: issue_depth_offset(const DepthOffsetAttrib *attrib) { int offset = attrib->get_offset(); - scrn.pD3DDevice->SetRenderState(D3DRS_ZBIAS, offset); + _pD3DDevice->SetRenderState(D3DRS_ZBIAS, offset); } //////////////////////////////////////////////////////////////////// @@ -3837,7 +3802,7 @@ bind_light(PointLight *light, int light_id) { alight.Attenuation1 = att[1]; alight.Attenuation2 = att[2]; - HRESULT res = scrn.pD3DDevice->SetLight(light_id, &alight); + HRESULT res = _pD3DDevice->SetLight(light_id, &alight); } //////////////////////////////////////////////////////////////////// @@ -3878,7 +3843,7 @@ bind_light(DirectionalLight *light, int light_id) { alight.Attenuation1 = 0.0f; // linear alight.Attenuation2 = 0.0f; // quadratic - HRESULT res = scrn.pD3DDevice->SetLight(light_id, &alight); + HRESULT res = _pD3DDevice->SetLight(light_id, &alight); } //////////////////////////////////////////////////////////////////// @@ -3928,7 +3893,7 @@ bind_light(Spotlight *light, int light_id) { alight.Attenuation1 = att[1]; alight.Attenuation2 = att[2]; - HRESULT res = scrn.pD3DDevice->SetLight(light_id, &alight); + HRESULT res = _pD3DDevice->SetLight(light_id, &alight); } //////////////////////////////////////////////////////////////////// @@ -3970,7 +3935,7 @@ begin_scene() { return false; } - HRESULT hr = scrn.pD3DDevice->BeginScene(); + HRESULT hr = _pD3DDevice->BeginScene(); if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST) { @@ -4004,7 +3969,7 @@ begin_scene() { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: end_scene() { - HRESULT hr = scrn.pD3DDevice->EndScene(); + HRESULT hr = _pD3DDevice->EndScene(); if (FAILED(hr)) { @@ -4284,7 +4249,7 @@ get_fog_mode_type(Fog::Mode m) const { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: enable_lighting(bool enable) { - scrn.pD3DDevice->SetRenderState(D3DRS_LIGHTING, (DWORD)enable); + _pD3DDevice->SetRenderState(D3DRS_LIGHTING, (DWORD)enable); } //////////////////////////////////////////////////////////////////// @@ -4297,7 +4262,7 @@ enable_lighting(bool enable) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: set_ambient_light(const Colorf &color) { - scrn.pD3DDevice->SetRenderState(D3DRS_AMBIENT, + _pD3DDevice->SetRenderState(D3DRS_AMBIENT, Colorf_to_D3DCOLOR(color)); } @@ -4310,7 +4275,7 @@ set_ambient_light(const Colorf &color) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: enable_light(int light_id, bool enable) { - HRESULT res = scrn.pD3DDevice->LightEnable(light_id, enable); + HRESULT res = _pD3DDevice->LightEnable(light_id, enable); #ifdef GSG_VERBOSE dxgsg8_cat.debug() @@ -4356,7 +4321,7 @@ enable_clip_plane(int plane_id, bool enable) { _clip_plane_bits &= ~bitflag; } - scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, _clip_plane_bits); + _pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, _clip_plane_bits); } //////////////////////////////////////////////////////////////////// @@ -4377,7 +4342,7 @@ bind_clip_plane(PlaneNode *plane, int plane_id) { LMatrix4f rel_mat = plane_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default); Planef world_plane = plane->get_plane() * rel_mat; - scrn.pD3DDevice->SetClipPlane(plane_id, world_plane.get_data()); + _pD3DDevice->SetClipPlane(plane_id, world_plane.get_data()); } void DXGraphicsStateGuardian8:: @@ -4399,8 +4364,8 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, ColorBlendAttrib::Mode color_blend_mode, TransparencyAttrib::Mode transparency_mode) { - if((color_write_mode == ColorWriteAttrib::M_off) && !scrn.bCanDirectDisableColorWrites) { - // need !scrn.bCanDirectDisableColorWrites guard because other issue_colorblend,issue_transp + if((color_write_mode == ColorWriteAttrib::M_off) && !_pScrn->bCanDirectDisableColorWrites) { + // need !_pScrn->bCanDirectDisableColorWrites guard because other issue_colorblend,issue_transp // will come this way, and they should ignore the colorwriteattrib value since it's been // handled separately in set_color_writemask enable_blend(true); @@ -4547,30 +4512,41 @@ dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) { free_nondx_resources(); - PRINT_REFCNT(dxgsg,scrn.pD3DDevice); + PRINT_REFCNT(dxgsg8,_pD3DDevice); // these 2 calls release ddraw surfaces and vbuffers. unsafe unless not on exit release_all_textures(); release_all_geoms(); - PRINT_REFCNT(dxgsg,scrn.pD3DDevice); + PRINT_REFCNT(dxgsg8,_pD3DDevice); // delete non-panda-texture/geom DX objects (VBs/textures/shaders) - SAFE_DELSHADER(Vertex,_CurVertexShader,scrn.pD3DDevice); - SAFE_DELSHADER(Pixel,_CurPixelShader,scrn.pD3DDevice); + SAFE_DELSHADER(Vertex,_CurVertexShader,_pD3DDevice); + SAFE_DELSHADER(Pixel,_CurPixelShader,_pD3DDevice); SAFE_RELEASE(_pGlobalTexture); - PRINT_REFCNT(dxgsg,scrn.pD3DDevice); + PRINT_REFCNT(dxgsg8,_pD3DDevice); // Do a safe check for releasing the D3DDEVICE. RefCount should be zero. - // if we're called from exit(), scrn.pD3DDevice may already have been released - if (scrn.pD3DDevice!=NULL) { + // if we're called from exit(), _pD3DDevice may already have been released + if (_pD3DDevice!=NULL) { for(int i=0;iSetTexture(i,NULL); // d3d should release this stuff internally anyway, but whatever - RELEASE(scrn.pD3DDevice,dxgsg8,"d3dDevice",RELEASE_DOWN_TO_ZERO); + _pD3DDevice->SetTexture(i,NULL); // d3d should release this stuff internally anyway, but whatever + RELEASE(_pD3DDevice,dxgsg8,"d3dDevice",RELEASE_DOWN_TO_ZERO); + _pScrn->pD3DDevice = NULL; } - RELEASE(scrn.pD3D8,dxgsg8,"ID3D8",RELEASE_DOWN_TO_ZERO); + // Releasing pD3D is now the responsibility of the GraphicsPipe destructor +} + +void DXGraphicsStateGuardian8:: +set_context(DXScreenData *pNewContextData) { + // dont do copy from window since dx_init sets fields too. + // simpler to keep all of it in one place, so use ptr to window struct + + assert(pNewContextData!=NULL); + _pScrn = pNewContextData; + _pD3DDevice = _pScrn->pD3DDevice; //copy this one field for speed of deref } bool refill_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) { @@ -4598,7 +4574,7 @@ bool recreate_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) { // Re-fill the contents of textures and vertex buffers // which just got restored now. - IDirect3DTexture8 *ddtex = dtc->CreateTexture(dxgsg->scrn); + IDirect3DTexture8 *ddtex = dtc->CreateTexture(*dxgsg->_pScrn); return ddtex!=NULL; } @@ -4617,14 +4593,14 @@ HRESULT DXGraphicsStateGuardian8::DeleteAllDeviceObjects(void) { dxgsg8_cat.debug() << "release of all textures complete\n"; // delete non-panda-texture/geom DX objects (VBs/textures/shaders) - SAFE_DELSHADER(Vertex,_CurVertexShader,scrn.pD3DDevice); - SAFE_DELSHADER(Pixel,_CurPixelShader,scrn.pD3DDevice); + SAFE_DELSHADER(Vertex,_CurVertexShader,_pD3DDevice); + SAFE_DELSHADER(Pixel,_CurPixelShader,_pD3DDevice); SAFE_RELEASE(_pGlobalTexture); - assert(scrn.pD3DDevice); + assert(_pD3DDevice); - SAFE_DELSHADER(Vertex,_CurVertexShader,scrn.pD3DDevice); - SAFE_DELSHADER(Pixel,_CurPixelShader,scrn.pD3DDevice); + SAFE_DELSHADER(Vertex,_CurVertexShader,_pD3DDevice); + SAFE_DELSHADER(Pixel,_CurPixelShader,_pD3DDevice); SAFE_RELEASE(_pGlobalTexture); return S_OK; @@ -4653,7 +4629,7 @@ HRESULT DXGraphicsStateGuardian8::ReleaseAllDeviceObjects(void) { // Description: redraw primary buffer //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8::show_frame(bool bNoNewFrameDrawn) { - if(scrn.pD3DDevice==NULL) + if(_pD3DDevice==NULL) return; // DO_PSTATS_STUFF(PStatTimer timer(_win->_swap_pcollector)); // this times just the flip, so it must go here in dxgsg, instead of wdxdisplay, which would time the whole frame @@ -4662,11 +4638,11 @@ void DXGraphicsStateGuardian8::show_frame(bool bNoNewFrameDrawn) { if(bNoNewFrameDrawn) { // a new frame has not been rendered, we just want to display the last thing // that was drawn into backbuf, if backbuf is valid - if(scrn.PresParams.SwapEffect==D3DSWAPEFFECT_DISCARD) { + if(_pScrn->PresParams.SwapEffect==D3DSWAPEFFECT_DISCARD) { // in DISCARD mode, old backbufs are not guaranteed to have valid pixels, // so we cant copy back->front here. just give up. return; - } else if(scrn.PresParams.SwapEffect==D3DSWAPEFFECT_FLIP) { + } else if(_pScrn->PresParams.SwapEffect==D3DSWAPEFFECT_FLIP) { /* bugbug: here we should use CopyRects here to copy backbuf to front (except in the case of frames 1 and 2 where we have no valid data in the backbuffer yet, for those cases give up and return). @@ -4680,7 +4656,7 @@ void DXGraphicsStateGuardian8::show_frame(bool bNoNewFrameDrawn) { // may work ok as long as backbuf hasnt been touched } - hr = scrn.pD3DDevice->Present((CONST RECT*)NULL,(CONST RECT*)NULL,(HWND)NULL,NULL); + hr = _pD3DDevice->Present((CONST RECT*)NULL,(CONST RECT*)NULL,(HWND)NULL,NULL); if(FAILED(hr)) { if(hr == D3DERR_DEVICELOST) { CheckCooperativeLevel(); @@ -4695,8 +4671,8 @@ HRESULT DXGraphicsStateGuardian8::reset_d3d_device(D3DPRESENT_PARAMETERS *pPresP HRESULT hr; assert(IS_VALID_PTR(pPresParams)); - assert(IS_VALID_PTR(scrn.pD3D8)); - assert(IS_VALID_PTR(scrn.pD3DDevice)); + assert(IS_VALID_PTR(_pScrn->pD3D8)); + assert(IS_VALID_PTR(_pD3DDevice)); ReleaseAllDeviceObjects(); @@ -4704,21 +4680,21 @@ HRESULT DXGraphicsStateGuardian8::reset_d3d_device(D3DPRESENT_PARAMETERS *pPresP // for windowed make sure out format matches the desktop fmt, in case the // desktop mode has been changed - scrn.pD3D8->GetAdapterDisplayMode(scrn.CardIDNum, &scrn.DisplayMode); - pPresParams->BackBufferFormat = scrn.DisplayMode.Format; + _pScrn->pD3D8->GetAdapterDisplayMode(_pScrn->CardIDNum, &_pScrn->DisplayMode); + pPresParams->BackBufferFormat = _pScrn->DisplayMode.Format; } - hr=scrn.pD3DDevice->Reset(pPresParams); + hr=_pD3DDevice->Reset(pPresParams); if(SUCCEEDED(hr)) { - if(pPresParams!=&scrn.PresParams) - memcpy(&scrn.PresParams,pPresParams,sizeof(D3DPRESENT_PARAMETERS)); + if(pPresParams!=&_pScrn->PresParams) + memcpy(&_pScrn->PresParams,pPresParams,sizeof(D3DPRESENT_PARAMETERS)); } return hr; } bool DXGraphicsStateGuardian8:: CheckCooperativeLevel(bool bDoReactivateWindow) { - HRESULT hr = scrn.pD3DDevice->TestCooperativeLevel(); + HRESULT hr = _pD3DDevice->TestCooperativeLevel(); if(SUCCEEDED(hr)) { assert(SUCCEEDED(_last_testcooplevel_result)); @@ -4726,39 +4702,43 @@ CheckCooperativeLevel(bool bDoReactivateWindow) { } switch(hr) { - case D3DERR_DEVICENOTRESET: - _bDXisReady = false; - hr=reset_d3d_device(&scrn.PresParams); - if (FAILED(hr)) { - // I think this shouldnt fail unless I've screwed up the PresParams from the original working ones somehow - dxgsg8_cat.error() - << "CheckCooperativeLevel Reset() failed, hr = " << D3DERRORSTRING(hr); - exit(1); - } - - if(bDoReactivateWindow) { - // _win->reactivate_window(); //must reactivate window before you can restore surfaces (otherwise you are in WRONGVIDEOMODE, and DDraw RestoreAllSurfaces fails) - } - hr = scrn.pD3DDevice->TestCooperativeLevel(); - if(FAILED(hr)) { - // internal chk, shouldnt fail - dxgsg8_cat.error() - << "TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr); - exit(1); - } - - _bDXisReady = TRUE; - break; - - case D3DERR_DEVICELOST: - if(SUCCEEDED(_last_testcooplevel_result)) { - if(_bDXisReady) { - // _win->deactivate_window(); + case D3DERR_DEVICENOTRESET: _bDXisReady = false; - if(dxgsg8_cat.is_debug()) - dxgsg8_cat.debug() << "D3D Device was Lost, waiting...\n"; - } - } + hr=reset_d3d_device(&_pScrn->PresParams); + if (FAILED(hr)) { + // I think this shouldnt fail unless I've screwed up the PresParams from the original working ones somehow + dxgsg8_cat.error() + << "CheckCooperativeLevel Reset() failed, hr = " << D3DERRORSTRING(hr); + exit(1); + } + + // BUGBUG: is taking this out wrong?? + /* + if(bDoReactivateWindow) { + _win->reactivate_window(); //must reactivate window before you can restore surfaces (otherwise you are in WRONGVIDEOMODE, and DDraw RestoreAllSurfaces fails) + } + */ + + hr = _pD3DDevice->TestCooperativeLevel(); + if(FAILED(hr)) { + // internal chk, shouldnt fail + dxgsg8_cat.error() + << "TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr); + exit(1); + } + + _bDXisReady = TRUE; + break; + + case D3DERR_DEVICELOST: + if(SUCCEEDED(_last_testcooplevel_result)) { + if(_bDXisReady) { + // _win->deactivate_window(); + _bDXisReady = false; + if(dxgsg8_cat.is_debug()) + dxgsg8_cat.debug() << "D3D Device was Lost, waiting...\n"; + } + } } _last_testcooplevel_result = hr; @@ -4772,12 +4752,12 @@ CheckCooperativeLevel(bool bDoReactivateWindow) { // Description: we receive the new x and y position of the client //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8::adjust_view_rect(int x, int y) { - if (scrn.view_rect.left != x || scrn.view_rect.top != y) { + if (_pScrn->view_rect.left != x || _pScrn->view_rect.top != y) { - scrn.view_rect.right = x + RECT_XSIZE(scrn.view_rect); - scrn.view_rect.left = x; - scrn.view_rect.bottom = y + RECT_YSIZE(scrn.view_rect); - scrn.view_rect.top = y; + _pScrn->view_rect.right = x + RECT_XSIZE(_pScrn->view_rect); + _pScrn->view_rect.left = x; + _pScrn->view_rect.bottom = y + RECT_YSIZE(_pScrn->view_rect); + _pScrn->view_rect.top = y; // set_clipper(clip_rect); } diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index e94f7db46a..c947e9480b 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -70,7 +70,7 @@ class EXPCL_PANDADX DXGraphicsStateGuardian8 : public GraphicsStateGuardian { friend class DXTextureContext8; public: - DXGraphicsStateGuardian8(GraphicsWindow *win); + DXGraphicsStateGuardian8(const FrameBufferProperties &properties); ~DXGraphicsStateGuardian8(); virtual void reset(); @@ -150,7 +150,8 @@ public: public: // recreate_tex_callback needs these to be public - DXScreenData scrn; + DXScreenData *_pScrn; + LPDIRECT3DDEVICE8 _pD3DDevice; // same as pScrn->_pD3DDevice, cached for spd protected: virtual void enable_lighting(bool enable); @@ -303,7 +304,9 @@ protected: DWORD _clip_plane_bits; RenderModeAttrib::Mode _current_fill_mode; //poinr/wireframe/solid - GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports + + // unused right now + //GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports // Cur Texture State TextureApplyAttrib::Mode _CurTexBlendMode; @@ -320,9 +323,20 @@ protected: bool _overlay_windows_supported; +#if 0 + // This is here just as a temporary hack so this file will still + // compile. However, it is never initialized and will certainly + // cause the code to crash when it is referenced. (This used to be + // inherited from the base class, but the new design requires that a + // GSG may be used for multiple windows, so it doesn't make sense to + // store a single window pointer any more.) + GraphicsWindow *_win; +#endif + public: static GraphicsStateGuardian* make_DXGraphicsStateGuardian8(const FactoryParams ¶ms); + void set_context(DXScreenData *pNewContextData); static TypeHandle get_class_type(void); static void init_type(void); @@ -347,7 +361,7 @@ public: bool CheckCooperativeLevel(bool bDoReactivateWindow = false); void show_frame(bool bNoNewFrameDrawn = false); - void dx_init(HCURSOR hMouseCursor); + void dx_init(void); void support_overlay_window(bool flag); @@ -355,7 +369,8 @@ private: static TypeHandle _type_handle; }; -#include "DXGraphicsStateGuardian8.I" +HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark); +#include "DXGraphicsStateGuardian8.I" #endif diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index ce1d95ab10..923641a8d8 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -1000,6 +1000,8 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { assert(pbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now assert(pixbuf_type==PixelBuffer::T_unsigned_byte); // cant handle anything else now + //PRINT_REFCNT(dxgsg8,scrn.pD3D8); + if((pixbuf_type!=PixelBuffer::T_unsigned_byte) || (pbuf->get_component_width()!=1)) { dxgsg8_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n"; return NULL; @@ -1411,7 +1413,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0, TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) { - dxgsg8_cat.error() << "pD3DDevice->CreateTexture() failed!" << D3DERRORSTRING(hr); + dxgsg8_cat.error() << "D3D CreateTexture failed!" << D3DERRORSTRING(hr); goto error_exit; } @@ -1427,11 +1429,21 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { #endif #endif - hr = FillDDSurfTexturePixels(); - if(FAILED(hr)) { - goto error_exit; + // Note: user may want to create an empty "texture" that will be written to by rendering and copy operations. + // this will never have a backing store of main memory in panda fmt, and on disk in a file. + // so for this case, you dont want to call FillDDSurf. + // need a better way for user to indicate this usage than lack of ram_image, because it conflicts + // with the multi-open case mentioned below + + if(_texture->has_ram_image()) { + hr = FillDDSurfTexturePixels(); + if(FAILED(hr)) { + goto error_exit; + } } + // PRINT_REFCNT(dxgsg8,scrn.pD3D8); + // Return the newly created texture return _pD3DTexture8; @@ -1547,18 +1559,21 @@ FillDDSurfTexturePixels(void) { if(bUsingTempPixBuf) { SAFE_DELETE_ARRAY(pPixels); } - RELEASE(pMipLevel0,dxgsg8,"texture",RELEASE_ONCE); + RELEASE(pMipLevel0,dxgsg8,"FillDDSurf MipLev0 texture ptr",RELEASE_ONCE); return hr; } - - //----------------------------------------------------------------------------- // Name: DeleteTexture() // Desc: Release the surface used to store the texture //----------------------------------------------------------------------------- void DXTextureContext8:: DeleteTexture( ) { + if(_pD3DTexture8==NULL) { + // dont bother printing the msg below, since we already released it. + return; + } + if(dxgsg8_cat.is_spam()) { dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n"; } @@ -1603,6 +1618,9 @@ TextureContext(tex) { DXTextureContext8:: ~DXTextureContext8() { + if(dxgsg8_cat.is_spam()) { + dxgsg8_cat.spam() << "Deleting DX8 TexContext for " << _tex->get_name() << "\n"; + } DeleteTexture(); TextureContext::~TextureContext(); _tex = NULL; diff --git a/panda/src/dxgsg8/dxgsg8base.h b/panda/src/dxgsg8/dxgsg8base.h index 7ebbdd4e8c..b185cbad1c 100644 --- a/panda/src/dxgsg8/dxgsg8base.h +++ b/panda/src/dxgsg8/dxgsg8base.h @@ -19,9 +19,6 @@ #ifndef DXGSG8BASE_H #define DXGSG8BASE_H -#include -#include - // include win32 defns for everything up to WinServer2003, and assume I'm smart enough to // use GetProcAddress for backward compat on newer fns // Note DX8 cannot be installed on w95, so OK to assume base of win98 @@ -41,6 +38,9 @@ #include #undef WIN32_LEAN_AND_MEAN +#include "pandabase.h" +#include "graphicsWindow.h" + #if D3D_SDK_VERSION != 220 #error you have DX 8.0 headers, not DX 8.1, you need to install DX 8.1 SDK! #endif @@ -61,6 +61,11 @@ #endif #endif +// imperfect method to ID NVid? could also scan desc str, but that isnt fullproof either +#define IS_NVIDIA(DDDEVICEID) ((DDDEVICEID.VendorId==0x10DE) || (DDDEVICEID.VendorId==0x12D2)) +#define IS_ATI(DDDEVICEID) (DDDEVICEID.VendorId==0x1002) +#define IS_MATROX(DDDEVICEID) (DDDEVICEID.VendorId==0x102B) + #define D3D_MAXTEXTURESTAGES 8 typedef enum {VertexShader,PixelShader} ShaderType; @@ -82,12 +87,15 @@ typedef DWORD DXShaderHandle; // for stuff outside a panda class #define SAFE_RELEASE(p) { if(p) { assert(IS_VALID_PTR(p)); (p)->Release(); (p)=NULL; } } +#define SAFE_FREELIB(hDLL) { if(hDLL!=NULL) { FreeLibrary(hDLL);hDLL = NULL; } } // this is bDoDownToZero argument to RELEASE() #define RELEASE_DOWN_TO_ZERO true #define RELEASE_ONCE false -//#define DEBUG_RELEASES + +// uncomment to add refcnt debug output +#define DEBUG_RELEASES #ifdef DEBUG_RELEASES #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \ @@ -183,7 +191,7 @@ typedef enum { typedef struct { LPDIRECT3DDEVICE8 pD3DDevice; - LPDIRECT3D8 pD3D8; + LPDIRECT3D8 pD3D8; // copied from DXGraphicsPipe8 for convenience HWND hWnd; HMONITOR hMon; DWORD MaxAvailVidMem; @@ -203,5 +211,11 @@ typedef struct { D3DADAPTER_IDENTIFIER8 DXDeviceID; } DXScreenData; + +//utility stuff +extern map g_D3DFORMATmap; +extern void Init_D3DFORMAT_map(void); +extern const char *D3DFormatStr(D3DFORMAT fmt); + #endif diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.cxx b/panda/src/dxgsg8/wdxGraphicsPipe8.cxx index 5f56a71319..1abb08b2cc 100644 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsPipe8.cxx @@ -23,10 +23,8 @@ TypeHandle wdxGraphicsPipe8::_type_handle; // #define LOWVIDMEMTHRESHOLD 3500000 -// #define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 #define LOWVIDMEMTHRESHOLD 5700000 // 4MB cards should fall below this #define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 // if # is > 1MB, card is lying and I cant tell what it is - #define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF //////////////////////////////////////////////////////////////////// @@ -38,6 +36,7 @@ wdxGraphicsPipe8:: wdxGraphicsPipe8() { _hDDrawDLL = NULL; _hD3D8_DLL = NULL; + _pD3D8 = NULL; _is_valid = init(); } @@ -48,14 +47,10 @@ wdxGraphicsPipe8() { //////////////////////////////////////////////////////////////////// wdxGraphicsPipe8:: ~wdxGraphicsPipe8() { - if (_hDDrawDLL != NULL) { - FreeLibrary(_hDDrawDLL); - _hDDrawDLL = NULL; - } - if(_hD3D8_DLL != NULL) { - FreeLibrary(_hD3D8_DLL); - _hD3D8_DLL = NULL; - } + + RELEASE(_pD3D8,wdxdisplay8,"ID3D8",RELEASE_DOWN_TO_ZERO); + SAFE_FREELIB(_hD3D8_DLL); + SAFE_FREELIB(_hDDrawDLL); } //////////////////////////////////////////////////////////////////// @@ -91,12 +86,14 @@ pipe_constructor() { // Description: Creates a new window on the pipe, if possible. //////////////////////////////////////////////////////////////////// PT(GraphicsWindow) wdxGraphicsPipe8:: -make_window() { +make_window(GraphicsStateGuardian *gsg) { if (!_is_valid) { return NULL; } - return new wdxGraphicsWindow8(this); + // thanks to the dumb threading requirements this constructor actually does nothing but create an empty c++ object + // no windows are really opened until wdxGraphicsWindow8->open_window() is called + return new wdxGraphicsWindow8(this, gsg); } //////////////////////////////////////////////////////////////////// @@ -110,50 +107,72 @@ make_window() { //////////////////////////////////////////////////////////////////// bool wdxGraphicsPipe8:: init() { - static const char * const ddraw_name = "ddraw.dll"; - _hDDrawDLL = LoadLibrary(ddraw_name); - if(_hDDrawDLL == 0) { - wdxdisplay8_cat.error() - << "can't locate " << ddraw_name << "!\n"; - return false; + if(!MyLoadLib(_hDDrawDLL,"ddraw.dll")) { + goto error; } - _DirectDrawCreateEx = - (LPDIRECTDRAWCREATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawCreateEx"); - if (_DirectDrawCreateEx == NULL) { - wdxdisplay8_cat.error() - << "GetProcAddr failed for DDCreateEx" << endl; - return false; + if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawCreateEx, "DirectDrawCreateEx")) { + goto error; } - _DirectDrawEnumerateExA = (LPDIRECTDRAWENUMERATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawEnumerateExA"); - if (_DirectDrawEnumerateExA == NULL) { - wdxdisplay8_cat.error() - << "GetProcAddr failed for DirectDrawEnumerateEx! (win95 system?)\n"; - return false; + if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawEnumerateExA, "DirectDrawEnumerateExA")) { + goto error; } - static const char * const d3d8_name = "d3d8.dll"; - _hD3D8_DLL = LoadLibrary(d3d8_name); - if (_hD3D8_DLL == 0) { - wdxdisplay8_cat.error() - << "PandaDX8 requires DX8, can't locate " << d3d8_name << "!\n"; - return false; + if(!MyLoadLib(_hD3D8_DLL,"d3d8.dll")) { + goto error; } - // dont want to statically link to possibly non-existent d3d8 dll, - // so must call D3DCr8 indirectly - static const char * const d3dcreate8_name = "Direct3DCreate8"; - _Direct3DCreate8 = - (Direct3DCreate8_ProcPtr)GetProcAddress(_hD3D8_DLL, d3dcreate8_name); - - if (_Direct3DCreate8 == NULL) { - wdxdisplay8_cat.error() - << "GetProcAddress for " << d3dcreate8_name << "failed!" << endl; - return false; + if(!MyGetProcAddr(_hD3D8_DLL, (FARPROC*)&_Direct3DCreate8, "Direct3DCreate8")) { + goto error; } +/* + wdxGraphicsPipe8 *dxpipe; + DCAST_INTO_V(dxpipe, _pipe); + + nassertv(_gsg == (GraphicsStateGuardian *)NULL); + _dxgsg = new DXGraphicsStateGuardian8(this); + _gsg = _dxgsg; + + // Tell the associated dxGSG about the window handle. + _dxgsg->scrn.hWnd = _hWnd; + */ + + // Create a Direct3D object. + + // these were taken from the 8.0 and 8.1 d3d8.h SDK headers + #define D3D_SDK_VERSION_8_0 120 + #define D3D_SDK_VERSION_8_1 220 + + // are we using 8.0 or 8.1? + WIN32_FIND_DATA TempFindData; + HANDLE hFind; + char tmppath[_MAX_PATH + 128]; + GetSystemDirectory(tmppath, MAX_PATH); + strcat(tmppath, "\\dpnhpast.dll"); + hFind = FindFirstFile (tmppath, &TempFindData); + if (hFind != INVALID_HANDLE_VALUE) { + FindClose(hFind); + _bIsDX81 = true; + _pD3D8 = (*_Direct3DCreate8)(D3D_SDK_VERSION_8_1); + } else { + _bIsDX81 = false; + _pD3D8 = (*_Direct3DCreate8)(D3D_SDK_VERSION_8_0); + } + + if (_pD3D8 == NULL) { + wdxdisplay8_cat.error() << "Direct3DCreate8(8." << (_bIsDX81 ? "1" : "0") << ") failed!, error=" << GetLastError() << endl; + //release_gsg(); + goto error; + } + + Init_D3DFORMAT_map(); return find_all_card_memavails(); + + error: + // wdxdisplay8_cat.error() << ", error=" << GetLastError << endl; + return false; } //////////////////////////////////////////////////////////////////// @@ -260,9 +279,11 @@ find_all_card_memavails() { hr = pDD->GetAvailableVidMem(&ddsGAVMCaps, &dwVidMemTotal, &dwVidMemFree); if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "GetAvailableVidMem failed for device #"<< i<< D3DERRORSTRING(hr); - // goto skip_device; + wdxdisplay8_cat.error() << "GetAvailableVidMem failed for device #"<< i<< D3DERRORSTRING(hr); + // sometimes GetAvailableVidMem fails with hr=DDERR_NODIRECTDRAWHW for some unknown reason (bad drivers?) + // see bugs: 15327,18122, others. is it because D3D8 object has already been created? + if(hr==DDERR_NODIRECTDRAWHW) + continue; exit(1); // probably want to exit, since it may be my fault } @@ -306,8 +327,7 @@ find_all_card_memavails() { // registry location for a given card // assume buggy drivers (this means you, FireGL2) may return zero - // (or small amts) for dwVidMemTotal, so ignore value if its < - // CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD + // (or small amts) for dwVidMemTotal, so ignore value if its < CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD bool bLowVidMemFlag = ((dwVidMemTotal > CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) && (dwVidMemTotal< LOWVIDMEMTHRESHOLD)); @@ -352,3 +372,519 @@ dx7_driver_enum_callback(GUID *pGUID, TCHAR *strDesc, TCHAR *strName, return DDENUMRET_OK; } + +////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsWindow8::find_best_depth_format +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsPipe8:: +find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode, + D3DFORMAT *pBestFmt, bool bWantStencil, + bool bForce16bpp, bool bVerboseMode) 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_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 = (bForce16bpp || + (IS_NVIDIA(Display.DXDeviceID) && IS_16BPP_DISPLAY_FORMAT(TestDisplayMode.Format))); + + if (bVerboseMode) { + wdxdisplay8_cat.info() + << "FindBestDepthFmt: bSelectOnly16bpp: " << bOnlySelect16bpp << endl; + } + + for (int i=0; i < NUM_TEST_ZFMTS; i++) { + D3DFORMAT TestDepthFmt = + (bWantStencil ? StencilPrefList[i] : NoStencilPrefList[i]); + + if (bOnlySelect16bpp && !IS_16BPP_ZBUFFER(TestDepthFmt)) { + continue; + } + + hr = Display.pD3D8->CheckDeviceFormat(Display.CardIDNum, + D3DDEVTYPE_HAL, + TestDisplayMode.Format, + D3DUSAGE_DEPTHSTENCIL, + D3DRTYPE_SURFACE,TestDepthFmt); + + if (FAILED(hr)) { + if (hr == D3DERR_NOTAVAILABLE) { + if (bVerboseMode) + wdxdisplay8_cat.info() + << "FindBestDepthFmt: ChkDevFmt returns NotAvail for " + << D3DFormatStr(TestDepthFmt) << endl; + continue; + } + + wdxdisplay8_cat.error() + << "unexpected CheckDeviceFormat failure" << D3DERRORSTRING(hr) + << endl; + exit(1); + } + + hr = Display.pD3D8->CheckDepthStencilMatch(Display.CardIDNum, + D3DDEVTYPE_HAL, + TestDisplayMode.Format, // adapter format + TestDisplayMode.Format, // backbuffer fmt (should be the same in my apps) + TestDepthFmt); + if (SUCCEEDED(hr)) { + *pBestFmt = TestDepthFmt; + break; + } else { + if (hr==D3DERR_NOTAVAILABLE) { + if (bVerboseMode) { + wdxdisplay8_cat.info() + << "FindBestDepthFmt: ChkDepMatch returns NotAvail for " + << D3DFormatStr(TestDisplayMode.Format) << ", " + << D3DFormatStr(TestDepthFmt) << endl; + } + } else { + wdxdisplay8_cat.error() + << "unexpected CheckDepthStencilMatch failure for " + << D3DFormatStr(TestDisplayMode.Format) << ", " + << D3DFormatStr(TestDepthFmt) << endl; + exit(1); + } + } + } + + if (bVerboseMode) { + wdxdisplay8_cat.info() + << "FindBestDepthFmt returns fmt " << D3DFormatStr(*pBestFmt) << endl; + } + + return (*pBestFmt != D3DFMT_UNKNOWN); +} + + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsWindow8::special_check_fullscreen_resolution +// Access: Private +// Description: overrides of the general estimator for known working +// cases +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsPipe8:: +special_check_fullscreen_resolution(DXScreenData &scrn,UINT x_size,UINT y_size) { + DWORD VendorId = scrn.DXDeviceID.VendorId; + DWORD DeviceId = scrn.DXDeviceID.DeviceId; + + switch (VendorId) { + case 0x8086: // Intel + /*for now, just validate all the intel cards at these resolutions. + I dont have a complete list of intel deviceIDs (missing 82830, 845, etc) + // Intel i810,i815,82810 + if ((DeviceId==0x7121)||(DeviceId==0x7123)||(DeviceId==0x7125)|| + (DeviceId==0x1132)) + */ + if ((x_size == 640) && (y_size == 480)) { + return true; + } + if ((x_size == 800) && (y_size == 600)) { + return true; + } + if ((x_size == 1024) && (y_size == 768)) { + return true; + } + break; + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsWindow8::search_for_valid_displaymode +// Access: Private +// Description: All ptr args are output parameters. If no valid mode +// found, returns *pSuggestedPixFmt = D3DFMT_UNKNOWN; +//////////////////////////////////////////////////////////////////// +void wdxGraphicsPipe8:: +search_for_valid_displaymode(DXScreenData &scrn, + UINT RequestedX_Size, UINT RequestedY_Size, + bool bWantZBuffer, bool bWantStencil, + UINT *pSupportedScreenDepthsMask, + bool *pCouldntFindAnyValidZBuf, + D3DFORMAT *pSuggestedPixFmt, + bool bForce16bppZBuffer, + bool bVerboseMode) { + + assert(IS_VALID_PTR(scrn.pD3D8)); + HRESULT hr; + +#ifndef NDEBUG + // no longer true, due to special_check_fullscreen_res, where lowvidmem cards are allowed higher resolutions + // if (_dxgsg->scrn.bIsLowVidMemCard) + // nassertv((RequestedX_Size==640)&&(RequestedY_Size==480)); +#endif + + *pSuggestedPixFmt = D3DFMT_UNKNOWN; + *pSupportedScreenDepthsMask = 0x0; + *pCouldntFindAnyValidZBuf = false; + + int cNumModes = scrn.pD3D8->GetAdapterModeCount(scrn.CardIDNum); + D3DDISPLAYMODE BestDispMode; + ZeroMemory(&BestDispMode,sizeof(BestDispMode)); + + if (bVerboseMode) { + wdxdisplay8_cat.info() + << "searching for valid display modes at res: (" + << RequestedX_Size << "," << RequestedY_Size + << "), TotalModes: " << cNumModes << endl; + } + + // ignore memory based checks for min res 640x480. some cards just + // dont give accurate memavails. (should I do the check anyway for + // 640x480 32bpp?) + bool bDoMemBasedChecks = + ((!((RequestedX_Size==640)&&(RequestedY_Size==480))) && + (scrn.MaxAvailVidMem!=UNKNOWN_VIDMEM_SIZE) && + (!special_check_fullscreen_resolution(scrn,RequestedX_Size,RequestedY_Size))); + + if (bVerboseMode || wdxdisplay8_cat.is_spam()) { + wdxdisplay8_cat.info() + << "DoMemBasedChecks = " << bDoMemBasedChecks << endl; + } + + for (int i=0; i < cNumModes; i++) { + D3DDISPLAYMODE dispmode; + hr = scrn.pD3D8->EnumAdapterModes(scrn.CardIDNum,i,&dispmode); + if (FAILED(hr)) { + wdxdisplay8_cat.error() + << "EnumAdapterDisplayMode failed for device #" + << scrn.CardIDNum << D3DERRORSTRING(hr); + exit(1); + } + + if ((dispmode.Width!=RequestedX_Size) || + (dispmode.Height!=RequestedY_Size)) { + continue; + } + + if ((dispmode.RefreshRate<60) && (dispmode.RefreshRate>1)) { + // dont want refresh rates under 60Hz, but 0 or 1 might indicate + // a default refresh rate, which is usually >=60 + if (bVerboseMode) { + wdxdisplay8_cat.info() + << "skipping mode[" << i << "], bad refresh rate: " + << dispmode.RefreshRate << endl; + } + continue; + } + + // Note no attempt is made to verify if format will work at + // requested size, so even if this call succeeds, could still get + // an out-of-video-mem error + + hr = scrn.pD3D8->CheckDeviceFormat(scrn.CardIDNum, D3DDEVTYPE_HAL, dispmode.Format, + D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, + dispmode.Format); + if (FAILED(hr)) { + if (hr==D3DERR_NOTAVAILABLE) { + if (bVerboseMode) { + wdxdisplay8_cat.info() + << "skipping mode[" << i + << "], CheckDevFmt returns NotAvail for fmt: " + << D3DFormatStr(dispmode.Format) << endl; + } + continue; + } else { + wdxdisplay8_cat.error() + << "CheckDeviceFormat failed for device #" + << scrn.CardIDNum << D3DERRORSTRING(hr); + exit(1); + } + } + + bool bIs16bppRenderTgt = IS_16BPP_DISPLAY_FORMAT(dispmode.Format); + float RendTgtMinMemReqmt; + + // if we have a valid memavail value, try to determine if we have + // enough space + if (bDoMemBasedChecks) { + // assume user is testing fullscreen, not windowed, so use the + // dwTotal value see if 3 scrnbufs (front/back/z)at 16bpp at + // x_size*y_size will fit with a few extra megs for texmem + + // 8MB Rage Pro says it has 6.8 megs Total free and will run at + // 1024x768, so formula makes it so that is OK + +#define REQD_TEXMEM 1800000 + + float bytes_per_pixel = (bIs16bppRenderTgt ? 2 : 4); + +// cant do this check yet since gsg doesnt exist! +// assert((_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_double_buffer) != 0); + + // *2 for double buffer + + RendTgtMinMemReqmt = + ((float)RequestedX_Size) * ((float)RequestedY_Size) * + bytes_per_pixel * 2 + REQD_TEXMEM; + + if (bVerboseMode || wdxdisplay8_cat.is_spam()) + wdxdisplay8_cat.info() + << "Testing Mode (" < scrn.MaxAvailVidMem) { + if (bVerboseMode || wdxdisplay8_cat.is_debug()) + wdxdisplay8_cat.info() + << "not enough VidMem for render tgt, skipping display fmt " + << D3DFormatStr(dispmode.Format) << " (" + << (int)RendTgtMinMemReqmt << " > " + << scrn.MaxAvailVidMem << ")\n"; + continue; + } + } + + if (bWantZBuffer) { + D3DFORMAT zformat; + if (!find_best_depth_format(scrn,dispmode, &zformat, + bWantStencil, bForce16bppZBuffer)) { + *pCouldntFindAnyValidZBuf=true; + continue; + } + + float MinMemReqmt = 0.0f; + + if (bDoMemBasedChecks) { + // test memory again, this time including zbuf size + float zbytes_per_pixel = (IS_16BPP_ZBUFFER(zformat) ? 2 : 4); + float MinMemReqmt = RendTgtMinMemReqmt + ((float)RequestedX_Size)*((float)RequestedY_Size)*zbytes_per_pixel; + + if (bVerboseMode || wdxdisplay8_cat.is_spam()) + wdxdisplay8_cat.info() + << "Testing Mode w/Z (" << RequestedX_Size << "x" + << RequestedY_Size << "," << D3DFormatStr(dispmode.Format) + << ")\nReqdVidMem: "<< (int)MinMemReqmt << " AvailVidMem: " + << scrn.MaxAvailVidMem << endl; + + if (MinMemReqmt > scrn.MaxAvailVidMem) { + if (bVerboseMode || wdxdisplay8_cat.is_debug()) + wdxdisplay8_cat.info() + << "not enough VidMem for RendTgt+zbuf, skipping display fmt " + << D3DFormatStr(dispmode.Format) << " (" << (int)MinMemReqmt + << " > " << scrn.MaxAvailVidMem << ")\n"; + continue; + } + } + + if ((!bDoMemBasedChecks) || (MinMemReqmtscrn.hWnd = _hWnd; + + if (pD3D8 == NULL) { + wdxdisplay8_cat.error() + << "Direct3DCreate8 failed!\n"; + release_gsg(); + return; + } + + if (!choose_adapter(pD3D8)) { + wdxdisplay8_cat.error() + << "Unable to find suitable rendering device.\n"; + release_gsg(); + return; + } + + create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer); + */ +} + +map g_D3DFORMATmap; + +void Init_D3DFORMAT_map(void) { + if(g_D3DFORMATmap.size()!=0) + return; + + #define INSERT_ELEM(XX) g_D3DFORMATmap[XX##_FLAG] = D3DFMT_##XX; + + INSERT_ELEM(R8G8B8); + INSERT_ELEM(A8R8G8B8); + INSERT_ELEM(X8R8G8B8); + INSERT_ELEM(R5G6B5); + INSERT_ELEM(X1R5G5B5); + INSERT_ELEM(A1R5G5B5); + INSERT_ELEM(A4R4G4B4); + INSERT_ELEM(R3G3B2); + INSERT_ELEM(A8); + INSERT_ELEM(A8R3G3B2); + INSERT_ELEM(X4R4G4B4); + INSERT_ELEM(A2B10G10R10); + INSERT_ELEM(G16R16); + INSERT_ELEM(A8P8); + INSERT_ELEM(P8); + INSERT_ELEM(L8); + INSERT_ELEM(A8L8); + INSERT_ELEM(A4L4); + INSERT_ELEM(V8U8); + INSERT_ELEM(L6V5U5); + INSERT_ELEM(X8L8V8U8); + INSERT_ELEM(Q8W8V8U8); + INSERT_ELEM(V16U16); + INSERT_ELEM(W11V11U10); + INSERT_ELEM(A2W10V10U10); + INSERT_ELEM(UYVY); + INSERT_ELEM(YUY2); + INSERT_ELEM(DXT1); + INSERT_ELEM(DXT2); + INSERT_ELEM(DXT3); + INSERT_ELEM(DXT4); + INSERT_ELEM(DXT5); +} + + +const char *D3DFormatStr(D3DFORMAT fmt) { + +#define CASESTR(XX) case XX: return #XX; + + switch(fmt) { + CASESTR(D3DFMT_UNKNOWN); + CASESTR(D3DFMT_R8G8B8); + CASESTR(D3DFMT_A8R8G8B8); + CASESTR(D3DFMT_X8R8G8B8); + CASESTR(D3DFMT_R5G6B5); + CASESTR(D3DFMT_X1R5G5B5); + CASESTR(D3DFMT_A1R5G5B5); + CASESTR(D3DFMT_A4R4G4B4); + CASESTR(D3DFMT_R3G3B2); + CASESTR(D3DFMT_A8); + CASESTR(D3DFMT_A8R3G3B2); + CASESTR(D3DFMT_X4R4G4B4); + CASESTR(D3DFMT_A2B10G10R10); + CASESTR(D3DFMT_G16R16); + CASESTR(D3DFMT_A8P8); + CASESTR(D3DFMT_P8); + CASESTR(D3DFMT_L8); + CASESTR(D3DFMT_A8L8); + CASESTR(D3DFMT_A4L4); + CASESTR(D3DFMT_V8U8); + CASESTR(D3DFMT_L6V5U5); + CASESTR(D3DFMT_X8L8V8U8); + CASESTR(D3DFMT_Q8W8V8U8); + CASESTR(D3DFMT_V16U16); + CASESTR(D3DFMT_W11V11U10); + CASESTR(D3DFMT_A2W10V10U10); + CASESTR(D3DFMT_UYVY); + CASESTR(D3DFMT_YUY2); + CASESTR(D3DFMT_DXT1); + CASESTR(D3DFMT_DXT2); + CASESTR(D3DFMT_DXT3); + CASESTR(D3DFMT_DXT4); + CASESTR(D3DFMT_DXT5); + CASESTR(D3DFMT_D16_LOCKABLE); + CASESTR(D3DFMT_D32); + CASESTR(D3DFMT_D15S1); + CASESTR(D3DFMT_D24S8); + CASESTR(D3DFMT_D16); + CASESTR(D3DFMT_D24X8); + CASESTR(D3DFMT_D24X4S4); + CASESTR(D3DFMT_VERTEXDATA); + CASESTR(D3DFMT_INDEX16); + CASESTR(D3DFMT_INDEX32); + } + + return "Invalid D3DFORMAT"; +} + diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.h b/panda/src/dxgsg8/wdxGraphicsPipe8.h index 9a0a13c24a..6e11ad22f4 100644 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.h +++ b/panda/src/dxgsg8/wdxGraphicsPipe8.h @@ -22,7 +22,7 @@ #include "pandabase.h" #include "winGraphicsPipe.h" #include "pvector.h" - +#include "dxgsg8base.h" #include typedef struct { @@ -48,8 +48,25 @@ public: virtual string get_interface_name() const; static PT(GraphicsPipe) pipe_constructor(); + virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties); + + bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode, + D3DFORMAT *pBestFmt, bool bWantStencil, + bool bForce16bpp, bool bVerboseMode = false) const; + + void search_for_valid_displaymode(DXScreenData &scrn, + UINT RequestedX_Size, UINT RequestedY_Size, + bool bWantZBuffer, bool bWantStencil, + UINT *pSupportedScreenDepthsMask, + bool *pCouldntFindAnyValidZBuf, + D3DFORMAT *pSuggestedPixFmt, + bool bForce16bppZBuffer, + bool bVerboseMode = false); + + bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size,UINT y_size); + protected: - virtual PT(GraphicsWindow) make_window(); + virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg); private: bool init(); @@ -62,6 +79,8 @@ private: private: HINSTANCE _hDDrawDLL; HINSTANCE _hD3D8_DLL; + LPDIRECT3D8 _pD3D8; + typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion); typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter); @@ -83,7 +102,7 @@ private: typedef pvector CardIDs; CardIDs _card_ids; - + bool _bIsDX81; public: static TypeHandle get_class_type() { diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx index ff99a9417c..f6b86df1e6 100644 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx @@ -20,8 +20,8 @@ #include #include #include -#include "wdxGraphicsWindow8.h" #include "wdxGraphicsPipe8.h" +#include "wdxGraphicsWindow8.h" #include "config_dxgsg8.h" #include "keyboardButton.h" @@ -37,13 +37,10 @@ TypeHandle wdxGraphicsWindow8::_type_handle; -#define LAST_ERROR 0 -#define ERRORBOX_TITLE "Panda3D Error" #define WDX_WINDOWCLASSNAME "wdxDisplay" #define WDX_WINDOWCLASSNAME_NOCURSOR WDX_WINDOWCLASSNAME "_NoCursor" #define DEFAULT_CURSOR IDC_ARROW - // define this to enable debug testing of dinput joystick //#define DINPUT_DEBUG_POLL @@ -60,50 +57,15 @@ wdxGraphicsWindow8* global_wdxwinptr = NULL; // need this for temporary windpro LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam,LPARAM lparam); -// imperfect method to ID NVid? could also scan desc str, but that isnt fullproof either -#define IS_NVIDIA(DDDEVICEID) ((DDDEVICEID.VendorId==0x10DE) || (DDDEVICEID.VendorId==0x12D2)) -#define IS_ATI(DDDEVICEID) (DDDEVICEID.VendorId==0x1002) -#define IS_MATROX(DDDEVICEID) (DDDEVICEID.VendorId==0x102B) - +/* // because we dont have access to ModifierButtons, as a hack just synchronize state of these // keys on get/lose keybd focus #define NUM_MODIFIER_KEYS 16 unsigned int hardcoded_modifier_buttons[NUM_MODIFIER_KEYS]={VK_SHIFT,VK_MENU,VK_CONTROL,VK_SPACE,VK_TAB, VK_UP,VK_DOWN,VK_LEFT,VK_RIGHT,VK_PRIOR,VK_NEXT,VK_HOME,VK_END, VK_INSERT,VK_DELETE,VK_ESCAPE}; - -#define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF - -// pops up MsgBox w/system error msg -#define LAST_ERROR 0 -void PrintErrorMessage(DWORD msgID) { - LPTSTR pMessageBuffer; - - if (msgID==LAST_ERROR) - msgID=GetLastError(); - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL,msgID, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language - (LPTSTR) &pMessageBuffer, // the weird ptrptr->ptr cast is intentional, see FORMAT_MESSAGE_ALLOCATE_BUFFER - 1024, NULL); - MessageBox(GetDesktopWindow(),pMessageBuffer,_T(ERRORBOX_TITLE),MB_OK); - wdxdisplay8_cat.fatal() << "System error msg: " << pMessageBuffer << endl; - LocalFree( pMessageBuffer ); -} - -void ClearToBlack(HWND hWnd, const WindowProperties &props) { - // clear to black - HDC hDC=GetDC(hWnd); // GetDC is not particularly fast. if this needs to be super-quick, we should cache GetDC's hDC - RECT clrRect = { - props.get_x_origin(), props.get_y_origin(), - props.get_x_origin() + props.get_x_size(), - props.get_y_origin() + props.get_y_size() - }; - FillRect(hDC,&clrRect,(HBRUSH)GetStockObject(BLACK_BRUSH)); - ReleaseDC(hWnd,hDC); - GdiFlush(); -} +*/ +//#define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsWindow8::Constructor @@ -111,12 +73,16 @@ void ClearToBlack(HWND hWnd, const WindowProperties &props) { // Description: //////////////////////////////////////////////////////////////////// wdxGraphicsWindow8:: -wdxGraphicsWindow8(GraphicsPipe *pipe) : - WinGraphicsWindow(pipe) +wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) : + WinGraphicsWindow(pipe, gsg) { - _dxgsg = (DXGraphicsStateGuardian8 *)NULL; + // dont actually create the window in the constructor. reason: multi-threading requires + // panda C++ window object to exist in separate thread from actual API window + + _dxgsg = DCAST(DXGraphicsStateGuardian8, gsg); _depth_buffer_bpp = 0; _awaiting_restore = false; + ZeroMemory(&_wcontext,sizeof(_wcontext)); } //////////////////////////////////////////////////////////////////// @@ -128,78 +94,50 @@ wdxGraphicsWindow8:: ~wdxGraphicsWindow8() { } -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::make_gsg -// Access: Public, Virtual -// Description: Creates a new GSG for the window and stores it in the -// _gsg pointer. This should only be called from within -// the draw thread. -//////////////////////////////////////////////////////////////////// void wdxGraphicsWindow8:: -make_gsg() { - wdxGraphicsPipe8 *dxpipe; - DCAST_INTO_V(dxpipe, _pipe); +make_current(void) { + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_V(dxgsg, _gsg); + //wglMakeCurrent(_hdc, wdxgsg->_context); + dxgsg->set_context(&_wcontext); - nassertv(_gsg == (GraphicsStateGuardian *)NULL); - _dxgsg = new DXGraphicsStateGuardian8(this); - _gsg = _dxgsg; - - // Tell the associated dxGSG about the window handle. - _dxgsg->scrn.hWnd = _mwindow; - - // Create a Direct3D object. - LPDIRECT3D8 pD3D8; - - // these were taken from the 8.0 and 8.1 d3d8.h SDK headers -#define D3D_SDK_VERSION_8_0 120 -#define D3D_SDK_VERSION_8_1 220 - - // are we using 8.0 or 8.1? - WIN32_FIND_DATA TempFindData; - HANDLE hFind; - char tmppath[MAX_PATH + 128]; - GetSystemDirectory(tmppath, MAX_PATH); - strcat(tmppath, "\\dpnhpast.dll"); - hFind = FindFirstFile (tmppath, &TempFindData); - if (hFind != INVALID_HANDLE_VALUE) { - FindClose(hFind); - _dxgsg->scrn.bIsDX81 = true; - pD3D8 = (*dxpipe->_Direct3DCreate8)(D3D_SDK_VERSION_8_1); - } else { - _dxgsg->scrn.bIsDX81 = false; - pD3D8 = (*dxpipe->_Direct3DCreate8)(D3D_SDK_VERSION_8_0); - } - - if (pD3D8 == NULL) { - wdxdisplay8_cat.error() - << "Direct3DCreate8 failed!\n"; - release_gsg(); - return; - } - - if (!choose_adapter(pD3D8)) { - wdxdisplay8_cat.error() - << "Unable to find suitable rendering device.\n"; - release_gsg(); - return; - } - - create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer); + // Now that we have made the context current to a window, we can + // reset the GSG state if this is the first time it has been used. + // (We can't just call reset() when we construct the GSG, because + // reset() requires having a current context.) + dxgsg->reset_if_new(); +} + +/* BUGBUG: need to reinstate these methods ASAP. they were incorrectly moved from the GraphicsWindow to the GSG + apps need to know the framebuffer format so they can create texture/rendertgt with same fmt +int wdxGraphicsWindow8:: +get_depth_bitwidth(void) { + assert(_dxgsg!=NULL); + if(_dxgsg->scrn.PresParams.EnableAutoDepthStencil) + return _dxgsg->scrn.depth_buffer_bitdepth; + else return 0; + +// GetSurfaceDesc is not reliable, on GF2, GetSurfDesc returns 32bpp when you created a 24bpp zbuf +// instead store the depth used at creation time + +// DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); +// _dxgsg->_zbuf->GetSurfaceDesc(&ddsd); +// return ddsd.ddpfPixelFormat.dwRGBBitCount; } -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. This should only -// be called from within the draw thread. -//////////////////////////////////////////////////////////////////// void wdxGraphicsWindow8:: -release_gsg() { - if (_gsg != (GraphicsStateGuardian *)NULL) { - GraphicsWindow::release_gsg(); - } -} +get_framebuffer_format(PixelBuffer::Type &fb_type, PixelBuffer::Format &fb_format) { + assert(_dxgsg!=NULL); + + fb_type = PixelBuffer::T_unsigned_byte; + // this is sortof incorrect, since for F_rgb5 it's really 5 bits per channel + //would have to change a lot of texture stuff to make this correct though + + if(IS_16BPP_DISPLAY_FORMAT(_dxgsg->scrn.PresParams.BackBufferFormat)) + fb_format = PixelBuffer::F_rgb5; + else fb_format = PixelBuffer::F_rgb; +} +*/ //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsWindow8::verify_window_sizes @@ -222,6 +160,9 @@ verify_window_sizes(int numsizes, int *dimen) { int num_valid_modes = 0; + wdxGraphicsPipe8 *dxpipe; + DCAST_INTO_R(dxpipe, _pipe, 0); + // not requesting same refresh rate since changing res might not // support same refresh rate at new size @@ -235,18 +176,18 @@ verify_window_sizes(int numsizes, int *dimen) { bool CouldntFindAnyValidZBuf; D3DFORMAT newPixFmt = D3DFMT_UNKNOWN; - if (special_check_fullscreen_resolution(x_size, y_size)) { + if (dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) { // bypass the test below for certain cards we know have valid modes bIsGoodMode=true; } else { - if (_dxgsg->scrn.bIsLowVidMemCard) { + if (_wcontext.bIsLowVidMemCard) { bIsGoodMode = ((x_size == 640) && (y_size == 480)); } else { - search_for_valid_displaymode(x_size, y_size, _dxgsg->scrn.PresParams.EnableAutoDepthStencil != false, - IS_STENCIL_FORMAT(_dxgsg->scrn.PresParams.AutoDepthStencilFormat), - &_dxgsg->scrn.SupportedScreenDepthsMask, - &CouldntFindAnyValidZBuf, &newPixFmt); + dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size, _wcontext.PresParams.EnableAutoDepthStencil != false, + IS_STENCIL_FORMAT(_wcontext.PresParams.AutoDepthStencilFormat), + &_wcontext.SupportedScreenDepthsMask, + &CouldntFindAnyValidZBuf, &newPixFmt, dx_force_16bpp_zbuffer); bIsGoodMode = (newPixFmt != D3DFMT_UNKNOWN); } } @@ -380,58 +321,61 @@ bool wdxGraphicsWindow8:: do_fullscreen_resize(int x_size, int y_size) { bool bCouldntFindValidZBuf; D3DFORMAT pixFmt; - bool bNeedZBuffer = (_dxgsg->scrn.PresParams.EnableAutoDepthStencil!=false); - bool bNeedStencilBuffer = IS_STENCIL_FORMAT(_dxgsg->scrn.PresParams.AutoDepthStencilFormat); + bool bNeedZBuffer = (_wcontext.PresParams.EnableAutoDepthStencil!=false); + bool bNeedStencilBuffer = IS_STENCIL_FORMAT(_wcontext.PresParams.AutoDepthStencilFormat); + + wdxGraphicsPipe8 *dxpipe; + DCAST_INTO_R(dxpipe, _pipe, false); bool bIsGoodMode=false; - if (!special_check_fullscreen_resolution(x_size,y_size)) { + if (!dxpipe->special_check_fullscreen_resolution(_wcontext, x_size,y_size)) { // bypass the lowvidmem test below for certain "lowmem" cards we know have valid modes - // wdxdisplay8_cat.info() << "1111111 lowvidmemcard="<< _dxgsg->scrn.bIsLowVidMemCard << endl; - if (_dxgsg->scrn.bIsLowVidMemCard && (!((x_size==640) && (y_size==480)))) { - wdxdisplay8_cat.error() << "resize() failed: will not try to resize low vidmem device #" << _dxgsg->scrn.CardIDNum << " to non-640x480!\n"; + // wdxdisplay8_cat.info() << "1111111 lowvidmemcard="<< _wcontext.bIsLowVidMemCard << endl; + if (_wcontext.bIsLowVidMemCard && (!((x_size==640) && (y_size==480)))) { + wdxdisplay8_cat.error() << "resize() failed: will not try to resize low vidmem device #" << _wcontext.CardIDNum << " to non-640x480!\n"; goto Error_Return; } } // must ALWAYS use search_for_valid_displaymode even if we know // a-priori that res is valid so we can get a valid pixfmt - search_for_valid_displaymode(x_size, y_size, + dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size, bNeedZBuffer, bNeedStencilBuffer, - &_dxgsg->scrn.SupportedScreenDepthsMask, + &_wcontext.SupportedScreenDepthsMask, &bCouldntFindValidZBuf, - &pixFmt); + &pixFmt, dx_force_16bpp_zbuffer); bIsGoodMode=(pixFmt!=D3DFMT_UNKNOWN); if (!bIsGoodMode) { wdxdisplay8_cat.error() << "resize() failed: " << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes") - << " at " << x_size << "x" << y_size << " for device #" << _dxgsg->scrn.CardIDNum <scrn.DisplayMode.Width=x_size; - _dxgsg->scrn.DisplayMode.Height=y_size; - _dxgsg->scrn.DisplayMode.Format = pixFmt; - _dxgsg->scrn.DisplayMode.RefreshRate = D3DPRESENT_RATE_DEFAULT; + _wcontext.DisplayMode.Width=x_size; + _wcontext.DisplayMode.Height=y_size; + _wcontext.DisplayMode.Format = pixFmt; + _wcontext.DisplayMode.RefreshRate = D3DPRESENT_RATE_DEFAULT; - _dxgsg->scrn.PresParams.BackBufferFormat = pixFmt; // make reset_device_resize use presparams or displaymode?? + _wcontext.PresParams.BackBufferFormat = pixFmt; // make reset_device_resize use presparams or displaymode?? bool bResizeSucceeded = reset_device_resize_window(x_size, y_size); if (!bResizeSucceeded) { wdxdisplay8_cat.error() << "resize() failed with OUT-OF-MEMORY error!\n"; - if ((!IS_16BPP_DISPLAY_FORMAT(_dxgsg->scrn.PresParams.BackBufferFormat)) && - (_dxgsg->scrn.SupportedScreenDepthsMask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) { + if ((!IS_16BPP_DISPLAY_FORMAT(_wcontext.PresParams.BackBufferFormat)) && + (_wcontext.SupportedScreenDepthsMask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) { // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers - _dxgsg->scrn.DisplayMode.Format = ((_dxgsg->scrn.SupportedScreenDepthsMask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5); + _wcontext.DisplayMode.Format = ((_wcontext.SupportedScreenDepthsMask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5); dx_force_16bpp_zbuffer=true; if (wdxdisplay8_cat.info()) - wdxdisplay8_cat.info() << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #"<< _dxgsg->scrn.CardIDNum << endl; + wdxdisplay8_cat.info() << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #"<< _wcontext.CardIDNum << endl; bResizeSucceeded= reset_device_resize_window(x_size, y_size); // create the new resized rendertargets } @@ -445,6 +389,238 @@ do_fullscreen_resize(int x_size, int y_size) { return bResizeSucceeded; } +#if 1 +////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::window_proc +// Access: Private +// Description: This is the nonstatic window_proc function. It is +// called to handle window events for this particular +// window. +//////////////////////////////////////////////////////////////////// +LONG wdxGraphicsWindow8:: +window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + return WinGraphicsWindow::window_proc(hwnd,msg,wparam,lparam); +} + +#else + +//////////////////////////////////////////////////////////////////// +// Function: window_proc +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +LONG wdxGraphicsWindow8:: +window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + int button = -1; + int x, y, width, height; + + switch(msg) { + case WM_SETCURSOR: { + // Turn off any GDI window cursor + // dx8 cursor not working yet + + if(dx_use_dx_cursor && is_fullscreen()) { + // SetCursor( NULL ); + // _dxgsg->scrn.pD3DDevice->ShowCursor(true); + + set_cursor_visibility(true); + return TRUE; // prevent Windows from setting cursor to window class cursor (see docs on WM_SETCURSOR) + } + break; + } + + case WM_PAINT: { + // primarily seen when app window is 'uncovered' + if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) { + // let DefWndProc do WM_ERASEBKGND & just draw black, + // rather than forcing Present to stretchblt the old window contents + // into the new size + break; + } + + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + if(DX_IS_READY) { + _dxgsg->show_frame(true); // 'true' since just want to show the last rendered backbuf, if any + } + EndPaint(hwnd, &ps); + return 0; + } + + case WM_IME_STARTCOMPOSITION: + // In case we're running fullscreen mode, we have to turn on + // explicit DX support for overlay windows now, so we'll be able + // to see the IME window. + _dxgsg->support_overlay_window(true); + break; + + case WM_IME_ENDCOMPOSITION: + // Turn off the support for overlay windows, since we're done + // with the IME window for now and it just slows things down. + _dxgsg->support_overlay_window(false); + break; + + case WM_ENTERSIZEMOVE: + if(_dxgsg!=NULL) + _dxgsg->SetDXReady(false); // dont see pic during resize + _WindowAdjustingType = MovingOrResizing; + break; + + case WM_EXITSIZEMOVE: { + #ifdef _DEBUG + wdxdisplay_cat.spam() << "WM_EXITSIZEMOVE received" << endl; + #endif + + if(_WindowAdjustingType==Resizing) { + bool bSucceeded=handle_windowed_resize(hwnd,true); + + if(!bSucceeded) { + #if 0 + bugbug need to fix this stuff + SetWindowPos(hwnd,NULL,0,0,lastxsize,lastysize,SWP_NOMOVE | + #endif + } + } + + _WindowAdjustingType = NotAdjusting; + _dxgsg->SetDXReady(true); + return 0; + } + + case WM_SIZE: { + + #ifdef _DEBUG + { + width = LOWORD(lparam); height = HIWORD(lparam); + wdxdisplay_cat.spam() << "WM_SIZE received with width:" << width << " height: " << height << " flags: " << + ((wparam == SIZE_MAXHIDE)? "SIZE_MAXHIDE " : "") << ((wparam == SIZE_MAXSHOW)? "SIZE_MAXSHOW " : "") << + ((wparam == SIZE_MINIMIZED)? "SIZE_MINIMIZED " : "") << ((wparam == SIZE_RESTORED)? "SIZE_RESTORED " : "") << + ((wparam == SIZE_MAXIMIZED)? "SIZE_MAXIMIZED " : "") << endl; + } + #endif + // old comment -- added SIZE_RESTORED to handle 3dfx case + if(_props._fullscreen || ((_dxgsg==NULL) || (_dxgsg->scrn.hWnd==NULL)) || ((wparam != SIZE_RESTORED) && (wparam != SIZE_MAXIMIZED))) + break; + + width = LOWORD(lparam); height = HIWORD(lparam); + + if((_props._xsize != width) || (_props._ysize != height)) { + _WindowAdjustingType = Resizing; + + // for maximized,unmaximize, need to call resize code artificially + // since no WM_EXITSIZEMOVE is generated. + if(wparam==SIZE_MAXIMIZED) { + _bSizeIsMaximized=TRUE; + window_proc(hwnd, WM_EXITSIZEMOVE, 0x0,0x0); + } else if((wparam==SIZE_RESTORED) && _bSizeIsMaximized) { + _bSizeIsMaximized=FALSE; // only want to reinit dx if restoring from maximized state + window_proc(hwnd, WM_EXITSIZEMOVE, 0x0,0x0); + } + } + + break; + } + + case WM_ERASEBKGND: { + // WM_ERASEBKGND will be ignored during resizing, because + // we dont want WM_PAINT's generated as user is manually resizing window. + + // for the intermediate resizing images that WM_PAINT would show to be useful, + // the panda window parameters need to be reset on every + // WM_SIZE event and that isnt happening yet + + if(_WindowAdjustingType) + break; + return 0; // dont let GDI waste time redrawing the deflt background + } + + case WM_TIMER: + // 2 cases of app deactivation: + // + // 1) user has switched out of fullscreen mode + // this is first signalled when ACTIVATEAPP returns false + // for this case, we dont wake up until WM_SIZE returns restore or maximize + // and WM_TIMER just periodically reawakens app for idle processing + + // unfortunately this doesnt seem to work because RestoreAllSurfaces doesn't + // seem to think we're back in the original displaymode even after I've received + // the WM_DISPLAYCHANGE msg, and returns WRONGMODE error. So the only way I can + // think of to make this work is to have the timer periodically check for restored + // coop level, as it does in case 2) + + // + // 2) windowed app has lost access to dx because another app has taken dx exclusive mode + // here we rely on WM_TIMER to periodically check if it is ok to reawaken app. + // windowed apps currently run regardless of if its window is in the foreground + // so we cannot rely on window messages to reawaken app + + if((wparam==_PandaPausedTimer) && ((!_window_active)||_active_minimized_fullscreen)) { + assert(_dxgsg!=NULL); + _dxgsg->CheckCooperativeLevel(DO_REACTIVATE_WINDOW); + + // wdxdisplay_cat.spam() << "periodic return of control to app\n"; + _return_control_to_app = true; + // throw_event("PandaPaused"); + // do we still need to do this since I return control to app periodically using timer msgs? + // does app need to know to avoid major computation? + } + + #ifdef DINPUT_DEBUG_POLL + // probably want to get rid of this in favor of event-based input + if(dx_use_joystick && (wparam==_pParentWindowGroup->_pDInputInfo->_JoystickPollTimer)) { + DIJOYSTATE2 js; + ZeroMemory(&js,sizeof(js)); + if(_pParentWindowGroup->_pDInputInfo->ReadJoystick(0,js)) { + // for now just print stuff out to make sure it works + wdxdisplay_cat.debug() << "joyPos (X: " << js.lX << ",Y: " << js.lY << ",Z: " << js.lZ << ")\n"; + for(int i=0;i<128;i++) { + if(js.rgbButtons[i]!=0) + wdxdisplay_cat.debug() << "joyButton "<< i << " pressed\n"; + } + } else { + wdxdisplay_cat.error() << "read of Joystick failed!\n"; + exit(1); + } + } + #endif + return 0; + + case WM_CLOSE: + #ifdef _DEBUG + wdxdisplay_cat.spam() << "WM_CLOSE received\n"; + #endif + // close_window(); + delete _pParentWindowGroup; + + // BUGBUG: right now there is no way to tell the panda app the graphics window is invalid or + // has been closed by the user, to prevent further methods from being called on the window. + // this needs to be added to panda for multiple windows to work. in the meantime, just + // trigger an exit here if # windows==0, since that is the expected behavior when all + // windows are closed (should be done by the app though, and it assumes you only make this + // type of panda gfx window) + + if(hwnd_pandawin_map.size()==0) { + exit(0); + } + return 0; + + case WM_ACTIVATEAPP: { + #ifdef _DEBUG + wdxdisplay_cat.spam() << "WM_ACTIVATEAPP(" << (bool)(wparam!=0) <<") received\n"; + #endif + + if((!wparam) && _props._fullscreen) { + deactivate_window(); + return 0; + } // dont want to reactivate until window is actually un-minimized (see WM_SIZE) + break; + } + } + + return WinGraphicsWindow::window_proc(hwnd,msg,wparam,lparam); +} +#endif + //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsWindow8::create_screen_buffers_and_device // Access: Private @@ -455,7 +631,11 @@ do_fullscreen_resize(int x_size, int y_size) { //////////////////////////////////////////////////////////////////// void wdxGraphicsWindow8:: create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer) { - // only want this to apply to initial startup + wdxGraphicsPipe8 *dxpipe; + DCAST_INTO_V(dxpipe, _pipe); + + // only want dx_pick_best_screenres to apply to initial startup, and + // since the initial res has already been picked, dont use auto-res-select in any future init sequence. dx_pick_best_screenres = false; DWORD dwRenderWidth=Display.DisplayMode.Width; @@ -465,8 +645,12 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer D3DPRESENT_PARAMETERS* pPresParams = &Display.PresParams; RECT view_rect; HRESULT hr; - int framebuffer_mode = get_properties().get_framebuffer_mode(); - bool bWantStencil = ((framebuffer_mode & WindowProperties::FM_stencil) != 0); + + // BUGBUG: need to change panda to put frame buffer properties with GraphicsWindow, not GSG!! + int frame_buffer_mode = _gsg->get_properties().get_frame_buffer_mode(); + bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0); + + PRINT_REFCNT(wdxdisplay8,pD3D8); assert(pD3D8!=NULL); assert(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION); @@ -492,7 +676,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer } if (Display.PresParams.EnableAutoDepthStencil) { - if (!find_best_depth_format(Display, Display.DisplayMode, + if (!dxpipe->find_best_depth_format(Display, Display.DisplayMode, &Display.PresParams.AutoDepthStencilFormat, bWantStencil, false)) { wdxdisplay8_cat.error() @@ -538,7 +722,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer pPresParams->BackBufferHeight = Display.DisplayMode.Height; DWORD dwBehaviorFlags=0x0; - if (_dxgsg->scrn.bIsTNLDevice) { + if (_wcontext.bIsTNLDevice) { dwBehaviorFlags|=D3DCREATE_HARDWARE_VERTEXPROCESSING; // note: we could create a pure device in this case if I eliminated the GetRenderState calls in dxgsg @@ -571,7 +755,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer ClearToBlack(Display.hWnd, get_properties()); - hr = pD3D8->CreateDevice(Display.CardIDNum, D3DDEVTYPE_HAL, _mwindow, + hr = pD3D8->CreateDevice(Display.CardIDNum, D3DDEVTYPE_HAL, _hWnd, dwBehaviorFlags, pPresParams, &Display.pD3DDevice); if (FAILED(hr)) { @@ -618,7 +802,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer assert((dwRenderWidth==pPresParams->BackBufferWidth)&&(dwRenderHeight==pPresParams->BackBufferHeight)); - hr = pD3D8->CreateDevice(Display.CardIDNum, D3DDEVTYPE_HAL, _mwindow, + hr = pD3D8->CreateDevice(Display.CardIDNum, D3DDEVTYPE_HAL, _hWnd, dwBehaviorFlags, pPresParams, &Display.pD3DDevice); if (FAILED(hr)) { @@ -629,7 +813,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer // ======================================================== - PRINT_REFCNT(wdxdisplay,_dxgsg->scrn.pD3DDevice); + PRINT_REFCNT(wdxdisplay8,_wcontext.pD3DDevice); if (pPresParams->EnableAutoDepthStencil) { _dxgsg->_buffer_mask |= RenderBuffer::T_depth; @@ -674,7 +858,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer } //////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::choose_adapter +// Function: wdxGraphicsWindow8::choose_device // Access: Private // Description: Looks at the list of available graphics adapters and // chooses a suitable one for the window. @@ -682,16 +866,19 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer // Returns true if successful, false on failure. //////////////////////////////////////////////////////////////////// bool wdxGraphicsWindow8:: -choose_adapter(LPDIRECT3D8 pD3D8) { +choose_device(void) { HRESULT hr; - int num_adapters = pD3D8->GetAdapterCount(); + wdxGraphicsPipe8 *dxpipe; + DCAST_INTO_R(dxpipe, _pipe, false); + + int num_adapters = dxpipe->_pD3D8->GetAdapterCount(); DXDeviceInfoVec device_infos; for (int i = 0; i < num_adapters; i++) { D3DADAPTER_IDENTIFIER8 adapter_info; ZeroMemory(&adapter_info, sizeof(D3DADAPTER_IDENTIFIER8)); - hr = pD3D8->GetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &adapter_info); + hr = dxpipe->_pD3D8->GetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &adapter_info); if (FAILED(hr)) { wdxdisplay8_cat.fatal() << "D3D GetAdapterID(" << i << ") failed: " @@ -702,7 +889,7 @@ choose_adapter(LPDIRECT3D8 pD3D8) { LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion; wdxdisplay8_cat.info() - << "D3D8 Adapter[" << i << "]: " << adapter_info.Description + << "D3D8." << (dxpipe->_bIsDX81 ?"1":"0") << " Adapter[" << i << "]: " << adapter_info.Description << ", Driver: " << adapter_info.Driver << ", DriverVersion: (" << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "." << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart) @@ -711,7 +898,7 @@ choose_adapter(LPDIRECT3D8 pD3D8) { << " SubsysID: 0x" << (void*) adapter_info.SubSysId << " Revision: 0x" << (void*) adapter_info.Revision << endl; - HMONITOR hMon = pD3D8->GetAdapterMonitor(i); + HMONITOR hMon = dxpipe->_pD3D8->GetAdapterMonitor(i); if (hMon == NULL) { wdxdisplay8_cat.info() << "D3D8 Adapter[" << i << "]: seems to be disabled, skipping it\n"; @@ -760,9 +947,237 @@ choose_adapter(LPDIRECT3D8 pD3D8) { } } - return search_for_device(pD3D8, &device_infos[adapter_num]); + UINT good_device_count=0; + for(UINT devnum=0;devnum0); + _hOldForegroundWindow=GetForegroundWindow(); + _bClosingAllWindows= false; + + UINT num_windows=_windows.size(); + + #define D3D8_NAME "d3d8.dll" + #define D3DCREATE8 "Direct3DCreate8" + + _hD3D8_DLL = LoadLibrary(D3D8_NAME); + if(_hD3D8_DLL == 0) { + wdxdisplay_cat.fatal() << "PandaDX8 requires DX8, can't locate " << D3D8_NAME <<"!\n"; + exit(1); + } + + _hMouseCursor = NULL; + _bLoadedCustomCursor = false; + + _pDInputInfo = NULL; + + // can only get multimon HW acceleration in fullscrn on DX7 + + UINT numMonitors = GetSystemMetrics(SM_CMONITORS); + + if(numMonitors < num_windows) { + if(numMonitors==0) { + numMonitors=1; //win95 system will fail this call + } else { + wdxdisplay_cat.fatal() << "system has only " << numMonitors << " monitors attached, couldn't find enough devices to meet multi window reqmt of " << num_windows << endl; + exit(1); + } + } + + // Do all DX7 stuff first + // find_all_card_memavails(); + + LPDIRECT3D8 pD3D8; + + typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion); + + // dont want to statically link to possibly non-existent d3d8 dll, so must call D3DCr8 indirectly + Direct3DCreate8_ProcPtr D3DCreate8_Ptr = + (Direct3DCreate8_ProcPtr) GetProcAddress(_hD3D8_DLL, D3DCREATE8); + + if(D3DCreate8_Ptr == NULL) { + wdxdisplay_cat.fatal() << "GetProcAddress for "<< D3DCREATE8 << "failed!" << endl; + exit(1); + } + +// these were taken from the 8.0 and 8.1 d3d8.h SDK headers +#define D3D_SDK_VERSION_8_0 120 +#define D3D_SDK_VERSION_8_1 220 + + // are we using 8.0 or 8.1? + WIN32_FIND_DATA TempFindData; + HANDLE hFind; + char tmppath[MAX_PATH]; + GetSystemDirectory(tmppath,MAX_PATH); + strcat(tmppath,"\\dpnhpast.dll"); + hFind = FindFirstFile ( tmppath,&TempFindData ); + if(hFind != INVALID_HANDLE_VALUE) { + FindClose(hFind); + _bIsDX81=true; + pD3D8 = (*D3DCreate8_Ptr)(D3D_SDK_VERSION_8_1); + } else { + _bIsDX81=false; + pD3D8 = (*D3DCreate8_Ptr)(D3D_SDK_VERSION_8_0); + } + + if(pD3D8==NULL) { + wdxdisplay_cat.fatal() << D3DCREATE8 << " failed!\n"; + exit(1); + } + + _numAdapters = pD3D8->GetAdapterCount(); + if(_numAdapters < num_windows) { + wdxdisplay_cat.fatal() << "couldn't find enough devices attached to meet multi window reqmt of " << num_windows << endl; + exit(1); + } + + for(UINT i=0;i<_numAdapters;i++) { + D3DADAPTER_IDENTIFIER8 adapter_info; + ZeroMemory(&adapter_info,sizeof(D3DADAPTER_IDENTIFIER8)); + hr = pD3D8->GetAdapterIdentifier(i,D3DENUM_NO_WHQL_LEVEL,&adapter_info); + if(FAILED(hr)) { + wdxdisplay_cat.fatal() << "D3D GetAdapterID failed" << D3DERRORSTRING(hr); + } + + LARGE_INTEGER *DrvVer=&adapter_info.DriverVersion; + + wdxdisplay_cat.info() << "D3D8 Adapter[" << i << "]: " << adapter_info.Description << + ", Driver: " << adapter_info.Driver << ", DriverVersion: (" + << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "." + << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart) << ")\nVendorID: 0x" + << (void*) adapter_info.VendorId << " DeviceID: 0x" << (void*) adapter_info.DeviceId + << " SubsysID: 0x" << (void*) adapter_info.SubSysId << " Revision: 0x" + << (void*) adapter_info.Revision << endl; + + HMONITOR hMon=pD3D8->GetAdapterMonitor(i); + if(hMon==NULL) { + wdxdisplay_cat.info() << "D3D8 Adapter[" << i << "]: seems to be disabled, skipping it\n"; + continue; + } + + DXDeviceInfo devinfo; + ZeroMemory(&devinfo,sizeof(devinfo)); + memcpy(&devinfo.guidDeviceIdentifier,&adapter_info.DeviceIdentifier,sizeof(GUID)); + strncpy(devinfo.szDescription,adapter_info.Description,MAX_DEVICE_IDENTIFIER_STRING); + strncpy(devinfo.szDriver,adapter_info.Driver,MAX_DEVICE_IDENTIFIER_STRING); + devinfo.VendorID=adapter_info.VendorId; + devinfo.DeviceID=adapter_info.DeviceId; + devinfo.hMon=hMon; + devinfo.cardID=i; + + _DeviceInfoVec.push_back(devinfo); + } + + for(UINT i=0;iconfig_window(this); + } + + UINT good_device_count=0; + + if(num_windows==1) { + UINT D3DAdapterNum = D3DADAPTER_DEFAULT; + + if(dx_preferred_deviceID!=-1) { + if(dx_preferred_deviceID>=(int)_numAdapters) { + wdxdisplay_cat.fatal() << "invalid 'dx-preferred-device-id', valid values are 0-" << _numAdapters-1 << ", using default adapter 0 instead\n"; + } else D3DAdapterNum=dx_preferred_deviceID; + } + if(_windows[0]->search_for_device(pD3D8,&(_DeviceInfoVec[D3DAdapterNum]))) + good_device_count=1; + } else { + for(UINT devnum=0;devnum<_DeviceInfoVec.size() && (good_device_count < num_windows);devnum++) { + if(_windows[devnum]->search_for_device(pD3D8,&(_DeviceInfoVec[devnum]))) + good_device_count++; + } + } + + if(good_device_count < num_windows) { + if(good_device_count==0) + wdxdisplay_cat.fatal() << "no usable display devices, exiting...\n"; + else wdxdisplay_cat.fatal() << "multi-device request for " << num_windows << "devices, found only "<< good_device_count << " usable ones, exiting!"; + exit(1); + } + + _DeviceInfoVec.clear(); // dont need this anymore + + if(wdxdisplay_cat.is_debug() && (g_pCardIDVec!=NULL)) { + // print out the MaxAvailVidMems + for(UINT i=0;i<_windows.size();i++) { + D3DADAPTER_IDENTIFIER8 adapter_info; + pD3D8->GetAdapterIdentifier(_windows[i]->_wcontext.CardIDNum,D3DENUM_NO_WHQL_LEVEL,&adapter_info); + wdxdisplay_cat.info() << "D3D8 Adapter[" << i << "]: " << adapter_info.Description + << ", MaxAvailVideoMem: " << _windows[i]->_wcontext.MaxAvailVidMem + << ", IsLowVidMemCard: " << (_windows[i]->_wcontext.bIsLowVidMemCard ? "true" : "false") << endl; + } + } + + CreateWindows(); // creates win32 windows (need to do this before Setting coopLvls and display modes, + // but after we have all the monitor handles needed by CreateWindow() + +// SetCoopLevelsAndDisplayModes(); + + if(dx_show_fps_meter) + _windows[0]->_dxgsg->_bShowFPSMeter = true; // just show fps on 1st mon + + for(UINT i=0;iCreateScreenBuffersAndDevice(_windows[i]->_wcontext); + } + + for(UINT i=0;ifinish_window_setup(); + } + + SAFE_DELETE(g_pCardIDVec); // dont need this anymore + + for(UINT i=0;i_dxgsg->SetDXReady(true); + } + + dx_pick_best_screenres = false; // only want to do this on startup, not resize + + #ifdef DINPUT_DEBUG_POLL + if(dx_use_joystick) { + _pDInputInfo = new DInput8Info; + assert(_pDInputInfo !=NULL); + if(!_pDInputInfo->InitDirectInput()) { + wdxdisplay_cat.error() << "InitDirectInput failed!\n"; + exit(1); + } + + if(!_pDInputInfo->CreateJoystickOrPad(_hParentWindow)) { // associate w/parent window of group for now + wdxdisplay_cat.error() << "CreateJoystickOrPad failed!\n"; + exit(1); + } + + // for now, just set up a WM_TIMER to poll the joystick. + // could configure it to do event-based input, and that is default w/action mapping + // which would be better, less processor intensive + + #define POLL_FREQUENCY_HZ 3 + _pDInputInfo->_JoystickPollTimer = SetTimer(_hParentWindow, JOYSTICK_POLL_TIMER_ID, 1000/POLL_FREQUENCY_HZ, NULL); + if(_pDInputInfo->_JoystickPollTimer!=JOYSTICK_POLL_TIMER_ID) { + wdxdisplay_cat.error() << "Error in joystick SetTimer!\n"; + } + } + #endif +} +*/ + //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsWindow8::search_for_device // Access: Private @@ -770,24 +1185,25 @@ choose_adapter(LPDIRECT3D8 pD3D8) { // rendering. //////////////////////////////////////////////////////////////////// bool wdxGraphicsWindow8:: -search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { - wdxGraphicsPipe8 *dxpipe; - DCAST_INTO_R(dxpipe, _pipe, false); +search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info) { + assert(dxpipe != NULL); WindowProperties properties = get_properties(); DWORD dwRenderWidth = properties.get_x_size(); DWORD dwRenderHeight = properties.get_y_size(); HRESULT hr; + LPDIRECT3D8 pD3D8 = dxpipe->_pD3D8; - assert(_dxgsg != NULL); - _dxgsg->scrn.pD3D8 = pD3D8; - _dxgsg->scrn.CardIDNum = device_info->cardID; // could this change by end? + assert(_dxgsg != NULL); + _wcontext.pD3D8 = pD3D8; + _wcontext.bIsDX81 = dxpipe->_bIsDX81; + _wcontext.CardIDNum = device_info->cardID; // could this change by end? - int framebuffer_mode = get_properties().get_framebuffer_mode(); - bool bWantStencil = ((framebuffer_mode & WindowProperties::FM_stencil) != 0); + int frame_buffer_mode = _gsg->get_properties().get_frame_buffer_mode(); + bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0); hr = pD3D8->GetAdapterIdentifier(device_info->cardID, D3DENUM_NO_WHQL_LEVEL, - &_dxgsg->scrn.DXDeviceID); + &_wcontext.DXDeviceID); if (FAILED(hr)) { wdxdisplay8_cat.error() << "D3D GetAdapterID failed" << D3DERRORSTRING(hr); @@ -810,11 +1226,11 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { } //search_for_valid_displaymode needs these to be set - memcpy(&_dxgsg->scrn.d3dcaps, &d3dcaps,sizeof(D3DCAPS8)); - _dxgsg->scrn.CardIDNum = device_info->cardID; + memcpy(&_wcontext.d3dcaps, &d3dcaps,sizeof(D3DCAPS8)); + _wcontext.CardIDNum = device_info->cardID; - _dxgsg->scrn.MaxAvailVidMem = UNKNOWN_VIDMEM_SIZE; - _dxgsg->scrn.bIsLowVidMemCard = false; + _wcontext.MaxAvailVidMem = UNKNOWN_VIDMEM_SIZE; + _wcontext.bIsLowVidMemCard = false; // bugbug: wouldnt we like to do GetAVailVidMem so we can do // upper-limit memory computation for dx8 cards too? otherwise @@ -835,7 +1251,7 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { for (IDnum=0; IDnum < dxpipe->_card_ids.size(); IDnum++) { // wdxdisplay8_cat.info() // << "comparing '" << dxpipe->_card_ids[IDnum].Driver - // << "' to '" << _dxgsg->scrn.DXDeviceID.Driver << "'\n"; + // << "' to '" << _wcontext.DXDeviceID.Driver << "'\n"; if (//(stricmp(dxpipe->_card_ids[IDnum].szDriver,device_info->szDriver)==0) && (device_info->VendorID==dxpipe->_card_ids[IDnum].VendorID) && (device_info->DeviceID==dxpipe->_card_ids[IDnum].DeviceID) && @@ -844,8 +1260,8 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { } if (IDnum < dxpipe->_card_ids.size()) { - _dxgsg->scrn.MaxAvailVidMem = dxpipe->_card_ids[IDnum].MaxAvailVidMem; - _dxgsg->scrn.bIsLowVidMemCard = dxpipe->_card_ids[IDnum].bIsLowVidMemCard; + _wcontext.MaxAvailVidMem = dxpipe->_card_ids[IDnum].MaxAvailVidMem; + _wcontext.bIsLowVidMemCard = dxpipe->_card_ids[IDnum].bIsLowVidMemCard; } else { wdxdisplay8_cat.error() << "Error: couldnt find a CardID match in DX7 info, assuming card is not a lowmem card\n"; @@ -855,7 +1271,7 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { if ((bWantStencil) && (d3dcaps.StencilCaps==0x0)) { wdxdisplay8_cat.fatal() << "Stencil ability requested, but device #" << device_info->cardID - << " (" << _dxgsg->scrn.DXDeviceID.Description + << " (" << _wcontext.DXDeviceID.Description << "), has no stencil capability!\n"; return false; } @@ -864,27 +1280,27 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { // supported in HW (see GF2) for this case, you probably want MIXED // processing to use HW for fixed-fn vertex processing and SW for // vtx shaders - _dxgsg->scrn.bIsTNLDevice = + _wcontext.bIsTNLDevice = ((d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0); - _dxgsg->scrn.bCanUseHWVertexShaders = + _wcontext.bCanUseHWVertexShaders = (d3dcaps.VertexShaderVersion >= D3DVS_VERSION(1, 0)); - _dxgsg->scrn.bCanUsePixelShaders = + _wcontext.bCanUsePixelShaders = (d3dcaps.PixelShaderVersion >= D3DPS_VERSION(1, 0)); bool bNeedZBuffer = ((!(d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) && - ((framebuffer_mode & WindowProperties::FM_depth) != 0)); + ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0)); - _dxgsg->scrn.PresParams.EnableAutoDepthStencil = bNeedZBuffer; + _wcontext.PresParams.EnableAutoDepthStencil = bNeedZBuffer; D3DFORMAT pixFmt = D3DFMT_UNKNOWN; if (is_fullscreen()) { bool bCouldntFindValidZBuf; - if (!_dxgsg->scrn.bIsLowVidMemCard) { + if (!_wcontext.bIsLowVidMemCard) { bool bUseDefaultSize = dx_pick_best_screenres && - ((_dxgsg->scrn.MaxAvailVidMem == UNKNOWN_VIDMEM_SIZE) || - is_badvidmem_card(&_dxgsg->scrn.DXDeviceID)); + ((_wcontext.MaxAvailVidMem == UNKNOWN_VIDMEM_SIZE) || + is_badvidmem_card(&_wcontext.DXDeviceID)); if (dx_pick_best_screenres && !bUseDefaultSize) { typedef struct { @@ -914,20 +1330,20 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { for(int i = NumResLims - 1; i >= 0; i--) { // find biggest slot card can handle - if (_dxgsg->scrn.MaxAvailVidMem > MemRes[i].memlimit) { + if (_wcontext.MaxAvailVidMem > MemRes[i].memlimit) { dwRenderWidth = MemRes[i].scrnX; dwRenderHeight = MemRes[i].scrnY; wdxdisplay8_cat.info() << "pick_best_screenres: trying " << dwRenderWidth << "x" << dwRenderHeight << " based on " - << _dxgsg->scrn.MaxAvailVidMem << " bytes avail\n"; + << _wcontext.MaxAvailVidMem << " bytes avail\n"; - search_for_valid_displaymode(dwRenderWidth, dwRenderHeight, + dxpipe->search_for_valid_displaymode(_wcontext,dwRenderWidth, dwRenderHeight, bNeedZBuffer, bWantStencil, - &_dxgsg->scrn.SupportedScreenDepthsMask, + &_wcontext.SupportedScreenDepthsMask, &bCouldntFindValidZBuf, - &pixFmt); + &pixFmt, dx_force_16bpp_zbuffer); // note I'm not saving refresh rate, will just use adapter // default at given res for now @@ -940,7 +1356,7 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { << "skipping scrnres; " << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes") << " at " << dwRenderWidth << "x" << dwRenderHeight - << " for device #" << _dxgsg->scrn.CardIDNum << endl; + << " for device #" << _wcontext.CardIDNum << endl; } } // otherwise just go with whatever was specified (we probably shouldve marked this card as lowmem if it gets to end of loop w/o breaking @@ -954,11 +1370,11 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { dwRenderHeight=600; } - search_for_valid_displaymode(dwRenderWidth, dwRenderHeight, + dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight, bNeedZBuffer, bWantStencil, - &_dxgsg->scrn.SupportedScreenDepthsMask, + &_wcontext.SupportedScreenDepthsMask, &bCouldntFindValidZBuf, - &pixFmt); + &pixFmt, dx_force_16bpp_zbuffer); // note I'm not saving refresh rate, will just use adapter // default at given res for now @@ -966,14 +1382,14 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { if (pixFmt == D3DFMT_UNKNOWN) { wdxdisplay8_cat.error() << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes") - << " at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << _dxgsg->scrn.CardIDNum <search_for_valid_displaymode(_wcontext,dwRenderWidth, dwRenderHeight, bNeedZBuffer, bWantStencil, - &_dxgsg->scrn.SupportedScreenDepthsMask, + &_wcontext.SupportedScreenDepthsMask, &bCouldntFindValidZBuf, - &pixFmt, true); + &pixFmt, dx_force_16bpp_zbuffer, true); return false; } } @@ -983,40 +1399,42 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { dwRenderHeight=480; dx_force_16bpptextures = true; - // force 16bpp zbuf? or let user get extra bits if they have the mem? + // need to autoforce 16bpp zbuf? or let user use that extra mem for textures/framebuf res/etc? + // most lowmem cards only do 16bpp Z anyway, but we wont force it for now - search_for_valid_displaymode(dwRenderWidth, dwRenderHeight, + dxpipe->search_for_valid_displaymode(_wcontext,dwRenderWidth, dwRenderHeight, bNeedZBuffer, bWantStencil, - &_dxgsg->scrn.SupportedScreenDepthsMask, + &_wcontext.SupportedScreenDepthsMask, &bCouldntFindValidZBuf, - &pixFmt); + &pixFmt, dx_force_16bpp_zbuffer); // hack: figuring out exactly what res to use is tricky, instead I will // just use 640x480 if we have < 3 meg avail - if (_dxgsg->scrn.SupportedScreenDepthsMask & R5G6B5_FLAG) { + if (_wcontext.SupportedScreenDepthsMask & R5G6B5_FLAG) { pixFmt = D3DFMT_R5G6B5; - } else if (_dxgsg->scrn.SupportedScreenDepthsMask & X1R5G5B5_FLAG) { + } else if (_wcontext.SupportedScreenDepthsMask & X1R5G5B5_FLAG) { pixFmt = D3DFMT_X1R5G5B5; } else { wdxdisplay8_cat.fatal() << "Low Memory VidCard has no supported FullScreen 16bpp resolutions at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << device_info->cardID << " (" - << _dxgsg->scrn.DXDeviceID.Description << "), skipping device...\n"; + << _wcontext.DXDeviceID.Description << "), skipping device...\n"; // run it again in verbose mode to get more dbg info to log - search_for_valid_displaymode(dwRenderWidth, dwRenderHeight, + dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight, bNeedZBuffer, bWantStencil, - &_dxgsg->scrn.SupportedScreenDepthsMask, + &_wcontext.SupportedScreenDepthsMask, &bCouldntFindValidZBuf, - &pixFmt, true); + &pixFmt, dx_force_16bpp_zbuffer, + true /* verbose mode on*/); return false; } if (wdxdisplay8_cat.is_info()) { wdxdisplay8_cat.info() - << "Available VidMem (" << _dxgsg->scrn.MaxAvailVidMem + << "Available VidMem (" << _wcontext.MaxAvailVidMem << ") is under threshold, using 640x480 16bpp rendertargets to save tex vidmem.\n"; } } @@ -1034,11 +1452,11 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { pixFmt = dispmode.Format; } - _dxgsg->scrn.DisplayMode.Width = dwRenderWidth; - _dxgsg->scrn.DisplayMode.Height = dwRenderHeight; - _dxgsg->scrn.DisplayMode.Format = pixFmt; - _dxgsg->scrn.DisplayMode.RefreshRate = D3DPRESENT_RATE_DEFAULT; - _dxgsg->scrn.hMon = device_info->hMon; + _wcontext.DisplayMode.Width = dwRenderWidth; + _wcontext.DisplayMode.Height = dwRenderHeight; + _wcontext.DisplayMode.Format = pixFmt; + _wcontext.DisplayMode.RefreshRate = D3DPRESENT_RATE_DEFAULT; + _wcontext.hMon = device_info->hMon; if (dwRenderWidth != properties.get_x_size() || dwRenderHeight != properties.get_y_size()) { @@ -1063,286 +1481,6 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { return true; } -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::special_check_fullscreen_resolution -// Access: Private -// Description: overrides of the general estimator for known working -// cases -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -special_check_fullscreen_resolution(UINT x_size,UINT y_size) { - assert(IS_VALID_PTR(_dxgsg)); - - DWORD VendorId = _dxgsg->scrn.DXDeviceID.VendorId; - DWORD DeviceId = _dxgsg->scrn.DXDeviceID.DeviceId; - switch (VendorId) { - case 0x8086: // Intel - /*for now, just validate all the intel cards at these resolutions. - I dont have a complete list of intel deviceIDs (missing 82830, 845, etc) - // Intel i810,i815,82810 - if ((DeviceId==0x7121)||(DeviceId==0x7123)||(DeviceId==0x7125)|| - (DeviceId==0x1132)) - */ - if ((x_size == 640) && (y_size == 480)) { - return true; - } - if ((x_size == 800) && (y_size == 600)) { - return true; - } - if ((x_size == 1024) && (y_size == 768)) { - return true; - } - break; - } - - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::search_for_valid_displaymode -// Access: Private -// Description: All ptr args are output parameters. If no valid mode -// found, returns *pSuggestedPixFmt = D3DFMT_UNKNOWN; -//////////////////////////////////////////////////////////////////// -void wdxGraphicsWindow8:: -search_for_valid_displaymode(UINT RequestedX_Size, UINT RequestedY_Size, - bool bWantZBuffer, bool bWantStencil, - UINT *pSupportedScreenDepthsMask, - bool *pCouldntFindAnyValidZBuf, - D3DFORMAT *pSuggestedPixFmt, - bool bVerboseMode) { - assert(IS_VALID_PTR(_dxgsg)); - assert(IS_VALID_PTR(_dxgsg->scrn.pD3D8)); - HRESULT hr; - -#ifndef NDEBUG - // no longer true, due to special_check_fullscreen_res, where lowvidmem cards are allowed higher resolutions - // if (_dxgsg->scrn.bIsLowVidMemCard) - // nassertv((RequestedX_Size==640)&&(RequestedY_Size==480)); -#endif - - *pSuggestedPixFmt = D3DFMT_UNKNOWN; - *pSupportedScreenDepthsMask = 0x0; - *pCouldntFindAnyValidZBuf = false; - - int cNumModes = _dxgsg->scrn.pD3D8->GetAdapterModeCount(_dxgsg->scrn.CardIDNum); - D3DDISPLAYMODE BestDispMode; - ZeroMemory(&BestDispMode,sizeof(BestDispMode)); - - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "searching for valid display modes at res: (" - << RequestedX_Size << "," << RequestedY_Size - << "), TotalModes: " << cNumModes << endl; - } - - // ignore memory based checks for min res 640x480. some cards just - // dont give accurate memavails. (should I do the check anyway for - // 640x480 32bpp?) - bool bDoMemBasedChecks = - ((!((RequestedX_Size==640)&&(RequestedY_Size==480))) && - (_dxgsg->scrn.MaxAvailVidMem!=UNKNOWN_VIDMEM_SIZE) && - (!special_check_fullscreen_resolution(RequestedX_Size,RequestedY_Size))); - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) { - wdxdisplay8_cat.info() - << "DoMemBasedChecks = " << bDoMemBasedChecks << endl; - } - - for (int i=0; i < cNumModes; i++) { - D3DDISPLAYMODE dispmode; - hr = _dxgsg->scrn.pD3D8->EnumAdapterModes(_dxgsg->scrn.CardIDNum,i,&dispmode); - if (FAILED(hr)) { - wdxdisplay8_cat.error() - << "EnumAdapterDisplayMode failed for device #" - << _dxgsg->scrn.CardIDNum << D3DERRORSTRING(hr); - exit(1); - } - - if ((dispmode.Width!=RequestedX_Size) || - (dispmode.Height!=RequestedY_Size)) { - continue; - } - - if ((dispmode.RefreshRate<60) && (dispmode.RefreshRate>1)) { - // dont want refresh rates under 60Hz, but 0 or 1 might indicate - // a default refresh rate, which is usually >=60 - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "skipping mode[" << i << "], bad refresh rate: " - << dispmode.RefreshRate << endl; - } - continue; - } - - // Note no attempt is made to verify if format will work at - // requested size, so even if this call succeeds, could still get - // an out-of-video-mem error - - hr = _dxgsg->scrn.pD3D8->CheckDeviceFormat(_dxgsg->scrn.CardIDNum, - D3DDEVTYPE_HAL, dispmode.Format, - D3DUSAGE_RENDERTARGET, - D3DRTYPE_SURFACE, - dispmode.Format); - if (FAILED(hr)) { - if (hr==D3DERR_NOTAVAILABLE) { - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "skipping mode[" << i - << "], CheckDevFmt returns NotAvail for fmt: " - << D3DFormatStr(dispmode.Format) << endl; - } - continue; - } else { - wdxdisplay8_cat.error() - << "CheckDeviceFormat failed for device #" - << _dxgsg->scrn.CardIDNum << D3DERRORSTRING(hr); - exit(1); - } - } - - bool bIs16bppRenderTgt = IS_16BPP_DISPLAY_FORMAT(dispmode.Format); - float RendTgtMinMemReqmt; - - // if we have a valid memavail value, try to determine if we have - // enough space - if (bDoMemBasedChecks) { - // assume user is testing fullscreen, not windowed, so use the - // dwTotal value see if 3 scrnbufs (front/back/z)at 16bpp at - // x_size*y_size will fit with a few extra megs for texmem - - // 8MB Rage Pro says it has 6.8 megs Total free and will run at - // 1024x768, so formula makes it so that is OK - -#define REQD_TEXMEM 1800000 - - float bytes_per_pixel = (bIs16bppRenderTgt ? 2 : 4); - assert((get_properties().get_framebuffer_mode() & WindowProperties::FM_double_buffer) != 0); - - // *2 for double buffer - - RendTgtMinMemReqmt = - ((float)RequestedX_Size) * ((float)RequestedY_Size) * - bytes_per_pixel * 2 + REQD_TEXMEM; - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) - wdxdisplay8_cat.info() - << "Testing Mode (" <scrn.MaxAvailVidMem << endl; - - if (RendTgtMinMemReqmt > _dxgsg->scrn.MaxAvailVidMem) { - if (bVerboseMode || wdxdisplay8_cat.is_debug()) - wdxdisplay8_cat.info() - << "not enough VidMem for render tgt, skipping display fmt " - << D3DFormatStr(dispmode.Format) << " (" - << (int)RendTgtMinMemReqmt << " > " - << _dxgsg->scrn.MaxAvailVidMem << ")\n"; - continue; - } - } - - if (bWantZBuffer) { - D3DFORMAT zformat; - if (!find_best_depth_format(_dxgsg->scrn,dispmode, &zformat, - bWantStencil, false)) { - *pCouldntFindAnyValidZBuf=true; - continue; - } - - float MinMemReqmt = 0.0f; - - if (bDoMemBasedChecks) { - // test memory again, this time including zbuf size - float zbytes_per_pixel = (IS_16BPP_ZBUFFER(zformat) ? 2 : 4); - float MinMemReqmt = RendTgtMinMemReqmt + ((float)RequestedX_Size)*((float)RequestedY_Size)*zbytes_per_pixel; - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) - wdxdisplay8_cat.info() - << "Testing Mode w/Z (" << RequestedX_Size << "x" - << RequestedY_Size << "," << D3DFormatStr(dispmode.Format) - << ")\nReqdVidMem: "<< (int)MinMemReqmt << " AvailVidMem: " - << _dxgsg->scrn.MaxAvailVidMem << endl; - - if (MinMemReqmt > _dxgsg->scrn.MaxAvailVidMem) { - if (bVerboseMode || wdxdisplay8_cat.is_debug()) - wdxdisplay8_cat.info() - << "not enough VidMem for RendTgt+zbuf, skipping display fmt " - << D3DFormatStr(dispmode.Format) << " (" << (int)MinMemReqmt - << " > " << _dxgsg->scrn.MaxAvailVidMem << ")\n"; - continue; - } - } - - if ((!bDoMemBasedChecks) || (MinMemReqmt<_dxgsg->scrn.MaxAvailVidMem)) { - if (!IS_16BPP_ZBUFFER(zformat)) { - // see if things fit with a 16bpp zbuffer - - if (!find_best_depth_format(_dxgsg->scrn, dispmode, &zformat, - bWantStencil, true, bVerboseMode)) { - if (bVerboseMode) - wdxdisplay8_cat.info() - << "FindBestDepthFmt rejected Mode[" << i << "] (" - << RequestedX_Size << "x" << RequestedY_Size - << "," << D3DFormatStr(dispmode.Format) << endl; - *pCouldntFindAnyValidZBuf=true; - continue; - } - - // right now I'm not going to use these flags, just let the - // create fail out-of-mem and retry at 16bpp - *pSupportedScreenDepthsMask |= - (IS_16BPP_DISPLAY_FORMAT(dispmode.Format) ? DISPLAY_16BPP_REQUIRES_16BPP_ZBUFFER_FLAG : DISPLAY_32BPP_REQUIRES_16BPP_ZBUFFER_FLAG); - } - } - } - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) - wdxdisplay8_cat.info() - << "Validated Mode (" << RequestedX_Size << "x" - << RequestedY_Size << "," << D3DFormatStr(dispmode.Format) << endl; - - switch (dispmode.Format) { - case D3DFMT_X1R5G5B5: - *pSupportedScreenDepthsMask |= X1R5G5B5_FLAG; - break; - case D3DFMT_X8R8G8B8: - *pSupportedScreenDepthsMask |= X8R8G8B8_FLAG; - break; - case D3DFMT_R8G8B8: - *pSupportedScreenDepthsMask |= R8G8B8_FLAG; - break; - case D3DFMT_R5G6B5: - *pSupportedScreenDepthsMask |= R5G6B5_FLAG; - break; - default: - // Render target formats should be only D3DFMT_X1R5G5B5, - // D3DFMT_R5G6B5, D3DFMT_X8R8G8B8 (or R8G8B8?) - wdxdisplay8_cat.error() - << "unrecognized supported fmt "<< D3DFormatStr(dispmode.Format) - << " returned by EnumAdapterDisplayModes!\n"; - } - } - - // note: this chooses 32bpp, which may not be preferred over 16 for - // memory & speed reasons on some older cards in particular - if (*pSupportedScreenDepthsMask & X8R8G8B8_FLAG) { - *pSuggestedPixFmt = D3DFMT_X8R8G8B8; - } else if (*pSupportedScreenDepthsMask & R8G8B8_FLAG) { - *pSuggestedPixFmt = D3DFMT_R8G8B8; - } else if (*pSupportedScreenDepthsMask & R5G6B5_FLAG) { - *pSuggestedPixFmt = D3DFMT_R5G6B5; - } else if (*pSupportedScreenDepthsMask & X1R5G5B5_FLAG) { - *pSuggestedPixFmt = D3DFMT_X1R5G5B5; - } - - if (bVerboseMode || wdxdisplay8_cat.is_spam()) { - wdxdisplay8_cat.info() - << "search_for_valid_device returns fmt: " - << D3DFormatStr(*pSuggestedPixFmt) << endl; - } -} //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsWindow8::reset_device_resize_window @@ -1353,12 +1491,11 @@ search_for_valid_displaymode(UINT RequestedX_Size, UINT RequestedY_Size, //////////////////////////////////////////////////////////////////// bool wdxGraphicsWindow8:: reset_device_resize_window(UINT new_xsize, UINT new_ysize) { - DXScreenData *pScrn = &_dxgsg->scrn; assert((new_xsize > 0) && (new_ysize > 0)); bool bRetval = true; D3DPRESENT_PARAMETERS d3dpp; - memcpy(&d3dpp, &pScrn->PresParams, sizeof(D3DPRESENT_PARAMETERS)); + memcpy(&d3dpp, &_wcontext.PresParams, sizeof(D3DPRESENT_PARAMETERS)); d3dpp.BackBufferWidth = new_xsize; d3dpp.BackBufferHeight = new_ysize; HRESULT hr = _dxgsg->reset_d3d_device(&d3dpp); @@ -1368,7 +1505,7 @@ reset_device_resize_window(UINT new_xsize, UINT new_ysize) { wdxdisplay8_cat.error() << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr); if (hr == D3DERR_OUTOFVIDEOMEMORY) { - hr = _dxgsg->reset_d3d_device(&pScrn->PresParams); + hr = _dxgsg->reset_d3d_device(&_wcontext.PresParams); if (FAILED(hr)) { wdxdisplay8_cat.error() << "reset_device_resize_window Reset() failed OutOfVidmem, then failed again doing Reset w/original params:" << D3DERRORSTRING(hr); @@ -1376,8 +1513,8 @@ reset_device_resize_window(UINT new_xsize, UINT new_ysize) { } else { if (wdxdisplay8_cat.is_info()) wdxdisplay8_cat.info() - << "reset of original size (" << pScrn->PresParams.BackBufferWidth - << "," << pScrn->PresParams.BackBufferHeight << ") succeeded\n"; + << "reset of original size (" << _wcontext.PresParams.BackBufferWidth + << "," << _wcontext.PresParams.BackBufferHeight << ") succeeded\n"; } } else { wdxdisplay8_cat.fatal() @@ -1398,30 +1535,32 @@ reset_device_resize_window(UINT new_xsize, UINT new_ysize) { // // Assumes CreateDevice or Device->Reset() has just been // called, and the new size is specified in -// _dxgsg->scrn.PresParams. +// _wcontext.PresParams. //////////////////////////////////////////////////////////////////// void wdxGraphicsWindow8:: init_resized_window() { - DXScreenData *pDisplay=&_dxgsg->scrn; HRESULT hr; - DWORD newWidth = pDisplay->PresParams.BackBufferWidth; - DWORD newHeight = pDisplay->PresParams.BackBufferHeight; + DWORD newWidth = _wcontext.PresParams.BackBufferWidth; + DWORD newHeight = _wcontext.PresParams.BackBufferHeight; - if (pDisplay->PresParams.Windowed) { + assert((newWidth!=0) && (newHeight!=0)); + assert(_wcontext.hWnd!=NULL); + + if (_wcontext.PresParams.Windowed) { POINT ul,lr; RECT client_rect; // need to figure out x,y origin offset of window client area on screen // (we already know the client area size) - GetClientRect(pDisplay->hWnd, &client_rect); + GetClientRect(_wcontext.hWnd, &client_rect); ul.x = client_rect.left; ul.y = client_rect.top; lr.x = client_rect.right; lr.y=client_rect.bottom; - ClientToScreen(pDisplay->hWnd, &ul); - ClientToScreen(pDisplay->hWnd, &lr); + ClientToScreen(_wcontext.hWnd, &ul); + ClientToScreen(_wcontext.hWnd, &lr); client_rect.left = ul.x; client_rect.top = ul.y; client_rect.right = lr.x; @@ -1452,111 +1591,26 @@ init_resized_window() { // resized(newWidth, newHeight); // update panda channel/display rgn info, _props.x_size, _props.y_size // clear window to black ASAP - ClearToBlack(pDisplay->hWnd, get_properties()); + assert(_wcontext.hWnd!=NULL); + ClearToBlack(_wcontext.hWnd, get_properties()); // clear textures and VB's out of video&AGP mem, so cache is reset - hr = pDisplay->pD3DDevice->ResourceManagerDiscardBytes(0); + hr = _wcontext.pD3DDevice->ResourceManagerDiscardBytes(0); if (FAILED(hr)) { wdxdisplay8_cat.error() << "ResourceManagerDiscardBytes failed for device #" - << pDisplay->CardIDNum << D3DERRORSTRING(hr); + << _wcontext.CardIDNum << D3DERRORSTRING(hr); } - _dxgsg->dx_init(_mouse_cursor); -} + _dxgsg->set_context(&_wcontext); + // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts + _dxgsg->dx_init(); -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsWindow8::find_best_depth_format -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -bool wdxGraphicsWindow8:: -find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode, - D3DFORMAT *pBestFmt, bool bWantStencil, - bool bForce16bpp, bool bVerboseMode) 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_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 || bForce16bpp || - (IS_NVIDIA(Display.DXDeviceID) && IS_16BPP_DISPLAY_FORMAT(TestDisplayMode.Format))); - - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "FindBestDepthFmt: bSelectOnly16bpp: " << bOnlySelect16bpp << endl; + if(dx_use_dx_cursor && is_fullscreen()) { + hr = CreateDX8Cursor(_wcontext.pD3DDevice,_mouse_cursor,dx_show_cursor_watermark); + if(FAILED(hr)) + wdxdisplay8_cat.error() << "CreateDX8Cursor failed!" << D3DERRORSTRING(hr); } - - for (int i=0; i < NUM_TEST_ZFMTS; i++) { - D3DFORMAT TestDepthFmt = - (bWantStencil ? StencilPrefList[i] : NoStencilPrefList[i]); - - if (bOnlySelect16bpp && !IS_16BPP_ZBUFFER(TestDepthFmt)) { - continue; - } - - hr = Display.pD3D8->CheckDeviceFormat(Display.CardIDNum, - D3DDEVTYPE_HAL, - TestDisplayMode.Format, - D3DUSAGE_DEPTHSTENCIL, - D3DRTYPE_SURFACE,TestDepthFmt); - - if (FAILED(hr)) { - if (hr == D3DERR_NOTAVAILABLE) { - if (bVerboseMode) - wdxdisplay8_cat.info() - << "FindBestDepthFmt: ChkDevFmt returns NotAvail for " - << D3DFormatStr(TestDepthFmt) << endl; - continue; - } - - wdxdisplay8_cat.error() - << "unexpected CheckDeviceFormat failure" << D3DERRORSTRING(hr) - << endl; - exit(1); - } - - hr = Display.pD3D8->CheckDepthStencilMatch(Display.CardIDNum, - D3DDEVTYPE_HAL, - TestDisplayMode.Format, // adapter format - TestDisplayMode.Format, // backbuffer fmt (should be the same in my apps) - TestDepthFmt); - if (SUCCEEDED(hr)) { - *pBestFmt = TestDepthFmt; - break; - } else { - if (hr==D3DERR_NOTAVAILABLE) { - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "FindBestDepthFmt: ChkDepMatch returns NotAvail for " - << D3DFormatStr(TestDisplayMode.Format) << ", " - << D3DFormatStr(TestDepthFmt) << endl; - } - } else { - wdxdisplay8_cat.error() - << "unexpected CheckDepthStencilMatch failure for " - << D3DFormatStr(TestDisplayMode.Format) << ", " - << D3DFormatStr(TestDepthFmt) << endl; - exit(1); - } - } - } - - if (bVerboseMode) { - wdxdisplay8_cat.info() - << "FindBestDepthFmt returns fmt " << D3DFormatStr(*pBestFmt) << endl; - } - - return (*pBestFmt != D3DFMT_UNKNOWN); } //////////////////////////////////////////////////////////////////// @@ -1605,3 +1659,57 @@ is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID) { return false; } + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsWindow8::open_window +// Access: Protected, Virtual +// Description: Opens the window right now. Called from the window +// thread. Returns true if the window is successfully +// opened, or false if there was a problem. +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsWindow8:: +open_window(void) { + if(!choose_device()) { + return false; + } + + if (!WinGraphicsWindow::open_window()) { + return false; + } + + _wcontext.hWnd = _hWnd; + create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer); + + return true; +} + +bool wdxGraphicsWindow8:: +handle_mouse_motion(int x, int y) { + (void) WinGraphicsWindow::handle_mouse_motion(x,y); + if(dx_use_dx_cursor && is_fullscreen() && (_wcontext.pD3DDevice!=NULL)) { + _wcontext.pD3DDevice->SetCursorPosition(x,y,D3DCURSOR_IMMEDIATE_UPDATE); + // return true to indicate wind_proc should return 0 instead of going to DefaultWindowProc + return true; + } + return false; +} + +#if 0 +// does NOT override _props._bCursorIsVisible +INLINE void wdxGraphicsWindow:: +set_cursor_visibility(bool bVisible) { + if(_props._bCursorIsVisible) { + if(dx_use_dx_cursor) { + ShowCursor(false); + if(IS_VALID_PTR(_wcontext.pD3DDevice)) + _dxgsg->scrn.pD3DDevice->ShowCursor(bVisible); + } else { + ShowCursor(bVisible); + } + } else { + ShowCursor(false); + if(dx_use_dx_cursor && IS_VALID_PTR(_wcontext.pD3DDevice)) + _dxgsg->scrn.pD3DDevice->ShowCursor(false); + } +} +#endif diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.h b/panda/src/dxgsg8/wdxGraphicsWindow8.h index 815bdbb717..24bdb7865c 100644 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.h +++ b/panda/src/dxgsg8/wdxGraphicsWindow8.h @@ -16,8 +16,8 @@ // //////////////////////////////////////////////////////////////////// -#ifndef WDXGRAPHICSWINDOW8_H -#define WDXGRAPHICSWINDOW8_H +#ifndef wdxGraphicsWindow8_H +#define wdxGraphicsWindow8_H #include "pandabase.h" #include "winGraphicsWindow.h" @@ -39,16 +39,16 @@ static const int WDXWIN_EVENT = 8; //////////////////////////////////////////////////////////////////// class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow { public: - wdxGraphicsWindow8(GraphicsPipe *pipe); + wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); virtual ~wdxGraphicsWindow8(); - - virtual void make_gsg(); - virtual void release_gsg(); + virtual bool open_window(void); virtual int verify_window_sizes(int numsizes, int *dimen); virtual bool begin_frame(); virtual void end_flip(); + virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + virtual bool handle_mouse_motion(int x, int y); protected: virtual void fullscreen_restored(WindowProperties &properties); @@ -60,30 +60,26 @@ private: void create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer); - bool choose_adapter(LPDIRECT3D8 pD3D8); - bool search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info); + bool choose_device(void); + bool search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info); // void set_coop_levels_and_display_modes(); - bool special_check_fullscreen_resolution(UINT x_size,UINT y_size); - +/* void search_for_valid_displaymode(UINT RequestedX_Size, UINT RequestedY_Size, bool bWantZBuffer, bool bWantStencil, UINT *pSupportedScreenDepthsMask, bool *pCouldntFindAnyValidZBuf, D3DFORMAT *pSuggestedPixFmt, bool bVerboseMode = false); - +*/ bool reset_device_resize_window(UINT new_xsize, UINT new_ysize); void init_resized_window(); - bool find_best_depth_format(DXScreenData &Display, - D3DDISPLAYMODE &TestDisplayMode, - D3DFORMAT *pBestFmt, bool bWantStencil, - bool bForce16bpp, bool bVerboseMode = false) const; - static int D3DFMT_to_DepthBits(D3DFORMAT fmt); static bool is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID); DXGraphicsStateGuardian8 *_dxgsg; + DXScreenData _wcontext; + int _depth_buffer_bpp; bool _awaiting_restore; @@ -100,6 +96,7 @@ public: return get_class_type(); } virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + virtual void make_current(void); private: static TypeHandle _type_handle; diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 24ef6fb790..7c96f6aa44 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -198,10 +198,15 @@ open_window(const WindowProperties &props, GraphicsPipe *pipe) { wf->set_two_sided(get_two_sided()); wf->set_lighting(get_lighting()); wf->set_background_type(get_background_type()); + + GraphicsWindow *win = wf->open_window(props, &_engine, pipe); + if (win == (GraphicsWindow *)NULL) { + // Oops, couldn't make an actual window. + delete wf; + return NULL; + } + _windows.push_back(wf); - - wf->open_window(props, &_engine, pipe); - return wf; } diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index ad6b36cd5e..e297db1463 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -95,7 +95,14 @@ open_window(const WindowProperties &props, GraphicsEngine *engine, GraphicsPipe *pipe) { nassertr(_window == (GraphicsWindow *)NULL, _window); - _window = engine->make_window(pipe); + PT(GraphicsStateGuardian) gsg = engine->make_gsg(pipe); + if (gsg == (GraphicsStateGuardian *)NULL) { + // No GSG, no window. + framework_cat.fatal() << "open_window: failed to create gsg object!\n"; + return NULL; + } + + _window = engine->make_window(pipe, gsg); if (_window != (GraphicsWindow *)NULL) { _window->request_properties(props); set_background_type(_background_type); diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 9831639d19..64480ad90d 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -163,8 +163,9 @@ uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source, // Description: //////////////////////////////////////////////////////////////////// GLGraphicsStateGuardian:: -GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) { - reset(); +GLGraphicsStateGuardian(const FrameBufferProperties &properties) : + GraphicsStateGuardian(properties) +{ } //////////////////////////////////////////////////////////////////// @@ -174,9 +175,7 @@ GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) { //////////////////////////////////////////////////////////////////// GLGraphicsStateGuardian:: ~GLGraphicsStateGuardian() { - free_pointers(); - release_all_textures(); - release_all_geoms(); + close_gsg(); } //////////////////////////////////////////////////////////////////// @@ -1637,7 +1636,9 @@ release_texture(TextureContext *tc) { GLTextureContext *gtc = DCAST(GLTextureContext, tc); Texture *tex = tc->_texture; - if (!is_closed()) { + if (!_closing_gsg) { + // Don't bother to delete the GL texture if we're about to destroy + // the context anyway. glDeleteTextures(1, >c->_index); } gtc->_index = 0; @@ -1651,7 +1652,9 @@ release_texture(TextureContext *tc) { tex->clear_gsg(this); delete gtc; - report_gl_errors(); + if (!_closing_gsg) { + report_gl_errors(); + } } //////////////////////////////////////////////////////////////////// @@ -1898,6 +1901,9 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { + // This code is now invalidated by the new design; perhaps the + // interface is not needed anyway. +#if 0 nassertv(tc != NULL && pb != NULL); Texture *tex = tc->_texture; @@ -1914,6 +1920,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { pop_frame_buffer(old_fb); report_gl_errors(); +#endif } //////////////////////////////////////////////////////////////////// @@ -3000,6 +3007,9 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr, //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { + // This code is now invalidated by the new design; perhaps the + // interface is not needed anyway. +#if 0 nassertv(pb != NULL && dr != NULL); nassertv(!pb->_image.empty()); DisplayRegionStack old_dr = push_display_region(dr); @@ -3109,6 +3119,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { pop_display_region(old_dr); report_gl_errors(); +#endif } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index f09784597d..1a73eb3c96 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -63,8 +63,8 @@ INLINE ostream &operator << (ostream &out, GLenum v) { //////////////////////////////////////////////////////////////////// class EXPCL_PANDAGL GLGraphicsStateGuardian : public GraphicsStateGuardian { public: - GLGraphicsStateGuardian(GraphicsWindow *win); - ~GLGraphicsStateGuardian(); + GLGraphicsStateGuardian(const FrameBufferProperties &properties); + virtual ~GLGraphicsStateGuardian(); virtual void reset(); diff --git a/panda/src/glxdisplay/Sources.pp b/panda/src/glxdisplay/Sources.pp index 51a3580cb4..32264f9a2a 100644 --- a/panda/src/glxdisplay/Sources.pp +++ b/panda/src/glxdisplay/Sources.pp @@ -13,6 +13,8 @@ config_glxdisplay.cxx config_glxdisplay.h \ glxGraphicsPipe.I glxGraphicsPipe.cxx \ glxGraphicsPipe.h glxGraphicsWindow.I glxGraphicsWindow.cxx \ + glxGraphicsStateGuardian.h glxGraphicsStateGuardian.I \ + glxGraphicsStateGuardian.cxx \ glxGraphicsWindow.h #define INSTALL_HEADERS \ diff --git a/panda/src/glxdisplay/config_glxdisplay.cxx b/panda/src/glxdisplay/config_glxdisplay.cxx index fa898fa4f6..a4f9eef777 100644 --- a/panda/src/glxdisplay/config_glxdisplay.cxx +++ b/panda/src/glxdisplay/config_glxdisplay.cxx @@ -19,6 +19,7 @@ #include "config_glxdisplay.h" #include "glxGraphicsPipe.h" #include "glxGraphicsWindow.h" +#include "glxGraphicsStateGuardian.h" #include "graphicsPipeSelection.h" #include "dconfig.h" @@ -47,12 +48,11 @@ init_libglxdisplay() { glxGraphicsPipe::init_type(); glxGraphicsWindow::init_type(); + glxGraphicsStateGuardian::init_type(); GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); selection->add_pipe_type(glxGraphicsPipe::get_class_type(), glxGraphicsPipe::pipe_constructor); } -bool gl_show_fps_meter = config_glxdisplay.GetBool("show-fps-meter", false); -float gl_fps_meter_update_interval = max((float)0.5,config_glxdisplay.GetFloat("fps-meter-update-interval", 1.7)); const string display_cfg = config_glxdisplay.GetString("display", ""); diff --git a/panda/src/glxdisplay/config_glxdisplay.h b/panda/src/glxdisplay/config_glxdisplay.h index 5d5f67771b..1f07963290 100644 --- a/panda/src/glxdisplay/config_glxdisplay.h +++ b/panda/src/glxdisplay/config_glxdisplay.h @@ -26,8 +26,6 @@ NotifyCategoryDecl(glxdisplay, EXPCL_PANDAGL, EXPTP_PANDAGL); extern EXPCL_PANDAGL void init_libglxdisplay(); -extern bool gl_show_fps_meter; -extern float gl_fps_meter_update_interval; extern const string display_cfg; #endif /* __CONFIG_GLXDISPLAY_H__ */ diff --git a/panda/src/glxdisplay/glxGraphicsPipe.cxx b/panda/src/glxdisplay/glxGraphicsPipe.cxx index abfb044a18..22116716a9 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.cxx +++ b/panda/src/glxdisplay/glxGraphicsPipe.cxx @@ -18,7 +18,9 @@ #include "glxGraphicsPipe.h" #include "glxGraphicsWindow.h" +#include "glxGraphicsStateGuardian.h" #include "config_glxdisplay.h" +#include "frameBufferProperties.h" #include "mutexHolder.h" #include @@ -116,18 +118,363 @@ pipe_constructor() { return new glxGraphicsPipe; } +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsPipe::make_gsg +// Access: Protected, Virtual +// Description: Creates a new GSG to use the pipe (but no windows +// have been created yet for the GSG). This method will +// be called in the draw thread for the GSG. +//////////////////////////////////////////////////////////////////// +PT(GraphicsStateGuardian) glxGraphicsPipe:: +make_gsg(const FrameBufferProperties &properties) { + if (!_is_valid) { + return NULL; + } + + FrameBufferProperties new_properties = properties; + XVisualInfo *visual = choose_visual(new_properties); + + // Attempt to create a GL context. + GLXContext context = glXCreateContext(_display, visual, None, GL_TRUE); + if (context == NULL) { + glxdisplay_cat.error() + << "Could not create GL context.\n"; + XFree(visual); + return NULL; + } + + // Now we can make a GSG. + PT(glxGraphicsStateGuardian) gsg = + new glxGraphicsStateGuardian(new_properties); + gsg->_context = context; + gsg->_visual = visual; + gsg->_display = _display; + + return gsg.p(); +} + //////////////////////////////////////////////////////////////////// // Function: glxGraphicsPipe::make_window // Access: Protected, Virtual // Description: Creates a new window on the pipe, if possible. //////////////////////////////////////////////////////////////////// PT(GraphicsWindow) glxGraphicsPipe:: -make_window() { +make_window(GraphicsStateGuardian *gsg) { if (!_is_valid) { return NULL; } - return new glxGraphicsWindow(this); + return new glxGraphicsWindow(this, gsg); +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsPipe::choose visual +// Access: Private +// Description: Selects an appropriate X visual for the given frame +// buffer properties. Returns the visual pointer if +// successful, or NULL otherwise. +// +// If successful, this may modify properties to reflect +// the actual visual chosen. +//////////////////////////////////////////////////////////////////// +XVisualInfo *glxGraphicsPipe:: +choose_visual(FrameBufferProperties &properties) const { + int frame_buffer_mode = 0; + int want_depth_bits = 0; + int want_color_bits = 0; + + if (properties.has_frame_buffer_mode()) { + frame_buffer_mode = properties.get_frame_buffer_mode(); + } + + if (properties.has_depth_bits()) { + want_depth_bits = properties.get_depth_bits(); + } + + if (properties.has_color_bits()) { + want_color_bits = properties.get_color_bits(); + } + + /* + if (frame_buffer_mode & FrameBufferProperties::FM_multisample) { + if (!glx_supports("GLX_SGIS_multisample")) { + glxdisplay_cat.info() + << "multisample not supported by this glx implementation.\n"; + frame_buffer_mode &= ~FrameBufferProperties::FM_multisample; + } + } + */ + + XVisualInfo *visual = + try_for_visual(frame_buffer_mode, want_depth_bits, want_color_bits); + + // This is the severity level at which we'll report the details of + // the visual we actually do find. Normally, it's debug-level + // information: we don't care about that much detail. + NotifySeverity show_visual_severity = NS_debug; + + if (visual == NULL) { + glxdisplay_cat.info() + << "glxGraphicsWindow::choose_visual() - visual with requested\n" + << " capabilities not found; trying for lesser visual.\n"; + + // If we're unable to get the visual we asked for, however, we + // probably *do* care to know the details about what we actually + // got, even if we don't have debug mode set. So we'll report the + // visual at a higher level. + show_visual_severity = NS_info; + + bool special_size_request = + (want_depth_bits != 1 || want_color_bits != 1); + + // We try to be smart about choosing a close match for the visual. + // First, we'll eliminate some of the more esoteric options one at + // a time, then two at a time, and finally we'll try just the bare + // minimum. + + if (special_size_request) { + // Actually, first we'll eliminate all of the minimum sizes, to + // try to open a window with all of the requested options, but + // maybe not as many bits in some options as we'd like. + visual = try_for_visual(frame_buffer_mode, 1, 1); + } + + if (visual == NULL) { + // Ok, not good enough. Now try to eliminate options, but keep + // as many bits as we asked for. + + // This array keeps the bitmasks of options that we pull out of + // the requested frame_buffer_mode, in order. + + static const int strip_properties[] = { + // One esoteric option removed. + FrameBufferProperties::FM_multisample, + FrameBufferProperties::FM_stencil, + FrameBufferProperties::FM_accum, + FrameBufferProperties::FM_alpha, + FrameBufferProperties::FM_stereo, + + // Two esoteric options removed. + FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_multisample, + FrameBufferProperties::FM_accum | FrameBufferProperties::FM_multisample, + FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_multisample, + FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample, + FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum, + FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo, + FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_multisample, + FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample, + + // All esoteric options removed. + FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample, + + // All esoteric options, plus some we'd really really prefer, + // removed. + FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample | FrameBufferProperties::FM_double_buffer, + + // A zero marks the end of the array. + 0 + }; + + pset tried_masks; + tried_masks.insert(frame_buffer_mode); + + int i; + for (i = 0; visual == NULL && strip_properties[i] != 0; i++) { + int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i]; + if (tried_masks.insert(new_frame_buffer_mode).second) { + visual = try_for_visual(new_frame_buffer_mode, want_depth_bits, + want_color_bits); + } + } + + if (special_size_request) { + tried_masks.clear(); + tried_masks.insert(frame_buffer_mode); + + if (visual == NULL) { + // Try once more, this time eliminating all of the size + // requests. + for (i = 0; visual == NULL && strip_properties[i] != 0; i++) { + int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i]; + if (tried_masks.insert(new_frame_buffer_mode).second) { + visual = try_for_visual(new_frame_buffer_mode, 1, 1); + } + } + } + } + + if (visual == NULL) { + // Here's our last-ditch desparation attempt: give us any GLX + // visual at all! + visual = try_for_visual(0, 1, 1); + } + + if (visual == NULL) { + glxdisplay_cat.error() + << "Could not get any GLX visual.\n"; + return NULL; + } + } + } + + glxdisplay_cat.info() + << "Got visual 0x" << hex << (int)visual->visualid << dec << ".\n"; + + // Now update our frambuffer_mode and bit depth appropriately. + int render_mode, double_buffer, stereo, red_size, green_size, blue_size, + alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, + depth_size, stencil_size; + + glXGetConfig(_display, visual, GLX_RGBA, &render_mode); + glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer); + glXGetConfig(_display, visual, GLX_STEREO, &stereo); + glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size); + glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size); + glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size); + glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size); + glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size); + glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size); + glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size); + glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size); + glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size); + glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size); + + frame_buffer_mode = 0; + if (double_buffer) { + frame_buffer_mode |= FrameBufferProperties::FM_double_buffer; + } + if (stereo) { + frame_buffer_mode |= FrameBufferProperties::FM_stereo; + } + if (!render_mode) { + frame_buffer_mode |= FrameBufferProperties::FM_index; + } + if (stencil_size != 0) { + frame_buffer_mode |= FrameBufferProperties::FM_stencil; + } + if (depth_size != 0) { + frame_buffer_mode |= FrameBufferProperties::FM_depth; + } + if (alpha_size != 0) { + frame_buffer_mode |= FrameBufferProperties::FM_alpha; + } + if (ared_size + agreen_size + ablue_size != 0) { + frame_buffer_mode |= FrameBufferProperties::FM_accum; + } + + properties.set_frame_buffer_mode(frame_buffer_mode); + properties.set_color_bits(red_size + green_size + blue_size + alpha_size); + properties.set_depth_bits(depth_size); + + if (glxdisplay_cat.is_on(show_visual_severity)) { + glxdisplay_cat.out(show_visual_severity) + << "GLX Visual Info (# bits of each):" << endl + << " RGBA: " << red_size << " " << green_size << " " << blue_size + << " " << alpha_size << endl + << " Accum RGBA: " << ared_size << " " << agreen_size << " " + << ablue_size << " " << aalpha_size << endl + << " Depth: " << depth_size << endl + << " Stencil: " << stencil_size << endl + << " DoubleBuffer? " << double_buffer << endl + << " Stereo? " << stereo << endl; + } + + return visual; +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsPipe::try_for_visual +// Access: Private +// Description: Attempt to get the requested visual, if it is +// available. It's just a wrapper around +// glXChooseVisual(). It returns the visual information +// if possible, or NULL if it is not. +//////////////////////////////////////////////////////////////////// +XVisualInfo *glxGraphicsPipe:: +try_for_visual(int framebuffer_mode, + int want_depth_bits, int want_color_bits) const { + static const int max_attrib_list = 32; + int attrib_list[max_attrib_list]; + int n=0; + + glxdisplay_cat.debug() + << "Trying for visual with: RGB(" << want_color_bits << ")"; + + int want_color_component_bits; + if (framebuffer_mode & FrameBufferProperties::FM_alpha) { + want_color_component_bits = max(want_color_bits / 4, 1); + } else { + want_color_component_bits = max(want_color_bits / 3, 1); + } + + attrib_list[n++] = GLX_RGBA; + attrib_list[n++] = GLX_RED_SIZE; + attrib_list[n++] = want_color_component_bits; + attrib_list[n++] = GLX_GREEN_SIZE; + attrib_list[n++] = want_color_component_bits; + attrib_list[n++] = GLX_BLUE_SIZE; + attrib_list[n++] = want_color_component_bits; + + if (framebuffer_mode & FrameBufferProperties::FM_alpha) { + glxdisplay_cat.debug(false) << " ALPHA"; + attrib_list[n++] = GLX_ALPHA_SIZE; + attrib_list[n++] = want_color_component_bits; + } + if (framebuffer_mode & FrameBufferProperties::FM_double_buffer) { + glxdisplay_cat.debug(false) << " DOUBLEBUFFER"; + attrib_list[n++] = GLX_DOUBLEBUFFER; + } + if (framebuffer_mode & FrameBufferProperties::FM_stereo) { + glxdisplay_cat.debug(false) << " STEREO"; + attrib_list[n++] = GLX_STEREO; + } + if (framebuffer_mode & FrameBufferProperties::FM_depth) { + glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")"; + attrib_list[n++] = GLX_DEPTH_SIZE; + attrib_list[n++] = want_depth_bits; + } + if (framebuffer_mode & FrameBufferProperties::FM_stencil) { + glxdisplay_cat.debug(false) << " STENCIL"; + attrib_list[n++] = GLX_STENCIL_SIZE; + attrib_list[n++] = 1; + } + if (framebuffer_mode & FrameBufferProperties::FM_accum) { + glxdisplay_cat.debug(false) << " ACCUM"; + attrib_list[n++] = GLX_ACCUM_RED_SIZE; + attrib_list[n++] = want_color_component_bits; + attrib_list[n++] = GLX_ACCUM_GREEN_SIZE; + attrib_list[n++] = want_color_component_bits; + attrib_list[n++] = GLX_ACCUM_BLUE_SIZE; + attrib_list[n++] = want_color_component_bits; + if (framebuffer_mode & FrameBufferProperties::FM_alpha) { + attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE; + attrib_list[n++] = want_color_component_bits; + } + } +#if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) + if (framebuffer_mode & FrameBufferProperties::FM_multisample) { + glxdisplay_cat.debug(false) << " MULTISAMPLE"; + attrib_list[n++] = GLX_SAMPLES_SGIS; + // We decide 4 is minimum number of samples + attrib_list[n++] = 4; + } +#endif + + // Terminate the list + nassertr(n < max_attrib_list, NULL); + attrib_list[n] = (int)None; + + XVisualInfo *vinfo = glXChooseVisual(_display, _screen, attrib_list); + + if (glxdisplay_cat.is_debug()) { + if (vinfo != NULL) { + glxdisplay_cat.debug(false) << ", match found!\n"; + } else { + glxdisplay_cat.debug(false) << ", no match.\n"; + } + } + + return vinfo; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glxdisplay/glxGraphicsPipe.h b/panda/src/glxdisplay/glxGraphicsPipe.h index 173667c509..e4a3c6a05e 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.h +++ b/panda/src/glxdisplay/glxGraphicsPipe.h @@ -22,17 +22,20 @@ #include "pandabase.h" #include "graphicsPipe.h" -#include - class glxGraphicsWindow; +class FrameBufferProperties; #ifdef CPPPARSER // A simple hack so interrogate can parse this file. typedef int Display; typedef int Window; typedef int XErrorEvent; +typedef int XVisualInfo; typedef int Atom; -#endif +#else +#include +#include +#endif // CPPPARSER //////////////////////////////////////////////////////////////////// // Class : glxGraphicsPipe @@ -55,9 +58,14 @@ public: INLINE Atom get_wm_delete_window() const; protected: - virtual PT(GraphicsWindow) make_window(); + virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties); + virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg); private: + XVisualInfo *choose_visual(FrameBufferProperties &properties) const; + XVisualInfo *try_for_visual(int framebuffer_mode, + int want_depth_bits, int want_color_bits) const; + static void install_error_handlers(); static int error_handler(Display *display, XErrorEvent *error); static int io_error_handler(Display *display); diff --git a/panda/src/glxdisplay/glxGraphicsWindow.cxx b/panda/src/glxdisplay/glxGraphicsWindow.cxx index c07212fd07..4089652afe 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.cxx +++ b/panda/src/glxdisplay/glxGraphicsWindow.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "glxGraphicsWindow.h" +#include "glxGraphicsStateGuardian.h" #include "config_glxdisplay.h" #include "glxGraphicsPipe.h" @@ -39,16 +40,14 @@ TypeHandle glxGraphicsWindow::_type_handle; // Description: //////////////////////////////////////////////////////////////////// glxGraphicsWindow:: -glxGraphicsWindow(GraphicsPipe *pipe) : - GraphicsWindow(pipe) +glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) : + GraphicsWindow(pipe, gsg) { glxGraphicsPipe *glx_pipe; DCAST_INTO_V(glx_pipe, _pipe); _display = glx_pipe->get_display(); _screen = glx_pipe->get_screen(); - _xwindow = (Window)0; - _context = (GLXContext)0; - _visual = (XVisualInfo *)NULL; + _xwindow = (Window)NULL; _awaiting_configure = false; _wm_delete_window = glx_pipe->get_wm_delete_window(); @@ -66,49 +65,6 @@ glxGraphicsWindow:: ~glxGraphicsWindow() { } -//////////////////////////////////////////////////////////////////// -// Function: glxGraphicsWindow::make_gsg -// Access: Public, Virtual -// Description: Creates a new GSG for the window and stores it in the -// _gsg pointer. This should only be called from within -// the draw thread. -//////////////////////////////////////////////////////////////////// -void glxGraphicsWindow:: -make_gsg() { - nassertv(_gsg == (GraphicsStateGuardian *)NULL); - - // First, we need to create the rendering context. - _context = glXCreateContext(_display, _visual, None, GL_TRUE); - if (!_context) { - glxdisplay_cat.error() - << "Could not create GLX context.\n"; - return; - } - - // And make sure the new context is current. - glXMakeCurrent(_display, _xwindow, _context); - - // Now we can make a GSG. - _gsg = new GLGraphicsStateGuardian(this); -} - -//////////////////////////////////////////////////////////////////// -// Function: glxGraphicsWindow::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. This should only -// be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void glxGraphicsWindow:: -release_gsg() { - if (_gsg != (GraphicsStateGuardian *)NULL) { - glXMakeCurrent(_display, _xwindow, _context); - GraphicsWindow::release_gsg(); - glXDestroyContext(_display, _context); - _context = (GLXContext)0; - } -} - //////////////////////////////////////////////////////////////////// // Function: glxGraphicsWindow::make_current // Access: Public, Virtual @@ -118,8 +74,30 @@ release_gsg() { //////////////////////////////////////////////////////////////////// void glxGraphicsWindow:: make_current() { - nassertv(_gsg != (GraphicsStateGuardian *)NULL); - glXMakeCurrent(_display, _xwindow, _context); + glxGraphicsStateGuardian *glxgsg; + DCAST_INTO_V(glxgsg, _gsg); + glXMakeCurrent(_display, _xwindow, glxgsg->_context); + + // Now that we have made the context current to a window, we can + // reset the GSG state if this is the first time it has been used. + // (We can't just call reset() when we construct the GSG, because + // reset() requires having a current context.) + glxgsg->reset_if_new(); +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsWindow::release_gsg +// Access: Public +// Description: Releases the current GSG pointer, if it is currently +// held, and resets the GSG to NULL. The window will be +// permanently unable to render; this is normally called +// only just before destroying the window. This should +// only be called from within the draw thread. +//////////////////////////////////////////////////////////////////// +void glxGraphicsWindow:: +release_gsg() { + glXMakeCurrent(_display, None, NULL); + GraphicsWindow::release_gsg(); } //////////////////////////////////////////////////////////////////// @@ -159,7 +137,7 @@ begin_frame() { void glxGraphicsWindow:: begin_flip() { if (_gsg != (GraphicsStateGuardian *)NULL) { - glXMakeCurrent(_display, _xwindow, _context); + make_current(); glXSwapBuffers(_display, _xwindow); } } @@ -371,7 +349,7 @@ set_properties_now(WindowProperties &properties) { //////////////////////////////////////////////////////////////////// void glxGraphicsWindow:: close_window() { - if (_xwindow != (Window)0) { + if (_xwindow != (Window)NULL) { XDestroyWindow(_display, _xwindow); _xwindow = (Window)0; @@ -404,12 +382,12 @@ open_window() { glxGraphicsPipe *glx_pipe; DCAST_INTO_R(glx_pipe, _pipe, false); + glxGraphicsStateGuardian *glxgsg; + DCAST_INTO_R(glxgsg, _gsg, false); + Window root_window = glx_pipe->get_root(); - if (!choose_visual()) { - return false; - } - setup_colormap(); + setup_colormap(glxgsg->_visual); _event_mask = ButtonPressMask | ButtonReleaseMask | @@ -434,7 +412,7 @@ open_window() { _properties.get_x_origin(), _properties.get_y_origin(), _properties.get_x_size(), _properties.get_y_size(), 0, - _visual->depth, InputOutput, _visual->visual, + glxgsg->_visual->depth, InputOutput, glxgsg->_visual->visual, attrib_mask, &wa); if (_xwindow == (Window)0) { @@ -538,315 +516,6 @@ set_wm_properties(const WindowProperties &properties) { sizeof(protocols) / sizeof(Atom)); } -//////////////////////////////////////////////////////////////////// -// Function: glxGraphicsWindow::try_for_visual -// Access: Private -// Description: Attempt to get the requested visual, if it is -// available. It's just a wrapper around -// glXChooseVisual(). It returns the visual information -// if possible, or NULL if it is not. -//////////////////////////////////////////////////////////////////// -XVisualInfo *glxGraphicsWindow:: -try_for_visual(int framebuffer_mode, - int want_depth_bits, int want_color_bits) const { - static const int max_attrib_list = 32; - int attrib_list[max_attrib_list]; - int n=0; - - glxdisplay_cat.debug() - << "Trying for visual with: RGB(" << want_color_bits << ")"; - - int want_color_component_bits; - if (framebuffer_mode & WindowProperties::FM_alpha) { - want_color_component_bits = max(want_color_bits / 4, 1); - } else { - want_color_component_bits = max(want_color_bits / 3, 1); - } - - attrib_list[n++] = GLX_RGBA; - attrib_list[n++] = GLX_RED_SIZE; - attrib_list[n++] = want_color_component_bits; - attrib_list[n++] = GLX_GREEN_SIZE; - attrib_list[n++] = want_color_component_bits; - attrib_list[n++] = GLX_BLUE_SIZE; - attrib_list[n++] = want_color_component_bits; - - if (framebuffer_mode & WindowProperties::FM_alpha) { - glxdisplay_cat.debug(false) << " ALPHA"; - attrib_list[n++] = GLX_ALPHA_SIZE; - attrib_list[n++] = want_color_component_bits; - } - if (framebuffer_mode & WindowProperties::FM_double_buffer) { - glxdisplay_cat.debug(false) << " DOUBLEBUFFER"; - attrib_list[n++] = GLX_DOUBLEBUFFER; - } - if (framebuffer_mode & WindowProperties::FM_stereo) { - glxdisplay_cat.debug(false) << " STEREO"; - attrib_list[n++] = GLX_STEREO; - } - if (framebuffer_mode & WindowProperties::FM_depth) { - glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")"; - attrib_list[n++] = GLX_DEPTH_SIZE; - attrib_list[n++] = want_depth_bits; - } - if (framebuffer_mode & WindowProperties::FM_stencil) { - glxdisplay_cat.debug(false) << " STENCIL"; - attrib_list[n++] = GLX_STENCIL_SIZE; - attrib_list[n++] = 1; - } - if (framebuffer_mode & WindowProperties::FM_accum) { - glxdisplay_cat.debug(false) << " ACCUM"; - attrib_list[n++] = GLX_ACCUM_RED_SIZE; - attrib_list[n++] = want_color_component_bits; - attrib_list[n++] = GLX_ACCUM_GREEN_SIZE; - attrib_list[n++] = want_color_component_bits; - attrib_list[n++] = GLX_ACCUM_BLUE_SIZE; - attrib_list[n++] = want_color_component_bits; - if (framebuffer_mode & WindowProperties::FM_alpha) { - attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE; - attrib_list[n++] = want_color_component_bits; - } - } -#if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) - if (framebuffer_mode & WindowProperties::FM_multisample) { - glxdisplay_cat.debug(false) << " MULTISAMPLE"; - attrib_list[n++] = GLX_SAMPLES_SGIS; - // We decide 4 is minimum number of samples - attrib_list[n++] = 4; - } -#endif - - // Terminate the list - nassertr(n < max_attrib_list, NULL); - attrib_list[n] = (int)None; - - XVisualInfo *vinfo = glXChooseVisual(_display, _screen, attrib_list); - - if (glxdisplay_cat.is_debug()) { - if (vinfo != NULL) { - glxdisplay_cat.debug(false) << ", match found!\n"; - } else { - glxdisplay_cat.debug(false) << ", no match.\n"; - } - } - - return vinfo; -} - -//////////////////////////////////////////////////////////////////// -// Function: glxGraphicsWindow::choose visual -// Access: Private -// Description: Selects an appropriate X visual for the window based -// on the window properties. Returns true if -// successful, false otherwise. -// -// Initializes _visual, and modifies _properties -// according to the actual visual chosen. -//////////////////////////////////////////////////////////////////// -bool glxGraphicsWindow:: -choose_visual() { - int framebuffer_mode = 0; - int want_depth_bits = 0; - int want_color_bits = 0; - - if (_properties.has_framebuffer_mode()) { - framebuffer_mode = _properties.get_framebuffer_mode(); - } - - if (_properties.has_depth_bits()) { - want_depth_bits = _properties.get_depth_bits(); - } - - if (_properties.has_color_bits()) { - want_color_bits = _properties.get_color_bits(); - } - - /* - if (framebuffer_mode & WindowProperties::FM_multisample) { - if (!glx_supports("GLX_SGIS_multisample")) { - glxdisplay_cat.info() - << "multisample not supported by this glx implementation.\n"; - framebuffer_mode &= ~WindowProperties::FM_multisample; - } - } - */ - - _visual = try_for_visual(framebuffer_mode, want_depth_bits, want_color_bits); - - // This is the severity level at which we'll report the details of - // the visual we actually do find. Normally, it's debug-level - // information: we don't care about that much detail. - NotifySeverity show_visual_severity = NS_debug; - - if (_visual == NULL) { - glxdisplay_cat.info() - << "glxGraphicsWindow::choose_visual() - visual with requested\n" - << " capabilities not found; trying for lesser visual.\n"; - - // If we're unable to get the visual we asked for, however, we - // probably *do* care to know the details about what we actually - // got, even if we don't have debug mode set. So we'll report the - // visual at a higher level. - show_visual_severity = NS_info; - - bool special_size_request = - (want_depth_bits != 1 || want_color_bits != 1); - - // We try to be smart about choosing a close match for the visual. - // First, we'll eliminate some of the more esoteric options one at - // a time, then two at a time, and finally we'll try just the bare - // minimum. - - if (special_size_request) { - // Actually, first we'll eliminate all of the minimum sizes, to - // try to open a window with all of the requested options, but - // maybe not as many bits in some options as we'd like. - _visual = try_for_visual(framebuffer_mode, 1, 1); - } - - if (_visual == NULL) { - // Ok, not good enough. Now try to eliminate options, but keep - // as many bits as we asked for. - - // This array keeps the bitmasks of options that we pull out of - // the requested framebuffer_mode, in order. - - static const int strip_properties[] = { - // One esoteric option removed. - WindowProperties::FM_multisample, - WindowProperties::FM_stencil, - WindowProperties::FM_accum, - WindowProperties::FM_alpha, - WindowProperties::FM_stereo, - - // Two esoteric options removed. - WindowProperties::FM_stencil | WindowProperties::FM_multisample, - WindowProperties::FM_accum | WindowProperties::FM_multisample, - WindowProperties::FM_alpha | WindowProperties::FM_multisample, - WindowProperties::FM_stereo | WindowProperties::FM_multisample, - WindowProperties::FM_stencil | WindowProperties::FM_accum, - WindowProperties::FM_alpha | WindowProperties::FM_stereo, - WindowProperties::FM_stencil | WindowProperties::FM_accum | WindowProperties::FM_multisample, - WindowProperties::FM_alpha | WindowProperties::FM_stereo | WindowProperties::FM_multisample, - - // All esoteric options removed. - WindowProperties::FM_stencil | WindowProperties::FM_accum | WindowProperties::FM_alpha | WindowProperties::FM_stereo | WindowProperties::FM_multisample, - - // All esoteric options, plus some we'd really really prefer, - // removed. - WindowProperties::FM_stencil | WindowProperties::FM_accum | WindowProperties::FM_alpha | WindowProperties::FM_stereo | WindowProperties::FM_multisample | WindowProperties::FM_double_buffer, - - // A zero marks the end of the array. - 0 - }; - - pset tried_masks; - tried_masks.insert(framebuffer_mode); - - int i; - for (i = 0; _visual == NULL && strip_properties[i] != 0; i++) { - int new_framebuffer_mode = framebuffer_mode & ~strip_properties[i]; - if (tried_masks.insert(new_framebuffer_mode).second) { - _visual = try_for_visual(new_framebuffer_mode, want_depth_bits, - want_color_bits); - } - } - - if (special_size_request) { - tried_masks.clear(); - tried_masks.insert(framebuffer_mode); - - if (_visual == NULL) { - // Try once more, this time eliminating all of the size - // requests. - for (i = 0; _visual == NULL && strip_properties[i] != 0; i++) { - int new_framebuffer_mode = framebuffer_mode & ~strip_properties[i]; - if (tried_masks.insert(new_framebuffer_mode).second) { - _visual = try_for_visual(new_framebuffer_mode, 1, 1); - } - } - } - } - - if (_visual == NULL) { - // Here's our last-ditch desparation attempt: give us any GLX - // visual at all! - _visual = try_for_visual(0, 1, 1); - } - - if (_visual == NULL) { - glxdisplay_cat.error() - << "Could not get any GLX visual.\n"; - return false; - } - } - } - - glxdisplay_cat.info() - << "Got visual 0x" << hex << (int)_visual->visualid << dec << ".\n"; - - // Now update our frambuffer_mode and bit depth appropriately. - int render_mode, double_buffer, stereo, red_size, green_size, blue_size, - alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, - depth_size, stencil_size; - - glXGetConfig(_display, _visual, GLX_RGBA, &render_mode); - glXGetConfig(_display, _visual, GLX_DOUBLEBUFFER, &double_buffer); - glXGetConfig(_display, _visual, GLX_STEREO, &stereo); - glXGetConfig(_display, _visual, GLX_RED_SIZE, &red_size); - glXGetConfig(_display, _visual, GLX_GREEN_SIZE, &green_size); - glXGetConfig(_display, _visual, GLX_BLUE_SIZE, &blue_size); - glXGetConfig(_display, _visual, GLX_ALPHA_SIZE, &alpha_size); - glXGetConfig(_display, _visual, GLX_ACCUM_RED_SIZE, &ared_size); - glXGetConfig(_display, _visual, GLX_ACCUM_GREEN_SIZE, &agreen_size); - glXGetConfig(_display, _visual, GLX_ACCUM_BLUE_SIZE, &ablue_size); - glXGetConfig(_display, _visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size); - glXGetConfig(_display, _visual, GLX_DEPTH_SIZE, &depth_size); - glXGetConfig(_display, _visual, GLX_STENCIL_SIZE, &stencil_size); - - framebuffer_mode = 0; - if (double_buffer) { - framebuffer_mode |= WindowProperties::FM_double_buffer; - } - if (stereo) { - framebuffer_mode |= WindowProperties::FM_stereo; - } - if (!render_mode) { - framebuffer_mode |= WindowProperties::FM_index; - } - if (stencil_size != 0) { - framebuffer_mode |= WindowProperties::FM_stencil; - } - if (depth_size != 0) { - framebuffer_mode |= WindowProperties::FM_depth; - } - if (alpha_size != 0) { - framebuffer_mode |= WindowProperties::FM_alpha; - } - if (ared_size + agreen_size + ablue_size != 0) { - framebuffer_mode |= WindowProperties::FM_accum; - } - - _properties.set_framebuffer_mode(framebuffer_mode); - _properties.set_color_bits(red_size + green_size + blue_size + alpha_size); - _properties.set_depth_bits(depth_size); - - if (glxdisplay_cat.is_on(show_visual_severity)) { - glxdisplay_cat.out(show_visual_severity) - << "GLX Visual Info (# bits of each):" << endl - << " RGBA: " << red_size << " " << green_size << " " << blue_size - << " " << alpha_size << endl - << " Accum RGBA: " << ared_size << " " << agreen_size << " " - << ablue_size << " " << aalpha_size << endl - << " Depth: " << depth_size << endl - << " Stencil: " << stencil_size << endl - << " DoubleBuffer? " << double_buffer << endl - << " Stereo? " << stereo << endl; - } - - return true; -} - //////////////////////////////////////////////////////////////////// // Function: glxGraphicsWindow::setup_colormap // Access: Private @@ -854,17 +523,17 @@ choose_visual() { // stores in in the _colormap method. //////////////////////////////////////////////////////////////////// void glxGraphicsWindow:: -setup_colormap() { +setup_colormap(XVisualInfo *visual) { glxGraphicsPipe *glx_pipe; DCAST_INTO_V(glx_pipe, _pipe); Window root_window = glx_pipe->get_root(); - int visual_class = _visual->c_class; + int visual_class = visual->c_class; int rc, is_rgb; switch (visual_class) { case PseudoColor: - rc = glXGetConfig(_display, _visual, GLX_RGBA, &is_rgb); + rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb); if (rc == 0 && is_rgb) { glxdisplay_cat.warning() << "mesa pseudocolor not supported.\n"; @@ -873,19 +542,19 @@ setup_colormap() { } else { _colormap = XCreateColormap(_display, root_window, - _visual->visual, AllocAll); + visual->visual, AllocAll); } break; case TrueColor: case DirectColor: _colormap = XCreateColormap(_display, root_window, - _visual->visual, AllocNone); + visual->visual, AllocNone); break; case StaticColor: case StaticGray: case GrayScale: _colormap = XCreateColormap(_display, root_window, - _visual->visual, AllocNone); + visual->visual, AllocNone); break; default: glxdisplay_cat.error() diff --git a/panda/src/glxdisplay/glxGraphicsWindow.h b/panda/src/glxdisplay/glxGraphicsWindow.h index 5ebd437e04..bdf5ba9cee 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.h +++ b/panda/src/glxdisplay/glxGraphicsWindow.h @@ -36,12 +36,11 @@ class glxGraphicsPipe; //////////////////////////////////////////////////////////////////// class glxGraphicsWindow : public GraphicsWindow { public: - glxGraphicsWindow(GraphicsPipe *pipe); + glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); virtual ~glxGraphicsWindow(); - virtual void make_gsg(); - virtual void release_gsg(); virtual void make_current(); + virtual void release_gsg(); virtual bool begin_frame(); virtual void begin_flip(); @@ -56,10 +55,7 @@ protected: private: void set_wm_properties(const WindowProperties &properties); - XVisualInfo *try_for_visual(int framebuffer_mode, - int want_depth_bits, int want_color_bits) const; - bool choose_visual(); - void setup_colormap(); + void setup_colormap(XVisualInfo *visual); ButtonHandle get_button(XKeyEvent *key_event); static Bool check_event(Display *display, XEvent *event, char *arg); @@ -68,8 +64,6 @@ private: Display *_display; int _screen; Window _xwindow; - GLXContext _context; - XVisualInfo *_visual; Colormap _colormap; long _event_mask; bool _awaiting_configure; diff --git a/panda/src/wgldisplay/Sources.pp b/panda/src/wgldisplay/Sources.pp index bf9a3b2e1c..0d53314ee6 100644 --- a/panda/src/wgldisplay/Sources.pp +++ b/panda/src/wgldisplay/Sources.pp @@ -15,11 +15,15 @@ #define INSTALL_HEADERS \ config_wgldisplay.h \ wglGraphicsPipe.I wglGraphicsPipe.h \ + wglGraphicsStateGuardian.I wglGraphicsStateGuardian.h \ wglGraphicsWindow.I wglGraphicsWindow.h // Win32Defs.h #define INCLUDED_SOURCES \ - config_wgldisplay.cxx wglGraphicsPipe.cxx wglGraphicsWindow.cxx + config_wgldisplay.cxx \ + wglGraphicsPipe.cxx \ + wglGraphicsStateGuardian.cxx \ + wglGraphicsWindow.cxx #define SOURCES \ $[INSTALL_HEADERS] diff --git a/panda/src/wgldisplay/config_wgldisplay.cxx b/panda/src/wgldisplay/config_wgldisplay.cxx index 7ecfa3005f..951b718597 100644 --- a/panda/src/wgldisplay/config_wgldisplay.cxx +++ b/panda/src/wgldisplay/config_wgldisplay.cxx @@ -18,6 +18,7 @@ #include "config_wgldisplay.h" #include "wglGraphicsPipe.h" +#include "wglGraphicsStateGuardian.h" #include "wglGraphicsWindow.h" #include "graphicsPipeSelection.h" #include "dconfig.h" @@ -46,6 +47,7 @@ init_libwgldisplay() { initialized = true; wglGraphicsPipe::init_type(); + wglGraphicsStateGuardian::init_type(); wglGraphicsWindow::init_type(); GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); diff --git a/panda/src/wgldisplay/wglGraphicsPipe.cxx b/panda/src/wgldisplay/wglGraphicsPipe.cxx index 504f4734e9..0cdfc120c1 100644 --- a/panda/src/wgldisplay/wglGraphicsPipe.cxx +++ b/panda/src/wgldisplay/wglGraphicsPipe.cxx @@ -18,6 +18,10 @@ #include "wglGraphicsPipe.h" #include "config_wgldisplay.h" +#include "config_windisplay.h" + +typedef enum {Software, MCD, ICD} OGLDriverType; +static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" }; TypeHandle wglGraphicsPipe::_type_handle; @@ -66,12 +70,241 @@ pipe_constructor() { return new wglGraphicsPipe; } +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsPipe::make_gsg +// Access: Protected, Virtual +// Description: Creates a new GSG to use the pipe (but no windows +// have been created yet for the GSG). This method will +// be called in the draw thread for the GSG. +//////////////////////////////////////////////////////////////////// +PT(GraphicsStateGuardian) wglGraphicsPipe:: +make_gsg(const FrameBufferProperties &properties) { + if (!_is_valid) { + return NULL; + } + + FrameBufferProperties new_properties = properties; + + // Get a handle to the screen's DC so we can choose a pixel format + // (and a corresponding set of frame buffer properties) suitable for + // rendering to windows on this screen. + HDC hdc = GetDC(NULL); + int pfnum = choose_pfnum(new_properties, hdc); + + if (gl_force_pixfmt != 0) { + wgldisplay_cat.info() + << "overriding pixfmt choice algorithm (" << pfnum + << ") with gl-force-pixfmt(" << gl_force_pixfmt << ")\n"; + pfnum = gl_force_pixfmt; + } + + if (wgldisplay_cat.is_debug()) { + wgldisplay_cat.debug() + << "config() - picking pixfmt #" << pfnum <debug() + << "----------------" << endl; + + if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0) { + wgldisplay_cat->debug() + << "want alpha, pfd says '" + << (int)(pfd.cAlphaBits) << "'" << endl; + } + if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0) { + wgldisplay_cat->debug() + << "want depth, pfd says '" + << (int)(pfd.cDepthBits) << "'" << endl; + } + if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0) { + wgldisplay_cat->debug() + << "want stencil, pfd says '" + << (int)(pfd.cStencilBits) << "'" << endl; + } + wgldisplay_cat->debug() + << "final flag check " << (int)(pfd.dwFlags & dwReqFlags) << " =? " + << (int)dwReqFlags << endl; + wgldisplay_cat->debug() + << "pfd bits = " << (int)(pfd.cColorBits) << endl; + wgldisplay_cat->debug() + << "cur_bpp = " << cur_bpp << endl; + } + + if ((frame_buffer_mode & FrameBufferProperties::FM_double_buffer) != 0) { + dwReqFlags|= PFD_DOUBLEBUFFER; + } + if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0 && + (pfd.cAlphaBits==0)) { + continue; + } + if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0 && + (pfd.cDepthBits==0)) { + continue; + } + if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0 && + (pfd.cStencilBits==0)) { + continue; + } + + if ((pfd.dwFlags & dwReqFlags) != dwReqFlags) { + continue; + } + + // now we ignore the specified want_color_bits for windowed mode + // instead we use the current screen depth + + if ((pfd.cColorBits!=cur_bpp) && + (!((cur_bpp==16) && (pfd.cColorBits==15))) && + (!((cur_bpp==32) && (pfd.cColorBits==24)))) { + continue; + } + + // We've passed all the tests, go ahead and pick this fmt. + // Note: could go continue looping looking for more alpha bits or + // more depth bits so this would pick 16bpp depth buffer, probably + // not 24bpp + break; + } + + if (pfnum > MaxPixFmtNum) { + pfnum = 0; + } + + return pfnum; } diff --git a/panda/src/wgldisplay/wglGraphicsPipe.h b/panda/src/wgldisplay/wglGraphicsPipe.h index 5b7a9c9279..93db70d6f6 100644 --- a/panda/src/wgldisplay/wglGraphicsPipe.h +++ b/panda/src/wgldisplay/wglGraphicsPipe.h @@ -37,7 +37,13 @@ public: static PT(GraphicsPipe) pipe_constructor(); protected: - virtual PT(GraphicsWindow) make_window(); + virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties); + virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg); + +private: + int choose_pfnum(FrameBufferProperties &properties, HDC hdc) const; + int find_pixfmtnum(FrameBufferProperties &properties, HDC hdc, + bool bLookforHW) const; public: static TypeHandle get_class_type() { diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.I b/panda/src/wgldisplay/wglGraphicsStateGuardian.I index 2dcd1ea755..3afca78bc5 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.I +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.I @@ -15,3 +15,31 @@ // panda3d@yahoogroups.com . // //////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsStateGuardian::get_pfnum +// Access: Public +// Description: Returns the pixel format number chosen for windows +// that use this context. +//////////////////////////////////////////////////////////////////// +INLINE int wglGraphicsStateGuardian:: +get_pfnum() const { + return _pfnum; +} + +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsStateGuardian::get_context +// Access: Public +// Description: Returns the GL context associated with the GSG. If +// the context has not yet been created, this creates a +// suitable context for rendering to the indicated +// window. This means that this method may only be +// called from within the draw thread. +//////////////////////////////////////////////////////////////////// +INLINE HGLRC wglGraphicsStateGuardian:: +get_context(HDC hdc) { + if (!_made_context) { + make_context(hdc); + } + return _context; +} diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index 5d6bc4c602..3393b77127 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -27,10 +27,13 @@ TypeHandle wglGraphicsStateGuardian::_type_handle; // Description: //////////////////////////////////////////////////////////////////// wglGraphicsStateGuardian:: -wglGraphicsStateGuardian(const FrameBufferProperties &properties) : - GLGraphicsStateGuardian(properties) +wglGraphicsStateGuardian(const FrameBufferProperties &properties, + int pfnum) : + GLGraphicsStateGuardian(properties), + _pfnum(pfnum) { - _context = (HGLRC)0; + _made_context = false; + _context = (HGLRC)NULL; } //////////////////////////////////////////////////////////////////// @@ -45,3 +48,27 @@ wglGraphicsStateGuardian:: _context = (HGLRC)NULL; } } + +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsStateGuardian::make_context +// Access: Private +// Description: Creates a suitable context for rendering into the +// given window. This should only be called from the +// draw thread. +//////////////////////////////////////////////////////////////////// +void wglGraphicsStateGuardian:: +make_context(HDC hdc) { + // We should only call this once for a particular GSG. + nassertv(!_made_context); + + _made_context = true; + + // Attempt to create a context. + _context = wglCreateContext(hdc); + + if (_context == NULL) { + wgldisplay_cat.error() + << "Could not create GL context.\n"; + return; + } +} diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.h b/panda/src/wgldisplay/wglGraphicsStateGuardian.h index 659eb87913..a2cb510b6d 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.h +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.h @@ -30,12 +30,18 @@ //////////////////////////////////////////////////////////////////// class wglGraphicsStateGuardian : public GLGraphicsStateGuardian { public: - wglGraphicsStateGuardian(const FrameBufferProperties &properties); + wglGraphicsStateGuardian(const FrameBufferProperties &properties, int pfnum); virtual ~wglGraphicsStateGuardian(); - HGLRC _context; + INLINE int get_pfnum() const; + INLINE HGLRC get_context(HDC hdc); + +private: + void make_context(HDC hdc); + + bool _made_context; int _pfnum; - PIXELFORMATDESCRIPTOR _pixelformat; + HGLRC _context; public: static TypeHandle get_class_type() { diff --git a/panda/src/wgldisplay/wglGraphicsWindow.cxx b/panda/src/wgldisplay/wglGraphicsWindow.cxx index d2a0a721ec..b33cb99707 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.cxx +++ b/panda/src/wgldisplay/wglGraphicsWindow.cxx @@ -25,9 +25,6 @@ #include #include -typedef enum {Software, MCD, ICD} OGLDriverType; -static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" }; - TypeHandle wglGraphicsWindow::_type_handle; static char *ConvDDErrorToString(const HRESULT &error); @@ -132,10 +129,9 @@ GetAvailVidMem() { // Description: //////////////////////////////////////////////////////////////////// wglGraphicsWindow:: -wglGraphicsWindow(GraphicsPipe *pipe) : - WinGraphicsWindow(pipe) +wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) : + WinGraphicsWindow(pipe, gsg) { - _context = (HGLRC)0; _hdc = (HDC)0; } @@ -148,49 +144,6 @@ wglGraphicsWindow:: ~wglGraphicsWindow() { } -//////////////////////////////////////////////////////////////////// -// Function: wglGraphicsWindow::make_gsg -// Access: Public, Virtual -// Description: Creates a new GSG for the window and stores it in the -// _gsg pointer. This should only be called from within -// the draw thread. -//////////////////////////////////////////////////////////////////// -void wglGraphicsWindow:: -make_gsg() { - nassertv(_gsg == (GraphicsStateGuardian *)NULL); - - _context = wglCreateContext(_hdc); - if (!_context) { - wgldisplay_cat.error() - << "Could not create GL context.\n"; - return; - } - - // And make sure the new context is current. - wglMakeCurrent(_hdc, _context); - - // Now we can make a GSG. - _gsg = new GLGraphicsStateGuardian(this); -} - -//////////////////////////////////////////////////////////////////// -// Function: wglGraphicsWindow::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. This should only -// be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void wglGraphicsWindow:: -release_gsg() { - if (_gsg != (GraphicsStateGuardian *)NULL) { - wglMakeCurrent(_hdc, _context); - GraphicsWindow::release_gsg(); - wglDeleteContext(_context); - wglMakeCurrent(_hdc, NULL); - _context = (HGLRC)0; - } -} - //////////////////////////////////////////////////////////////////// // Function: wglGraphicsWindow::make_current // Access: Public, Virtual @@ -200,8 +153,30 @@ release_gsg() { //////////////////////////////////////////////////////////////////// void wglGraphicsWindow:: make_current() { - nassertv(_gsg != (GraphicsStateGuardian *)NULL); - wglMakeCurrent(_hdc, _context); + wglGraphicsStateGuardian *wglgsg; + DCAST_INTO_V(wglgsg, _gsg); + wglMakeCurrent(_hdc, wglgsg->get_context(_hdc)); + + // Now that we have made the context current to a window, we can + // reset the GSG state if this is the first time it has been used. + // (We can't just call reset() when we construct the GSG, because + // reset() requires having a current context.) + wglgsg->reset_if_new(); +} + +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsWindow::release_gsg +// Access: Public, Virtual +// Description: Releases the current GSG pointer, if it is currently +// held, and resets the GSG to NULL. The window will be +// permanently unable to render; this is normally called +// only just before destroying the window. This should +// only be called from within the draw thread. +//////////////////////////////////////////////////////////////////// +void wglGraphicsWindow:: +release_gsg() { + wglMakeCurrent(_hdc, NULL); + GraphicsWindow::release_gsg(); } //////////////////////////////////////////////////////////////////// @@ -221,7 +196,7 @@ make_current() { void wglGraphicsWindow:: begin_flip() { if (_gsg != (GraphicsStateGuardian *)NULL) { - wglMakeCurrent(_hdc, _context); + make_current(); glFinish(); SwapBuffers(_hdc); } @@ -235,7 +210,7 @@ begin_flip() { //////////////////////////////////////////////////////////////////// void wglGraphicsWindow:: close_window() { - ReleaseDC(_mwindow, _hdc); + ReleaseDC(_hWnd, _hdc); _hdc = (HDC)0; WinGraphicsWindow::close_window(); } @@ -253,42 +228,31 @@ open_window() { return false; } + wglGraphicsStateGuardian *wglgsg; + DCAST_INTO_R(wglgsg, _gsg, false); + + _hdc = GetDC(_hWnd); + // Set up the pixel format of the window appropriately for GL. - _hdc = GetDC(_mwindow); + int pfnum = wglgsg->get_pfnum(); - int pfnum = choose_pfnum(); - - if (gl_force_pixfmt != 0) { - wgldisplay_cat.info() - << "overriding pixfmt choice algorithm (" << pfnum - << ") with gl-force-pixfmt(" << gl_force_pixfmt << ")\n"; - pfnum = gl_force_pixfmt; - } - - if (wgldisplay_cat.is_debug()) { - wgldisplay_cat.debug() - << "config() - picking pixfmt #" << pfnum <debug() - << "----------------" << endl; - - if ((framebuffer_mode & WindowProperties::FM_alpha) != 0) { - wgldisplay_cat->debug() - << "want alpha, pfd says '" - << (int)(pfd.cAlphaBits) << "'" << endl; - } - if ((framebuffer_mode & WindowProperties::FM_depth) != 0) { - wgldisplay_cat->debug() - << "want depth, pfd says '" - << (int)(pfd.cDepthBits) << "'" << endl; - } - if ((framebuffer_mode & WindowProperties::FM_stencil) != 0) { - wgldisplay_cat->debug() - << "want stencil, pfd says '" - << (int)(pfd.cStencilBits) << "'" << endl; - } - wgldisplay_cat->debug() - << "final flag check " << (int)(pfd.dwFlags & dwReqFlags) << " =? " - << (int)dwReqFlags << endl; - wgldisplay_cat->debug() - << "pfd bits = " << (int)(pfd.cColorBits) << endl; - wgldisplay_cat->debug() - << "cur_bpp = " << cur_bpp << endl; - } - - if ((framebuffer_mode & WindowProperties::FM_double_buffer) != 0) { - dwReqFlags|= PFD_DOUBLEBUFFER; - } - if ((framebuffer_mode & WindowProperties::FM_alpha) != 0 && - (pfd.cAlphaBits==0)) { - continue; - } - if ((framebuffer_mode & WindowProperties::FM_depth) != 0 && - (pfd.cDepthBits==0)) { - continue; - } - if ((framebuffer_mode & WindowProperties::FM_stencil) != 0 && - (pfd.cStencilBits==0)) { - continue; - } - - if ((pfd.dwFlags & dwReqFlags) != dwReqFlags) { - continue; - } - - // now we ignore the specified want_color_bits for windowed mode - // instead we use the current screen depth - - if ((pfd.cColorBits!=cur_bpp) && - (!((cur_bpp==16) && (pfd.cColorBits==15))) && - (!((cur_bpp==32) && (pfd.cColorBits==24)))) { - continue; - } - - // We've passed all the tests, go ahead and pick this fmt. - // Note: could go continue looping looking for more alpha bits or - // more depth bits so this would pick 16bpp depth buffer, probably - // not 24bpp - break; - } - - if (pfnum > MaxPixFmtNum) { - pfnum = 0; - } - - return pfnum; -} - //////////////////////////////////////////////////////////////////// // Function: wglGraphicsWindow::setup_colormap // Access: Private @@ -523,21 +309,15 @@ find_pixfmtnum(bool bLookforHW) const { // creating a GL context. //////////////////////////////////////////////////////////////////// void wglGraphicsWindow:: -setup_colormap() { - PIXELFORMATDESCRIPTOR pfd; +setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat) { LOGPALETTE *logical; int n; - /* grab the pixel format */ - memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - DescribePixelFormat(_hdc, GetPixelFormat(_hdc), - sizeof(PIXELFORMATDESCRIPTOR), &pfd); - - if (!(pfd.dwFlags & PFD_NEED_PALETTE || - pfd.iPixelType == PFD_TYPE_COLORINDEX)) + if (!(pixelformat.dwFlags & PFD_NEED_PALETTE || + pixelformat.iPixelType == PFD_TYPE_COLORINDEX)) return; - n = 1 << pfd.cColorBits; + n = 1 << pixelformat.cColorBits; /* allocate a bunch of memory for the logical palette (assume 256 colors in a Win32 palette */ @@ -552,20 +332,20 @@ setup_colormap() { /* start with a copy of the current system palette */ GetSystemPaletteEntries(_hdc, 0, 256, &logical->palPalEntry[0]); - if (pfd.iPixelType == PFD_TYPE_RGBA) { - int redMask = (1 << pfd.cRedBits) - 1; - int greenMask = (1 << pfd.cGreenBits) - 1; - int blueMask = (1 << pfd.cBlueBits) - 1; + if (pixelformat.iPixelType == PFD_TYPE_RGBA) { + int redMask = (1 << pixelformat.cRedBits) - 1; + int greenMask = (1 << pixelformat.cGreenBits) - 1; + int blueMask = (1 << pixelformat.cBlueBits) - 1; int i; /* fill in an RGBA color palette */ for (i = 0; i < n; ++i) { logical->palPalEntry[i].peRed = - (((i >> pfd.cRedShift) & redMask) * 255) / redMask; + (((i >> pixelformat.cRedShift) & redMask) * 255) / redMask; logical->palPalEntry[i].peGreen = - (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; + (((i >> pixelformat.cGreenShift) & greenMask) * 255) / greenMask; logical->palPalEntry[i].peBlue = - (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; + (((i >> pixelformat.cBlueShift) & blueMask) * 255) / blueMask; logical->palPalEntry[i].peFlags = 0; } } diff --git a/panda/src/wgldisplay/wglGraphicsWindow.h b/panda/src/wgldisplay/wglGraphicsWindow.h index 7b703d9046..1c1d0ce8e4 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.h +++ b/panda/src/wgldisplay/wglGraphicsWindow.h @@ -29,12 +29,11 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDAGL wglGraphicsWindow : public WinGraphicsWindow { public: - wglGraphicsWindow(GraphicsPipe *pipe); + wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); virtual ~wglGraphicsWindow(); - virtual void make_gsg(); - virtual void release_gsg(); virtual void make_current(); + virtual void release_gsg(); virtual void begin_flip(); @@ -45,17 +44,13 @@ protected: DWORD &bitdepth); private: - int choose_pfnum() const; - int find_pixfmtnum(bool bLookforHW) const; - void setup_colormap(); + void setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat); #ifdef _DEBUG static void print_pfd(PIXELFORMATDESCRIPTOR *pfd, char *msg); #endif - HGLRC _context; HDC _hdc; - PIXELFORMATDESCRIPTOR _pixelformat; HPALETTE _colormap; public: diff --git a/panda/src/wgldisplay/wgldisplay_composite1.cxx b/panda/src/wgldisplay/wgldisplay_composite1.cxx index a810e1c47f..664bc9857d 100644 --- a/panda/src/wgldisplay/wgldisplay_composite1.cxx +++ b/panda/src/wgldisplay/wgldisplay_composite1.cxx @@ -1,4 +1,5 @@ #include "config_wgldisplay.cxx" #include "wglGraphicsPipe.cxx" +#include "wglGraphicsStateGuardian.cxx" #include "wglGraphicsWindow.cxx" diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index 745b1b5696..4ca2d8bbc4 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -51,3 +51,21 @@ WinGraphicsPipe:: _hUser32 = NULL; } } + +bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName) { + *pFn = (FARPROC) GetProcAddress(hDLL, szExportedFnName); + if (*pFn == NULL) { + windisplay_cat.error() << "GetProcAddr failed for " << szExportedFnName << ", error=" << GetLastError() <left; - ul.y = view_rect->top; - lr.x = view_rect->right; - lr.y = view_rect->bottom; - - ClientToScreen(hwnd, &ul); - ClientToScreen(hwnd, &lr); - - view_rect->left = ul.x; - view_rect->top = ul.y; - view_rect->right = lr.x; - view_rect->bottom = lr.y; -} - //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::open_fullscreen_window // Access: Private @@ -516,10 +490,10 @@ open_fullscreen_window() { // up the desktop during the mode change register_window_class(); HINSTANCE hinstance = GetModuleHandle(NULL); - _mwindow = CreateWindow(_window_class_name, title.c_str(), window_style, + _hWnd = CreateWindow(_window_class_name, title.c_str(), window_style, 0, 0, dwWidth, dwHeight, hDesktopWindow, NULL, hinstance, 0); - if (!_mwindow) { + if (!_hWnd) { windisplay_cat.error() << "CreateWindow() failed!" << endl; show_error_message(); @@ -601,13 +575,13 @@ open_regular_window() { register_window_class(); HINSTANCE hinstance = GetModuleHandle(NULL); - _mwindow = CreateWindow(_window_class_name, title.c_str(), window_style, + _hWnd = CreateWindow(_window_class_name, title.c_str(), window_style, win_rect.left, win_rect.top, win_rect.right - win_rect.left, win_rect.bottom - win_rect.top, NULL, NULL, hinstance, 0); - if (!_mwindow) { + if (!_hWnd) { windisplay_cat.error() << "CreateWindow() failed!" << endl; show_error_message(); @@ -672,342 +646,373 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { int button = -1; switch (msg) { - case WM_MOUSEMOVE: - if (!_tracking_mouse_leaving) { - // need to re-call TrackMouseEvent every time mouse re-enters window - track_mouse_leaving(hwnd); - } - set_cursor_in_window(); - handle_mouse_motion(translate_mouse(LOWORD(lparam)), - translate_mouse(HIWORD(lparam))); - break; - - case WM_MOUSELEAVE: - _tracking_mouse_leaving = false; - handle_mouse_exit(); - set_cursor_out_of_window(); - break; - - case WM_CREATE: - track_mouse_leaving(hwnd); - - // Assume the mouse cursor is within the window initially. It - // remains to be seen whether this is assumption does any harm. - set_cursor_in_window(); - break; - - case WM_CLOSE: - properties.set_open(false); - system_changed_properties(properties); - - // TODO: make sure we release the GSG properly. - break; - - case WM_ACTIVATE: - properties.set_minimized((wparam & 0xffff0000) != 0); - if ((wparam & 0xffff) != WA_INACTIVE) { - properties.set_foreground(true); - if (is_fullscreen()) { - // When a fullscreen window goes active, it automatically gets - // un-minimized. - ChangeDisplaySettings(&_fullscreen_display_mode, CDS_FULLSCREEN); - GdiFlush(); - SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, - SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER); - fullscreen_restored(properties); - } - } else { - properties.set_foreground(false); - if (is_fullscreen()) { - // When a fullscreen window goes inactive, it automatically - // gets minimized. - properties.set_minimized(true); - - // It seems order is important here. We must minimize the - // window before restoring the display settings, or risk - // losing the graphics context. - ShowWindow(_mwindow, SW_MINIMIZE); - GdiFlush(); - ChangeDisplaySettings(NULL, 0x0); - fullscreen_minimized(properties); - } - } - system_changed_properties(properties); - break; - - case WM_SIZE: - // for maximized, unmaximize, need to call resize code - // artificially since no WM_EXITSIZEMOVE is generated. - if (wparam == SIZE_MAXIMIZED) { - _maximized = true; - handle_reshape(); - - } else if (wparam == SIZE_RESTORED && _maximized) { - // SIZE_RESTORED might mean we restored to its original size - // before the maximize, but it might also be called while the - // user is resizing the window by hand. Checking the _maximized - // flag that we set above allows us to differentiate the two - // cases. - _maximized = false; - handle_reshape(); - } - break; - - case WM_EXITSIZEMOVE: - handle_reshape(); - break; - - case WM_LBUTTONDOWN: - button = 0; - // fall through - case WM_MBUTTONDOWN: - if (button < 0) { - button = 1; - } - // fall through - case WM_RBUTTONDOWN: - if (button < 0) { - button = 2; - } - SetCapture(hwnd); - handle_keypress(MouseButton::button(button), - translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam))); - break; - - case WM_LBUTTONUP: - button = 0; - // fall through - case WM_MBUTTONUP: - if (button < 0) { - button = 1; - } - // fall through - case WM_RBUTTONUP: - if (button < 0) { - button = 2; - } - ReleaseCapture(); - handle_keyrelease(MouseButton::button(button)); - break; - - case WM_IME_NOTIFY: - if (wparam == IMN_SETOPENSTATUS) { - HIMC hIMC = ImmGetContext(hwnd); - nassertr(hIMC != 0, 0); - _ime_open = (ImmGetOpenStatus(hIMC) != 0); - if (!_ime_open) { - _ime_active = false; // Sanity enforcement. - } - ImmReleaseContext(hwnd, hIMC); - } - break; - - case WM_IME_STARTCOMPOSITION: - _ime_active = true; - break; - - case WM_IME_ENDCOMPOSITION: - _ime_active = false; - break; - - case WM_IME_COMPOSITION: - if (lparam & GCS_RESULTSTR) { - HIMC hIMC = ImmGetContext(hwnd); - nassertr(hIMC != 0, 0); - - static const int max_ime_result = 128; - static char ime_result[max_ime_result]; - - if (_ime_composition_w) { - // Since ImmGetCompositionStringA() doesn't seem to work - // for Win2000 (it always returns question mark - // characters), we have to use ImmGetCompositionStringW() - // on this OS. This is actually the easier of the two - // functions to use. - - DWORD result_size = - ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, - ime_result, max_ime_result); - - // Add this string into the text buffer of the application. - - // ImmGetCompositionStringW() returns a string, but it's - // filled in with wstring data: every two characters defines a - // 16-bit unicode char. The docs aren't clear on the - // endianness of this. I guess it's safe to assume all Win32 - // machines are little-endian. - for (DWORD i = 0; i < result_size; i += 2) { - int result = - ((int)(unsigned char)ime_result[i + 1] << 8) | - (unsigned char)ime_result[i]; - _input_devices[0].keystroke(result); + case WM_MOUSEMOVE: + if (!_tracking_mouse_leaving) { + // need to re-call TrackMouseEvent every time mouse re-enters window + track_mouse_leaving(hwnd); } - } else { - // On the other hand, ImmGetCompositionStringW() doesn't - // work on Win95 or Win98; for these OS's we must use - // ImmGetCompositionStringA(). - DWORD result_size = - ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, - ime_result, max_ime_result); - - // ImmGetCompositionStringA() returns an encoded ANSI - // string, which we now have to map to wide-character - // Unicode. - static const int max_wide_result = 128; - static wchar_t wide_result[max_wide_result]; - - int wide_size = - MultiByteToWideChar(CP_ACP, 0, - ime_result, result_size, - wide_result, max_wide_result); - if (wide_size == 0) { - show_error_message(); - } - for (int i = 0; i < wide_size; i++) { - _input_devices[0].keystroke(wide_result[i]); - } - } - - ImmReleaseContext(hwnd, hIMC); - return 0; - } - break; + set_cursor_in_window(); + if(handle_mouse_motion(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)))) + return 0; + break; - case WM_CHAR: - // Ignore WM_CHAR messages if we have the IME open, since - // everything will come in through WM_IME_COMPOSITION. (It's - // supposed to come in through WM_CHAR, too, but there seems to - // be a bug in Win2000 in that it only sends question mark - // characters through here.) - if (!_ime_open) { - _input_devices[0].keystroke(wparam); - } - break; - - case WM_SYSKEYDOWN: - { - // Alt and F10 are sent as WM_SYSKEYDOWN instead of WM_KEYDOWN - // want to use defwindproc on Alt syskey so std windows cmd - // Alt-F4 works, etc - POINT point; - GetCursorPos(&point); - ScreenToClient(hwnd, &point); - handle_keypress(lookup_key(wparam), point.x, point.y); - if (wparam == VK_F10) { - // bypass default windproc F10 behavior (it activates the main - // menu, but we have none) - return 0; - } - } - break; - - case WM_SYSCOMMAND: - if (wparam == SC_KEYMENU) { - // if Alt is released (alone w/o other keys), defwindproc will - // send this command, which will 'activate' the title bar menu - // (we have none) and give focus to it. we dont want this to - // happen, so kill this msg - return 0; - } - break; + case WM_MOUSELEAVE: + _tracking_mouse_leaving = false; + handle_mouse_exit(); + set_cursor_out_of_window(); + break; - case WM_KEYDOWN: - { - POINT point; - - GetCursorPos(&point); - ScreenToClient(hwnd, &point); - handle_keypress(lookup_key(wparam), point.x, point.y); - - // Handle Cntrl-V paste from clipboard. Is there a better way - // to detect this hotkey? - if ((wparam=='V') && (GetKeyState(VK_CONTROL) < 0) && - !_input_devices.empty()) { - HGLOBAL hglb; - char *lptstr; - - if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) { - // Maybe we should support CF_UNICODETEXT if it is available - // too? - hglb = GetClipboardData(CF_TEXT); - if (hglb!=NULL) { - lptstr = (char *) GlobalLock(hglb); - if (lptstr != NULL) { - char *pChar; - for (pChar=lptstr; *pChar!=NULL; pChar++) { - _input_devices[0].keystroke((uchar)*pChar); - } - GlobalUnlock(hglb); + // if cursor is invisible, make it visible when moving in the window bars & menus, so user can use click in them + case WM_NCMOUSEMOVE: { + if(!_properties.get_cursor_hidden()) { + if(!_bCursor_in_WindowClientArea) { + // SetCursor(_pParentWindowGroup->_hMouseCursor); + ShowCursor(true); + _bCursor_in_WindowClientArea=true; + } } - } - CloseClipboard(); - } + break; } - } - break; - - case WM_SYSKEYUP: - case WM_KEYUP: - handle_keyrelease(lookup_key(wparam)); - break; - - case WM_KILLFOCUS: - // Record the current state of the keyboard when the focus is - // lost, so we can check it for changes when we regain focus. - GetKeyboardState(_keyboard_state); - break; - - case WM_SETFOCUS: - { - // When we lose focus, the app may miss key-up events for keys - // that were formerly held down (and vice-versa). Therefore, - // when focus is regained, compare the state of the keyboard to - // the last known state (stored above, when focus was lost) to - // regenerate the lost keyboard events. - - if (GetForegroundWindow() != _mwindow) { - // Sometimes, particularly on window create, it appears we get - // a WM_SETFOCUS event even though the window hasn't really - // received focus yet. That's bad and confuses the - // GetKeyboardState logic, below. The above check filters out - // this case (while testing GetFocus() instead of - // GetForegroundWindow() doesn't). - windisplay_cat.debug() - << "Got incorrect WM_SETFOCUS\n"; + + case WM_NCMOUSELEAVE: { + if(!_properties.get_cursor_hidden()) { + ShowCursor(false); + // SetCursor(NULL); + _bCursor_in_WindowClientArea=false; + } + break; + } + + case WM_CREATE: { + track_mouse_leaving(hwnd); + _bCursor_in_WindowClientArea=false; + ClearToBlack(hwnd,_properties); + + POINT cpos; + GetCursorPos(&cpos); + ScreenToClient(hwnd,&cpos); + RECT clientRect; + GetClientRect(hwnd, &clientRect); + if(PtInRect(&clientRect,cpos)) + set_cursor_in_window(); // should window focus be true as well? + else set_cursor_out_of_window(); + break; } - - BYTE new_keyboard_state[num_virtual_keys]; - GetKeyboardState(new_keyboard_state); - for (int i = 0; i < num_virtual_keys; i++) { - // Filter out these particular three. We don't want to test - // these, because these are virtual duplicates for - // VK_LSHIFT/VK_RSHIFT, etc.; and the left/right equivalent is - // also in the table. If we respect both VK_LSHIFT as well as - // VK_SHIFT, we'll generate two keyboard messages when - // VK_LSHIFT changes state. - if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) { - if (((new_keyboard_state[i] ^ _keyboard_state[i]) & 0x80) != 0) { - // This key has changed state. - if ((new_keyboard_state[i] & 0x80) != 0) { - // The key is now held down. - handle_keyresume(lookup_key(i)); - } else { - // The key is now released. - handle_keyrelease(lookup_key(i)); + + case WM_CLOSE: + properties.set_open(false); + system_changed_properties(properties); + + // TODO: make sure we release the GSG properly. + break; + + case WM_ACTIVATE: + properties.set_minimized((wparam & 0xffff0000) != 0); + if ((wparam & 0xffff) != WA_INACTIVE) { + properties.set_foreground(true); + if (is_fullscreen()) { + // When a fullscreen window goes active, it automatically gets + // un-minimized. + ChangeDisplaySettings(&_fullscreen_display_mode, CDS_FULLSCREEN); + GdiFlush(); + SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0, + SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER); + fullscreen_restored(properties); + } + } else { + properties.set_foreground(false); + if (is_fullscreen()) { + // When a fullscreen window goes inactive, it automatically + // gets minimized. + properties.set_minimized(true); + + // It seems order is important here. We must minimize the + // window before restoring the display settings, or risk + // losing the graphics context. + ShowWindow(_hWnd, SW_MINIMIZE); + GdiFlush(); + ChangeDisplaySettings(NULL, 0x0); + fullscreen_minimized(properties); + } + } + system_changed_properties(properties); + break; + + case WM_SIZE: + // for maximized, unmaximize, need to call resize code + // artificially since no WM_EXITSIZEMOVE is generated. + if (wparam == SIZE_MAXIMIZED) { + _maximized = true; + handle_reshape(); + + } else if (wparam == SIZE_RESTORED && _maximized) { + // SIZE_RESTORED might mean we restored to its original size + // before the maximize, but it might also be called while the + // user is resizing the window by hand. Checking the _maximized + // flag that we set above allows us to differentiate the two + // cases. + _maximized = false; + handle_reshape(); + } + break; + + case WM_EXITSIZEMOVE: + handle_reshape(); + break; + + case WM_LBUTTONDOWN: + button = 0; + // fall through + case WM_MBUTTONDOWN: + if (button < 0) { + button = 1; + } + // fall through + case WM_RBUTTONDOWN: + if (button < 0) { + button = 2; + } + SetCapture(hwnd); + handle_keypress(MouseButton::button(button), + translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam))); + break; + + case WM_LBUTTONUP: + button = 0; + // fall through + case WM_MBUTTONUP: + if (button < 0) { + button = 1; + } + // fall through + case WM_RBUTTONUP: + if (button < 0) { + button = 2; + } + ReleaseCapture(); + handle_keyrelease(MouseButton::button(button)); + break; + + case WM_IME_NOTIFY: + if (wparam == IMN_SETOPENSTATUS) { + HIMC hIMC = ImmGetContext(hwnd); + nassertr(hIMC != 0, 0); + _ime_open = (ImmGetOpenStatus(hIMC) != 0); + if (!_ime_open) { + _ime_active = false; // Sanity enforcement. + } + ImmReleaseContext(hwnd, hIMC); + } + break; + + case WM_IME_STARTCOMPOSITION: + _ime_active = true; + break; + + case WM_IME_ENDCOMPOSITION: + _ime_active = false; + break; + + case WM_IME_COMPOSITION: + if (lparam & GCS_RESULTSTR) { + HIMC hIMC = ImmGetContext(hwnd); + nassertr(hIMC != 0, 0); + + static const int max_ime_result = 128; + static char ime_result[max_ime_result]; + + if (_ime_composition_w) { + // Since ImmGetCompositionStringA() doesn't seem to work + // for Win2000 (it always returns question mark + // characters), we have to use ImmGetCompositionStringW() + // on this OS. This is actually the easier of the two + // functions to use. + + DWORD result_size = + ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, + ime_result, max_ime_result); + + // Add this string into the text buffer of the application. + + // ImmGetCompositionStringW() returns a string, but it's + // filled in with wstring data: every two characters defines a + // 16-bit unicode char. The docs aren't clear on the + // endianness of this. I guess it's safe to assume all Win32 + // machines are little-endian. + for (DWORD i = 0; i < result_size; i += 2) { + int result = + ((int)(unsigned char)ime_result[i + 1] << 8) | + (unsigned char)ime_result[i]; + _input_devices[0].keystroke(result); + } + } else { + // On the other hand, ImmGetCompositionStringW() doesn't + // work on Win95 or Win98; for these OS's we must use + // ImmGetCompositionStringA(). + DWORD result_size = + ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, + ime_result, max_ime_result); + + // ImmGetCompositionStringA() returns an encoded ANSI + // string, which we now have to map to wide-character + // Unicode. + static const int max_wide_result = 128; + static wchar_t wide_result[max_wide_result]; + + int wide_size = + MultiByteToWideChar(CP_ACP, 0, + ime_result, result_size, + wide_result, max_wide_result); + if (wide_size == 0) { + show_error_message(); + } + for (int i = 0; i < wide_size; i++) { + _input_devices[0].keystroke(wide_result[i]); + } + } + + ImmReleaseContext(hwnd, hIMC); + return 0; + } + break; + + case WM_CHAR: + // Ignore WM_CHAR messages if we have the IME open, since + // everything will come in through WM_IME_COMPOSITION. (It's + // supposed to come in through WM_CHAR, too, but there seems to + // be a bug in Win2000 in that it only sends question mark + // characters through here.) + if (!_ime_open) { + _input_devices[0].keystroke(wparam); + } + break; + + case WM_SYSKEYDOWN: + { + // Alt and F10 are sent as WM_SYSKEYDOWN instead of WM_KEYDOWN + // want to use defwindproc on Alt syskey so std windows cmd + // Alt-F4 works, etc + POINT point; + GetCursorPos(&point); + ScreenToClient(hwnd, &point); + handle_keypress(lookup_key(wparam), point.x, point.y); + if (wparam == VK_F10) { + // bypass default windproc F10 behavior (it activates the main + // menu, but we have none) + return 0; + } + } + break; + + case WM_SYSCOMMAND: + if (wparam == SC_KEYMENU) { + // if Alt is released (alone w/o other keys), defwindproc will + // send this command, which will 'activate' the title bar menu + // (we have none) and give focus to it. we dont want this to + // happen, so kill this msg + return 0; + } + break; + + case WM_KEYDOWN: + { + POINT point; + + GetCursorPos(&point); + ScreenToClient(hwnd, &point); + handle_keypress(lookup_key(wparam), point.x, point.y); + + // Handle Cntrl-V paste from clipboard. Is there a better way + // to detect this hotkey? + if ((wparam=='V') && (GetKeyState(VK_CONTROL) < 0) && + !_input_devices.empty()) { + HGLOBAL hglb; + char *lptstr; + + if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) { + // Maybe we should support CF_UNICODETEXT if it is available + // too? + hglb = GetClipboardData(CF_TEXT); + if (hglb!=NULL) { + lptstr = (char *) GlobalLock(hglb); + if (lptstr != NULL) { + char *pChar; + for (pChar=lptstr; *pChar!=NULL; pChar++) { + _input_devices[0].keystroke((uchar)*pChar); + } + GlobalUnlock(hglb); + } + } + CloseClipboard(); } } } - } - - // Save the new keyboard state, just for good measure. This - // really shouldn't be necessary, but it protects against - // inadvertently getting WM_SETFOCUS twice in a row, for - // instance. - memcpy(_keyboard_state, new_keyboard_state, - sizeof(BYTE) * num_virtual_keys); - } - break; + break; + + case WM_SYSKEYUP: + case WM_KEYUP: + handle_keyrelease(lookup_key(wparam)); + break; + + case WM_KILLFOCUS: + // Record the current state of the keyboard when the focus is + // lost, so we can check it for changes when we regain focus. + GetKeyboardState(_keyboard_state); + break; + + case WM_SETFOCUS: + { + // When we lose focus, the app may miss key-up events for keys + // that were formerly held down (and vice-versa). Therefore, + // when focus is regained, compare the state of the keyboard to + // the last known state (stored above, when focus was lost) to + // regenerate the lost keyboard events. + + if (GetForegroundWindow() != _hWnd) { + // Sometimes, particularly on window create, it appears we get + // a WM_SETFOCUS event even though the window hasn't really + // received focus yet. That's bad and confuses the + // GetKeyboardState logic, below. The above check filters out + // this case (while testing GetFocus() instead of + // GetForegroundWindow() doesn't). + if(windisplay_cat.is_debug()) + windisplay_cat.debug() << "Ignoring non-foreground WM_SETFOCUS\n"; + break; + } + + BYTE new_keyboard_state[num_virtual_keys]; + GetKeyboardState(new_keyboard_state); + for (int i = 0; i < num_virtual_keys; i++) { + // Filter out these particular three. We don't want to test + // these, because these are virtual duplicates for + // VK_LSHIFT/VK_RSHIFT, etc.; and the left/right equivalent is + // also in the table. If we respect both VK_LSHIFT as well as + // VK_SHIFT, we'll generate two keyboard messages when + // VK_LSHIFT changes state. + if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) { + if (((new_keyboard_state[i] ^ _keyboard_state[i]) & 0x80) != 0) { + // This key has changed state. + if ((new_keyboard_state[i] & 0x80) != 0) { + // The key is now held down. + // cerr << "key is down: " << lookup_key(i) << "\n"; + handle_keyresume(lookup_key(i)); + } else { + // The key is now released. + handle_keyrelease(lookup_key(i)); + } + } + } + } + + // Save the new keyboard state, just for good measure. This + // really shouldn't be necessary, but it protects against + // inadvertently getting WM_SETFOCUS twice in a row, for + // instance. + memcpy(_keyboard_state, new_keyboard_state, + sizeof(BYTE) * num_virtual_keys); + } + break; } return DefWindowProc(hwnd, msg, wparam, lparam); @@ -1370,3 +1375,90 @@ lookup_key(WPARAM wparam) const { } return ButtonHandle::none(); } + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::handle_mouse_motion +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +bool WinGraphicsWindow:: +handle_mouse_motion(int x, int y) { + _input_devices[0].set_pointer_in_window(x, y); + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::handle_mouse_exit +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void WinGraphicsWindow:: +handle_mouse_exit() { + // note: 'mouse_motion' is considered the 'entry' event + _input_devices[0].set_pointer_out_of_window(); +} + +// pops up MsgBox w/system error msg +void PrintErrorMessage(DWORD msgID) { + LPTSTR pMessageBuffer; + + if (msgID==PRINT_LAST_ERROR) + msgID=GetLastError(); + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL,msgID, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language + (LPTSTR) &pMessageBuffer, // the weird ptrptr->ptr cast is intentional, see FORMAT_MESSAGE_ALLOCATE_BUFFER + 1024, NULL); + MessageBox(GetDesktopWindow(),pMessageBuffer,_T(errorbox_title),MB_OK); + windisplay_cat.fatal() << "System error msg: " << pMessageBuffer << endl; + LocalFree( pMessageBuffer ); +} + +void +ClearToBlack(HWND hWnd, const WindowProperties &props) { + if (!props.has_origin()) { + windisplay_cat.info() + << "Skipping ClearToBlack, no origin specified yet.\n"; + return; + } + + if (windisplay_cat.is_debug()) { + windisplay_cat.debug() + << "ClearToBlack(" << hWnd << ", " << props << ")\n"; + } + // clear to black + HDC hDC=GetDC(hWnd); // GetDC is not particularly fast. if this needs to be super-quick, we should cache GetDC's hDC + RECT clrRect = { + props.get_x_origin(), props.get_y_origin(), + props.get_x_origin() + props.get_x_size(), + props.get_y_origin() + props.get_y_size() + }; + FillRect(hDC,&clrRect,(HBRUSH)GetStockObject(BLACK_BRUSH)); + ReleaseDC(hWnd,hDC); + GdiFlush(); +} + +//////////////////////////////////////////////////////////////////// +// Function: get_client_rect_screen +// Description: Fills view_rect with the coordinates of the client +// area of the indicated window, converted to screen +// coordinates. +//////////////////////////////////////////////////////////////////// +void get_client_rect_screen(HWND hwnd, RECT *view_rect) { + GetClientRect(hwnd, view_rect); + + POINT ul, lr; + ul.x = view_rect->left; + ul.y = view_rect->top; + lr.x = view_rect->right; + lr.y = view_rect->bottom; + + ClientToScreen(hwnd, &ul); + ClientToScreen(hwnd, &lr); + + view_rect->left = ul.x; + view_rect->top = ul.y; + view_rect->right = lr.x; + view_rect->bottom = lr.y; +} diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 8409e3e84b..b52d9f8967 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -48,13 +48,18 @@ class WinGraphicsPipe; //////////////////////////////////////////////////////////////////// class EXPCL_PANDAWIN WinGraphicsWindow : public GraphicsWindow { public: - WinGraphicsWindow(GraphicsPipe *pipe); + WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); virtual ~WinGraphicsWindow(); virtual void begin_flip(); virtual void process_events(); virtual void set_properties_now(WindowProperties &properties); + virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + virtual bool handle_mouse_motion(int x, int y); + virtual void handle_mouse_exit(void); + protected: virtual void close_window(); @@ -71,20 +76,13 @@ protected: virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size, DWORD &bitdepth); - void get_client_rect_screen(HWND hwnd, RECT *view_rect); - private: bool open_fullscreen_window(); bool open_regular_window(); void track_mouse_leaving(HWND hwnd); - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - static LONG WINAPI - static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); static void process_1_event(); - INLINE void handle_mouse_motion(int x, int y); - INLINE void handle_mouse_exit(void); INLINE void handle_keypress(ButtonHandle key, int x, int y); INLINE void handle_keyresume(ButtonHandle key); INLINE void handle_keyrelease(ButtonHandle key); @@ -100,7 +98,7 @@ private: static void show_error_message(DWORD message_id = 0); protected: - HWND _mwindow; + HWND _hWnd; private: bool _ime_open; @@ -108,6 +106,7 @@ private: bool _ime_composition_w; bool _tracking_mouse_leaving; bool _maximized; + bool _bCursor_in_WindowClientArea; DEVMODE _fullscreen_display_mode; // This is used to remember the state of the keyboard when keyboard @@ -164,6 +163,12 @@ private: static TypeHandle _type_handle; }; + +#define PRINT_LAST_ERROR 0 +extern EXPCL_PANDAWIN void PrintErrorMessage(DWORD msgID); +extern EXPCL_PANDAWIN void ClearToBlack(HWND hWnd, const WindowProperties &props); +extern EXPCL_PANDAWIN void get_client_rect_screen(HWND hwnd, RECT *view_rect); + #include "winGraphicsWindow.I" #endif