Browse Source

move red-blue-stereo support lower; cache cull results between left and right stereo channels

David Rose 20 years ago
parent
commit
90902c5cca

+ 7 - 0
panda/src/display/config_display.cxx

@@ -156,6 +156,13 @@ ConfigVariableBool red_blue_stereo
 	  "by default, if the framebuffer does not support true stereo "
 	  "rendering."));
 
+ConfigVariableString red_blue_stereo_colors
+("red-blue-stereo-colors", "red blue",
+ PRC_DESC("This defines the color channels that are used for the left and "
+          "right eye, respectively, for red-blue-stereo mode.  This should "
+          "be a two-word string, where each word is one of 'red', 'blue', "
+          "'green', or 'alpha'."));
+
 ConfigVariableBool invert_red_blue_stereo
 ("invert-red-blue-stereo", false,
  PRC_DESC("When this is true, the red and blue colors of red-blue stereo mode "

+ 1 - 0
panda/src/display/config_display.h

@@ -58,6 +58,7 @@ extern EXPCL_PANDA ConfigVariableBool support_rescale_normal;
 extern EXPCL_PANDA ConfigVariableBool copy_texture_inverted;
 extern EXPCL_PANDA ConfigVariableBool window_inverted;
 extern EXPCL_PANDA ConfigVariableBool red_blue_stereo;
+extern EXPCL_PANDA ConfigVariableString red_blue_stereo_colors;
 extern EXPCL_PANDA ConfigVariableBool invert_red_blue_stereo;
 extern EXPCL_PANDA ConfigVariableBool depth_offset_decals;
 extern EXPCL_PANDA ConfigVariableBool auto_generate_mipmaps;

+ 30 - 95
panda/src/display/graphicsEngine.cxx

@@ -689,32 +689,7 @@ flip_frame() {
     do_flip_frame();
   }
 }
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::render_subframe
-//       Access: Published
-//  Description: Performs a complete cull and draw pass for one
-//               particular display region.  This is normally useful
-//               only for special effects, like shaders, that require
-//               a complete offscreen render pass before they can
-//               complete.
-//
-//               This always executes completely within the calling
-//               thread, regardless of the threading model in use.
-//               Thus, it must always be called from the draw thread,
-//               whichever thread that may be.
-////////////////////////////////////////////////////////////////////
-void GraphicsEngine::
-render_subframe(GraphicsOutput *win, DisplayRegion *dr,
-                bool cull_sorting) {
-  if (cull_sorting) {
-    cull_to_bins(win, dr);
-  } else {
-    cull_and_draw_together(win, dr);
-  }
-}
-
+ 
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::add_callback
 //       Access: Public
@@ -826,8 +801,8 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist) {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::cull_and_draw_together
 //       Access: Private
-//  Description: This variant of cull_and_draw_together() is called
-//               only by render_subframe().
+//  Description: Called only from within the inner loop in
+//               cull_and_draw_together(), above.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
@@ -863,6 +838,11 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 cull_to_bins(const GraphicsEngine::Windows &wlist) {
+  // Keep track of the cameras we have already used in this thread to
+  // render DisplayRegions.
+  typedef pmap<NodePath, DisplayRegion *> AlreadyCulled;
+  AlreadyCulled already_culled;
+
   Windows::const_iterator wi;
   for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
     GraphicsOutput *win = (*wi);
@@ -871,7 +851,26 @@ cull_to_bins(const GraphicsEngine::Windows &wlist) {
       for (int i = 0; i < num_display_regions; ++i) {
         DisplayRegion *dr = win->get_active_display_region(i);
         if (dr != (DisplayRegion *)NULL) {
-          cull_to_bins(win, dr);
+          NodePath camera = dr->get_camera();
+          AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(camera, NULL)).first;
+          if ((*aci).second == NULL) {
+            // We have not used this camera already in this thread.
+            // Perform the cull operation.
+            (*aci).second = dr;
+            cull_to_bins(win, dr);
+
+          } else {
+            // We have already culled a scene using this camera in
+            // this thread, and now we're being asked to cull another
+            // scene using the same camera.  (Maybe this represents
+            // two different DisplayRegions for the left and right
+            // channels of a stereo image.)  Of course, the cull
+            // result will be the same, so just use the result from
+            // the other DisplayRegion.
+            DisplayRegion *other_dr = (*aci).second;
+            dr->set_cull_result(other_dr->get_cull_result(),
+                                setup_scene(win->get_gsg(), dr));
+          }
         }
       }
     }
@@ -881,9 +880,8 @@ cull_to_bins(const GraphicsEngine::Windows &wlist) {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::cull_to_bins
 //       Access: Private
-//  Description: This variant of cull_to_bins() is called
-//               by render_subframe(), as well as within the
-//               implementation of cull_to_bins(), above.
+//  Description: Called only within the inner loop of cull_to_bins(),
+//               above.
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 cull_to_bins(GraphicsOutput *win, DisplayRegion *dr) {
@@ -1178,31 +1176,6 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
     initial_state = initial_state->compose(get_invert_polygon_state());
   }
 
-  if (window->get_red_blue_stereo()) {
-    // If the window has red-blue stereo mode, apply the appropriate
-    // color mask to the initial state.
-    switch (dr->get_stereo_channel()) {
-    case Lens::SC_left:
-      if (invert_red_blue_stereo) {
-	initial_state = initial_state->compose(get_blue_channel_state());
-      } else {
-	initial_state = initial_state->compose(get_red_channel_state());
-      }
-      break;
-
-    case Lens::SC_right:
-      if (invert_red_blue_stereo) {
-	initial_state = initial_state->compose(get_red_channel_state());
-      } else {
-	initial_state = initial_state->compose(get_blue_channel_state());
-      }
-      break;
-
-    case Lens::SC_both:
-      break;
-    }
-  }
-
   scene_setup->set_display_region(dr);
   scene_setup->set_viewport_size(dr->get_pixel_width(), dr->get_pixel_height());
   scene_setup->set_scene_root(scene_root);
@@ -1540,44 +1513,6 @@ get_invert_polygon_state() {
   return state;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::get_red_channel_state
-//       Access: Protected, Static
-//  Description: Returns a RenderState for rendering only to the red
-//               channel of the color buffer, for implementing
-//               red-blue stereo.
-////////////////////////////////////////////////////////////////////
-const RenderState *GraphicsEngine::
-get_red_channel_state() {
-  // Once someone asks for this pointer, we hold its reference count
-  // and never free it.
-  static CPT(RenderState) state = (const RenderState *)NULL;
-  if (state == (const RenderState *)NULL) {
-    state = RenderState::make(ColorWriteAttrib::make(ColorWriteAttrib::C_red));
-  }
-
-  return state;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::get_blue_channel_state
-//       Access: Protected, Static
-//  Description: Returns a RenderState for rendering only to the blue
-//               channel of the color buffer, for implementing
-//               red-blue stereo.
-////////////////////////////////////////////////////////////////////
-const RenderState *GraphicsEngine::
-get_blue_channel_state() {
-  // Once someone asks for this pointer, we hold its reference count
-  // and never free it.
-  static CPT(RenderState) state = (const RenderState *)NULL;
-  if (state == (const RenderState *)NULL) {
-    state = RenderState::make(ColorWriteAttrib::make(ColorWriteAttrib::C_blue));
-  }
-
-  return state;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::get_window_renderer
 //       Access: Private

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

@@ -96,9 +96,6 @@ PUBLISHED:
   void open_windows();
   void sync_frame();
   void flip_frame();
-  
-  void render_subframe(GraphicsOutput *win, DisplayRegion *dr,
-                       bool cull_sorting);
 
 public:
   enum ThreadState {
@@ -180,8 +177,6 @@ private:
 #endif  // DO_PSTATS
 
   static const RenderState *get_invert_polygon_state();
-  static const RenderState *get_red_channel_state();
-  static const RenderState *get_blue_channel_state();
 
   // The WindowRenderer class records the stages of the pipeline that
   // each thread (including the main thread, a.k.a. "app") should

+ 43 - 4
panda/src/display/graphicsOutput.I

@@ -231,16 +231,29 @@ get_inverted() const {
 //  Description: Enables red-blue stereo mode on this particular
 //               window.  When red-blue stereo mode is in effect,
 //               DisplayRegions that have the "left" channel set will
-//               render in the red channel only, while DisplayRegions
-//               that have the "right" channel set will render in the
-//               blue channel only.
+//               render in the red (or specified) channel only, while
+//               DisplayRegions that have the "right" channel set will
+//               render in the blue (or specified) channel only.
+//
+//               The remaining two parameters specify the particular
+//               color channel(s) to associate with each eye.  Use the
+//               bits defined in ColorWriteAttrib::Channels.
 //
 //               This can be used to achieve a cheesy stereo mode in
 //               the absence of hardware-supported stereo.
 ////////////////////////////////////////////////////////////////////
 INLINE void GraphicsOutput::
-set_red_blue_stereo(bool red_blue_stereo) {
+set_red_blue_stereo(bool red_blue_stereo,
+                    unsigned int left_eye_color_mask,
+                    unsigned int right_eye_color_mask) {
   _red_blue_stereo = red_blue_stereo;
+  if (_red_blue_stereo) {
+    _left_eye_color_mask = left_eye_color_mask;
+    _right_eye_color_mask = right_eye_color_mask;
+  } else {
+    _left_eye_color_mask = 0x0f;
+    _right_eye_color_mask = 0x0f;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -254,6 +267,32 @@ get_red_blue_stereo() const {
   return _red_blue_stereo;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_left_eye_color_mask
+//       Access: Published
+//  Description: Returns the color mask in effect when rendering a
+//               left-eye view in red_blue stereo mode.  This is one
+//               or more bits defined in ColorWriteAttrib::Channels.
+//               See set_red_blue_stereo().
+////////////////////////////////////////////////////////////////////
+INLINE unsigned int GraphicsOutput::
+get_left_eye_color_mask() const {
+  return _left_eye_color_mask;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_right_eye_color_mask
+//       Access: Published
+//  Description: Returns the color mask in effect when rendering a
+//               right-eye view in red_blue stereo mode.  This is one
+//               or more bits defined in ColorWriteAttrib::Channels.
+//               See set_red_blue_stereo().
+////////////////////////////////////////////////////////////////////
+INLINE unsigned int GraphicsOutput::
+get_right_eye_color_mask() const {
+  return _right_eye_color_mask;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::is_stereo
 //       Access: Published

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

@@ -89,6 +89,8 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
   _one_shot = false;
   _inverted = window_inverted;
   _red_blue_stereo = false;
+  _left_eye_color_mask = 0x0f;
+  _right_eye_color_mask = 0x0f;
   _delete_flag = false;
   _texture_card = 0;
   _trigger_copy = false;

+ 8 - 1
panda/src/display/graphicsOutput.h

@@ -113,8 +113,13 @@ PUBLISHED:
   void set_inverted(bool inverted);
   INLINE bool get_inverted() const;
 
-  INLINE void set_red_blue_stereo(bool red_blue_stereo);
+  INLINE void set_red_blue_stereo(bool red_blue_stereo,
+                                  unsigned int left_eye_color_mask,
+                                  unsigned int right_eye_color_mask);
   INLINE bool get_red_blue_stereo() const;
+  INLINE unsigned int get_left_eye_color_mask() const;
+  INLINE unsigned int get_right_eye_color_mask() const;
+
   INLINE bool is_stereo() const;
 
   INLINE void clear_delete_flag();
@@ -240,6 +245,8 @@ protected:
   bool _one_shot;
   bool _inverted;
   bool _red_blue_stereo;
+  unsigned int _left_eye_color_mask;
+  unsigned int _right_eye_color_mask;
   bool _delete_flag;
 
   // These weak pointers are used to keep track of whether the

+ 0 - 51
panda/src/display/graphicsStateGuardian.I

@@ -559,24 +559,6 @@ get_global_gsg() {
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::set_scene
-//       Access: Public
-//  Description: Sets the SceneSetup object that indicates the initial
-//               camera position, etc.  This must be called before
-//               traversal begins.  Returns true if the scene is
-//               acceptable, false if something's wrong.
-////////////////////////////////////////////////////////////////////
-INLINE bool GraphicsStateGuardian::
-set_scene(SceneSetup *scene_setup) {
-  _scene_setup = scene_setup;
-  _current_lens = scene_setup->get_lens();
-  if (_current_lens == (Lens *)NULL) {
-    return false;
-  }
-  return prepare_lens(scene_setup->get_display_region()->get_stereo_channel());
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_scene
 //       Access: Public
@@ -605,39 +587,6 @@ clear(DisplayRegion *dr) {
   pop_display_region(old_dr);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::force_normals
-//       Access: Public
-//  Description: Temporarily forces the GSG to issue normals to the
-//               graphics pipe.  Normally, the GSG will issue normals
-//               only if lighting is on.
-//
-//               This call must be matched with exactly one call to
-//               undo_force_normals().
-////////////////////////////////////////////////////////////////////
-INLINE int GraphicsStateGuardian::
-force_normals() {
-  nassertr(_force_normals >= 0, _force_normals);
-  _force_normals++;
-  return _force_normals;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::undo_force_normals
-//       Access: Public
-//  Description: Undoes the effect of a previous call to
-//               force_normals().
-//
-//               This call must be matched with one-to-one with a
-//               previous call to force_normals().
-////////////////////////////////////////////////////////////////////
-INLINE int GraphicsStateGuardian::
-undo_force_normals() {
-  _force_normals--;
-  nassertr(_force_normals >= 0, _force_normals);
-  return _force_normals;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::reset_if_new
 //       Access: Public

+ 37 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -33,6 +33,7 @@
 #include "geomTristrips.h"
 #include "geomTrifans.h"
 #include "geomLinestrips.h"
+#include "colorWriteAttrib.h"
 #include "shader.h"
 
 #include <algorithm>
@@ -283,11 +284,13 @@ reset() {
   _scene_setup = _scene_null;
   
   _buffer_mask = 0;
+  _color_write_mask = ColorWriteAttrib::C_all;
   _color_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f);
   _depth_clear_value = 1.0f;
   _stencil_clear_value = 0.0f;
   _accum_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f);
-  _force_normals = 0;
+
+  _is_stereo = get_properties().is_stereo();
 
   _has_scene_graph_color = false;
   _transform_stale = true;
@@ -345,6 +348,39 @@ get_render_buffer(int buffer_type) {
   return RenderBuffer(this, buffer_type & _buffer_mask);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::set_scene
+//       Access: Public
+//  Description: Sets the SceneSetup object that indicates the initial
+//               camera position, etc.  This must be called before
+//               traversal begins.  Returns true if the scene is
+//               acceptable, false if something's wrong.
+////////////////////////////////////////////////////////////////////
+bool GraphicsStateGuardian::
+set_scene(SceneSetup *scene_setup) {
+  _scene_setup = scene_setup;
+  _current_lens = scene_setup->get_lens();
+  if (_current_lens == (Lens *)NULL) {
+    return false;
+  }
+  DisplayRegion *dr = scene_setup->get_display_region();
+  Lens::StereoChannel stereo_channel = dr->get_stereo_channel();
+  switch (stereo_channel) {
+  case Lens::SC_left:
+    _color_write_mask = dr->get_window()->get_left_eye_color_mask();
+    break;
+
+  case Lens::SC_right:
+    _color_write_mask = dr->get_window()->get_right_eye_color_mask();
+    break;
+
+  case Lens::SC_both:
+    _color_write_mask = ColorWriteAttrib::C_all;
+  }
+
+  return prepare_lens(stereo_channel);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_prepared_objects
 //       Access: Public, Virtual

+ 4 - 9
panda/src/display/graphicsStateGuardian.h

@@ -125,7 +125,7 @@ PUBLISHED:
   INLINE static GraphicsStateGuardian *get_global_gsg();
 
 public:
-  INLINE bool set_scene(SceneSetup *scene_setup);
+  bool set_scene(SceneSetup *scene_setup);
   INLINE SceneSetup *get_scene() const;
 
   virtual PreparedGraphicsObjects *get_prepared_objects();
@@ -163,9 +163,6 @@ public:
   virtual void prepare_display_region()=0;
   virtual bool prepare_lens(Lens::StereoChannel stereo_channel);
 
-  INLINE int force_normals();
-  INLINE int undo_force_normals();
-
   virtual bool begin_frame();
   virtual bool begin_scene();
   virtual void end_scene();
@@ -284,6 +281,7 @@ protected:
   CPT(GeomVertexData) _vertex_data;
 
   int _buffer_mask;
+  unsigned int _color_write_mask;
   Colorf _color_clear_value;
   float _depth_clear_value;
   bool _stencil_clear_value;
@@ -296,16 +294,13 @@ protected:
   CPT(DisplayRegion) _current_display_region;
   CPT(Lens) _current_lens;
 
-  // This is used by wants_normals().  It's used as a semaphore:
-  // increment it to enable normals, and decrement it when you're
-  // done.  The graphics engine will apply normals if it is nonzero.
-  int _force_normals;
-
   CoordinateSystem _coordinate_system;
   CoordinateSystem _internal_coordinate_system;
   CPT(TransformState) _cs_transform;
   CPT(TransformState) _inv_cs_transform;
 
+  bool _is_stereo;
+
   Colorf _scene_graph_color;
   bool _has_scene_graph_color;
   bool _transform_stale;

+ 46 - 0
panda/src/display/graphicsWindow.cxx

@@ -24,6 +24,7 @@
 #include "mutexHolder.h"
 #include "reMutexHolder.h"
 #include "throw_event.h"
+#include "string_utils.h"
 
 TypeHandle GraphicsWindow::_type_handle;
 
@@ -50,6 +51,10 @@ GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
   }
 
   _red_blue_stereo = red_blue_stereo && !_gsg->get_properties().is_stereo();
+  if (_red_blue_stereo) {
+    _left_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(0));
+    _right_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(1));
+  }
 
   _properties.set_open(false);
   _properties.set_undecorated(false);
@@ -724,3 +729,44 @@ system_changed_size(int x_size, int y_size) {
     set_size_and_recalc(x_size, y_size);
   }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::parse_color_mask
+//       Access: Private, Static
+//  Description: Parses one of the keywords in the
+//               red-blue-stereo-colors Config.prc variable, and
+//               returns the corresponding bitmask.
+//
+//               These bitmask values are taken from ColorWriteAttrib.
+////////////////////////////////////////////////////////////////////
+unsigned int GraphicsWindow::
+parse_color_mask(const string &word) {
+  unsigned int result = 0;
+  vector_string components;
+  tokenize(word, components, "|");
+
+  vector_string::const_iterator ci;
+  for (ci = components.begin(); ci != components.end(); ++ci) {
+    string w = downcase(*ci);
+    if (w == "red" || w == "r") {
+      result |= 0x001;
+
+    } else if (w == "green" || w == "g") {
+      result |= 0x002;
+
+    } else if (w == "blue" || w == "b") {
+      result |= 0x004;
+
+    } else if (w == "alpha" || w == "a") {
+      result |= 0x008;
+
+    } else if (w == "off") {
+      
+    } else {
+      display_cat.warning()
+        << "Invalid color in red-blue-stereo-colors: " << (*ci) << "\n";
+    }
+  }
+
+  return result;
+}

+ 3 - 0
panda/src/display/graphicsWindow.h

@@ -101,6 +101,9 @@ protected:
   // thread other than the window thread.
   void system_changed_properties(const WindowProperties &properties);
   void system_changed_size(int x_size, int y_size);
+
+private:
+  static unsigned int parse_color_mask(const string &word);
   
 protected:
   typedef vector_GraphicsWindowInputDevice InputDevices;

+ 4 - 4
panda/src/framework/windowFramework.cxx

@@ -967,7 +967,7 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_color(_window->get_clear_color());
     _display_region_3d->set_clear_depth(_window->get_clear_depth());
     if (_display_region_right) {
-      _display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
+      _display_region_right->set_clear_color_active(true);
       _display_region_right->set_clear_depth_active(true);
       _display_region_right->set_clear_color(_window->get_clear_color());
       _display_region_right->set_clear_depth(_window->get_clear_depth());
@@ -980,7 +980,7 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
     _display_region_3d->set_clear_depth(1.0f);
     if (_display_region_right) {
-      _display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
+      _display_region_right->set_clear_color_active(true);
       _display_region_right->set_clear_depth_active(true);
       _display_region_right->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
       _display_region_right->set_clear_depth(1.0f);
@@ -993,7 +993,7 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
     _display_region_3d->set_clear_depth(1.0f);
     if (_display_region_right) {
-      _display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
+      _display_region_right->set_clear_color_active(true);
       _display_region_right->set_clear_depth_active(true);
       _display_region_right->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
       _display_region_right->set_clear_depth(1.0f);
@@ -1006,7 +1006,7 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
     _display_region_3d->set_clear_depth(1.0f);
     if (_display_region_right) {
-      _display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
+      _display_region_right->set_clear_color_active(true);
       _display_region_right->set_clear_depth_active(true);
       _display_region_right->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
       _display_region_right->set_clear_depth(1.0f);

+ 18 - 25
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -794,8 +794,6 @@ reset() {
     GLP(Disable)(GL_MULTISAMPLE);
   }
 
-  _stereo = ((get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_stereo) != 0);
-
   // Set up all the enabled/disabled flags to GL's known initial
   // values: everything off.
   _multisample_mode = 0;
@@ -817,8 +815,6 @@ reset() {
   GLP(Disable)(GL_DITHER);
   _dithering_enabled = false;
 
-  _texgen_forced_normal = false;
-
   _current_shader_expansion = (ShaderExpansion *)NULL;
   _current_shader_context = (CLP(ShaderContext) *)NULL;
   _vertex_array_shader_expansion = (ShaderExpansion *)NULL;
@@ -3185,7 +3181,9 @@ do_issue_blending() {
   // all the other blending-related stuff doesn't matter.  If the
   // device doesn't support color-write, we use blending tricks
   // to effectively disable color write.
-  if (_target._color_write->get_channels() == ColorWriteAttrib::C_off) {
+  unsigned int color_channels = 
+    _target._color_write->get_channels() & _color_write_mask;
+  if (color_channels == ColorWriteAttrib::C_off) {
     if (_target._color_write != _state._color_write) {
       enable_multisample_alpha_one(false);
       enable_multisample_alpha_mask(false);
@@ -3202,11 +3200,10 @@ do_issue_blending() {
   } else {
     if (_target._color_write != _state._color_write) {
       if (CLP(color_mask)) {
-        unsigned int channels = _target._color_write->get_channels();
-        GLP(ColorMask)((channels & ColorWriteAttrib::C_red) != 0,
-                       (channels & ColorWriteAttrib::C_green) != 0,
-                       (channels & ColorWriteAttrib::C_blue) != 0,
-                       (channels & ColorWriteAttrib::C_alpha) != 0);
+        GLP(ColorMask)((color_channels & ColorWriteAttrib::C_red) != 0,
+                       (color_channels & ColorWriteAttrib::C_green) != 0,
+                       (color_channels & ColorWriteAttrib::C_blue) != 0,
+                       (color_channels & ColorWriteAttrib::C_alpha) != 0);
       }
     }
   }
@@ -3734,7 +3731,7 @@ set_draw_buffer(const RenderBuffer &rb) {
     break;
 
   case RenderBuffer::T_front_right:
-    if (_stereo) {
+    if (_is_stereo) {
       GLP(DrawBuffer)(GL_FRONT_RIGHT);
     } else {
       GLP(DrawBuffer)(GL_FRONT);
@@ -3742,7 +3739,7 @@ set_draw_buffer(const RenderBuffer &rb) {
     break;
 
   case RenderBuffer::T_front_left:
-    if (_stereo) {
+    if (_is_stereo) {
       GLP(DrawBuffer)(GL_FRONT_LEFT);
     } else {
       GLP(DrawBuffer)(GL_FRONT);
@@ -3750,7 +3747,7 @@ set_draw_buffer(const RenderBuffer &rb) {
     break;
 
   case RenderBuffer::T_back_right:
-    if (_stereo) {
+    if (_is_stereo) {
       GLP(DrawBuffer)(GL_BACK_RIGHT);
     } else {
       GLP(DrawBuffer)(GL_BACK);
@@ -3758,7 +3755,7 @@ set_draw_buffer(const RenderBuffer &rb) {
     break;
 
   case RenderBuffer::T_back_left:
-    if (_stereo) {
+    if (_is_stereo) {
       GLP(DrawBuffer)(GL_BACK_LEFT);
     } else {
       GLP(DrawBuffer)(GL_BACK);
@@ -3768,6 +3765,13 @@ set_draw_buffer(const RenderBuffer &rb) {
   default:
     GLP(DrawBuffer)(GL_FRONT_AND_BACK);
   }
+
+  // Also ensure that any global color channels are masked out.
+  GLP(ColorMask)((_color_write_mask & ColorWriteAttrib::C_red) != 0,
+                 (_color_write_mask & ColorWriteAttrib::C_green) != 0,
+                 (_color_write_mask & ColorWriteAttrib::C_blue) != 0,
+                 (_color_write_mask & ColorWriteAttrib::C_alpha) != 0);
+  
   report_my_gl_errors();
 }
 
@@ -5432,17 +5436,6 @@ do_issue_tex_gen() {
     }
   }
 
-  // Certain texgen modes (sphere_map, cube_map) require forcing the
-  // normal to be sent to the GL while the texgen mode is in effect.
-  if (force_normal != _texgen_forced_normal) {
-    if (force_normal) {
-      force_normals();
-    } else  {
-      undo_force_normals();
-    }
-    _texgen_forced_normal = force_normal;
-  }
-
   report_my_gl_errors();
 }
 

+ 0 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -289,8 +289,6 @@ protected:
     MM_alpha_mask = 0x0004,
   };
 
-  bool _stereo;
-
   int _multisample_mode;
   bool _line_smooth_enabled;
   bool _point_smooth_enabled;
@@ -306,7 +304,6 @@ protected:
   int _decal_level;
   
   bool _dithering_enabled;
-  bool _texgen_forced_normal;
 
   LMatrix4f _projection_mat;
   int _viewport_width;