瀏覽代碼

merge window_devel_2003_02_21 to trunk

David Rose 23 年之前
父節點
當前提交
a16fe56c74
共有 63 個文件被更改,包括 3600 次插入2401 次删除
  1. 15 10
      panda/src/chancfg/chancfg.cxx
  2. 6 0
      panda/src/display/Sources.pp
  3. 2 0
      panda/src/display/display_composite2.cxx
  4. 44 8
      panda/src/display/graphicsEngine.I
  5. 165 77
      panda/src/display/graphicsEngine.cxx
  6. 24 5
      panda/src/display/graphicsEngine.h
  7. 32 0
      panda/src/display/graphicsPipe.cxx
  8. 8 5
      panda/src/display/graphicsPipe.h
  9. 42 7
      panda/src/display/graphicsStateGuardian.I
  10. 7 5
      panda/src/display/graphicsStateGuardian.cxx
  11. 16 7
      panda/src/display/graphicsStateGuardian.h
  12. 17 53
      panda/src/display/graphicsWindow.cxx
  13. 2 4
      panda/src/display/graphicsWindow.h
  14. 0 144
      panda/src/display/windowProperties.I
  15. 1 65
      panda/src/display/windowProperties.cxx
  16. 0 37
      panda/src/display/windowProperties.h
  17. 3 2
      panda/src/distort/nonlinearImager.cxx
  18. 2 0
      panda/src/distort/nonlinearImager.h
  19. 16 16
      panda/src/dxgsg7/dxGraphicsStateGuardian7.I
  20. 219 193
      panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx
  21. 17 11
      panda/src/dxgsg7/dxGraphicsStateGuardian7.h
  22. 5 2
      panda/src/dxgsg7/dxgsg7base.h
  23. 24 18
      panda/src/dxgsg7/wdxGraphicsPipe7.cxx
  24. 3 1
      panda/src/dxgsg7/wdxGraphicsPipe7.h
  25. 157 106
      panda/src/dxgsg7/wdxGraphicsWindow7.cxx
  26. 6 6
      panda/src/dxgsg7/wdxGraphicsWindow7.h
  27. 2 54
      panda/src/dxgsg8/config_dxgsg8.cxx
  28. 2 2
      panda/src/dxgsg8/config_dxgsg8.h
  29. 20 20
      panda/src/dxgsg8/dxGraphicsStateGuardian8.I
  30. 178 213
      panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx
  31. 20 5
      panda/src/dxgsg8/dxGraphicsStateGuardian8.h
  32. 25 7
      panda/src/dxgsg8/dxTextureContext8.cxx
  33. 19 5
      panda/src/dxgsg8/dxgsg8base.h
  34. 585 49
      panda/src/dxgsg8/wdxGraphicsPipe8.cxx
  35. 22 3
      panda/src/dxgsg8/wdxGraphicsPipe8.h
  36. 583 167
      panda/src/dxgsg8/wdxGraphicsWindow8.cxx
  37. 13 16
      panda/src/dxgsg8/wdxGraphicsWindow8.h
  38. 7 2
      panda/src/framework/pandaFramework.cxx
  39. 8 1
      panda/src/framework/windowFramework.cxx
  40. 18 7
      panda/src/glgsg/glGraphicsStateGuardian.cxx
  41. 2 2
      panda/src/glgsg/glGraphicsStateGuardian.h
  42. 2 0
      panda/src/glxdisplay/Sources.pp
  43. 2 2
      panda/src/glxdisplay/config_glxdisplay.cxx
  44. 0 2
      panda/src/glxdisplay/config_glxdisplay.h
  45. 349 2
      panda/src/glxdisplay/glxGraphicsPipe.cxx
  46. 12 4
      panda/src/glxdisplay/glxGraphicsPipe.h
  47. 38 369
      panda/src/glxdisplay/glxGraphicsWindow.cxx
  48. 3 9
      panda/src/glxdisplay/glxGraphicsWindow.h
  49. 5 1
      panda/src/wgldisplay/Sources.pp
  50. 2 0
      panda/src/wgldisplay/config_wgldisplay.cxx
  51. 235 2
      panda/src/wgldisplay/wglGraphicsPipe.cxx
  52. 7 1
      panda/src/wgldisplay/wglGraphicsPipe.h
  53. 28 0
      panda/src/wgldisplay/wglGraphicsStateGuardian.I
  54. 30 3
      panda/src/wgldisplay/wglGraphicsStateGuardian.cxx
  55. 9 3
      panda/src/wgldisplay/wglGraphicsStateGuardian.h
  56. 47 267
      panda/src/wgldisplay/wglGraphicsWindow.cxx
  57. 3 8
      panda/src/wgldisplay/wglGraphicsWindow.h
  58. 1 0
      panda/src/wgldisplay/wgldisplay_composite1.cxx
  59. 18 0
      panda/src/windisplay/winGraphicsPipe.cxx
  60. 3 0
      panda/src/windisplay/winGraphicsPipe.h
  61. 0 21
      panda/src/windisplay/winGraphicsWindow.I
  62. 455 363
      panda/src/windisplay/winGraphicsWindow.cxx
  63. 14 9
      panda/src/windisplay/winGraphicsWindow.h

+ 15 - 10
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);
   float win_background_b = chanconfig.GetFloat("win-background-b", 0.41);
 
 
   // visual?  nope, that's handled with the mode.
   // 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;
   std::string title = cfg;
   title = overrides.defined(ChanCfgOverrides::Title) ?
   title = overrides.defined(ChanCfgOverrides::Title) ?
             overrides.getString(ChanCfgOverrides::Title) : 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;
   WindowProperties props;
   props.set_open(true);
   props.set_open(true);
   props.set_origin(origX, origY);
   props.set_origin(origX, origY);
   props.set_size(sizeX, sizeY);
   props.set_size(sizeX, sizeY);
   props.set_title(title);
   props.set_title(title);
-  props.set_framebuffer_mode(framebuffer_mode);
   props.set_undecorated(undecorated);
   props.set_undecorated(undecorated);
   props.set_fullscreen(fullscreen);
   props.set_fullscreen(fullscreen);
-  props.set_depth_bits(want_depth_bits);
-  props.set_color_bits(want_color_bits);
   props.set_cursor_hidden(!use_cursor);
   props.set_cursor_hidden(!use_cursor);
 
 
 
 
@@ -454,7 +457,9 @@ ChanConfig::ChanConfig(GraphicsEngine *engine, GraphicsPipe* pipe,
                         overrides.getBool(ChanCfgOverrides::Cameras) : true;
                         overrides.getBool(ChanCfgOverrides::Cameras) : true;
 
 
   // open that sucker
   // 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) {
   if(win == (GraphicsWindow *)NULL) {
     chancfg_cat.error() << "Could not create window" << endl;
     chancfg_cat.error() << "Could not create window" << endl;
     _graphics_window = (GraphicsWindow *)NULL;
     _graphics_window = (GraphicsWindow *)NULL;

+ 6 - 0
panda/src/display/Sources.pp

@@ -15,6 +15,7 @@
     displayRegion.I displayRegion.h  \
     displayRegion.I displayRegion.h  \
     displayRegionStack.I \
     displayRegionStack.I \
     displayRegionStack.h \
     displayRegionStack.h \
+    frameBufferProperties.I frameBufferProperties.h \
     frameBufferStack.I frameBufferStack.h \
     frameBufferStack.I frameBufferStack.h \
     geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
     geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
     graphicsChannel.I graphicsChannel.h \
     graphicsChannel.I graphicsChannel.h \
@@ -24,6 +25,7 @@
     graphicsPipeSelection.I graphicsPipeSelection.h \
     graphicsPipeSelection.I graphicsPipeSelection.h \
     graphicsStateGuardian.I \
     graphicsStateGuardian.I \
     graphicsStateGuardian.h graphicsWindow.I \
     graphicsStateGuardian.h graphicsWindow.I \
+    graphicsThreadingModel.I graphicsThreadingModel.h \
     graphicsWindow.h graphicsWindowInputDevice.I  \
     graphicsWindow.h graphicsWindowInputDevice.I  \
     graphicsWindowInputDevice.h \
     graphicsWindowInputDevice.h \
     windowProperties.I windowProperties.h \
     windowProperties.I windowProperties.h \
@@ -36,11 +38,13 @@
     config_display.cxx \
     config_display.cxx \
     clearableRegion.cxx \
     clearableRegion.cxx \
     displayRegion.cxx \
     displayRegion.cxx \
+    frameBufferProperties.cxx \
     geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx  \
     geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx  \
     graphicsEngine.cxx \
     graphicsEngine.cxx \
     graphicsLayer.cxx graphicsPipe.cxx \
     graphicsLayer.cxx graphicsPipe.cxx \
     graphicsPipeSelection.cxx \
     graphicsPipeSelection.cxx \
     graphicsStateGuardian.cxx  \
     graphicsStateGuardian.cxx  \
+    graphicsThreadingModel.cxx \
     graphicsWindow.cxx graphicsWindowInputDevice.cxx  \
     graphicsWindow.cxx graphicsWindowInputDevice.cxx  \
     windowProperties.cxx \
     windowProperties.cxx \
     hardwareChannel.cxx \
     hardwareChannel.cxx \
@@ -51,6 +55,7 @@
     clearableRegion.I clearableRegion.h \
     clearableRegion.I clearableRegion.h \
     displayRegion.I displayRegion.h displayRegionStack.I \
     displayRegion.I displayRegion.h displayRegionStack.I \
     displayRegionStack.h \
     displayRegionStack.h \
+    frameBufferProperties.I frameBufferProperties.h \
     frameBufferStack.I frameBufferStack.h \
     frameBufferStack.I frameBufferStack.h \
     geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
     geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
     graphicsChannel.I graphicsChannel.h \
     graphicsChannel.I graphicsChannel.h \
@@ -60,6 +65,7 @@
     graphicsPipeSelection.I graphicsPipeSelection.h \
     graphicsPipeSelection.I graphicsPipeSelection.h \
     graphicsStateGuardian.I \
     graphicsStateGuardian.I \
     graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \
     graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \
+    graphicsThreadingModel.I graphicsThreadingModel.h \
     graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
     graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
     windowProperties.I windowProperties.h \
     windowProperties.I windowProperties.h \
     hardwareChannel.I hardwareChannel.h \
     hardwareChannel.I hardwareChannel.h \

+ 2 - 0
panda/src/display/display_composite2.cxx

@@ -1,5 +1,7 @@
 #include "config_display.cxx"
 #include "config_display.cxx"
+#include "frameBufferProperties.cxx"
 #include "graphicsPipeSelection.cxx"
 #include "graphicsPipeSelection.cxx"
+#include "graphicsThreadingModel.cxx"
 #include "hardwareChannel.cxx"
 #include "hardwareChannel.cxx"
 #include "savedFrameBuffer.cxx"
 #include "savedFrameBuffer.cxx"
 #include "windowProperties.cxx"
 #include "windowProperties.cxx"

+ 44 - 8
panda/src/display/graphicsEngine.I

@@ -56,17 +56,53 @@ get_auto_flip() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::make_window
+//     Function: GraphicsEngine::make_gsg
 //       Access: Published
 //       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.
+//
+//               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_window() uses the default
+//               This flavor of make_gsg() uses the default
 //               threading model, specified via set_threading_model().
 //               threading model, specified via set_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::
 INLINE GraphicsWindow *GraphicsEngine::
-make_window(GraphicsPipe *pipe) {
-  return make_window(pipe, get_threading_model());
+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);
 }
 }

+ 165 - 77
panda/src/display/graphicsEngine.cxx

@@ -50,8 +50,17 @@ GraphicsEngine(Pipeline *pipeline) :
   if (_pipeline == (Pipeline *)NULL) {
   if (_pipeline == (Pipeline *)NULL) {
     _pipeline = Pipeline::get_render_pipeline();
     _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()
     display_cat.info()
       << "Using threading model " << _threading_model << "\n";
       << "Using threading model " << _threading_model << "\n";
   }
   }
@@ -70,49 +79,46 @@ GraphicsEngine::
   remove_all_windows();
   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
 //     Function: GraphicsEngine::set_threading_model
 //       Access: Published
 //       Access: Published
 //  Description: Specifies how windows created using future calls to
 //  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::
 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()
     display_cat.warning()
       << "Threading model " << threading_model
       << "Threading model " << threading_model
       << " requested but threading not supported.\n";
       << " 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
 //  Description: Returns the current default threading model.  See
 //               set_threading_model().
 //               set_threading_model().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-string GraphicsEngine::
+GraphicsThreadingModel GraphicsEngine::
 get_threading_model() const {
 get_threading_model() const {
-  string result;
+  GraphicsThreadingModel result;
   {
   {
     MutexHolder holder(_lock);
     MutexHolder holder(_lock);
     result = _threading_model;
     result = _threading_model;
@@ -138,51 +144,64 @@ get_threading_model() const {
   return result;
   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
 //     Function: GraphicsEngine::make_window
 //       Access: Published
 //       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::
 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) {
   if (window != (GraphicsWindow *)NULL) {
     MutexHolder holder(_lock);
     MutexHolder holder(_lock);
     _windows.insert(window);
     _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;
-    }
-
-    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);
+    WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
+    WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name());
+    draw->add_gsg(gsg);
 
 
-    if (cull_sorting) {
+    if (threading_model.get_cull_sorting()) {
       cull->add_window(cull->_cull, window);
       cull->add_window(cull->_cull, window);
       draw->add_window(draw->_draw, window);
       draw->add_window(draw->_draw, window);
     } else {
     } else {
@@ -869,6 +888,18 @@ get_window_renderer(const string &name) {
   return thread.p();
   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
 //     Function: GraphicsEngine::WindowRenderer::add_window
 //       Access: Public
 //       Access: Public
@@ -958,6 +989,26 @@ do_frame(GraphicsEngine *engine) {
   engine->cull_bin_draw(_cull);
   engine->cull_bin_draw(_cull);
   engine->cull_and_draw_together(_cdraw);
   engine->cull_and_draw_together(_cdraw);
   engine->process_events(_window);
   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.
 //  Description: Closes all the windows on the _window list.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::WindowRenderer::
 void GraphicsEngine::WindowRenderer::
-do_close(GraphicsEngine *) {
+do_close(GraphicsEngine *engine) {
   WindowProperties close_properties;
   WindowProperties close_properties;
   close_properties.set_open(false);
   close_properties.set_open(false);
 
 
@@ -1005,6 +1056,23 @@ do_close(GraphicsEngine *) {
     GraphicsWindow *win = (*wi);
     GraphicsWindow *win = (*wi);
     win->set_properties_now(close_properties);
     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
 //     Function: GraphicsEngine::RenderThread::Constructor
 //       Access: Public
 //       Access: Public

+ 24 - 5
panda/src/display/graphicsEngine.h

@@ -21,6 +21,8 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 #include "graphicsWindow.h"
 #include "graphicsWindow.h"
+#include "frameBufferProperties.h"
+#include "graphicsThreadingModel.h"
 #include "sceneSetup.h"
 #include "sceneSetup.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "thread.h"
 #include "thread.h"
@@ -32,6 +34,7 @@
 class Pipeline;
 class Pipeline;
 class DisplayRegion;
 class DisplayRegion;
 class GraphicsPipe;
 class GraphicsPipe;
+class FrameBufferProperties;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : GraphicsEngine
 //       Class : GraphicsEngine
@@ -53,15 +56,25 @@ PUBLISHED:
   GraphicsEngine(Pipeline *pipeline = NULL);
   GraphicsEngine(Pipeline *pipeline = NULL);
   ~GraphicsEngine();
   ~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 void set_auto_flip(bool auto_flip);
   INLINE bool get_auto_flip() const;
   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,
   GraphicsWindow *make_window(GraphicsPipe *pipe,
-                              const string &threading_model);
+                              GraphicsStateGuardian *gsg,
+                              const GraphicsThreadingModel &threading_model);
   bool remove_window(GraphicsWindow *window);
   bool remove_window(GraphicsWindow *window);
   void remove_all_windows();
   void remove_all_windows();
   bool is_empty() const;
   bool is_empty() const;
@@ -75,6 +88,7 @@ PUBLISHED:
 
 
 private:
 private:
   typedef pset< PT(GraphicsWindow) > Windows;
   typedef pset< PT(GraphicsWindow) > Windows;
+  typedef pset< PT(GraphicsStateGuardian) > GSGs;
 
 
   void cull_and_draw_together(const Windows &wlist);
   void cull_and_draw_together(const Windows &wlist);
   void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
   void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
@@ -86,6 +100,7 @@ private:
   void flip_windows(const GraphicsEngine::Windows &wlist);
   void flip_windows(const GraphicsEngine::Windows &wlist);
   void do_sync_frame();
   void do_sync_frame();
   void do_flip_frame();
   void do_flip_frame();
+  INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
 
 
   PT(SceneSetup) setup_scene(const NodePath &camera, 
   PT(SceneSetup) setup_scene(const NodePath &camera, 
                              GraphicsStateGuardian *gsg);
                              GraphicsStateGuardian *gsg);
@@ -104,6 +119,7 @@ private:
   // process, and the list of windows for each stage.
   // process, and the list of windows for each stage.
   class WindowRenderer {
   class WindowRenderer {
   public:
   public:
+    void add_gsg(GraphicsStateGuardian *gsg);
     void add_window(Windows &wlist, GraphicsWindow *window);
     void add_window(Windows &wlist, GraphicsWindow *window);
     void remove_window(GraphicsWindow *window);
     void remove_window(GraphicsWindow *window);
     void do_frame(GraphicsEngine *engine);
     void do_frame(GraphicsEngine *engine);
@@ -111,6 +127,7 @@ private:
     void do_release(GraphicsEngine *engine);
     void do_release(GraphicsEngine *engine);
     void do_close(GraphicsEngine *engine);
     void do_close(GraphicsEngine *engine);
     void do_pending(GraphicsEngine *engine);
     void do_pending(GraphicsEngine *engine);
+    bool any_done_gsgs() const;
 
 
     Windows _cull;    // cull stage
     Windows _cull;    // cull stage
     Windows _cdraw;   // cull-and-draw-together stage
     Windows _cdraw;   // cull-and-draw-together stage
@@ -118,6 +135,7 @@ private:
     Windows _window;  // window stage, i.e. process windowing events 
     Windows _window;  // window stage, i.e. process windowing events 
     Windows _pending_release; // moved from _draw, pending release_gsg.
     Windows _pending_release; // moved from _draw, pending release_gsg.
     Windows _pending_close;   // moved from _window, pending close.
     Windows _pending_close;   // moved from _window, pending close.
+    GSGs _gsgs;       // draw stage
     Mutex _wl_lock;
     Mutex _wl_lock;
   };
   };
 
 
@@ -148,7 +166,8 @@ private:
   WindowRenderer _app;
   WindowRenderer _app;
   typedef pmap<string, PT(RenderThread) > Threads;
   typedef pmap<string, PT(RenderThread) > Threads;
   Threads _threads;
   Threads _threads;
-  string _threading_model;
+  FrameBufferProperties _frame_buffer_properties;
+  GraphicsThreadingModel _threading_model;
   bool _auto_flip;
   bool _auto_flip;
 
 
   enum FlipState {
   enum FlipState {

+ 32 - 0
panda/src/display/graphicsPipe.cxx

@@ -100,3 +100,35 @@ HardwareChannel *GraphicsPipe::
 get_hw_channel(GraphicsWindow *, int) {
 get_hw_channel(GraphicsWindow *, int) {
   return (HardwareChannel*)0L;
   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();
+  }
+}

+ 8 - 5
panda/src/display/graphicsPipe.h

@@ -28,6 +28,8 @@
 
 
 class HardwareChannel;
 class HardwareChannel;
 class GraphicsWindow;
 class GraphicsWindow;
+class GraphicsStateGuardian;
+class FrameBufferProperties;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : GraphicsPipe
 //       Class : GraphicsPipe
@@ -69,11 +71,12 @@ public:
   virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index);
   virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index);
 
 
 protected:
 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;
   Mutex _lock;
 
 

+ 42 - 7
panda/src/display/graphicsStateGuardian.I

@@ -41,15 +41,37 @@ ClipPlaneInfo() {
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::is_closed
+//     Function: GraphicsStateGuardian::get_properties
 //       Access: Public
 //       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);
   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
 //     Function: GraphicsStateGuardian::modify_state
 //       Access: Public
 //       Access: Public

+ 7 - 5
panda/src/display/graphicsStateGuardian.cxx

@@ -81,12 +81,13 @@ TypeHandle GraphicsStateGuardian::_type_handle;
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsStateGuardian::
 GraphicsStateGuardian::
-GraphicsStateGuardian(GraphicsWindow *win) {
-  _win = win;
+GraphicsStateGuardian(const FrameBufferProperties &properties) {
+  _properties = properties;
   _coordinate_system = default_coordinate_system;
   _coordinate_system = default_coordinate_system;
   _current_display_region = (DisplayRegion*)0L;
   _current_display_region = (DisplayRegion*)0L;
   _current_lens = (Lens *)NULL;
   _current_lens = (Lens *)NULL;
-  reset();
+  _needs_reset = true;
+  _closing_gsg = false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -106,6 +107,8 @@ GraphicsStateGuardian::
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 reset() {
 reset() {
+  _needs_reset = false;
+
   _display_region_stack_level = 0;
   _display_region_stack_level = 0;
   _frame_buffer_stack_level = 0;
   _frame_buffer_stack_level = 0;
   _lens_stack_level = 0;
   _lens_stack_level = 0;
@@ -1374,11 +1377,10 @@ free_pointers() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 close_gsg() {
 close_gsg() {
+  _closing_gsg = true;
   free_pointers();
   free_pointers();
   release_all_textures();
   release_all_textures();
   release_all_geoms();
   release_all_geoms();
-
-  _win = (GraphicsWindow *)NULL;
 }
 }
 
 
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS

+ 16 - 7
panda/src/display/graphicsStateGuardian.h

@@ -23,10 +23,13 @@
 
 
 #include "savedFrameBuffer.h"
 #include "savedFrameBuffer.h"
 #include "frameBufferStack.h"
 #include "frameBufferStack.h"
+#include "frameBufferProperties.h"
 #include "displayRegionStack.h"
 #include "displayRegionStack.h"
 #include "lensStack.h"
 #include "lensStack.h"
 
 
 #include "graphicsStateGuardianBase.h"
 #include "graphicsStateGuardianBase.h"
+#include "graphicsThreadingModel.h"
+#include "graphicsPipe.h"
 #include "sceneSetup.h"
 #include "sceneSetup.h"
 #include "luse.h"
 #include "luse.h"
 #include "coordinateSystem.h"
 #include "coordinateSystem.h"
@@ -61,7 +64,7 @@ class EXPCL_PANDA GraphicsStateGuardian : public GraphicsStateGuardianBase {
   // Interfaces all GSGs should have
   // Interfaces all GSGs should have
   //
   //
 public:
 public:
-  GraphicsStateGuardian(GraphicsWindow *win);
+  GraphicsStateGuardian(const FrameBufferProperties &properties);
   virtual ~GraphicsStateGuardian();
   virtual ~GraphicsStateGuardian();
 
 
 PUBLISHED:
 PUBLISHED:
@@ -69,7 +72,9 @@ PUBLISHED:
   void release_all_geoms();
   void release_all_geoms();
 
 
 public:
 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 void set_scene(SceneSetup *scene_setup);
   INLINE SceneSetup *get_scene() const;
   INLINE SceneSetup *get_scene() const;
@@ -119,6 +124,7 @@ public:
   virtual CPT(RenderState) begin_decal_base_second();
   virtual CPT(RenderState) begin_decal_base_second();
   virtual void finish_decal();
   virtual void finish_decal();
 
 
+  INLINE void reset_if_new();
   virtual void reset();
   virtual void reset();
 
 
   INLINE void modify_state(const RenderState *state);
   INLINE void modify_state(const RenderState *state);
@@ -232,8 +238,6 @@ protected:
   int _frame_buffer_stack_level;
   int _frame_buffer_stack_level;
   int _lens_stack_level;
   int _lens_stack_level;
 
 
-  GraphicsWindow *_win;
-
   CPT(DisplayRegion) _current_display_region;
   CPT(DisplayRegion) _current_display_region;
   CPT(Lens) _current_lens;
   CPT(Lens) _current_lens;
 
 
@@ -261,6 +265,9 @@ protected:
   ColorBlendAttrib::Mode _color_blend_mode;
   ColorBlendAttrib::Mode _color_blend_mode;
   TransparencyAttrib::Mode _transparency_mode;
   TransparencyAttrib::Mode _transparency_mode;
 
 
+  bool _needs_reset;
+  bool _closing_gsg;
+
 public:
 public:
   // Statistics
   // Statistics
   static PStatCollector _total_texusage_pcollector;
   static PStatCollector _total_texusage_pcollector;
@@ -324,11 +331,12 @@ private:
   typedef pset<GeomNodeContext *> GeomNodes;
   typedef pset<GeomNodeContext *> GeomNodes;
   GeomNodes _prepared_geom_nodes;  
   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:
 public:
-  INLINE GraphicsWindow* get_window(void) const { return _win; }
+  void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg);
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
@@ -351,6 +359,7 @@ private:
 
 
   friend class GraphicsPipe;
   friend class GraphicsPipe;
   friend class GraphicsWindow;
   friend class GraphicsWindow;
+  friend class GraphicsEngine;
 };
 };
 
 
 #include "graphicsStateGuardian.I"
 #include "graphicsStateGuardian.I"

+ 17 - 53
panda/src/display/graphicsWindow.cxx

@@ -37,11 +37,12 @@ TypeHandle GraphicsWindow::_type_handle;
 //               GraphicsEngine::make_window() function.
 //               GraphicsEngine::make_window() function.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsWindow::
 GraphicsWindow::
-GraphicsWindow(GraphicsPipe *pipe) {
+GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, this);
   MemoryUsage::update_type(this, this);
 #endif
 #endif
   _pipe = pipe;
   _pipe = pipe;
+  _gsg = gsg;
 
 
   // Some default properties for windows unless specified otherwise.
   // Some default properties for windows unless specified otherwise.
   // Other properties (size, title, etc.) must be explicitly
   // Other properties (size, title, etc.) must be explicitly
@@ -51,11 +52,7 @@ GraphicsWindow(GraphicsPipe *pipe) {
   _properties.set_fullscreen(false);
   _properties.set_fullscreen(false);
   _properties.set_minimized(false);
   _properties.set_minimized(false);
   _properties.set_cursor_hidden(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;
   _display_regions_stale = false;
   _window_event = "window-event";
   _window_event = "window-event";
 
 
@@ -581,32 +578,11 @@ make_scratch_display_region(int x_size, int y_size) const {
 bool GraphicsWindow::
 bool GraphicsWindow::
 begin_frame() {
 begin_frame() {
   if (_gsg == (GraphicsStateGuardian *)NULL) {
   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();
   return _gsg->begin_frame();
 }
 }
 
 
@@ -653,40 +629,28 @@ end_frame() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::make_gsg
+//     Function: GraphicsWindow::make_current
 //       Access: Public, Virtual
 //       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.
+//  Description: This function will be called within the draw thread
+//               during begin_frame() to ensure the graphics context
+//               is ready for drawing.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindow::
 void GraphicsWindow::
-make_gsg() {
+make_current() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::release_gsg
 //     Function: GraphicsWindow::release_gsg
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Releases the current GSG pointer, if it is currently
 //  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.
+//               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::
 void GraphicsWindow::
 release_gsg() {
 release_gsg() {
-  if (_gsg != (GraphicsStateGuardian *)NULL) {
-    _gsg->close_gsg();
-    _gsg.clear();
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::make_current
-//       Access: Public, Virtual
-//  Description: This function will be called within the draw thread
-//               during begin_frame() to ensure the graphics context
-//               is ready for drawing.
-////////////////////////////////////////////////////////////////////
-void GraphicsWindow::
-make_current() {
+  _gsg.clear();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 4
panda/src/display/graphicsWindow.h

@@ -58,7 +58,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GraphicsWindow : public TypedReferenceCount, public ClearableRegion {
 class EXPCL_PANDA GraphicsWindow : public TypedReferenceCount, public ClearableRegion {
 protected:
 protected:
-  GraphicsWindow(GraphicsPipe *pipe);
+  GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
 
 
 private:
 private:
   GraphicsWindow(const GraphicsWindow &copy);
   GraphicsWindow(const GraphicsWindow &copy);
@@ -119,12 +119,10 @@ public:
   void clear();
   void clear();
   virtual void end_frame();
   virtual void end_frame();
 
 
-  virtual void make_gsg();
-  virtual void release_gsg();
-
   // This method is called in the draw thread prior to issuing any
   // This method is called in the draw thread prior to issuing any
   // drawing commands for the window.
   // drawing commands for the window.
   virtual void make_current();
   virtual void make_current();
+  virtual void release_gsg();
 
 
   // These methods will be called within the app (main) thread.
   // These methods will be called within the app (main) thread.
   virtual void begin_flip();
   virtual void begin_flip();

+ 0 - 144
panda/src/display/windowProperties.I

@@ -513,150 +513,6 @@ clear_cursor_hidden() {
   _flags &= ~F_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 &
 INLINE ostream &
 operator << (ostream &out, const WindowProperties &properties) {
 operator << (ostream &out, const WindowProperties &properties) {
   properties.output(out);
   properties.output(out);

+ 1 - 65
panda/src/display/windowProperties.cxx

@@ -43,9 +43,6 @@ operator = (const WindowProperties &copy) {
   _y_size = copy._y_size;
   _y_size = copy._y_size;
   _title = copy._title;
   _title = copy._title;
   _flags = copy._flags;
   _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 &&
           _y_origin == other._y_origin &&
           _x_size == other._x_size &&
           _x_size == other._x_size &&
           _y_size == other._y_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;
   _y_size = 0;
   _title = string();
   _title = string();
   _flags = 0;
   _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()) {
   if (other.has_cursor_hidden()) {
     set_cursor_hidden(other.get_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()) {
   if (has_cursor_hidden()) {
     out << (get_cursor_hidden() ? "cursor_hidden " : "!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() << " ";
-  }
 }
 }

+ 0 - 37
panda/src/display/windowProperties.h

@@ -38,22 +38,6 @@ PUBLISHED:
   bool operator == (const WindowProperties &other) const;
   bool operator == (const WindowProperties &other) const;
   INLINE 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();
   void clear();
   INLINE bool is_any_specified() const;
   INLINE bool is_any_specified() const;
   
   
@@ -104,21 +88,6 @@ PUBLISHED:
   INLINE bool has_cursor_hidden() const;
   INLINE bool has_cursor_hidden() const;
   INLINE void clear_cursor_hidden();
   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 add_properties(const WindowProperties &other);
 
 
   void output(ostream &out) const;
   void output(ostream &out) const;
@@ -137,9 +106,6 @@ private:
     S_minimized        = 0x0040,
     S_minimized        = 0x0040,
     S_open             = 0x0080,
     S_open             = 0x0080,
     S_cursor_hidden    = 0x0100,
     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
   // This bitmask represents the true/false settings for various
@@ -161,9 +127,6 @@ private:
   int _y_size;
   int _y_size;
   string _title;
   string _title;
   int _flags;
   int _flags;
-  int _framebuffer_mode;
-  int _depth_bits;
-  int _color_bits;
 };
 };
 
 
 INLINE ostream &operator << (ostream &out, const WindowProperties &properties);
 INLINE ostream &operator << (ostream &out, const WindowProperties &properties);

+ 3 - 2
panda/src/distort/nonlinearImager.cxx

@@ -259,8 +259,9 @@ int NonlinearImager::
 add_viewer(DisplayRegion *dr) {
 add_viewer(DisplayRegion *dr) {
   GraphicsWindow *win = dr->get_window();
   GraphicsWindow *win = dr->get_window();
   GraphicsStateGuardian *gsg = win->get_gsg();
   GraphicsStateGuardian *gsg = win->get_gsg();
-  nassertr(_viewers.empty() || gsg == _gsg, -1);
+  nassertr(_viewers.empty() || (gsg == _gsg && win == _win), -1);
   _gsg = gsg;
   _gsg = gsg;
+  _win = win;
 
 
   int previous_vi = find_viewer(dr);
   int previous_vi = find_viewer(dr);
   if (previous_vi >= 0) {
   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
   // Make a display region of the proper size and clear it to prepare for
   // rendering the scene.
   // rendering the scene.
   PT(DisplayRegion) scratch_region =
   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);
   scratch_region->set_camera(screen._source_camera);
   engine->render_subframe(_gsg, scratch_region, true);
   engine->render_subframe(_gsg, scratch_region, true);
 
 

+ 2 - 0
panda/src/distort/nonlinearImager.h

@@ -32,6 +32,7 @@
 
 
 class GraphicsEngine;
 class GraphicsEngine;
 class GraphicsStateGuardian;
 class GraphicsStateGuardian;
+class GraphicsWindow;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : NonlinearImager
 //       Class : NonlinearImager
@@ -162,6 +163,7 @@ private:
   Viewers _viewers;
   Viewers _viewers;
   Screens _screens;
   Screens _screens;
   GraphicsStateGuardian *_gsg;
   GraphicsStateGuardian *_gsg;
+  GraphicsWindow *_win;
 
 
   bool _stale;
   bool _stale;
 };
 };

+ 16 - 16
panda/src/dxgsg7/dxGraphicsStateGuardian7.I

@@ -30,12 +30,12 @@ enable_line_smooth(bool val) {
     _line_smooth_enabled = val;
     _line_smooth_enabled = val;
   #ifdef NDEBUG
   #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";
            dxgsg7_cat.error() << "no HW support for line smoothing!!\n";
     }
     }
   #endif
   #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
   #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";
            dxgsg7_cat.error() << "no HW support for color dithering!!\n";
         return;
         return;
     }
     }
   #endif
   #endif
 
 
     _dither_enabled = val;
     _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) {
 enable_stencil_test(bool val) {
   if (_stencil_test_enabled != val) {
   if (_stencil_test_enabled != val) {
     _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) {
 enable_blend(bool val) {
   if (_blend_enabled != val) {
   if (_blend_enabled != val) {
     _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) {
 set_shademode(D3DSHADEMODE val) {
   if (_CurShadeMode != val) {
   if (_CurShadeMode != val) {
     _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) {
 enable_primitive_clipping(bool val) {
   if (_clipping_enabled != val) {
   if (_clipping_enabled != val) {
     _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) {
 enable_fog(bool val) {
   if ((_fog_enabled != val) && (_doFogType!=None)) {
   if ((_fog_enabled != val) && (_doFogType!=None)) {
     _fog_enabled = val;
     _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) {
   if (_alpha_test_enabled != val) {
     _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
 #ifdef GSG_VERBOSE
     dxgsg7_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
     dxgsg7_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
 #endif
 #endif
-    scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT,
+    _pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT,
                 D3DRGBA(color[0], color[1], color[2], color[3]));
                 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;
     dxgsg7_cat.debug() << " , " << reference_alpha << ")" << endl;
 #endif
 #endif
-    scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func);
+    _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func);
   }
   }
 
 
   if(_alpha_func_refval != reference_alpha) {
   if(_alpha_func_refval != reference_alpha) {
       _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)
   if (_blend_source_func != sfunc)
     {
     {
     _blend_source_func = sfunc;
     _blend_source_func = sfunc;
-    scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc);
+    _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc);
 #ifdef GSG_VERBOSE
 #ifdef GSG_VERBOSE
     dxgsg7_cat.debug() << "dxSrcBlendFunc(";
     dxgsg7_cat.debug() << "dxSrcBlendFunc(";
     switch (sfunc)
     switch (sfunc)
@@ -265,7 +265,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
   if ( _blend_dest_func != dfunc)
   if ( _blend_dest_func != dfunc)
     {
     {
     _blend_dest_func = dfunc;
     _blend_dest_func = dfunc;
-    scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc);
+    _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc);
 #ifdef GSG_VERBOSE
 #ifdef GSG_VERBOSE
     dxgsg7_cat.debug() << "dxDstBlendFunc(";
     dxgsg7_cat.debug() << "dxDstBlendFunc(";
     switch (dfunc)
     switch (dfunc)
@@ -307,7 +307,7 @@ INLINE void DXGraphicsStateGuardian7::
 enable_zwritemask(bool val) {
 enable_zwritemask(bool val) {
     if (_depth_write_enabled != val) {
     if (_depth_write_enabled != val) {
         _depth_write_enabled = val;
         _depth_write_enabled = val;
-        scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, val);
+        _pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, val);
     }
     }
 }
 }
 
 

文件差異過大導致無法顯示
+ 219 - 193
panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx


+ 17 - 11
panda/src/dxgsg7/dxGraphicsStateGuardian7.h

@@ -65,7 +65,7 @@ class EXPCL_PANDADX DXGraphicsStateGuardian7 : public GraphicsStateGuardian {
   friend class DXTextureContext7;
   friend class DXTextureContext7;
 
 
 public:
 public:
-  DXGraphicsStateGuardian7(GraphicsWindow *win);
+  DXGraphicsStateGuardian7(const FrameBufferProperties &properties);
   ~DXGraphicsStateGuardian7();
   ~DXGraphicsStateGuardian7();
 
 
   virtual void reset();
   virtual void reset();
@@ -128,7 +128,7 @@ public:
   virtual void bind_light(DirectionalLight *light, int light_id);
   virtual void bind_light(DirectionalLight *light, int light_id);
   virtual void bind_light(Spotlight *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 bool begin_scene();
   virtual void end_scene();
   virtual void end_scene();
   virtual void end_frame();
   virtual void end_frame();
@@ -144,7 +144,8 @@ public:
 
 
 public:
 public:
   // recreate_tex_callback needs pDD,pD3DDevice to be 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
 #ifndef USE_TEXFMTVEC
   LPDDPIXELFORMAT   _pTexPixFmts;
   LPDDPIXELFORMAT   _pTexPixFmts;
@@ -225,6 +226,7 @@ protected:
   INLINE void enable_stencil_test(bool val);
   INLINE void enable_stencil_test(bool val);
   void report_texmgr_stats();
   void report_texmgr_stats();
   void draw_multitri(Geom *geom, D3DPRIMITIVETYPE tri_id);
   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(int nVerts, const Geom *geom, ushort perFlags);
   void draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom);
   void draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom);
@@ -301,7 +303,7 @@ protected:
   DWORD _clip_plane_bits;
   DWORD _clip_plane_bits;
 
 
   RenderModeAttrib::Mode _current_fill_mode;  //poinr/wireframe/solid
   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
   // Cur Texture State
   TextureApplyAttrib::Mode _CurTexBlendMode;
   TextureApplyAttrib::Mode _CurTexBlendMode;
@@ -321,6 +323,16 @@ protected:
 
 
   bool _overlay_windows_supported;
   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:
 public:
   static GraphicsStateGuardian*
   static GraphicsStateGuardian*
   make_DXGraphicsStateGuardian(const FactoryParams &params);
   make_DXGraphicsStateGuardian(const FactoryParams &params);
@@ -329,12 +341,6 @@ public:
   static void init_type(void);
   static void init_type(void);
   virtual TypeHandle get_type(void) const;
   virtual TypeHandle get_type(void) const;
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
   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;  }
 //  INLINE void Set_HDC(HDC hdc)  {  _front_hdc = hdc;  }
   void adjust_view_rect(int x, int y);
   void adjust_view_rect(int x, int y);
   INLINE void SetDXReady(bool stat)  {  _dx_ready = stat; }
   INLINE void SetDXReady(bool stat)  {  _dx_ready = stat; }
@@ -346,7 +352,7 @@ public:
   #define DO_REACTIVATE_WINDOW true
   #define DO_REACTIVATE_WINDOW true
   bool  CheckCooperativeLevel(bool bDoReactivateWindow = false);
   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_frame();
   void  show_full_screen_frame();
   void  show_full_screen_frame();
   void  show_windowed_frame();
   void  show_windowed_frame();

+ 5 - 2
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!
 #error DX7 headers not available, you need to install MS Platform SDK or DirectX 8+ SDK!
 #endif
 #endif
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
 // disable nameless struct 'warning'
 // disable nameless struct 'warning'
 #pragma warning (disable : 4201)
 #pragma warning (disable : 4201)
@@ -63,12 +63,14 @@ typedef pvector<DDPIXELFORMAT> DDPixelFormatVec;
 
 
 #define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
 #define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
 #define SAFE_DELETE_ARRAY(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()
 // this is bDoDownToZero argument to RELEASE()
 #define RELEASE_DOWN_TO_ZERO true
 #define RELEASE_DOWN_TO_ZERO true
 #define RELEASE_ONCE false
 #define RELEASE_ONCE false
 
 
-// #define DEBUG_RELEASES
+#define DEBUG_RELEASES
 
 
 #ifdef DEBUG_RELEASES
 #ifdef DEBUG_RELEASES
 #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero)             \
 #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero)             \
@@ -124,6 +126,7 @@ typedef struct {
       bool              bIsLowVidMemCard;
       bool              bIsLowVidMemCard;
       bool              bIsTNLDevice;
       bool              bIsTNLDevice;
       bool              bIsSWRast;
       bool              bIsSWRast;
+      bool              bIsFullScreen;
       WORD              depth_buffer_bitdepth;  //GetSurfaceDesc is not reliable so must store this explicitly
       WORD              depth_buffer_bitdepth;  //GetSurfaceDesc is not reliable so must store this explicitly
       WORD              CardIDNum;  // its posn in DisplayArray, for dbgprint purposes
       WORD              CardIDNum;  // its posn in DisplayArray, for dbgprint purposes
       DDDEVICEIDENTIFIER2 DXDeviceID;
       DDDEVICEIDENTIFIER2 DXDeviceID;

+ 24 - 18
panda/src/dxgsg7/wdxGraphicsPipe7.cxx

@@ -40,10 +40,7 @@ wdxGraphicsPipe7() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsPipe7::
 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.
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsWindow) wdxGraphicsPipe7::
 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::
 bool wdxGraphicsPipe7::
 init() {
 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;
   return true;
+
+error:
+  return false;  
 }
 }

+ 3 - 1
panda/src/dxgsg7/wdxGraphicsPipe7.h

@@ -34,9 +34,10 @@ public:
 
 
   virtual string get_interface_name() const;
   virtual string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
   static PT(GraphicsPipe) pipe_constructor();
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
 
 
 protected:
 protected:
-  virtual PT(GraphicsWindow) make_window();
+  virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
 
 
 private:
 private:
   bool init();
   bool init();
@@ -61,6 +62,7 @@ public:
   }
   }
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
 
 
+
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 
 

+ 157 - 106
panda/src/dxgsg7/wdxGraphicsWindow7.cxx

@@ -116,10 +116,11 @@ TypeHandle wdxGraphicsWindow7::_type_handle;
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsWindow7::
 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() {
 ~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
 //     Function: wdxGraphicsWindow7::make_gsg
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -144,9 +186,9 @@ make_gsg() {
   _dxgsg = new DXGraphicsStateGuardian7(this);
   _dxgsg = new DXGraphicsStateGuardian7(this);
   _gsg = _dxgsg;
   _gsg = _dxgsg;
   // Tell the associated dxGSG about the window handle.
   // 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()
     wdxdisplay7_cat.error()
       << "Unable to find suitable rendering device.\n";
       << "Unable to find suitable rendering device.\n";
     release_gsg();
     release_gsg();
@@ -156,30 +198,7 @@ make_gsg() {
   set_coop_levels_and_display_modes();
   set_coop_levels_and_display_modes();
   create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer);
   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
 //     Function: wdxGraphicsWindow7::end_flip
@@ -234,15 +253,15 @@ handle_reshape() {
   if (_dxgsg!=NULL) {
   if (_dxgsg!=NULL) {
     HRESULT hr;
     HRESULT hr;
 
 
-    if (_dxgsg->scrn.pddsBack == NULL) {
+    if (_wcontext.pddsBack == NULL) {
       // assume this is initial creation reshape and ignore this call
       // assume this is initial creation reshape and ignore this call
       return;
       return;
     }
     }
 
 
-    // Clear the back/primary surface to black
+    // Clear the back/primary surface to black using ddraw
     DX_DECLARE_CLEAN(DDBLTFX, bltfx);
     DX_DECLARE_CLEAN(DDBLTFX, bltfx);
     bltfx.dwDDFX |= DDBLTFX_NOTEARING;
     bltfx.dwDDFX |= DDBLTFX_NOTEARING;
-    hr = _dxgsg->scrn.pddsPrimary->Blt
+    hr = _wcontext.pddsPrimary->Blt
       (NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
       (NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
     if (FAILED(hr)) {
     if (FAILED(hr)) {
       wdxdisplay7_cat.fatal()
       wdxdisplay7_cat.fatal()
@@ -251,7 +270,7 @@ handle_reshape() {
       exit(1);
       exit(1);
     }
     }
 
 
-    hr = _dxgsg->scrn.pDD->TestCooperativeLevel();
+    hr = _wcontext.pDD->TestCooperativeLevel();
     if (FAILED(hr)) {
     if (FAILED(hr)) {
       wdxdisplay7_cat.error()
       wdxdisplay7_cat.error()
         << "TestCooperativeLevel failed : result = "
         << "TestCooperativeLevel failed : result = "
@@ -264,10 +283,13 @@ handle_reshape() {
     set_to_temp_rendertarget();
     set_to_temp_rendertarget();
 
 
     // create the new resized rendertargets
     // 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;
     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);
   DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_curmode);
 
 
-  hr = _dxgsg->scrn.pDD->GetDisplayMode(&ddsd_curmode);
+  hr = _wcontext.pDD->GetDisplayMode(&ddsd_curmode);
   if (FAILED(hr)) {
   if (FAILED(hr)) {
     wdxdisplay7_cat.fatal() 
     wdxdisplay7_cat.fatal() 
       << "resize() - GetDisplayMode failed, result = "
       << "resize() - GetDisplayMode failed, result = "
@@ -310,7 +332,7 @@ do_fullscreen_resize(int x_size, int y_size) {
   DMI.maxHeight = y_size;
   DMI.maxHeight = y_size;
   DMI.pDDSD_Arr = DDSD_Arr;
   DMI.pDDSD_Arr = DDSD_Arr;
 
 
-  hr = _dxgsg->scrn.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search,
+  hr = _wcontext.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search,
                                           &DMI, EnumDisplayModesCallBack);
                                           &DMI, EnumDisplayModesCallBack);
   if (FAILED(hr)) {
   if (FAILED(hr)) {
     wdxdisplay7_cat.fatal()
     wdxdisplay7_cat.fatal()
@@ -319,7 +341,7 @@ do_fullscreen_resize(int x_size, int y_size) {
     return false;
     return false;
   }
   }
 
 
-  DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth;
+  DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth;
 
 
   DWORD dwFullScreenBitDepth;
   DWORD dwFullScreenBitDepth;
   DWORD requested_bpp = ddsd_curmode.ddpfPixelFormat.dwRGBBitCount;
   DWORD requested_bpp = ddsd_curmode.ddpfPixelFormat.dwRGBBitCount;
@@ -341,7 +363,7 @@ do_fullscreen_resize(int x_size, int y_size) {
     return false;
     return false;
   }
   }
 
 
-  hr = _dxgsg->scrn.pDD->TestCooperativeLevel();
+  hr = _wcontext.pDD->TestCooperativeLevel();
   if (FAILED(hr)) {
   if (FAILED(hr)) {
     wdxdisplay7_cat.error()
     wdxdisplay7_cat.error()
       << "TestCooperativeLevel failed : result = " 
       << "TestCooperativeLevel failed : result = " 
@@ -354,7 +376,7 @@ do_fullscreen_resize(int x_size, int y_size) {
   _dxgsg->free_dxgsg_objects();
   _dxgsg->free_dxgsg_objects();
 
 
    // let driver choose default refresh rate (hopefully its >=60Hz)   
    // 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);
                                         0L, 0L);
   if (FAILED(hr)) {
   if (FAILED(hr)) {
     wdxdisplay7_cat.error()
     wdxdisplay7_cat.error()
@@ -366,17 +388,17 @@ do_fullscreen_resize(int x_size, int y_size) {
 
 
   if (wdxdisplay7_cat.is_debug()) {
   if (wdxdisplay7_cat.is_debug()) {
     DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34); 
     DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34); 
-    _dxgsg->scrn.pDD->GetDisplayMode(&ddsd34);
+    _wcontext.pDD->GetDisplayMode(&ddsd34);
     wdxdisplay7_cat.debug()
     wdxdisplay7_cat.debug()
       << "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight
       << "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight
       << " at "<< ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, "
       << " at "<< ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, "
       << ddsd34.dwRefreshRate << "Hz\n";
       << 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->RecreateAllVideoSurfaces();
   _dxgsg->SetDXReady(true);
   _dxgsg->SetDXReady(true);
   return true;
   return true;
@@ -400,8 +422,8 @@ set_to_temp_rendertarget() {
     
     
   DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
   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.dwFlags &= ~DDSD_PITCH;
   ddsd.dwWidth = 1; 
   ddsd.dwWidth = 1; 
@@ -418,9 +440,9 @@ set_to_temp_rendertarget() {
     return false;
     return false;
   }
   }
   
   
-  if (_dxgsg->scrn.pddsZBuf != NULL) {
+  if (_wcontext.pddsZBuf != NULL) {
     DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsdZ);
     DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsdZ);
-    _dxgsg->scrn.pddsZBuf->GetSurfaceDesc(&ddsdZ);
+    _wcontext.pddsZBuf->GetSurfaceDesc(&ddsdZ);
     ddsdZ.dwFlags &= ~DDSD_PITCH;
     ddsdZ.dwFlags &= ~DDSD_PITCH;
     ddsdZ.dwWidth = 1;
     ddsdZ.dwWidth = 1;
     ddsdZ.dwHeight = 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)) {
   if (FAILED(hr)) {
     wdxdisplay7_cat.error()
     wdxdisplay7_cat.error()
       << "Resize failed to set render target to temporary surface, result = " 
       << "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_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
       DDSCAPS_FLIP | DDSCAPS_COMPLEX;
       DDSCAPS_FLIP | DDSCAPS_COMPLEX;
     ddsd.dwBackBufferCount = 1;
     ddsd.dwBackBufferCount = 1;
+    Display.bIsFullScreen=true;
 
 
     if (dx_full_screen_antialiasing) {
     if (dx_full_screen_antialiasing) {
       // cant check that d3ddevice has this capability yet, so got to
       // 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
   //  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
 #ifndef NDEBUG
-  if ((framebuffer_mode & WindowProperties::FM_depth) == 0) {
+  if ((frame_buffer_mode & FrameBufferProperties::FM_depth) == 0) {
     wdxdisplay7_cat.info()
     wdxdisplay7_cat.info()
       << "no zbuffer requested, skipping zbuffer creation\n";
       << "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
   // Check if the device supports z-bufferless hidden surface
   // removal. If so, we don't really need a z-buffer
   // removal. If so, we don't really need a z-buffer
   if ((!(pD3DDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
   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
     // Get z-buffer dimensions from the render target
     DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd);
     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.
     // Setup the surface desc for the z-buffer.
     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
     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];
     DDPIXELFORMAT ZBufPixFmts[MAX_DX_ZBUF_FMTS];
     cNumZBufFmts=0;
     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?  
     // should we pay attn to these at some point?  
     //int want_depth_bits = _props._want_depth_bits; 
     //int want_depth_bits = _props._want_depth_bits; 
     //int want_color_bits = _props._want_color_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;
     LPDDPIXELFORMAT pCurPixFmt, pz16 = NULL, pz24 = NULL, pz32 = NULL;
     for (i = 0, pCurPixFmt = ZBufPixFmts; 
     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;}
 #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
       SET_ZBUF_DEPTH(16);    // need this for fast path rasterizers
     } else {
     } else {
       if (IS_NVIDIA(Display.DXDeviceID)) {
       if (IS_NVIDIA(Display.DXDeviceID)) {
@@ -945,6 +968,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
   Display.pddsZBuf = pZDDSurf;
   Display.pddsZBuf = pZDDSurf;
   Display.view_rect = view_rect;
   Display.view_rect = view_rect;
 
 
+  _dxgsg->set_context(&Display);
   //pDD, pPrimaryDDSurf, pBackDDSurf, pZDDSurf, pD3DI, pD3DDevice, view_rect);
   //pDD, pPrimaryDDSurf, pBackDDSurf, pZDDSurf, pD3DI, pD3DDevice, view_rect);
   _dxgsg->dx_init();
   _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
 //       Access: Private
 //  Description: Searches for a suitable hardware device for
 //  Description: Searches for a suitable hardware device for
 //               rendering.
 //               rendering.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool wdxGraphicsWindow7::
 bool wdxGraphicsWindow7::
-search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
+choose_device(int devnum, DXDeviceInfo *pDevinfo) {
   wdxGraphicsPipe7 *dxpipe;
   wdxGraphicsPipe7 *dxpipe;
   DCAST_INTO_R(dxpipe, _pipe, false);
   DCAST_INTO_R(dxpipe, _pipe, false);
 
 
@@ -992,16 +1016,16 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
     return false;
     return false;
   }
   }
 
 
-  _dxgsg->scrn.pDD = pDD;
+  _wcontext.pDD = pDD;
 
 
   // GetDeviceID bug writes an extra 4 bytes, so need xtra space
   // GetDeviceID bug writes an extra 4 bytes, so need xtra space
   BYTE id_arr[sizeof(DDDEVICEIDENTIFIER2) + 4];
   BYTE id_arr[sizeof(DDDEVICEIDENTIFIER2) + 4];
   pDD->GetDeviceIdentifier((DDDEVICEIDENTIFIER2 *)&id_arr, 0x0);
   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()) {
   if (wdxdisplay7_cat.is_info()) {
-    DDDEVICEIDENTIFIER2 *pDevID = &_dxgsg->scrn.DXDeviceID;
+    DDDEVICEIDENTIFIER2 *pDevID = &_wcontext.DXDeviceID;
     wdxdisplay7_cat.info() 
     wdxdisplay7_cat.info() 
       << "GfxCard: " << pDevID->szDescription <<  "; DriverFile: '" 
       << "GfxCard: " << pDevID->szDescription <<  "; DriverFile: '" 
       << pDevID->szDriver  
       << pDevID->szDriver  
@@ -1015,7 +1039,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
   }
   }
 
 
   // Query DirectDraw for access to Direct3D
   // 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) {
   if(hr != DD_OK) {
     wdxdisplay7_cat.fatal()
     wdxdisplay7_cat.fatal()
       << "QI for D3D failed : result = " << ConvD3DErrorToString(hr) << endl;
       << "QI for D3D failed : result = " << ConvD3DErrorToString(hr) << endl;
@@ -1029,7 +1053,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
 
 
   ZeroMemory(d3ddevs,3*sizeof(D3DDEVICEDESC7));
   ZeroMemory(d3ddevs,3*sizeof(D3DDEVICEDESC7));
 
 
-  hr = _dxgsg->scrn.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs);
+  hr = _wcontext.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs);
   if(hr != DD_OK) {
   if(hr != DD_OK) {
     wdxdisplay7_cat.fatal()
     wdxdisplay7_cat.fatal()
       << "EnumDevices failed : result = " << ConvD3DErrorToString(hr) << endl;
       << "EnumDevices failed : result = " << ConvD3DErrorToString(hr) << endl;
@@ -1048,7 +1072,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
   } else {
   } else {
     wdxdisplay7_cat.error()
     wdxdisplay7_cat.error()
       << "No 3D HW present on device #" << devnum << ", skipping it... ("
       << "No 3D HW present on device #" << devnum << ", skipping it... ("
-      << _dxgsg->scrn.DXDeviceID.szDescription<<")\n";
+      << _wcontext.DXDeviceID.szDescription<<")\n";
     goto error_exit;
     goto error_exit;
   }
   }
 
 
@@ -1056,10 +1080,10 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
     DeviceIdx = SWRASTIDX; 
     DeviceIdx = SWRASTIDX; 
   }
   }
     
     
-  memcpy(&_dxgsg->scrn.D3DDevDesc, &d3ddevs[DeviceIdx], 
+  memcpy(&_wcontext.D3DDevDesc, &d3ddevs[DeviceIdx], 
          sizeof(D3DDEVICEDESC7));
          sizeof(D3DDEVICEDESC7));
 
 
-  _dxgsg->scrn.bIsTNLDevice = (DeviceIdx == TNLHALIDX);
+  _wcontext.bIsTNLDevice = (DeviceIdx == TNLHALIDX);
 
 
   // Get Current VidMem avail.  Note this is only an estimate, when we
   // Get Current VidMem avail.  Note this is only an estimate, when we
   // switch to fullscreen mode from desktop, more vidmem will be
   // 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
   // 1.2 meg (contradicting above comment and what I think would be
   // correct behavior (shouldnt FS mode release the desktop vidmem?),
   // correct behavior (shouldnt FS mode release the desktop vidmem?),
   // so this is the true value
   // so this is the true value
-  _dxgsg->scrn.MaxAvailVidMem = dwVidMemTotal;
+  _wcontext.MaxAvailVidMem = dwVidMemTotal;
     
     
 #define LOWVIDMEMTHRESHOLD 5500000
 #define LOWVIDMEMTHRESHOLD 5500000
 #define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000     // every vidcard we deal with should have at least 1MB
 #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
   // 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>CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) && 
      (dwVidMemTotal< LOWVIDMEMTHRESHOLD));   
      (dwVidMemTotal< LOWVIDMEMTHRESHOLD));   
 
 
   if (!dx_do_vidmemsize_check) {
   if (!dx_do_vidmemsize_check) {
-    _dxgsg->scrn.MaxAvailVidMem = 0xFFFFFFFF;
-    _dxgsg->scrn.bIsLowVidMemCard = false; 
+    _wcontext.MaxAvailVidMem = 0xFFFFFFFF;
+    _wcontext.bIsLowVidMemCard = false; 
   }
   }
 
 
   if (DeviceIdx == SWRASTIDX) {
   if (DeviceIdx == SWRASTIDX) {
     // this will force 640x480x16, is this what we want for all sw rast?
     // 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;
     dx_force_16bpp_zbuffer = true;
   }
   }
 
 
@@ -1125,7 +1149,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
     if (FAILED(hr)) {
     if (FAILED(hr)) {
       wdxdisplay7_cat.fatal()
       wdxdisplay7_cat.fatal()
         << "EnumDisplayModes failed for device #" << devnum 
         << "EnumDisplayModes failed for device #" << devnum 
-        << " (" << _dxgsg->scrn.DXDeviceID.szDescription
+        << " (" << _wcontext.DXDeviceID.szDescription
         << "), result = " << ConvD3DErrorToString(hr) << endl;
         << "), result = " << ConvD3DErrorToString(hr) << endl;
       // goto skip_device;
       // goto skip_device;
       exit(1);  // probably want to exit, since it may be my fault
       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
     // resolution and best rendertarget bpp and still have at least 2
     // meg of texture vidmem
     // meg of texture vidmem
         
         
-    DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth;
+    DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth;
 
 
     DWORD dwFullScreenBitDepth;
     DWORD dwFullScreenBitDepth;
 
 
@@ -1158,12 +1182,12 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
       wdxdisplay7_cat.fatal() 
       wdxdisplay7_cat.fatal() 
         << "No Supported FullScreen resolutions at " << dwRenderWidth
         << "No Supported FullScreen resolutions at " << dwRenderWidth
         << "x" << dwRenderHeight << " for device #" << devnum 
         << "x" << dwRenderHeight << " for device #" << devnum 
-        << " (" << _dxgsg->scrn.DXDeviceID.szDescription
+        << " (" << _wcontext.DXDeviceID.szDescription
         << "), skipping device...\n";
         << "), skipping device...\n";
       goto error_exit;
       goto error_exit;
     }
     }
         
         
-    if (_dxgsg->scrn.bIsLowVidMemCard) {
+    if (_wcontext.bIsLowVidMemCard) {
       {
       {
         // hack: figuring out exactly what res to use is tricky,
         // hack: figuring out exactly what res to use is tricky,
         // instead I will just use 640x480 if we have < 3 meg avail
         // 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) {
   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;
   return true;
     
     
   // handle errors within this for device loop
   // handle errors within this for device loop
     
     
  error_exit:
  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;
   return false;
 }
 }
 
 
@@ -1220,16 +1244,15 @@ set_coop_levels_and_display_modes() {
     // tell d3d to preserve the fpu state across calls.  this hurts
     // tell d3d to preserve the fpu state across calls.  this hurts
     // perf, but is good for dbgging
     // perf, but is good for dbgging
     SCL_FPUFlag = DDSCL_FPUPRESERVE;
     SCL_FPUFlag = DDSCL_FPUPRESERVE;
-
   } else {
   } else {
     SCL_FPUFlag = DDSCL_FPUSETUP;
     SCL_FPUFlag = DDSCL_FPUSETUP;
   }
   }
 
 
-  DXScreenData *pScrn = &_dxgsg->scrn;
+  //  DXScreenData *pScrn = &_dxgsg->scrn;
 
 
   if (!is_fullscreen()) {
   if (!is_fullscreen()) {
-    hr = pScrn->pDD->SetCooperativeLevel(_mwindow, 
-                                         SCL_FPUFlag | DDSCL_NORMAL);
+    hr = _wcontext.pDD->SetCooperativeLevel(_hWnd, 
+                                            SCL_FPUFlag | DDSCL_NORMAL);
     if (FAILED(hr)) {
     if (FAILED(hr)) {
       wdxdisplay7_cat.fatal()
       wdxdisplay7_cat.fatal()
         << "SetCooperativeLevel failed : result = "
         << "SetCooperativeLevel failed : result = "
@@ -1246,7 +1269,7 @@ set_coop_levels_and_display_modes() {
   // restore that functionality.
   // restore that functionality.
   DWORD devnum = 0;
   DWORD devnum = 0;
   {
   {
-    DXScreenData *pScrn = &_dxgsg->scrn;
+    // DXScreenData *pScrn = &_dxgsg->scrn;
 
 
     // need to set focus/device windows for multimon
     // need to set focus/device windows for multimon
     // focus window is primary monitor that will receive keybd input
     // 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
     // SetCoopLevel twice.  so we do it, it really shouldnt be necessary
     // if drivers werent buggy
     // if drivers werent buggy
     for (int jj=0; jj<2; jj++) {
     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)) {
       if (FAILED(hr)) {
         wdxdisplay7_cat.fatal() 
         wdxdisplay7_cat.fatal() 
           << "SetCooperativeLevel failed for device #" << devnum 
           << "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)) {
     if (FAILED(hr)) {
       wdxdisplay7_cat.fatal()
       wdxdisplay7_cat.fatal()
         << "TestCooperativeLevel failed: result = " << ConvD3DErrorToString(hr)
         << "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";
         << "Full screen app failed to get exclusive mode on init, exiting..\n";
       exit(1);
       exit(1);
     }
     }
-    
+
     // note: its important we call SetDisplayMode on all cards before
     // note: its important we call SetDisplayMode on all cards before
     // creating surfaces on any of them to let driver choose default
     // creating surfaces on any of them to let driver choose default
     // refresh rate (hopefully its >=60Hz)
     // 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)) {
     if (FAILED(hr)) {
       wdxdisplay7_cat.fatal()
       wdxdisplay7_cat.fatal()
-        << "SetDisplayMode failed to set (" << pScrn->dwRenderWidth
-        << "x" <<pScrn->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;
         << ConvD3DErrorToString(hr) << endl;
       exit(1);
       exit(1);
     }
     }
     
     
     if(wdxdisplay7_cat.is_debug()) {
     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()
       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

+ 6 - 6
panda/src/dxgsg7/wdxGraphicsWindow7.h

@@ -42,13 +42,12 @@ typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID  *lplp
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX wdxGraphicsWindow7 : public WinGraphicsWindow {
 class EXPCL_PANDADX wdxGraphicsWindow7 : public WinGraphicsWindow {
 public:
 public:
-  wdxGraphicsWindow7(GraphicsPipe *pipe);
+  wdxGraphicsWindow7(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
   virtual ~wdxGraphicsWindow7();
   virtual ~wdxGraphicsWindow7();
-
-  virtual void make_gsg();
-  virtual void release_gsg();
-
   virtual void end_flip();
   virtual void end_flip();
+  //virtual bool begin_frame();
+  virtual void make_current(void);
+  virtual bool open_window(void);
 
 
 protected:
 protected:
   virtual void fullscreen_restored(WindowProperties &properties);
   virtual void fullscreen_restored(WindowProperties &properties);
@@ -59,10 +58,11 @@ private:
   bool set_to_temp_rendertarget();
   bool set_to_temp_rendertarget();
   void create_screen_buffers_and_device(DXScreenData &Display,
   void create_screen_buffers_and_device(DXScreenData &Display,
                                         bool force_16bpp_zbuffer);
                                         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();
   void set_coop_levels_and_display_modes();
 
 
   DXGraphicsStateGuardian7 *_dxgsg;
   DXGraphicsStateGuardian7 *_dxgsg;
+  DXScreenData _wcontext;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 2 - 54
panda/src/dxgsg8/config_dxgsg8.cxx

@@ -27,7 +27,8 @@
 #include <dconfig.h>
 #include <dconfig.h>
 
 
 Configure(config_dxgsg8);
 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");
 NotifyCategoryDef(wdxdisplay8, "windisplay");
 
 
 // Configure this variable true to cause the DXGSG to show each
 // Configure this variable true to cause the DXGSG to show each
@@ -196,58 +197,5 @@ init_libdxgsg8() {
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
   selection->add_pipe_type(wdxGraphicsPipe8::get_class_type(),
   selection->add_pipe_type(wdxGraphicsPipe8::get_class_type(),
                            wdxGraphicsPipe8::pipe_constructor);
                            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";
 }
 }
-

+ 2 - 2
panda/src/dxgsg8/config_dxgsg8.h

@@ -21,7 +21,7 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 #include "notifyCategoryProxy.h"
 #include "notifyCategoryProxy.h"
-#include <d3d8.h>
+#include "dxgsg8base.h"
 
 
 NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX);
 NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX);
 NotifyCategoryDecl(wdxdisplay8, 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 const bool link_tristrips;
 extern DWORD dx_multisample_antialiasing_level;
 extern DWORD dx_multisample_antialiasing_level;
 extern bool dx_use_triangle_mipgen_filter;
 extern bool dx_use_triangle_mipgen_filter;
-extern const char *D3DFormatStr(D3DFORMAT fmt);
 extern bool dx_use_dx_cursor;
 extern bool dx_use_dx_cursor;
 
 
+
 // debug flags we might want to use in full optimized build
 // debug flags we might want to use in full optimized build
 extern bool dx_ignore_mipmaps;
 extern bool dx_ignore_mipmaps;
 extern bool dx_mipmap_everything;
 extern bool dx_mipmap_everything;

+ 20 - 20
panda/src/dxgsg8/dxGraphicsStateGuardian8.I

@@ -30,12 +30,12 @@ enable_line_smooth(bool val) {
     _line_smooth_enabled = val;
     _line_smooth_enabled = val;
   #ifdef NDEBUG
   #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";
            dxgsg8_cat.error() << "no HW support for line smoothing!!\n";
     }
     }
   #endif
   #endif
 
 
-    scrn.pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val);
+    _pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val);
   }
   }
 }
 }
 
 
@@ -50,14 +50,14 @@ enable_dither(bool val) {
 
 
   #ifdef _DEBUG
   #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";
            dxgsg8_cat.error() << "no HW support for color dithering!!\n";
         return;
         return;
     }
     }
   #endif
   #endif
 
 
     _dither_enabled = val;
     _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) {
 enable_stencil_test(bool val) {
   if (_stencil_test_enabled != val) {
   if (_stencil_test_enabled != val) {
     _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) {
 enable_blend(bool val) {
   if (_blend_enabled != val) {
   if (_blend_enabled != val) {
     _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) {
 set_color_writemask(UINT color_writemask) {
   if (_color_writemask != color_writemask) {
   if (_color_writemask != color_writemask) {
     _color_writemask = color_writemask;
     _color_writemask = color_writemask;
-    if(scrn.bCanDirectDisableColorWrites) {
+    if(_pScrn->bCanDirectDisableColorWrites) {
         // only newer HW supports this rstate
         // only newer HW supports this rstate
-        scrn.pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask);
+        _pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask);
     } else {
     } else {
         // blending can only handle on/off
         // blending can only handle on/off
         assert((color_writemask==0x0)||(color_writemask==0xFFFFFFFF));
         assert((color_writemask==0x0)||(color_writemask==0xFFFFFFFF));
@@ -129,7 +129,7 @@ INLINE void DXGraphicsStateGuardian8::
 enable_gouraud_shading(bool val) {
 enable_gouraud_shading(bool val) {
   if (_bGouraudShadingOn != val) {
   if (_bGouraudShadingOn != val) {
     _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) {
 enable_primitive_clipping(bool val) {
   if (_clipping_enabled != val) {
   if (_clipping_enabled != val) {
     _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) {
 enable_fog(bool val) {
   if ((_fog_enabled != val) && (_doFogType!=None)) {
   if ((_fog_enabled != val) && (_doFogType!=None)) {
     _fog_enabled = val;
     _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
 #ifdef USE_VERTEX_SHADERS
   if(_CurVertexShader!=NULL) {
   if(_CurVertexShader!=NULL) {
     // this needs optimization
     // this needs optimization
-    HRESULT hr = scrn.pD3DDevice->SetVertexShader(_CurVertexShader);
+    HRESULT hr = _pD3DDevice->SetVertexShader(_CurVertexShader);
     #ifndef NDEBUG
     #ifndef NDEBUG
     if(FAILED(hr)) {
     if(FAILED(hr)) {
            dxgsg8_cat.error() << "SetVertexShader for custom vtx shader failed" << D3DERRORSTRING(hr);
            dxgsg8_cat.error() << "SetVertexShader for custom vtx shader failed" << D3DERRORSTRING(hr);
@@ -179,7 +179,7 @@ set_vertex_format(DWORD NewFvfType) {
   if (_CurFVFType != NewFvfType) {
   if (_CurFVFType != NewFvfType) {
     _CurFVFType = NewFvfType;
     _CurFVFType = NewFvfType;
 
 
-    HRESULT hr = scrn.pD3DDevice->SetVertexShader(NewFvfType);
+    HRESULT hr = _pD3DDevice->SetVertexShader(NewFvfType);
  #ifndef NDEBUG
  #ifndef NDEBUG
     if(FAILED(hr)) {
     if(FAILED(hr)) {
            dxgsg8_cat.error() << "SetVertexShader(0x" << (void*)NewFvfType<<") failed" << D3DERRORSTRING(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) {
   if (_alpha_test_enabled != val) {
     _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
 #ifdef GSG_VERBOSE
     dxgsg8_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
     dxgsg8_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
 #endif
 #endif
-    scrn.pD3DDevice->SetRenderState( D3DRS_AMBIENT,
+    _pD3DDevice->SetRenderState( D3DRS_AMBIENT,
                 D3DCOLOR_COLORVALUE(color[0], color[1], color[2], color[3]));
                 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;
     dxgsg8_cat.debug() << " , " << reference_alpha << ")" << endl;
 #endif
 #endif
-    scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func);
+    _pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func);
   }
   }
 
 
   if(_alpha_func_refval != reference_alpha) {
   if(_alpha_func_refval != reference_alpha) {
       _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)
   if (_blend_source_func != sfunc)
     {
     {
     _blend_source_func = sfunc;
     _blend_source_func = sfunc;
-    scrn.pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc);
+    _pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc);
 #ifdef GSG_VERBOSE
 #ifdef GSG_VERBOSE
     dxgsg8_cat.debug() << "dxSrcBlendFunc(";
     dxgsg8_cat.debug() << "dxSrcBlendFunc(";
     switch (sfunc)
     switch (sfunc)
@@ -323,7 +323,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
   if ( _blend_dest_func != dfunc)
   if ( _blend_dest_func != dfunc)
     {
     {
     _blend_dest_func = dfunc;
     _blend_dest_func = dfunc;
-    scrn.pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc);
+    _pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc);
 #ifdef GSG_VERBOSE
 #ifdef GSG_VERBOSE
     dxgsg8_cat.debug() << "dxDstBlendFunc(";
     dxgsg8_cat.debug() << "dxDstBlendFunc(";
     switch (dfunc)
     switch (dfunc)
@@ -365,7 +365,7 @@ INLINE void DXGraphicsStateGuardian8::
 enable_zwritemask(bool val) {
 enable_zwritemask(bool val) {
     if (_depth_write_enabled != val) {
     if (_depth_write_enabled != val) {
         _depth_write_enabled = val;
         _depth_write_enabled = val;
-        scrn.pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, val);
+        _pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, val);
     }
     }
 }
 }
 
 

文件差異過大導致無法顯示
+ 178 - 213
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx


+ 20 - 5
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -70,7 +70,7 @@ class EXPCL_PANDADX DXGraphicsStateGuardian8 : public GraphicsStateGuardian {
   friend class DXTextureContext8;
   friend class DXTextureContext8;
 
 
 public:
 public:
-  DXGraphicsStateGuardian8(GraphicsWindow *win);
+  DXGraphicsStateGuardian8(const FrameBufferProperties &properties);
   ~DXGraphicsStateGuardian8();
   ~DXGraphicsStateGuardian8();
 
 
   virtual void reset();
   virtual void reset();
@@ -150,7 +150,8 @@ public:
 
 
 public:
 public:
   // recreate_tex_callback needs these to be public
   // recreate_tex_callback needs these to be public
-  DXScreenData scrn;
+  DXScreenData *_pScrn;
+  LPDIRECT3DDEVICE8 _pD3DDevice;  // same as pScrn->_pD3DDevice, cached for spd
 
 
 protected:
 protected:
   virtual void enable_lighting(bool enable);
   virtual void enable_lighting(bool enable);
@@ -303,7 +304,9 @@ protected:
   DWORD _clip_plane_bits;
   DWORD _clip_plane_bits;
 
 
   RenderModeAttrib::Mode _current_fill_mode;  //poinr/wireframe/solid
   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
   // Cur Texture State
   TextureApplyAttrib::Mode _CurTexBlendMode;
   TextureApplyAttrib::Mode _CurTexBlendMode;
@@ -320,9 +323,20 @@ protected:
 
 
   bool _overlay_windows_supported;
   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:
 public:
   static GraphicsStateGuardian*
   static GraphicsStateGuardian*
   make_DXGraphicsStateGuardian8(const FactoryParams &params);
   make_DXGraphicsStateGuardian8(const FactoryParams &params);
+  void set_context(DXScreenData *pNewContextData);
 
 
   static TypeHandle get_class_type(void);
   static TypeHandle get_class_type(void);
   static void init_type(void);
   static void init_type(void);
@@ -347,7 +361,7 @@ public:
   bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
   bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
 
 
   void show_frame(bool bNoNewFrameDrawn = false);
   void show_frame(bool bNoNewFrameDrawn = false);
-  void dx_init(HCURSOR hMouseCursor);
+  void dx_init(void);
 
 
   void support_overlay_window(bool flag);
   void support_overlay_window(bool flag);
 
 
@@ -355,7 +369,8 @@ private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 };
 };
 
 
-#include "DXGraphicsStateGuardian8.I"
+HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark);
 
 
+#include "DXGraphicsStateGuardian8.I"
 #endif
 #endif
 
 

+ 25 - 7
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(pbuf->get_component_width()==sizeof(BYTE));   // cant handle anything else now
     assert(pixbuf_type==PixelBuffer::T_unsigned_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)) {
     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";
         dxgsg8_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n";
         return NULL;
         return NULL;
@@ -1411,7 +1413,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
 
 
     if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0,
     if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0,
                                                    TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) {
                                                    TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) {
-        dxgsg8_cat.error() << "pD3DDevice->CreateTexture() failed!" << D3DERRORSTRING(hr);
+        dxgsg8_cat.error() << "D3D CreateTexture failed!" << D3DERRORSTRING(hr);
         goto error_exit;
         goto error_exit;
     }
     }
 
 
@@ -1427,11 +1429,21 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
 #endif
 #endif
 #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 the newly created texture
     return _pD3DTexture8;
     return _pD3DTexture8;
 
 
@@ -1547,18 +1559,21 @@ FillDDSurfTexturePixels(void) {
     if(bUsingTempPixBuf) {
     if(bUsingTempPixBuf) {
       SAFE_DELETE_ARRAY(pPixels);
       SAFE_DELETE_ARRAY(pPixels);
     }
     }
-    RELEASE(pMipLevel0,dxgsg8,"texture",RELEASE_ONCE);
+    RELEASE(pMipLevel0,dxgsg8,"FillDDSurf MipLev0 texture ptr",RELEASE_ONCE);
     return hr;
     return hr;
 }
 }
 
 
-
-
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // Name: DeleteTexture()
 // Name: DeleteTexture()
 // Desc: Release the surface used to store the texture
 // Desc: Release the surface used to store the texture
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void DXTextureContext8::
 void DXTextureContext8::
 DeleteTexture( ) {
 DeleteTexture( ) {
+    if(_pD3DTexture8==NULL) {
+        // dont bother printing the msg below, since we already released it.
+        return;
+    }
+
     if(dxgsg8_cat.is_spam()) {
     if(dxgsg8_cat.is_spam()) {
         dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
         dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
     }
     }
@@ -1603,6 +1618,9 @@ TextureContext(tex) {
 
 
 DXTextureContext8::
 DXTextureContext8::
 ~DXTextureContext8() {
 ~DXTextureContext8() {
+    if(dxgsg8_cat.is_spam()) {
+        dxgsg8_cat.spam() << "Deleting DX8 TexContext for " << _tex->get_name() << "\n";
+    }
     DeleteTexture();
     DeleteTexture();
     TextureContext::~TextureContext();
     TextureContext::~TextureContext();
     _tex = NULL;
     _tex = NULL;

+ 19 - 5
panda/src/dxgsg8/dxgsg8base.h

@@ -19,9 +19,6 @@
 #ifndef DXGSG8BASE_H
 #ifndef DXGSG8BASE_H
 #define DXGSG8BASE_H
 #define DXGSG8BASE_H
 
 
-#include <pandabase.h>
-#include <graphicsWindow.h>
-
 // include win32 defns for everything up to WinServer2003, and assume I'm smart enough to
 // include win32 defns for everything up to WinServer2003, and assume I'm smart enough to
 // use GetProcAddress for backward compat on newer fns
 // use GetProcAddress for backward compat on newer fns
 // Note DX8 cannot be installed on w95, so OK to assume base of win98
 // Note DX8 cannot be installed on w95, so OK to assume base of win98
@@ -41,6 +38,9 @@
 #include <dxerr8.h>
 #include <dxerr8.h>
 #undef WIN32_LEAN_AND_MEAN
 #undef WIN32_LEAN_AND_MEAN
 
 
+#include "pandabase.h"
+#include "graphicsWindow.h"
+
 #if D3D_SDK_VERSION != 220
 #if D3D_SDK_VERSION != 220
 #error you have DX 8.0 headers, not DX 8.1, you need to install DX 8.1 SDK!
 #error you have DX 8.0 headers, not DX 8.1, you need to install DX 8.1 SDK!
 #endif
 #endif
@@ -61,6 +61,11 @@
 #endif
 #endif
 #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
 #define D3D_MAXTEXTURESTAGES 8
 
 
 typedef enum {VertexShader,PixelShader} ShaderType;
 typedef enum {VertexShader,PixelShader} ShaderType;
@@ -82,12 +87,15 @@ typedef DWORD DXShaderHandle;
 
 
 // for stuff outside a panda class
 // for stuff outside a panda class
 #define SAFE_RELEASE(p)      { if(p) { assert(IS_VALID_PTR(p)); (p)->Release(); (p)=NULL; } }
 #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()
 // this is bDoDownToZero argument to RELEASE()
 #define RELEASE_DOWN_TO_ZERO true
 #define RELEASE_DOWN_TO_ZERO true
 #define RELEASE_ONCE false
 #define RELEASE_ONCE false
 
 
-//#define DEBUG_RELEASES
+
+// uncomment to add refcnt debug output 
+#define DEBUG_RELEASES
 
 
 #ifdef DEBUG_RELEASES
 #ifdef DEBUG_RELEASES
 #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero)             {  \
 #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero)             {  \
@@ -183,7 +191,7 @@ typedef enum {
 
 
 typedef struct {
 typedef struct {
       LPDIRECT3DDEVICE8 pD3DDevice;
       LPDIRECT3DDEVICE8 pD3DDevice;
-      LPDIRECT3D8       pD3D8;
+      LPDIRECT3D8       pD3D8;  // copied from DXGraphicsPipe8 for convenience
       HWND              hWnd;
       HWND              hWnd;
       HMONITOR          hMon;
       HMONITOR          hMon;
       DWORD             MaxAvailVidMem;
       DWORD             MaxAvailVidMem;
@@ -203,5 +211,11 @@ typedef struct {
       D3DADAPTER_IDENTIFIER8 DXDeviceID;
       D3DADAPTER_IDENTIFIER8 DXDeviceID;
 } DXScreenData;
 } DXScreenData;
 
 
+
+//utility stuff
+extern map<D3DFORMAT_FLAG,D3DFORMAT> g_D3DFORMATmap;
+extern void Init_D3DFORMAT_map(void);
+extern const char *D3DFormatStr(D3DFORMAT fmt);
+
 #endif
 #endif
 
 

+ 585 - 49
panda/src/dxgsg8/wdxGraphicsPipe8.cxx

@@ -23,10 +23,8 @@
 TypeHandle wdxGraphicsPipe8::_type_handle;
 TypeHandle wdxGraphicsPipe8::_type_handle;
 
 
 // #define LOWVIDMEMTHRESHOLD 3500000
 // #define LOWVIDMEMTHRESHOLD 3500000
-// #define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000
 #define LOWVIDMEMTHRESHOLD 5700000  // 4MB cards should fall below this
 #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 CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000  // if # is > 1MB, card is lying and I cant tell what it is
-
 #define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF
 #define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -38,6 +36,7 @@ wdxGraphicsPipe8::
 wdxGraphicsPipe8() {
 wdxGraphicsPipe8() {
   _hDDrawDLL = NULL;
   _hDDrawDLL = NULL;
   _hD3D8_DLL = NULL;
   _hD3D8_DLL = NULL;
+  _pD3D8 = NULL;
   _is_valid = init();
   _is_valid = init();
 }
 }
 
 
@@ -48,14 +47,10 @@ wdxGraphicsPipe8() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsPipe8::
 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.
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsWindow) wdxGraphicsPipe8::
 PT(GraphicsWindow) wdxGraphicsPipe8::
-make_window() {
+make_window(GraphicsStateGuardian *gsg) {
   if (!_is_valid) {
   if (!_is_valid) {
     return NULL;
     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::
 bool wdxGraphicsPipe8::
 init() {
 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(!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 (_Direct3DCreate8 == NULL) {
-    wdxdisplay8_cat.error()
-      << "GetProcAddress for " << d3dcreate8_name << "failed!" << endl;
-    return false;
+  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();
   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);
     hr = pDD->GetAvailableVidMem(&ddsGAVMCaps, &dwVidMemTotal, &dwVidMemFree);
     if (FAILED(hr)) {
     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
       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
     // registry location for a given card
 
 
     // assume buggy drivers (this means you, FireGL2) may return zero
     // 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 = 
     bool bLowVidMemFlag = 
       ((dwVidMemTotal > CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) && 
       ((dwVidMemTotal > CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) && 
        (dwVidMemTotal< LOWVIDMEMTHRESHOLD));
        (dwVidMemTotal< LOWVIDMEMTHRESHOLD));
@@ -352,3 +372,519 @@ dx7_driver_enum_callback(GUID *pGUID, TCHAR *strDesc, TCHAR *strName,
 
 
   return DDENUMRET_OK;
   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 (" <<RequestedX_Size<<"x" << RequestedY_Size 
+          << "," << D3DFormatStr(dispmode.Format) << ")\nReqdVidMem: "
+          << (int)RendTgtMinMemReqmt << " AvailVidMem: " 
+          << scrn.MaxAvailVidMem << endl;
+
+      if (RendTgtMinMemReqmt > 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) || (MinMemReqmt<scrn.MaxAvailVidMem)) {
+        if (!IS_16BPP_ZBUFFER(zformat)) {
+          // see if things fit with a 16bpp zbuffer
+
+          if (!find_best_depth_format(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: wdxGraphicsPipew8::make_gsg
+//       Access: Public, Virtual
+//  Description: Creates a new empty GSG.  Can do no real initialization
+//               until window is opened, and we know the full device requirements
+////////////////////////////////////////////////////////////////////
+
+PT(GraphicsStateGuardian) wdxGraphicsPipe8::
+make_gsg(const FrameBufferProperties &properties) {
+
+
+  // FrameBufferProperties really belongs as part of the window/renderbuffer specification
+  // put here because of GLX multithreading requirement
+  PT(DXGraphicsStateGuardian8) gsg = new DXGraphicsStateGuardian8(properties);
+  return gsg.p();
+
+/*
+  nassertv(_gsg == (GraphicsStateGuardian *)NULL);
+  _dxgsg = new DXGraphicsStateGuardian8(this);
+  _gsg = _dxgsg;
+
+  // Tell the associated dxGSG about the window handle.
+  _dxgsg->scrn.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<D3DFORMAT_FLAG,D3DFORMAT> 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";
+}
+

+ 22 - 3
panda/src/dxgsg8/wdxGraphicsPipe8.h

@@ -22,7 +22,7 @@
 #include "pandabase.h"
 #include "pandabase.h"
 #include "winGraphicsPipe.h"
 #include "winGraphicsPipe.h"
 #include "pvector.h"
 #include "pvector.h"
-
+#include "dxgsg8base.h"
 #include <ddraw.h>
 #include <ddraw.h>
 
 
 typedef struct {
 typedef struct {
@@ -48,8 +48,25 @@ public:
   virtual string get_interface_name() const;
   virtual string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
   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:
 protected:
-  virtual PT(GraphicsWindow) make_window();
+  virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
 
 
 private:
 private:
   bool init();
   bool init();
@@ -62,6 +79,8 @@ private:
 private:
 private:
   HINSTANCE _hDDrawDLL;
   HINSTANCE _hDDrawDLL;
   HINSTANCE _hD3D8_DLL;
   HINSTANCE _hD3D8_DLL;
+  LPDIRECT3D8 _pD3D8;
+
 
 
   typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion);
   typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion);
   typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter);
   typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter);
@@ -83,7 +102,7 @@ private:
   
   
   typedef pvector<CardID> CardIDs;
   typedef pvector<CardID> CardIDs;
   CardIDs _card_ids;
   CardIDs _card_ids;
-
+  bool _bIsDX81;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

文件差異過大導致無法顯示
+ 583 - 167
panda/src/dxgsg8/wdxGraphicsWindow8.cxx


+ 13 - 16
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 "pandabase.h"
 #include "winGraphicsWindow.h"
 #include "winGraphicsWindow.h"
@@ -39,16 +39,16 @@ static const int WDXWIN_EVENT = 8;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow {
 class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow {
 public:
 public:
-  wdxGraphicsWindow8(GraphicsPipe *pipe);
+  wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
   virtual ~wdxGraphicsWindow8();
   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 int verify_window_sizes(int numsizes, int *dimen);
 
 
   virtual bool begin_frame();
   virtual bool begin_frame();
   virtual void end_flip();
   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:
 protected:
   virtual void fullscreen_restored(WindowProperties &properties);
   virtual void fullscreen_restored(WindowProperties &properties);
@@ -60,30 +60,26 @@ private:
   void create_screen_buffers_and_device(DXScreenData &Display,
   void create_screen_buffers_and_device(DXScreenData &Display,
                                         bool force_16bpp_zbuffer);
                                         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();
   //  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,
   void search_for_valid_displaymode(UINT RequestedX_Size, UINT RequestedY_Size,
                                     bool bWantZBuffer, bool bWantStencil,
                                     bool bWantZBuffer, bool bWantStencil,
                                     UINT *pSupportedScreenDepthsMask,
                                     UINT *pSupportedScreenDepthsMask,
                                     bool *pCouldntFindAnyValidZBuf,
                                     bool *pCouldntFindAnyValidZBuf,
                                     D3DFORMAT *pSuggestedPixFmt,
                                     D3DFORMAT *pSuggestedPixFmt,
                                     bool bVerboseMode = false);
                                     bool bVerboseMode = false);
-
+*/
   bool reset_device_resize_window(UINT new_xsize, UINT new_ysize);
   bool reset_device_resize_window(UINT new_xsize, UINT new_ysize);
   void init_resized_window();
   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 int D3DFMT_to_DepthBits(D3DFORMAT fmt);
   static bool is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID);
   static bool is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID);
 
 
   DXGraphicsStateGuardian8 *_dxgsg;
   DXGraphicsStateGuardian8 *_dxgsg;
+  DXScreenData _wcontext;
+
   int _depth_buffer_bpp;
   int _depth_buffer_bpp;
   bool _awaiting_restore;
   bool _awaiting_restore;
 
 
@@ -100,6 +96,7 @@ public:
     return get_class_type();
     return get_class_type();
   }
   }
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+  virtual void make_current(void);
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;

+ 7 - 2
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_two_sided(get_two_sided());
   wf->set_lighting(get_lighting());
   wf->set_lighting(get_lighting());
   wf->set_background_type(get_background_type());
   wf->set_background_type(get_background_type());
-  _windows.push_back(wf);
 
 
-  wf->open_window(props, &_engine, pipe);
+  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);
   return wf;
   return wf;
 }
 }
 
 

+ 8 - 1
panda/src/framework/windowFramework.cxx

@@ -95,7 +95,14 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
             GraphicsPipe *pipe) {
             GraphicsPipe *pipe) {
   nassertr(_window == (GraphicsWindow *)NULL, _window);
   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) {
   if (_window != (GraphicsWindow *)NULL) {
     _window->request_properties(props);
     _window->request_properties(props);
     set_background_type(_background_type);
     set_background_type(_background_type);

+ 18 - 7
panda/src/glgsg/glGraphicsStateGuardian.cxx

@@ -163,8 +163,9 @@ uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source,
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GLGraphicsStateGuardian::
 GLGraphicsStateGuardian::
-GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
-  reset();
+GLGraphicsStateGuardian(const FrameBufferProperties &properties) :
+  GraphicsStateGuardian(properties) 
+{
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -174,9 +175,7 @@ GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GLGraphicsStateGuardian::
 GLGraphicsStateGuardian::
 ~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);
   GLTextureContext *gtc = DCAST(GLTextureContext, tc);
   Texture *tex = tc->_texture;
   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, &gtc->_index);
     glDeleteTextures(1, &gtc->_index);
   }
   }
   gtc->_index = 0;
   gtc->_index = 0;
@@ -1651,7 +1652,9 @@ release_texture(TextureContext *tc) {
   tex->clear_gsg(this);
   tex->clear_gsg(this);
 
 
   delete gtc;
   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::
 void GLGraphicsStateGuardian::
 texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
 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);
   nassertv(tc != NULL && pb != NULL);
   Texture *tex = tc->_texture;
   Texture *tex = tc->_texture;
 
 
@@ -1914,6 +1920,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
 
 
   pop_frame_buffer(old_fb);
   pop_frame_buffer(old_fb);
   report_gl_errors();
   report_gl_errors();
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -3000,6 +3007,9 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GLGraphicsStateGuardian::
 void GLGraphicsStateGuardian::
 draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
 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 != NULL && dr != NULL);
   nassertv(!pb->_image.empty());
   nassertv(!pb->_image.empty());
   DisplayRegionStack old_dr = push_display_region(dr);
   DisplayRegionStack old_dr = push_display_region(dr);
@@ -3109,6 +3119,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
 
 
   pop_display_region(old_dr);
   pop_display_region(old_dr);
   report_gl_errors();
   report_gl_errors();
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/glgsg/glGraphicsStateGuardian.h

@@ -63,8 +63,8 @@ INLINE ostream &operator << (ostream &out, GLenum v) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAGL GLGraphicsStateGuardian : public GraphicsStateGuardian {
 class EXPCL_PANDAGL GLGraphicsStateGuardian : public GraphicsStateGuardian {
 public:
 public:
-  GLGraphicsStateGuardian(GraphicsWindow *win);
-  ~GLGraphicsStateGuardian();
+  GLGraphicsStateGuardian(const FrameBufferProperties &properties);
+  virtual ~GLGraphicsStateGuardian();
 
 
   virtual void reset();
   virtual void reset();
 
 

+ 2 - 0
panda/src/glxdisplay/Sources.pp

@@ -13,6 +13,8 @@
     config_glxdisplay.cxx config_glxdisplay.h \
     config_glxdisplay.cxx config_glxdisplay.h \
     glxGraphicsPipe.I glxGraphicsPipe.cxx \
     glxGraphicsPipe.I glxGraphicsPipe.cxx \
     glxGraphicsPipe.h glxGraphicsWindow.I glxGraphicsWindow.cxx \
     glxGraphicsPipe.h glxGraphicsWindow.I glxGraphicsWindow.cxx \
+    glxGraphicsStateGuardian.h glxGraphicsStateGuardian.I \
+    glxGraphicsStateGuardian.cxx \
     glxGraphicsWindow.h
     glxGraphicsWindow.h
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \

+ 2 - 2
panda/src/glxdisplay/config_glxdisplay.cxx

@@ -19,6 +19,7 @@
 #include "config_glxdisplay.h"
 #include "config_glxdisplay.h"
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsWindow.h"
 #include "glxGraphicsWindow.h"
+#include "glxGraphicsStateGuardian.h"
 #include "graphicsPipeSelection.h"
 #include "graphicsPipeSelection.h"
 #include "dconfig.h"
 #include "dconfig.h"
 
 
@@ -47,12 +48,11 @@ init_libglxdisplay() {
 
 
   glxGraphicsPipe::init_type();
   glxGraphicsPipe::init_type();
   glxGraphicsWindow::init_type();
   glxGraphicsWindow::init_type();
+  glxGraphicsStateGuardian::init_type();
 
 
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
   selection->add_pipe_type(glxGraphicsPipe::get_class_type(),
   selection->add_pipe_type(glxGraphicsPipe::get_class_type(),
                            glxGraphicsPipe::pipe_constructor);
                            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", "");
 const string display_cfg = config_glxdisplay.GetString("display", "");

+ 0 - 2
panda/src/glxdisplay/config_glxdisplay.h

@@ -26,8 +26,6 @@ NotifyCategoryDecl(glxdisplay, EXPCL_PANDAGL, EXPTP_PANDAGL);
 
 
 extern EXPCL_PANDAGL void init_libglxdisplay();
 extern EXPCL_PANDAGL void init_libglxdisplay();
 
 
-extern bool gl_show_fps_meter;
-extern float gl_fps_meter_update_interval;
 extern const string display_cfg;
 extern const string display_cfg;
 
 
 #endif /* __CONFIG_GLXDISPLAY_H__ */
 #endif /* __CONFIG_GLXDISPLAY_H__ */

+ 349 - 2
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -18,7 +18,9 @@
 
 
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsWindow.h"
 #include "glxGraphicsWindow.h"
+#include "glxGraphicsStateGuardian.h"
 #include "config_glxdisplay.h"
 #include "config_glxdisplay.h"
+#include "frameBufferProperties.h"
 #include "mutexHolder.h"
 #include "mutexHolder.h"
 
 
 #include <GL/glx.h>
 #include <GL/glx.h>
@@ -116,18 +118,363 @@ pipe_constructor() {
   return new glxGraphicsPipe;
   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
 //     Function: glxGraphicsPipe::make_window
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
 //  Description: Creates a new window on the pipe, if possible.
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsWindow) glxGraphicsPipe::
 PT(GraphicsWindow) glxGraphicsPipe::
-make_window() {
+make_window(GraphicsStateGuardian *gsg) {
   if (!_is_valid) {
   if (!_is_valid) {
     return NULL;
     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<int> 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;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 12 - 4
panda/src/glxdisplay/glxGraphicsPipe.h

@@ -22,17 +22,20 @@
 #include "pandabase.h"
 #include "pandabase.h"
 #include "graphicsPipe.h"
 #include "graphicsPipe.h"
 
 
-#include <X11/Xlib.h>
-
 class glxGraphicsWindow;
 class glxGraphicsWindow;
+class FrameBufferProperties;
 
 
 #ifdef CPPPARSER
 #ifdef CPPPARSER
 // A simple hack so interrogate can parse this file.
 // A simple hack so interrogate can parse this file.
 typedef int Display;
 typedef int Display;
 typedef int Window;
 typedef int Window;
 typedef int XErrorEvent;
 typedef int XErrorEvent;
+typedef int XVisualInfo;
 typedef int Atom;
 typedef int Atom;
-#endif
+#else
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+#endif  // CPPPARSER
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : glxGraphicsPipe
 //       Class : glxGraphicsPipe
@@ -55,9 +58,14 @@ public:
   INLINE Atom get_wm_delete_window() const;
   INLINE Atom get_wm_delete_window() const;
 
 
 protected:
 protected:
-  virtual PT(GraphicsWindow) make_window();
+  virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
+  virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
 
 
 private:
 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 void install_error_handlers();
   static int error_handler(Display *display, XErrorEvent *error);
   static int error_handler(Display *display, XErrorEvent *error);
   static int io_error_handler(Display *display);
   static int io_error_handler(Display *display);

+ 38 - 369
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "glxGraphicsWindow.h"
 #include "glxGraphicsWindow.h"
+#include "glxGraphicsStateGuardian.h"
 #include "config_glxdisplay.h"
 #include "config_glxdisplay.h"
 #include "glxGraphicsPipe.h"
 #include "glxGraphicsPipe.h"
 
 
@@ -39,16 +40,14 @@ TypeHandle glxGraphicsWindow::_type_handle;
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 glxGraphicsWindow::
 glxGraphicsWindow::
-glxGraphicsWindow(GraphicsPipe *pipe) :
-  GraphicsWindow(pipe) 
+glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
+  GraphicsWindow(pipe, gsg) 
 {
 {
   glxGraphicsPipe *glx_pipe;
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_V(glx_pipe, _pipe);
   DCAST_INTO_V(glx_pipe, _pipe);
   _display = glx_pipe->get_display();
   _display = glx_pipe->get_display();
   _screen = glx_pipe->get_screen();
   _screen = glx_pipe->get_screen();
-  _xwindow = (Window)0;
-  _context = (GLXContext)0;
-  _visual = (XVisualInfo *)NULL;
+  _xwindow = (Window)NULL;
   _awaiting_configure = false;
   _awaiting_configure = false;
   _wm_delete_window = glx_pipe->get_wm_delete_window();
   _wm_delete_window = glx_pipe->get_wm_delete_window();
 
 
@@ -67,59 +66,38 @@ glxGraphicsWindow::
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsWindow::make_gsg
+//     Function: glxGraphicsWindow::make_current
 //       Access: Public, Virtual
 //       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.
+//  Description: This function will be called within the draw thread
+//               during begin_frame() to ensure the graphics context
+//               is ready for drawing.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void glxGraphicsWindow::
 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);
+make_current() {
+  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
 //     Function: glxGraphicsWindow::release_gsg
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Releases the current GSG pointer, if it is currently
 //  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.
+//               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::
 void glxGraphicsWindow::
 release_gsg() {
 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
-//  Description: This function will be called within the draw thread
-//               during begin_frame() to ensure the graphics context
-//               is ready for drawing.
-////////////////////////////////////////////////////////////////////
-void glxGraphicsWindow::
-make_current() {
-  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
-  glXMakeCurrent(_display, _xwindow, _context);
+  glXMakeCurrent(_display, None, NULL);
+  GraphicsWindow::release_gsg();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -159,7 +137,7 @@ begin_frame() {
 void glxGraphicsWindow::
 void glxGraphicsWindow::
 begin_flip() {
 begin_flip() {
   if (_gsg != (GraphicsStateGuardian *)NULL) {
   if (_gsg != (GraphicsStateGuardian *)NULL) {
-    glXMakeCurrent(_display, _xwindow, _context);
+    make_current();
     glXSwapBuffers(_display, _xwindow);
     glXSwapBuffers(_display, _xwindow);
   }
   }
 }
 }
@@ -371,7 +349,7 @@ set_properties_now(WindowProperties &properties) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void glxGraphicsWindow::
 void glxGraphicsWindow::
 close_window() {
 close_window() {
-  if (_xwindow != (Window)0) {
+  if (_xwindow != (Window)NULL) {
     XDestroyWindow(_display, _xwindow);
     XDestroyWindow(_display, _xwindow);
     _xwindow = (Window)0;
     _xwindow = (Window)0;
 
 
@@ -404,12 +382,12 @@ open_window() {
 
 
   glxGraphicsPipe *glx_pipe;
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_R(glx_pipe, _pipe, false);
   DCAST_INTO_R(glx_pipe, _pipe, false);
+  glxGraphicsStateGuardian *glxgsg;
+  DCAST_INTO_R(glxgsg, _gsg, false);
+
   Window root_window = glx_pipe->get_root();
   Window root_window = glx_pipe->get_root();
 
 
-  if (!choose_visual()) {
-    return false;
-  }
-  setup_colormap();
+  setup_colormap(glxgsg->_visual);
 
 
   _event_mask =
   _event_mask =
     ButtonPressMask | ButtonReleaseMask |
     ButtonPressMask | ButtonReleaseMask |
@@ -434,7 +412,7 @@ open_window() {
      _properties.get_x_origin(), _properties.get_y_origin(),
      _properties.get_x_origin(), _properties.get_y_origin(),
      _properties.get_x_size(), _properties.get_y_size(),
      _properties.get_x_size(), _properties.get_y_size(),
      0,
      0,
-     _visual->depth, InputOutput, _visual->visual, 
+     glxgsg->_visual->depth, InputOutput, glxgsg->_visual->visual, 
      attrib_mask, &wa);
      attrib_mask, &wa);
 
 
   if (_xwindow == (Window)0) {
   if (_xwindow == (Window)0) {
@@ -538,315 +516,6 @@ set_wm_properties(const WindowProperties &properties) {
                   sizeof(protocols) / sizeof(Atom));
                   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<int> 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
 //     Function: glxGraphicsWindow::setup_colormap
 //       Access: Private
 //       Access: Private
@@ -854,17 +523,17 @@ choose_visual() {
 //               stores in in the _colormap method.
 //               stores in in the _colormap method.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void glxGraphicsWindow::
 void glxGraphicsWindow::
-setup_colormap() {
+setup_colormap(XVisualInfo *visual) {
   glxGraphicsPipe *glx_pipe;
   glxGraphicsPipe *glx_pipe;
   DCAST_INTO_V(glx_pipe, _pipe);
   DCAST_INTO_V(glx_pipe, _pipe);
   Window root_window = glx_pipe->get_root();
   Window root_window = glx_pipe->get_root();
 
 
-  int visual_class = _visual->c_class;
+  int visual_class = visual->c_class;
   int rc, is_rgb;
   int rc, is_rgb;
 
 
   switch (visual_class) {
   switch (visual_class) {
     case PseudoColor:
     case PseudoColor:
-      rc = glXGetConfig(_display, _visual, GLX_RGBA, &is_rgb);
+      rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb);
       if (rc == 0 && is_rgb) {
       if (rc == 0 && is_rgb) {
         glxdisplay_cat.warning()
         glxdisplay_cat.warning()
           << "mesa pseudocolor not supported.\n";
           << "mesa pseudocolor not supported.\n";
@@ -873,19 +542,19 @@ setup_colormap() {
 
 
       } else {
       } else {
         _colormap = XCreateColormap(_display, root_window,
         _colormap = XCreateColormap(_display, root_window,
-                                    _visual->visual, AllocAll);
+                                    visual->visual, AllocAll);
       }
       }
       break;
       break;
     case TrueColor:
     case TrueColor:
     case DirectColor:
     case DirectColor:
       _colormap = XCreateColormap(_display, root_window,
       _colormap = XCreateColormap(_display, root_window,
-                                  _visual->visual, AllocNone);
+                                  visual->visual, AllocNone);
       break;
       break;
     case StaticColor:
     case StaticColor:
     case StaticGray:
     case StaticGray:
     case GrayScale:
     case GrayScale:
       _colormap = XCreateColormap(_display, root_window,
       _colormap = XCreateColormap(_display, root_window,
-                                  _visual->visual, AllocNone);
+                                  visual->visual, AllocNone);
       break;
       break;
     default:
     default:
       glxdisplay_cat.error()
       glxdisplay_cat.error()

+ 3 - 9
panda/src/glxdisplay/glxGraphicsWindow.h

@@ -36,12 +36,11 @@ class glxGraphicsPipe;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class glxGraphicsWindow : public GraphicsWindow {
 class glxGraphicsWindow : public GraphicsWindow {
 public:
 public:
-  glxGraphicsWindow(GraphicsPipe *pipe);
+  glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
   virtual ~glxGraphicsWindow();
   virtual ~glxGraphicsWindow();
 
 
-  virtual void make_gsg();
-  virtual void release_gsg();
   virtual void make_current();
   virtual void make_current();
+  virtual void release_gsg();
 
 
   virtual bool begin_frame();
   virtual bool begin_frame();
   virtual void begin_flip();
   virtual void begin_flip();
@@ -56,10 +55,7 @@ protected:
 private:
 private:
   void set_wm_properties(const WindowProperties &properties);
   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);
   ButtonHandle get_button(XKeyEvent *key_event);
 
 
   static Bool check_event(Display *display, XEvent *event, char *arg);
   static Bool check_event(Display *display, XEvent *event, char *arg);
@@ -68,8 +64,6 @@ private:
   Display *_display;
   Display *_display;
   int _screen;
   int _screen;
   Window _xwindow;
   Window _xwindow;
-  GLXContext _context;
-  XVisualInfo *_visual;
   Colormap _colormap;
   Colormap _colormap;
   long _event_mask;
   long _event_mask;
   bool _awaiting_configure;
   bool _awaiting_configure;

+ 5 - 1
panda/src/wgldisplay/Sources.pp

@@ -15,11 +15,15 @@
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
      config_wgldisplay.h \
      config_wgldisplay.h \
      wglGraphicsPipe.I wglGraphicsPipe.h \
      wglGraphicsPipe.I wglGraphicsPipe.h \
+     wglGraphicsStateGuardian.I wglGraphicsStateGuardian.h \
      wglGraphicsWindow.I wglGraphicsWindow.h
      wglGraphicsWindow.I wglGraphicsWindow.h
 //     Win32Defs.h  
 //     Win32Defs.h  
     
     
   #define INCLUDED_SOURCES \
   #define INCLUDED_SOURCES \
-    config_wgldisplay.cxx wglGraphicsPipe.cxx wglGraphicsWindow.cxx
+    config_wgldisplay.cxx \
+    wglGraphicsPipe.cxx \
+    wglGraphicsStateGuardian.cxx \
+    wglGraphicsWindow.cxx
 
 
   #define SOURCES \
   #define SOURCES \
     $[INSTALL_HEADERS]
     $[INSTALL_HEADERS]

+ 2 - 0
panda/src/wgldisplay/config_wgldisplay.cxx

@@ -18,6 +18,7 @@
 
 
 #include "config_wgldisplay.h"
 #include "config_wgldisplay.h"
 #include "wglGraphicsPipe.h"
 #include "wglGraphicsPipe.h"
+#include "wglGraphicsStateGuardian.h"
 #include "wglGraphicsWindow.h"
 #include "wglGraphicsWindow.h"
 #include "graphicsPipeSelection.h"
 #include "graphicsPipeSelection.h"
 #include "dconfig.h"
 #include "dconfig.h"
@@ -46,6 +47,7 @@ init_libwgldisplay() {
   initialized = true;
   initialized = true;
 
 
   wglGraphicsPipe::init_type();
   wglGraphicsPipe::init_type();
+  wglGraphicsStateGuardian::init_type();
   wglGraphicsWindow::init_type();
   wglGraphicsWindow::init_type();
 
 
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();

+ 235 - 2
panda/src/wgldisplay/wglGraphicsPipe.cxx

@@ -18,6 +18,10 @@
 
 
 #include "wglGraphicsPipe.h"
 #include "wglGraphicsPipe.h"
 #include "config_wgldisplay.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;
 TypeHandle wglGraphicsPipe::_type_handle;
 
 
@@ -66,12 +70,241 @@ pipe_constructor() {
   return new wglGraphicsPipe;
   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 <<endl;
+  }
+
+  // Now we're done with the screen's hdc, so release it.
+  ReleaseDC(NULL, hdc);
+
+  // Now we can make a GSG.
+  PT(wglGraphicsStateGuardian) gsg = 
+    new wglGraphicsStateGuardian(new_properties, pfnum);
+
+  return gsg.p();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsPipe::make_window
 //     Function: wglGraphicsPipe::make_window
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
 //  Description: Creates a new window on the pipe, if possible.
 //  Description: Creates a new window on the pipe, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsWindow) wglGraphicsPipe::
 PT(GraphicsWindow) wglGraphicsPipe::
-make_window() {
-  return new wglGraphicsWindow(this);
+make_window(GraphicsStateGuardian *gsg) {
+  return new wglGraphicsWindow(this, gsg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsPipe::choose_pfnum
+//       Access: Private
+//  Description: Selects a suitable pixel format number for the given
+//               frame buffer properties.  Returns the selected number
+//               if successful, or 0 otherwise.
+//
+//               If successful, this may modify properties to reflect
+//               the actual visual chosen.
+////////////////////////////////////////////////////////////////////
+int wglGraphicsPipe::
+choose_pfnum(FrameBufferProperties &properties, HDC hdc) const {
+  int pfnum;
+  bool bUsingSoftware = false;
+
+  if (force_software_renderer) {
+    pfnum = find_pixfmtnum(properties, hdc, false);
+    
+    if (pfnum == 0) {
+      wgldisplay_cat.error()
+        << "Couldn't find compatible software-renderer OpenGL pixfmt, check your window properties!\n";
+      return 0;
+    }
+    bUsingSoftware = true;
+
+  } else {
+    pfnum = find_pixfmtnum(properties, hdc, true);
+    if (pfnum == 0) {
+      if (allow_software_renderer) {
+        pfnum = find_pixfmtnum(properties, hdc, false);
+        if (pfnum == 0) {
+          wgldisplay_cat.error()
+            << "Couldn't find HW or Software OpenGL pixfmt appropriate for this desktop!!\n";
+        }
+      } else {
+        wgldisplay_cat.error()
+          << "Couldn't find HW-accelerated OpenGL pixfmt appropriate for this desktop!!\n";
+      }
+      
+      if (pfnum == 0) {
+        wgldisplay_cat.error()
+          << "make sure OpenGL driver is installed, and try reducing the screen size, reducing the\n"
+          << "desktop screen pixeldepth to 16bpp,and check your panda window properties\n";
+        return 0;
+      }
+      bUsingSoftware = true;
+    }
+  }
+  
+  if (bUsingSoftware) {
+    wgldisplay_cat.info()
+      << "Couldn't find compatible OGL HW pixelformat, using software rendering.\n";
+  }
+  
+  return pfnum;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsPipe::find_pixfmtnum
+//       Access: Private
+//  Description: This helper routine looks for either HW-only or
+//               SW-only format, but not both.  Returns the
+//               pixelformat number, or 0 if a suitable format could
+//               not be found.
+////////////////////////////////////////////////////////////////////
+int wglGraphicsPipe::
+find_pixfmtnum(FrameBufferProperties &properties, HDC hdc,
+               bool bLookforHW) const {
+  int frame_buffer_mode = properties.get_frame_buffer_mode();
+  bool want_depth_bits = properties.has_depth_bits();
+  bool want_color_bits = properties.has_color_bits();
+  OGLDriverType drvtype;
+
+  PIXELFORMATDESCRIPTOR pfd;
+  ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
+  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+  pfd.nVersion = 1;
+
+  // just use the pixfmt of the current desktop
+
+  int MaxPixFmtNum = 
+    DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+  int cur_bpp = GetDeviceCaps(hdc,BITSPIXEL);
+  int pfnum;
+
+  for(pfnum = 1; pfnum <= MaxPixFmtNum; pfnum++) {
+    DescribePixelFormat(hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+    // official, nvidia sanctioned way.
+    if ((pfd.dwFlags & PFD_GENERIC_FORMAT) != 0) {
+      drvtype = Software;
+    } else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED) {
+      drvtype = MCD;
+    } else {
+      drvtype = ICD;
+    }
+
+    // skip driver types we are not looking for
+    if (bLookforHW) {
+      if (drvtype == Software) {
+        continue;
+      }
+    } else {
+      if (drvtype != Software) {
+        continue;
+      }
+    }
+
+    if ((pfd.iPixelType == PFD_TYPE_COLORINDEX) && 
+        (frame_buffer_mode & FrameBufferProperties::FM_index) == 0) {
+      continue;
+    }
+
+    DWORD dwReqFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW);
+
+    if (wgldisplay_cat.is_debug()) {
+      wgldisplay_cat->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;
 }
 }

+ 7 - 1
panda/src/wgldisplay/wglGraphicsPipe.h

@@ -37,7 +37,13 @@ public:
   static PT(GraphicsPipe) pipe_constructor();
   static PT(GraphicsPipe) pipe_constructor();
 
 
 protected:
 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:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 28 - 0
panda/src/wgldisplay/wglGraphicsStateGuardian.I

@@ -15,3 +15,31 @@
 // [email protected] .
 // [email protected] .
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     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;
+}

+ 30 - 3
panda/src/wgldisplay/wglGraphicsStateGuardian.cxx

@@ -27,10 +27,13 @@ TypeHandle wglGraphicsStateGuardian::_type_handle;
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 wglGraphicsStateGuardian::
 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;
     _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;
+  }
+}

+ 9 - 3
panda/src/wgldisplay/wglGraphicsStateGuardian.h

@@ -30,12 +30,18 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class wglGraphicsStateGuardian : public GLGraphicsStateGuardian {
 class wglGraphicsStateGuardian : public GLGraphicsStateGuardian {
 public:
 public:
-  wglGraphicsStateGuardian(const FrameBufferProperties &properties);
+  wglGraphicsStateGuardian(const FrameBufferProperties &properties, int pfnum);
   virtual ~wglGraphicsStateGuardian();
   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;
   int _pfnum;
-  PIXELFORMATDESCRIPTOR _pixelformat;
+  HGLRC _context;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 47 - 267
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -25,9 +25,6 @@
 #include <wingdi.h>
 #include <wingdi.h>
 #include <ddraw.h>
 #include <ddraw.h>
 
 
-typedef enum {Software, MCD, ICD} OGLDriverType;
-static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" };
-
 TypeHandle wglGraphicsWindow::_type_handle;
 TypeHandle wglGraphicsWindow::_type_handle;
 
 
 static char *ConvDDErrorToString(const HRESULT &error);
 static char *ConvDDErrorToString(const HRESULT &error);
@@ -132,10 +129,9 @@ GetAvailVidMem() {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 wglGraphicsWindow::
 wglGraphicsWindow::
-wglGraphicsWindow(GraphicsPipe *pipe) :
-  WinGraphicsWindow(pipe) 
+wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
+  WinGraphicsWindow(pipe, gsg) 
 {
 {
-  _context = (HGLRC)0;
   _hdc = (HDC)0;
   _hdc = (HDC)0;
 }
 }
 
 
@@ -149,59 +145,38 @@ wglGraphicsWindow::
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsWindow::make_gsg
+//     Function: wglGraphicsWindow::make_current
 //       Access: Public, Virtual
 //       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.
+//  Description: This function will be called within the draw thread
+//               during begin_frame() to ensure the graphics context
+//               is ready for drawing.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::
 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);
+make_current() {
+  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
 //     Function: wglGraphicsWindow::release_gsg
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: Releases the current GSG pointer, if it is currently
 //  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.
+//               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::
 void wglGraphicsWindow::
 release_gsg() {
 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
-//  Description: This function will be called within the draw thread
-//               during begin_frame() to ensure the graphics context
-//               is ready for drawing.
-////////////////////////////////////////////////////////////////////
-void wglGraphicsWindow::
-make_current() {
-  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
-  wglMakeCurrent(_hdc, _context);
+  wglMakeCurrent(_hdc, NULL);
+  GraphicsWindow::release_gsg();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -221,7 +196,7 @@ make_current() {
 void wglGraphicsWindow::
 void wglGraphicsWindow::
 begin_flip() {
 begin_flip() {
   if (_gsg != (GraphicsStateGuardian *)NULL) {
   if (_gsg != (GraphicsStateGuardian *)NULL) {
-    wglMakeCurrent(_hdc, _context);
+    make_current();
     glFinish();
     glFinish();
     SwapBuffers(_hdc);
     SwapBuffers(_hdc);
   }
   }
@@ -235,7 +210,7 @@ begin_flip() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::
 void wglGraphicsWindow::
 close_window() {
 close_window() {
-  ReleaseDC(_mwindow, _hdc);
+  ReleaseDC(_hWnd, _hdc);
   _hdc = (HDC)0;
   _hdc = (HDC)0;
   WinGraphicsWindow::close_window();
   WinGraphicsWindow::close_window();
 }
 }
@@ -253,42 +228,31 @@ open_window() {
     return false;
     return false;
   }
   }
 
 
-  // Set up the pixel format of the window appropriately for GL.
-  _hdc = GetDC(_mwindow);
+  wglGraphicsStateGuardian *wglgsg;
+  DCAST_INTO_R(wglgsg, _gsg, false);
 
 
-  int pfnum = choose_pfnum();
+  _hdc = GetDC(_hWnd);
 
 
-  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;
-  }
+  // Set up the pixel format of the window appropriately for GL.
+  int pfnum = wglgsg->get_pfnum();
 
 
-  if (wgldisplay_cat.is_debug()) {
-    wgldisplay_cat.debug()
-      << "config() - picking pixfmt #" << pfnum <<endl;
-  }
-  
+  PIXELFORMATDESCRIPTOR pixelformat;
   DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), 
   DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), 
-                      &_pixelformat);
+                      &pixelformat);
 
 
 #ifdef _DEBUG
 #ifdef _DEBUG
   char msg[200];
   char msg[200];
   sprintf(msg, "Selected GL PixelFormat is #%d", pfnum);
   sprintf(msg, "Selected GL PixelFormat is #%d", pfnum);
-  print_pfd(&_pixelformat, msg);
+  print_pfd(&pixelformat, msg);
 #endif
 #endif
 
 
-  if (!SetPixelFormat(_hdc, pfnum, &_pixelformat)) {
+  if (!SetPixelFormat(_hdc, pfnum, &pixelformat)) {
     wgldisplay_cat.error()
     wgldisplay_cat.error()
       << "SetPixelFormat(" << pfnum << ") failed after window create\n";
       << "SetPixelFormat(" << pfnum << ") failed after window create\n";
     close_window();
     close_window();
     return false;
     return false;
   }
   }
 
 
-  // Initializes _colormap
-  setup_colormap();
-
 #ifndef NDEBUG
 #ifndef NDEBUG
   if (gl_force_invalid) {
   if (gl_force_invalid) {
     wgldisplay_cat.error()
     wgldisplay_cat.error()
@@ -298,6 +262,9 @@ open_window() {
   }
   }
 #endif  // NDEBUG
 #endif  // NDEBUG
 
 
+  // Initializes _colormap
+  setup_colormap(pixelformat);
+
   return true;
   return true;
 }
 }
 
 
@@ -334,187 +301,6 @@ reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size, DWORD &bitdepth) {
   }
   }
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsWindow::choose_pfnum
-//       Access: Private
-//  Description: Selects a suitable pixel format number for the
-//               window, based on the requested properties.
-////////////////////////////////////////////////////////////////////
-int wglGraphicsWindow::
-choose_pfnum() const {
-  int pfnum;
-  bool bUsingSoftware = false;
-
-  if (force_software_renderer) {
-    pfnum = find_pixfmtnum(false);
-    
-    if (pfnum == 0) {
-      wgldisplay_cat.error()
-        << "Couldn't find compatible software-renderer OpenGL pixfmt, check your window properties!\n";
-      return 0;
-    }
-    bUsingSoftware = true;
-
-  } else {
-    pfnum = find_pixfmtnum(true);
-    if (pfnum == 0) {
-      if (allow_software_renderer) {
-        pfnum = find_pixfmtnum(false);
-        if(pfnum == 0) {
-          wgldisplay_cat.error()
-            << "Couldn't find HW or Software OpenGL pixfmt appropriate for this desktop!!\n";
-        }
-      } else {
-        wgldisplay_cat.error()
-          << "Couldn't find HW-accelerated OpenGL pixfmt appropriate for this desktop!!\n";
-      }
-      
-      if (pfnum == 0) {
-        wgldisplay_cat.error()
-          << "make sure OpenGL driver is installed, and try reducing the screen size, reducing the\n"
-          << "desktop screen pixeldepth to 16bpp,and check your panda window properties\n";
-        return 0;
-      }
-      bUsingSoftware=true;
-    }
-  }
-  
-  if (bUsingSoftware) {
-    wgldisplay_cat.info()
-      << "Couldn't find compatible OGL HW pixelformat, using software rendering.\n";
-  }
-  
-  return pfnum;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: wglGraphicsWindow::find_pixfmtnum
-//       Access: Private
-//  Description: This helper routine looks for either HW-only or
-//               SW-only format, but not both.  Returns the
-//               pixelformat number, or 0 if a suitable format could
-//               not be found.
-////////////////////////////////////////////////////////////////////
-int wglGraphicsWindow::
-find_pixfmtnum(bool bLookforHW) const {
-  int framebuffer_mode = _properties.get_framebuffer_mode();
-  bool want_depth_bits = _properties.has_depth_bits();
-  bool want_color_bits = _properties.has_color_bits();
-  OGLDriverType drvtype;
-
-  PIXELFORMATDESCRIPTOR pfd;
-  ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
-  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
-  pfd.nVersion = 1;
-
-  // just use the pixfmt of the current desktop
-
-  int MaxPixFmtNum = 
-    DescribePixelFormat(_hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-  int cur_bpp = GetDeviceCaps(_hdc,BITSPIXEL);
-  int pfnum;
-
-  for(pfnum = 1; pfnum <= MaxPixFmtNum; pfnum++) {
-    DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-
-    // official, nvidia sanctioned way.
-    if ((pfd.dwFlags & PFD_GENERIC_FORMAT) != 0) {
-      drvtype = Software;
-    } else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED) {
-      drvtype = MCD;
-    } else {
-      drvtype = ICD;
-    }
-
-    // skip driver types we are not looking for
-    if (bLookforHW) {
-      if (drvtype == Software) {
-        continue;
-      }
-    } else {
-      if (drvtype != Software) {
-        continue;
-      }
-    }
-
-    if ((pfd.iPixelType == PFD_TYPE_COLORINDEX) && 
-        (framebuffer_mode & WindowProperties::FM_index) == 0) {
-      continue;
-    }
-
-    DWORD dwReqFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW);
-
-    if (wgldisplay_cat.is_debug()) {
-      wgldisplay_cat->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
 //     Function: wglGraphicsWindow::setup_colormap
 //       Access: Private
 //       Access: Private
@@ -523,21 +309,15 @@ find_pixfmtnum(bool bLookforHW) const {
 //               creating a GL context.
 //               creating a GL context.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::
 void wglGraphicsWindow::
-setup_colormap() {
-  PIXELFORMATDESCRIPTOR pfd;
+setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat) {
   LOGPALETTE *logical;
   LOGPALETTE *logical;
   int n;
   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;
     return;
 
 
-  n = 1 << pfd.cColorBits;
+  n = 1 << pixelformat.cColorBits;
 
 
   /* allocate a bunch of memory for the logical palette (assume 256
   /* allocate a bunch of memory for the logical palette (assume 256
      colors in a Win32 palette */
      colors in a Win32 palette */
@@ -552,20 +332,20 @@ setup_colormap() {
   /* start with a copy of the current system palette */
   /* start with a copy of the current system palette */
   GetSystemPaletteEntries(_hdc, 0, 256, &logical->palPalEntry[0]);
   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;
     int i;
 
 
     /* fill in an RGBA color palette */
     /* fill in an RGBA color palette */
     for (i = 0; i < n; ++i) {
     for (i = 0; i < n; ++i) {
       logical->palPalEntry[i].peRed =
       logical->palPalEntry[i].peRed =
-        (((i >> pfd.cRedShift)   & redMask)   * 255) / redMask;
+        (((i >> pixelformat.cRedShift)   & redMask)   * 255) / redMask;
       logical->palPalEntry[i].peGreen =
       logical->palPalEntry[i].peGreen =
-        (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
+        (((i >> pixelformat.cGreenShift) & greenMask) * 255) / greenMask;
         logical->palPalEntry[i].peBlue =
         logical->palPalEntry[i].peBlue =
-        (((i >> pfd.cBlueShift)  & blueMask)  * 255) / blueMask;
+        (((i >> pixelformat.cBlueShift)  & blueMask)  * 255) / blueMask;
       logical->palPalEntry[i].peFlags = 0;
       logical->palPalEntry[i].peFlags = 0;
     }
     }
   }
   }

+ 3 - 8
panda/src/wgldisplay/wglGraphicsWindow.h

@@ -29,12 +29,11 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAGL wglGraphicsWindow : public WinGraphicsWindow {
 class EXPCL_PANDAGL wglGraphicsWindow : public WinGraphicsWindow {
 public:
 public:
-  wglGraphicsWindow(GraphicsPipe *pipe);
+  wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
   virtual ~wglGraphicsWindow();
   virtual ~wglGraphicsWindow();
 
 
-  virtual void make_gsg();
-  virtual void release_gsg();
   virtual void make_current();
   virtual void make_current();
+  virtual void release_gsg();
 
 
   virtual void begin_flip();
   virtual void begin_flip();
 
 
@@ -45,17 +44,13 @@ protected:
                                           DWORD &bitdepth);
                                           DWORD &bitdepth);
 
 
 private:
 private:
-  int choose_pfnum() const;
-  int find_pixfmtnum(bool bLookforHW) const;
-  void setup_colormap();
+  void setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat);
 
 
 #ifdef _DEBUG
 #ifdef _DEBUG
   static void print_pfd(PIXELFORMATDESCRIPTOR *pfd, char *msg);
   static void print_pfd(PIXELFORMATDESCRIPTOR *pfd, char *msg);
 #endif
 #endif
 
 
-  HGLRC _context;
   HDC _hdc;
   HDC _hdc;
-  PIXELFORMATDESCRIPTOR _pixelformat;
   HPALETTE _colormap;
   HPALETTE _colormap;
 
 
 public:
 public:

+ 1 - 0
panda/src/wgldisplay/wgldisplay_composite1.cxx

@@ -1,4 +1,5 @@
 #include "config_wgldisplay.cxx"
 #include "config_wgldisplay.cxx"
 #include "wglGraphicsPipe.cxx"
 #include "wglGraphicsPipe.cxx"
+#include "wglGraphicsStateGuardian.cxx"
 #include "wglGraphicsWindow.cxx"
 #include "wglGraphicsWindow.cxx"
 
 

+ 18 - 0
panda/src/windisplay/winGraphicsPipe.cxx

@@ -51,3 +51,21 @@ WinGraphicsPipe::
     _hUser32 = NULL;
     _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() <<endl;
+    return false;
+  }
+  return true;
+}
+
+bool MyLoadLib(HINSTANCE &hDLL, const char *DLLname) {
+  hDLL = LoadLibrary(DLLname);
+  if(hDLL == NULL) {
+    windisplay_cat.error() << "LoadLibrary failed for " << DLLname << ", error=" << GetLastError() <<endl;
+    return false;
+  }
+  return true;
+}

+ 3 - 0
panda/src/windisplay/winGraphicsPipe.h

@@ -66,6 +66,9 @@ private:
   friend class WinGraphicsWindow;
   friend class WinGraphicsWindow;
 };
 };
 
 
+extern EXPCL_PANDAWIN bool MyLoadLib(HINSTANCE &hDLL, const char *DLLname);
+extern EXPCL_PANDAWIN bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName);
+
 #include "winGraphicsPipe.I"
 #include "winGraphicsPipe.I"
 
 
 #endif
 #endif

+ 0 - 21
panda/src/windisplay/winGraphicsWindow.I

@@ -17,27 +17,6 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: WinGraphicsWindow::handle_mouse_motion
-//       Access: Private
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void WinGraphicsWindow::
-handle_mouse_motion(int x, int y) {
-  _input_devices[0].set_pointer_in_window(x, y);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: WinGraphicsWindow::handle_mouse_exit
-//       Access: Private
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void WinGraphicsWindow::
-handle_mouse_exit() {
-  // note: 'mouse_motion' is considered the 'entry' event
-  _input_devices[0].set_pointer_out_of_window();
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: WinGraphicsWindow::handle_keypress
 //     Function: WinGraphicsWindow::handle_keypress
 //       Access: Private
 //       Access: Private

+ 455 - 363
panda/src/windisplay/winGraphicsWindow.cxx

@@ -56,13 +56,13 @@ static const char * const errorbox_title = "Panda3D Error";
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 WinGraphicsWindow::
 WinGraphicsWindow::
-WinGraphicsWindow(GraphicsPipe *pipe) :
-  GraphicsWindow(pipe) 
+WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
+  GraphicsWindow(pipe, gsg) 
 {
 {
   GraphicsWindowInputDevice device =
   GraphicsWindowInputDevice device =
-    GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
+  GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
   _input_devices.push_back(device);
   _input_devices.push_back(device);
-  _mwindow = (HWND)0;
+  _hWnd = (HWND)0;
   _ime_open = false;
   _ime_open = false;
   _ime_active = false;
   _ime_active = false;
   _ime_composition_w = false;
   _ime_composition_w = false;
@@ -174,11 +174,11 @@ set_properties_now(WindowProperties &properties) {
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 close_window() {
 close_window() {
   set_cursor_out_of_window();
   set_cursor_out_of_window();
-  DestroyWindow(_mwindow);
+  DestroyWindow(_hWnd);
 
 
   // Remove the window handle from our global map.
   // Remove the window handle from our global map.
-  _window_handles.erase(_mwindow);
-  _mwindow = (HWND)0;
+  _window_handles.erase(_hWnd);
+  _hWnd = (HWND)0;
 
 
   if (is_fullscreen()) {
   if (is_fullscreen()) {
     // revert to default display mode.
     // revert to default display mode.
@@ -214,17 +214,17 @@ open_window() {
 
 
   // Now that we have a window handle, store it in our global map, so
   // Now that we have a window handle, store it in our global map, so
   // future messages for this window can be routed properly.
   // future messages for this window can be routed properly.
-  _window_handles.insert(WindowHandles::value_type(_mwindow, this));
+  _window_handles.insert(WindowHandles::value_type(_hWnd, this));
   
   
   // move window to top of zorder.
   // move window to top of zorder.
-  SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, 
+  SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0, 
                SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
                SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
   
   
   // need to do twice to override any minimized flags in StartProcessInfo
   // need to do twice to override any minimized flags in StartProcessInfo
-  ShowWindow(_mwindow, SW_SHOWNORMAL);
-  ShowWindow(_mwindow, SW_SHOWNORMAL);
+  ShowWindow(_hWnd, SW_SHOWNORMAL);
+  ShowWindow(_hWnd, SW_SHOWNORMAL);
   
   
-  if (!SetForegroundWindow(_mwindow)) {
+  if (!SetForegroundWindow(_hWnd)) {
     windisplay_cat.warning()
     windisplay_cat.warning()
       << "SetForegroundWindow() failed!\n";
       << "SetForegroundWindow() failed!\n";
   }
   }
@@ -232,10 +232,10 @@ open_window() {
   // Determine the initial open status of the IME.
   // Determine the initial open status of the IME.
   _ime_open = false;
   _ime_open = false;
   _ime_active = false;
   _ime_active = false;
-  HIMC hIMC = ImmGetContext(_mwindow);
+  HIMC hIMC = ImmGetContext(_hWnd);
   if (hIMC != 0) {
   if (hIMC != 0) {
     _ime_open = (ImmGetOpenStatus(hIMC) != 0);
     _ime_open = (ImmGetOpenStatus(hIMC) != 0);
-    ImmReleaseContext(_mwindow, hIMC);
+    ImmReleaseContext(_hWnd, hIMC);
   }
   }
 
 
   // Check the version of the OS we are running.  If we are running
   // Check the version of the OS we are running.  If we are running
@@ -323,10 +323,10 @@ do_reshape_request(int x_origin, int y_origin, int x_size, int y_size) {
     SetRect(&view_rect, x_origin, y_origin,
     SetRect(&view_rect, x_origin, y_origin,
             x_origin + x_size, y_origin + y_size);
             x_origin + x_size, y_origin + y_size);
     WINDOWINFO wi;
     WINDOWINFO wi;
-    GetWindowInfo(_mwindow, &wi);
+    GetWindowInfo(_hWnd, &wi);
     AdjustWindowRectEx(&view_rect, wi.dwStyle, false, wi.dwExStyle);
     AdjustWindowRectEx(&view_rect, wi.dwStyle, false, wi.dwExStyle);
 
 
-    SetWindowPos(_mwindow, NULL, view_rect.left, view_rect.top,
+    SetWindowPos(_hWnd, NULL, view_rect.left, view_rect.top,
                  view_rect.right - view_rect.left,
                  view_rect.right - view_rect.left,
                  view_rect.bottom - view_rect.top,
                  view_rect.bottom - view_rect.top,
                  SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
                  SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
@@ -353,9 +353,9 @@ do_reshape_request(int x_origin, int y_origin, int x_size, int y_size) {
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 handle_reshape() {
 handle_reshape() {
   RECT view_rect;
   RECT view_rect;
-  GetClientRect(_mwindow, &view_rect);
-  ClientToScreen(_mwindow, (POINT*)&view_rect.left);   // translates top,left pnt
-  ClientToScreen(_mwindow, (POINT*)&view_rect.right);  // translates right,bottom pnt
+  GetClientRect(_hWnd, &view_rect);
+  ClientToScreen(_hWnd, (POINT*)&view_rect.left);   // translates top,left pnt
+  ClientToScreen(_hWnd, (POINT*)&view_rect.right);  // translates right,bottom pnt
   
   
   WindowProperties properties;
   WindowProperties properties;
   properties.set_size((view_rect.right - view_rect.left), 
   properties.set_size((view_rect.right - view_rect.left), 
@@ -403,7 +403,7 @@ do_fullscreen_resize(int x_size, int y_size) {
   }
   }
 
 
   // this causes WM_SIZE msg to be produced
   // this causes WM_SIZE msg to be produced
-  SetWindowPos(_mwindow, NULL, 0,0, x_size, y_size, 
+  SetWindowPos(_hWnd, NULL, 0,0, x_size, y_size, 
                SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
                SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
   int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
   int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
 
 
@@ -437,32 +437,6 @@ void WinGraphicsWindow::
 reconsider_fullscreen_size(DWORD &, DWORD &, DWORD &) {
 reconsider_fullscreen_size(DWORD &, DWORD &, DWORD &) {
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: WinGraphicsWindow::get_client_rect_screen
-//       Access: Protected
-//  Description: Fills view_rect with the coordinates of the client
-//               area of the indicated window, converted to screen
-//               coordinates.
-////////////////////////////////////////////////////////////////////
-void WinGraphicsWindow::
-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;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: WinGraphicsWindow::open_fullscreen_window
 //     Function: WinGraphicsWindow::open_fullscreen_window
 //       Access: Private
 //       Access: Private
@@ -516,10 +490,10 @@ open_fullscreen_window() {
   // up the desktop during the mode change
   // up the desktop during the mode change
   register_window_class();
   register_window_class();
   HINSTANCE hinstance = GetModuleHandle(NULL);
   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, 
                           0, 0, dwWidth, dwHeight, 
                           hDesktopWindow, NULL, hinstance, 0);
                           hDesktopWindow, NULL, hinstance, 0);
-  if (!_mwindow) {
+  if (!_hWnd) {
     windisplay_cat.error()
     windisplay_cat.error()
       << "CreateWindow() failed!" << endl;
       << "CreateWindow() failed!" << endl;
     show_error_message();
     show_error_message();
@@ -601,13 +575,13 @@ open_regular_window() {
 
 
   register_window_class();
   register_window_class();
   HINSTANCE hinstance = GetModuleHandle(NULL);
   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.left, win_rect.top,
                           win_rect.right - win_rect.left,
                           win_rect.right - win_rect.left,
                           win_rect.bottom - win_rect.top,
                           win_rect.bottom - win_rect.top,
                           NULL, NULL, hinstance, 0);
                           NULL, NULL, hinstance, 0);
 
 
-  if (!_mwindow) {
+  if (!_hWnd) {
     windisplay_cat.error()
     windisplay_cat.error()
       << "CreateWindow() failed!" << endl;
       << "CreateWindow() failed!" << endl;
     show_error_message();
     show_error_message();
@@ -672,342 +646,373 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
   int button = -1;
   int button = -1;
 
 
   switch (msg) {
   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);
+      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();
+        if(handle_mouse_motion(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam))))
+            return 0;
+        break;
+    
+      case WM_MOUSELEAVE:
+        _tracking_mouse_leaving = false;
+        handle_mouse_exit();
+        set_cursor_out_of_window();
+        break;
+    
+      // 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;
+                }
+            }
+            break;
       }
       }
-    } 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);
+    
+      case WM_NCMOUSELEAVE: {
+            if(!_properties.get_cursor_hidden()) {
+                ShowCursor(false);
+                // SetCursor(NULL);
+                _bCursor_in_WindowClientArea=false;
+            }
+            break;
       }
       }
-    }
-    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.
+    
+      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;
       }
       }
-      ImmReleaseContext(hwnd, hIMC);
-    }
-    break;
     
     
-  case WM_IME_STARTCOMPOSITION:
-    _ime_active = true;
-    break;
+      case WM_CLOSE:
+        properties.set_open(false);
+        system_changed_properties(properties);
     
     
-  case WM_IME_ENDCOMPOSITION:
-    _ime_active = false;
-    break;
+        // 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_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.
+      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;
         
         
-        DWORD result_size =
-          ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
-                                   ime_result, max_ime_result);
+      case WM_IME_STARTCOMPOSITION:
+        _ime_active = true;
+        break;
         
         
-        // Add this string into the text buffer of the application.
+      case WM_IME_ENDCOMPOSITION:
+        _ime_active = false;
+        break;
         
         
-        // 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_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;
         }
         }
-      } 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];
+        break;
         
         
-        int wide_size =
-          MultiByteToWideChar(CP_ACP, 0,
-                              ime_result, result_size,
-                              wide_result, max_wide_result);
-        if (wide_size == 0) {
-          show_error_message();
+      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);
         }
         }
-        for (int i = 0; i < wide_size; i++) {
-          _input_devices[0].keystroke(wide_result[i]);
+        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;
+          }
         }
         }
-      }
-      
-      ImmReleaseContext(hwnd, hIMC);
-      return 0;
-    }
-    break;
+        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_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);
     
     
-  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);
+          // 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);
+                }
               }
               }
-              GlobalUnlock(hglb);
+              CloseClipboard();
             }
             }
           }
           }
-          CloseClipboard();
         }
         }
-      }
-    }
-    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";
         break;
         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_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);
         }
         }
-      }
-
-      // 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;
   }
   }
 
 
   return DefWindowProc(hwnd, msg, wparam, lparam);
   return DefWindowProc(hwnd, msg, wparam, lparam);
@@ -1370,3 +1375,90 @@ lookup_key(WPARAM wparam) const {
   }
   }
   return ButtonHandle::none();
   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;
+}

+ 14 - 9
panda/src/windisplay/winGraphicsWindow.h

@@ -48,13 +48,18 @@ class WinGraphicsPipe;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAWIN WinGraphicsWindow : public GraphicsWindow {
 class EXPCL_PANDAWIN WinGraphicsWindow : public GraphicsWindow {
 public:
 public:
-  WinGraphicsWindow(GraphicsPipe *pipe);
+  WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
   virtual ~WinGraphicsWindow();
   virtual ~WinGraphicsWindow();
 
 
   virtual void begin_flip();
   virtual void begin_flip();
 
 
   virtual void process_events();
   virtual void process_events();
   virtual void set_properties_now(WindowProperties &properties);
   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:
 protected:
   virtual void close_window();
   virtual void close_window();
@@ -71,20 +76,13 @@ protected:
   virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size, 
   virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size, 
                                           DWORD &bitdepth);
                                           DWORD &bitdepth);
 
 
-  void get_client_rect_screen(HWND hwnd, RECT *view_rect);
-
 private:
 private:
   bool open_fullscreen_window();
   bool open_fullscreen_window();
   bool open_regular_window();
   bool open_regular_window();
   void track_mouse_leaving(HWND hwnd);
   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();
   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_keypress(ButtonHandle key, int x, int y);
   INLINE void handle_keyresume(ButtonHandle key);
   INLINE void handle_keyresume(ButtonHandle key);
   INLINE void handle_keyrelease(ButtonHandle key);
   INLINE void handle_keyrelease(ButtonHandle key);
@@ -100,7 +98,7 @@ private:
   static void show_error_message(DWORD message_id = 0);
   static void show_error_message(DWORD message_id = 0);
 
 
 protected:
 protected:
-  HWND _mwindow;
+  HWND _hWnd;
 
 
 private:
 private:
   bool _ime_open;
   bool _ime_open;
@@ -108,6 +106,7 @@ private:
   bool _ime_composition_w;
   bool _ime_composition_w;
   bool _tracking_mouse_leaving;
   bool _tracking_mouse_leaving;
   bool _maximized;
   bool _maximized;
+  bool _bCursor_in_WindowClientArea;
   DEVMODE _fullscreen_display_mode;
   DEVMODE _fullscreen_display_mode;
 
 
   // This is used to remember the state of the keyboard when keyboard
   // This is used to remember the state of the keyboard when keyboard
@@ -164,6 +163,12 @@ private:
   static TypeHandle _type_handle;
   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"
 #include "winGraphicsWindow.I"
 
 
 #endif
 #endif

部分文件因文件數量過多而無法顯示