Browse Source

support stereo DisplayRegions

David Rose 20 years ago
parent
commit
47c2e41c75

+ 2 - 13
direct/src/showbase/ShowBase.py

@@ -807,19 +807,8 @@ class ShowBase(DirectObject.DirectObject):
         if stereo == None:
         if stereo == None:
             stereo = (win.isStereo() and self.config.GetBool('default-stereo-camera', 1))
             stereo = (win.isStereo() and self.config.GetBool('default-stereo-camera', 1))
         if stereo:
         if stereo:
-            # A stereo camera!  The first DisplayRegion becomes the
-            # left channel.
-            dr.setStereoChannel(Lens.SCLeft)
-
-            # So we'll need another DisplayRegion for the right channel.
-            dr = win.makeDisplayRegion(*displayRegion)
-            dr.setSort(sort)
-            dr.setClearDepthActive(1)
-            if clearColor:
-                dr.setClearColorActive(1)
-                dr.setClearColor(clearColor)
-            dr.setCamera(cam)
-            dr.setStereoChannel(Lens.SCRight)
+            # A stereo camera!
+            dr.setStereoChannel(Lens.SCStereo)
 
 
         return cam
         return cam
 
 

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

@@ -15,8 +15,6 @@
     config_display.h \
     config_display.h \
     drawableRegion.I drawableRegion.h \
     drawableRegion.I drawableRegion.h \
     displayRegion.I displayRegion.h  \
     displayRegion.I displayRegion.h  \
-    displayRegionStack.I \
-    displayRegionStack.h \
     frameBufferProperties.I frameBufferProperties.h \
     frameBufferProperties.I frameBufferProperties.h \
     graphicsEngine.I graphicsEngine.h \
     graphicsEngine.I graphicsEngine.h \
     graphicsOutput.I graphicsOutput.h \
     graphicsOutput.I graphicsOutput.h \
@@ -32,7 +30,6 @@
     graphicsDevice.h graphicsDevice.I \
     graphicsDevice.h graphicsDevice.I \
     parasiteBuffer.I parasiteBuffer.h \
     parasiteBuffer.I parasiteBuffer.h \
     windowProperties.I windowProperties.h \
     windowProperties.I windowProperties.h \
-    lensStack.I lensStack.h \
     lru.h
     lru.h
     
     
  #define INCLUDED_SOURCES  \
  #define INCLUDED_SOURCES  \
@@ -58,8 +55,7 @@
     standardMunger.I standardMunger.h \
     standardMunger.I standardMunger.h \
     config_display.h \
     config_display.h \
     drawableRegion.I drawableRegion.h \
     drawableRegion.I drawableRegion.h \
-    displayRegion.I displayRegion.h displayRegionStack.I \
-    displayRegionStack.h \
+    displayRegion.I displayRegion.h \
     frameBufferProperties.I frameBufferProperties.h \
     frameBufferProperties.I frameBufferProperties.h \
     graphicsEngine.I graphicsEngine.h \
     graphicsEngine.I graphicsEngine.h \
     graphicsOutput.I graphicsOutput.h \
     graphicsOutput.I graphicsOutput.h \
@@ -74,7 +70,6 @@
     graphicsDevice.I graphicsDevice.h \
     graphicsDevice.I graphicsDevice.h \
     parasiteBuffer.I parasiteBuffer.h \
     parasiteBuffer.I parasiteBuffer.h \
     windowProperties.I windowProperties.h \
     windowProperties.I windowProperties.h \
-    lensStack.I lensStack.h \
     renderBuffer.h
     renderBuffer.h
 
 
   #define IGATESCAN all
   #define IGATESCAN all

+ 31 - 0
panda/src/display/displayRegion.I

@@ -66,6 +66,37 @@ get_stereo_channel() {
   return cdata->_stereo_channel;
   return cdata->_stereo_channel;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::set_clear_depth_between_eyes
+//       Access: Published
+//  Description: Specifies whether the depth buffer is cleared again
+//               between the left and right eyes of a stereo
+//               DisplayRegion.  This has an effect only when
+//               get_stereo_channel() returns Lens::SC_stereo; other
+//               kinds of DisplayRegions are monocular and do not
+//               render two different eyes.
+//
+//               Normally, you want this to be true, since if you're
+//               using a depth buffer you normally need to clear it
+//               between the left and right eyes.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+set_clear_depth_between_eyes(bool clear_depth_between_eyes) {
+  _clear_depth_between_eyes = clear_depth_between_eyes;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_clear_depth_between_eyes
+//       Access: Published
+//  Description: Returns whether the depth buffer is cleared again
+//               between the left and right eyes of a stereo
+//               DisplayRegion.  See set_clear_depth_between_eyes().
+////////////////////////////////////////////////////////////////////
+INLINE bool DisplayRegion::
+get_clear_depth_between_eyes() const {
+  return _clear_depth_between_eyes;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::set_cube_map_index
 //     Function: DisplayRegion::set_cube_map_index
 //       Access: Published
 //       Access: Published

+ 7 - 4
panda/src/display/displayRegion.cxx

@@ -33,7 +33,8 @@ TypeHandle DisplayRegion::_type_handle;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DisplayRegion::
 DisplayRegion::
 DisplayRegion(GraphicsOutput *window) :
 DisplayRegion(GraphicsOutput *window) :
-  _window(window)
+  _window(window),
+  _clear_depth_between_eyes(true)
 {
 {
   _draw_buffer_type = window->get_draw_buffer_type();
   _draw_buffer_type = window->get_draw_buffer_type();
   compute_pixels_all_stages();
   compute_pixels_all_stages();
@@ -46,7 +47,8 @@ DisplayRegion(GraphicsOutput *window) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DisplayRegion::
 DisplayRegion::
 DisplayRegion(GraphicsOutput *window, float l, float r, float b, float t) :
 DisplayRegion(GraphicsOutput *window, float l, float r, float b, float t) :
-  _window(window)
+  _window(window),
+  _clear_depth_between_eyes(true)
 {
 {
   _draw_buffer_type = window->get_draw_buffer_type();
   _draw_buffer_type = window->get_draw_buffer_type();
   set_dimensions(l, r, b, t);
   set_dimensions(l, r, b, t);
@@ -356,7 +358,8 @@ set_stereo_channel(Lens::StereoChannel stereo_channel) {
     cdata->_draw_buffer_mask = ~(RenderBuffer::T_front_left | RenderBuffer::T_back_left);
     cdata->_draw_buffer_mask = ~(RenderBuffer::T_front_left | RenderBuffer::T_back_left);
     break;
     break;
 
 
-  case Lens::SC_both:
+  case Lens::SC_mono:
+  case Lens::SC_stereo:
     cdata->_draw_buffer_mask = ~0;
     cdata->_draw_buffer_mask = ~0;
     break;
     break;
   }
   }
@@ -759,7 +762,7 @@ CData() :
   _camera_node((Camera *)NULL),
   _camera_node((Camera *)NULL),
   _active(true),
   _active(true),
   _sort(0),
   _sort(0),
-  _stereo_channel(Lens::SC_both),
+  _stereo_channel(Lens::SC_mono),
   _draw_buffer_mask(~0),
   _draw_buffer_mask(~0),
   _cube_map_index(-1)
   _cube_map_index(-1)
 {
 {

+ 4 - 0
panda/src/display/displayRegion.h

@@ -92,6 +92,9 @@ PUBLISHED:
   void set_stereo_channel(Lens::StereoChannel stereo_channel);
   void set_stereo_channel(Lens::StereoChannel stereo_channel);
   INLINE Lens::StereoChannel get_stereo_channel();
   INLINE Lens::StereoChannel get_stereo_channel();
 
 
+  INLINE void set_clear_depth_between_eyes(bool clear_depth_between_eyes);
+  INLINE bool get_clear_depth_between_eyes() const;
+
   INLINE void set_cube_map_index(int cube_map_index);
   INLINE void set_cube_map_index(int cube_map_index);
   INLINE int get_cube_map_index() const;
   INLINE int get_cube_map_index() const;
 
 
@@ -130,6 +133,7 @@ private:
   // The associated window is a permanent property of the
   // The associated window is a permanent property of the
   // DisplayRegion.  It doesn't need to be cycled.
   // DisplayRegion.  It doesn't need to be cycled.
   GraphicsOutput *_window;
   GraphicsOutput *_window;
+  bool _clear_depth_between_eyes;
 
 
   // This is the data that is associated with the DisplayRegion that
   // This is the data that is associated with the DisplayRegion that
   // needs to be cycled every frame, but represents the parameters as
   // needs to be cycled every frame, but represents the parameters as

+ 0 - 61
panda/src/display/displayRegionStack.I

@@ -1,61 +0,0 @@
-// Filename: displayRegionStack.I
-// Created by:  drose (06Oct99)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegionStack::Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE DisplayRegionStack::
-DisplayRegionStack() {
-  _stack_level = -1;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegionStack::Destructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE DisplayRegionStack::
-~DisplayRegionStack() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegionStack::Copy Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE DisplayRegionStack::
-DisplayRegionStack(const DisplayRegionStack &copy) :
-  _display_region(copy._display_region),
-  _stack_level(copy._stack_level)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DisplayRegionStack::Copy Operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void DisplayRegionStack::
-operator =(const DisplayRegionStack &copy) {
-  _display_region = copy._display_region;
-  _stack_level = copy._stack_level;
-}

+ 0 - 51
panda/src/display/displayRegionStack.h

@@ -1,51 +0,0 @@
-// Filename: displayRegionStack.h
-// Created by:  drose (06Oct99)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef DISPLAYREGIONSTACK_H
-#define DISPLAYREGIONSTACK_H
-
-#include "pandabase.h"
-
-#include "displayRegion.h"
-
-class GraphicsStateGuardian;
-
-////////////////////////////////////////////////////////////////////
-//       Class : DisplayRegionStack
-// Description : An instance of this kind of object is returned by
-//               GraphicsStateGuardian::push_display_region().  It
-//               holds the information needed to restore the previous
-//               display region in the subsequent matching call to
-//               pop_display_region().
-////////////////////////////////////////////////////////////////////
-class DisplayRegionStack {
-public:
-  INLINE DisplayRegionStack();
-  INLINE ~DisplayRegionStack();
-  INLINE DisplayRegionStack(const DisplayRegionStack &copy);
-  INLINE void operator =(const DisplayRegionStack &copy);
-
-private:
-  CPT(DisplayRegion) _display_region;
-  int _stack_level;
-  friend class GraphicsStateGuardian;
-};
-
-#include "displayRegionStack.I"
-
-#endif

+ 56 - 37
panda/src/display/graphicsEngine.cxx

@@ -809,11 +809,16 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
   GraphicsStateGuardian *gsg = win->get_gsg();
   GraphicsStateGuardian *gsg = win->get_gsg();
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
 
+  win->change_scenes(dr);
+  gsg->prepare_display_region(dr, dr->get_stereo_channel());
+
   PT(SceneSetup) scene_setup = setup_scene(gsg, dr);
   PT(SceneSetup) scene_setup = setup_scene(gsg, dr);
-  if (setup_gsg(gsg, scene_setup)) {
-    win->change_scenes(dr);
-    DisplayRegionStack old_dr = gsg->push_display_region(dr);
-    gsg->prepare_display_region();
+  if (!gsg->set_scene(scene_setup)) {
+    // The scene or lens is inappropriate somehow.
+    display_cat.error()
+      << gsg->get_type() << " cannot render scene with specified lens.\n";
+
+  } else {
     if (dr->is_any_clear_active()) {
     if (dr->is_any_clear_active()) {
       gsg->clear(dr);
       gsg->clear(dr);
     }
     }
@@ -823,8 +828,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
       do_cull(&cull_handler, scene_setup, gsg);
       do_cull(&cull_handler, scene_setup, gsg);
       gsg->end_scene();
       gsg->end_scene();
     }
     }
-    
-    gsg->pop_display_region(old_dr);
   }
   }
 }
 }
 
 
@@ -1243,43 +1246,59 @@ do_draw(CullResult *cull_result, SceneSetup *scene_setup,
   PStatTimer timer(_draw_pcollector);
   PStatTimer timer(_draw_pcollector);
 
 
   GraphicsStateGuardian *gsg = win->get_gsg();
   GraphicsStateGuardian *gsg = win->get_gsg();
-  if (setup_gsg(gsg, scene_setup)) {
-    win->change_scenes(dr);
-    DisplayRegionStack old_dr = gsg->push_display_region(dr);
-    gsg->prepare_display_region();
+  win->change_scenes(dr);
+
+  if (dr->get_stereo_channel() == Lens::SC_stereo) {
+    // A special case.  For a stereo DisplayRegion, we render the left
+    // eye, followed by the right eye.
     if (dr->is_any_clear_active()) {
     if (dr->is_any_clear_active()) {
+      gsg->prepare_display_region(dr, Lens::SC_stereo);
       gsg->clear(dr);
       gsg->clear(dr);
     }
     }
-    if (gsg->begin_scene()) {
-      cull_result->draw();
-      gsg->end_scene();
-    }
-    gsg->pop_display_region(old_dr);
-  }
-}
+    gsg->prepare_display_region(dr, Lens::SC_left);
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsEngine::setup_gsg
-//       Access: Private
-//  Description: Sets up the GSG to draw the indicated scene.  Returns
-//               true if the scene (and its lens) is acceptable, false
-//               otherwise.
-////////////////////////////////////////////////////////////////////
-bool GraphicsEngine::
-setup_gsg(GraphicsStateGuardian *gsg, SceneSetup *scene_setup) {
-  if (scene_setup == (SceneSetup *)NULL) {
-    // No scene, no draw.
-    return false;
-  }
+    if (!gsg->set_scene(scene_setup)) {
+      // The scene or lens is inappropriate somehow.
+      display_cat.error()
+        << gsg->get_type() << " cannot render scene with specified lens.\n";
+    } else {
+      if (gsg->begin_scene()) {
+        cull_result->draw();
+        gsg->end_scene();
+      }
+      if (dr->get_clear_depth_between_eyes()) {
+        DrawableRegion clear_region;
+        clear_region.set_clear_depth_active(true);
+        clear_region.set_clear_depth(dr->get_clear_depth());
+        gsg->clear(&clear_region);
+      }
+      gsg->prepare_display_region(dr, Lens::SC_right);
+      gsg->set_scene(scene_setup);
+      if (gsg->begin_scene()) {
+        cull_result->draw();
+        gsg->end_scene();
+      }
+    }
 
 
-  if (!gsg->set_scene(scene_setup)) {
-    // The scene or lens is inappropriate somehow.
-    display_cat.error()
-      << gsg->get_type() << " cannot render scene with specified lens.\n";
-    return false;
+  } else {
+    // For a mono DisplayRegion, or a left/right eye only
+    // DisplayRegion, we just render that.
+    gsg->prepare_display_region(dr, dr->get_stereo_channel());
+
+    if (!gsg->set_scene(scene_setup)) {
+      // The scene or lens is inappropriate somehow.
+      display_cat.error()
+        << gsg->get_type() << " cannot render scene with specified lens.\n";
+    } else {
+      if (dr->is_any_clear_active()) {
+        gsg->clear(dr);
+      }
+      if (gsg->begin_scene()) {
+        cull_result->draw();
+        gsg->end_scene();
+      }
+    }
   }
   }
-
-  return true;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -160,8 +160,6 @@ private:
   void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
   void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
                GraphicsOutput *win, DisplayRegion *dr);
                GraphicsOutput *win, DisplayRegion *dr);
 
 
-  bool setup_gsg(GraphicsStateGuardian *gsg, SceneSetup *scene_setup);
-
   void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
   void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
                      const GraphicsThreadingModel &threading_model);
                      const GraphicsThreadingModel &threading_model);
   void do_remove_window(GraphicsOutput *window);
   void do_remove_window(GraphicsOutput *window);

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

@@ -1033,9 +1033,8 @@ clear() {
 
 
     nassertv(_gsg != (GraphicsStateGuardian *)NULL);
     nassertv(_gsg != (GraphicsStateGuardian *)NULL);
 
 
-    DisplayRegionStack old_dr = _gsg->push_display_region(_default_display_region);
+    _gsg->prepare_display_region(_default_display_region, Lens::SC_mono);
     _gsg->clear(this);
     _gsg->clear(this);
-    _gsg->pop_display_region(old_dr);
   }
   }
 }
 }
 
 

+ 12 - 65
panda/src/display/graphicsStateGuardian.I

@@ -569,24 +569,6 @@ get_scene() const {
   return _scene_setup;
   return _scene_setup;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::clear
-//       Access: Public
-//  Description: Clears the framebuffer within the indicated
-//               DisplayRegion, according to the flags indicated by
-//               the DisplayRegion object (inheriting from
-//               DrawableRegion).  Note that by default, a
-//               DisplayRegion does not have any clear flags set, in
-//               which case this function will do nothing.
-////////////////////////////////////////////////////////////////////
-INLINE void GraphicsStateGuardian::
-clear(DisplayRegion *dr) {
-  DisplayRegionStack old_dr = push_display_region(dr);
-  prepare_display_region();
-  clear((DrawableRegion *)dr);
-  pop_display_region(old_dr);
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::reset_if_new
 //     Function: GraphicsStateGuardian::reset_if_new
 //       Access: Public
 //       Access: Public
@@ -632,16 +614,24 @@ get_transform() {
 //     Function: GraphicsStateGuardian::get_current_display_region
 //     Function: GraphicsStateGuardian::get_current_display_region
 //       Access: Public
 //       Access: Public
 //  Description: Returns the current display region being rendered to,
 //  Description: Returns the current display region being rendered to,
-//               as set by the last call to push_display_region() (or
-//               restored by pop_display_region()).  This display
-//               region will be made active (if it is not already) by
-//               a call to prepare_display_region().
+//               as set by the last call to prepare_display_region().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const DisplayRegion *GraphicsStateGuardian::
 INLINE const DisplayRegion *GraphicsStateGuardian::
 get_current_display_region() const {
 get_current_display_region() const {
   return _current_display_region;
   return _current_display_region;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_current_stereo_channel
+//       Access: Public
+//  Description: Returns the current stereo channel being rendered to,
+//               as set by the last call to prepare_display_region().
+////////////////////////////////////////////////////////////////////
+INLINE Lens::StereoChannel GraphicsStateGuardian::
+get_current_stereo_channel() const {
+  return _current_stereo_channel;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_current_lens
 //     Function: GraphicsStateGuardian::get_current_lens
 //       Access: Public
 //       Access: Public
@@ -654,49 +644,6 @@ get_current_lens() const {
   return _current_lens;
   return _current_lens;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::push_display_region
-//       Access: Public
-//  Description: Saves the current display region information and sets
-//               up a new display region for rendering.  The return
-//               value from this function must eventually be passed to
-//               a matching pop_display_region() call.
-//
-//               The new display region will not actually be made
-//               active for rendering until the next call to
-//               prepare_display_region().  This is a state-changing
-//               optimization.
-////////////////////////////////////////////////////////////////////
-INLINE DisplayRegionStack GraphicsStateGuardian::
-push_display_region(const DisplayRegion *dr) {
-  DisplayRegionStack old;
-  old._display_region = _current_display_region;
-  old._stack_level = _display_region_stack_level;
-  _display_region_stack_level++;
-  _current_display_region = dr;
-  return old;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::pop_display_region
-//       Access: Public
-//  Description: Restores the display region previously in effect,
-//               before the matching call to push_display_region().
-//
-//               The newly-restored display region will not actually
-//               be made active for rendering until the next call to
-//               prepare_display_region().  This is a state-changing
-//               optimization.
-////////////////////////////////////////////////////////////////////
-INLINE void GraphicsStateGuardian::
-pop_display_region(DisplayRegionStack &node) {
-  nassertv(_display_region_stack_level > 0);
-  _display_region_stack_level--;
-  nassertv(node._stack_level == _display_region_stack_level);
-  _current_display_region = node._display_region;
-  node._stack_level = -1;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_cs_transform
 //     Function: GraphicsStateGuardian::get_cs_transform
 //       Access: Public
 //       Access: Public

+ 39 - 21
panda/src/display/graphicsStateGuardian.cxx

@@ -101,6 +101,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
   set_coordinate_system(get_default_coordinate_system());
   set_coordinate_system(get_default_coordinate_system());
 
 
   _current_display_region = (DisplayRegion*)0L;
   _current_display_region = (DisplayRegion*)0L;
+  _current_stereo_channel = Lens::SC_mono;
   _current_lens = (Lens *)NULL;
   _current_lens = (Lens *)NULL;
   _needs_reset = true;
   _needs_reset = true;
   _is_valid = false;
   _is_valid = false;
@@ -270,10 +271,6 @@ reset() {
   _needs_reset = false;
   _needs_reset = false;
   _is_valid = false;
   _is_valid = false;
 
 
-  _display_region_stack_level = 0;
-  _frame_buffer_stack_level = 0;
-  _lens_stack_level = 0;
-
   _state_rs = NULL;
   _state_rs = NULL;
   _target_rs = NULL;
   _target_rs = NULL;
   _state.clear_to_zero();
   _state.clear_to_zero();
@@ -363,22 +360,8 @@ set_scene(SceneSetup *scene_setup) {
   if (_current_lens == (Lens *)NULL) {
   if (_current_lens == (Lens *)NULL) {
     return false;
     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);
+  return prepare_lens();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -627,6 +610,10 @@ set_depth_clear_value(const float value) {
 //  Description: Clears the framebuffer within the current
 //  Description: Clears the framebuffer within the current
 //               DisplayRegion, according to the flags indicated by
 //               DisplayRegion, according to the flags indicated by
 //               the given DrawableRegion object.
 //               the given DrawableRegion object.
+//
+//               This does not set the DisplayRegion first.  You
+//               should call prepare_display_region() to specify the
+//               region you wish the clear operation to apply to.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 clear(DrawableRegion *clearable) {
 clear(DrawableRegion *clearable) {
@@ -643,11 +630,42 @@ clear(DrawableRegion *clearable) {
   }
   }
 
 
   if (clear_buffer_type != 0) {
   if (clear_buffer_type != 0) {
-    prepare_display_region();
     do_clear(get_render_buffer(clear_buffer_type));
     do_clear(get_render_buffer(clear_buffer_type));
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::prepare_display_region
+//       Access: Public, Virtual
+//  Description: Makes the specified DisplayRegion current.  All
+//               future drawing and clear operations will be
+//               constrained within the given DisplayRegion.
+//
+//               The stereo_channel parameter further qualifies the
+//               channel that is to be rendered into, in the case of a
+//               stereo display region.  Normally, in the monocular
+//               case, it is Lens::SC_mono.
+////////////////////////////////////////////////////////////////////
+void GraphicsStateGuardian::
+prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
+  _current_display_region = dr;
+  _current_stereo_channel = 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_mono:
+  case Lens::SC_stereo:
+    _color_write_mask = ColorWriteAttrib::C_all;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::prepare_lens
 //     Function: GraphicsStateGuardian::prepare_lens
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -661,7 +679,7 @@ clear(DrawableRegion *clearable) {
 //               false if it is not.
 //               false if it is not.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool GraphicsStateGuardian::
 bool GraphicsStateGuardian::
-prepare_lens(Lens::StereoChannel stereo_channel) {
+prepare_lens() {
   return false;
   return false;
 }
 }
 
 

+ 5 - 12
panda/src/display/graphicsStateGuardian.h

@@ -22,8 +22,6 @@
 #include "pandabase.h"
 #include "pandabase.h"
 
 
 #include "frameBufferProperties.h"
 #include "frameBufferProperties.h"
-#include "displayRegionStack.h"
-#include "lensStack.h"
 #include "preparedGraphicsObjects.h"
 #include "preparedGraphicsObjects.h"
 #include "lens.h"
 #include "lens.h"
 #include "graphicsStateGuardianBase.h"
 #include "graphicsStateGuardianBase.h"
@@ -158,10 +156,10 @@ public:
   virtual void do_clear(const RenderBuffer &buffer)=0;
   virtual void do_clear(const RenderBuffer &buffer)=0;
 
 
   void clear(DrawableRegion *clearable);
   void clear(DrawableRegion *clearable);
-  INLINE void clear(DisplayRegion *dr);
 
 
-  virtual void prepare_display_region()=0;
-  virtual bool prepare_lens(Lens::StereoChannel stereo_channel);
+  virtual void prepare_display_region(DisplayRegion *dr,
+                                      Lens::StereoChannel stereo_channel);
+  virtual bool prepare_lens();
 
 
   virtual bool begin_frame();
   virtual bool begin_frame();
   virtual bool begin_scene();
   virtual bool begin_scene();
@@ -194,11 +192,9 @@ public:
   RenderBuffer get_render_buffer(int buffer_type);
   RenderBuffer get_render_buffer(int buffer_type);
 
 
   INLINE const DisplayRegion *get_current_display_region() const;
   INLINE const DisplayRegion *get_current_display_region() const;
+  INLINE Lens::StereoChannel get_current_stereo_channel() const;
   INLINE const Lens *get_current_lens() const;
   INLINE const Lens *get_current_lens() const;
 
 
-  INLINE DisplayRegionStack push_display_region(const DisplayRegion *dr);
-  INLINE void pop_display_region(DisplayRegionStack &node);
-
   INLINE const TransformState *get_cs_transform() const;
   INLINE const TransformState *get_cs_transform() const;
   INLINE const TransformState *get_inv_cs_transform() const;
   INLINE const TransformState *get_inv_cs_transform() const;
 
 
@@ -287,11 +283,8 @@ protected:
   bool _stencil_clear_value;
   bool _stencil_clear_value;
   Colorf _accum_clear_value;
   Colorf _accum_clear_value;
 
 
-  int _display_region_stack_level;
-  int _frame_buffer_stack_level;
-  int _lens_stack_level;
-
   CPT(DisplayRegion) _current_display_region;
   CPT(DisplayRegion) _current_display_region;
+  Lens::StereoChannel _current_stereo_channel;
   CPT(Lens) _current_lens;
   CPT(Lens) _current_lens;
 
 
   CoordinateSystem _coordinate_system;
   CoordinateSystem _coordinate_system;

+ 0 - 61
panda/src/display/lensStack.I

@@ -1,61 +0,0 @@
-// Filename: lensStack.I
-// Created by:  drose (25Feb02)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: LensStack::Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE LensStack::
-LensStack() {
-  _stack_level = -1;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LensStack::Destructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE LensStack::
-~LensStack() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LensStack::Copy Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE LensStack::
-LensStack(const LensStack &copy) :
-  _lens(copy._lens),
-  _stack_level(copy._stack_level)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LensStack::Copy Operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void LensStack::
-operator =(const LensStack &copy) {
-  _lens = copy._lens;
-  _stack_level = copy._stack_level;
-}

+ 0 - 50
panda/src/display/lensStack.h

@@ -1,50 +0,0 @@
-// Filename: lensStack.h
-// Created by:  drose (25Feb02)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef LENSSTACK_H
-#define LENSSTACK_H
-
-#include "pandabase.h"
-
-#include "lens.h"
-
-class GraphicsStateGuardian;
-
-////////////////////////////////////////////////////////////////////
-//       Class : LensStack
-// Description : An instance of this kind of object is returned by
-//               GraphicsStateGuardian::push_lens().  It holds the
-//               information needed to restore the previous display
-//               region in the subsequent matching call to pop_lens().
-////////////////////////////////////////////////////////////////////
-class LensStack {
-public:
-  INLINE LensStack();
-  INLINE ~LensStack();
-  INLINE LensStack(const LensStack &copy);
-  INLINE void operator =(const LensStack &copy);
-
-private:
-  CPT(Lens) _lens;
-  int _stack_level;
-  friend class GraphicsStateGuardian;
-};
-
-#include "lensStack.I"
-
-#endif

+ 30 - 36
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -768,49 +768,43 @@ do_clear(const RenderBuffer &buffer) {
 //       scissor region and viewport)
 //       scissor region and viewport)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 void DXGraphicsStateGuardian9::
-prepare_display_region() {
+prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
+  nassertv(dr != (DisplayRegion *)NULL);
+  GraphicsStateGuardian::prepare_display_region(dr, stereo_channel);
 
 
 // DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::PRE prepare_display_region\n"; DBG_E
 // DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::PRE prepare_display_region\n"; DBG_E
 
 
-  if (_current_display_region == (DisplayRegion*)0L) {
-    dxgsg9_cat.error()
-      << "Invalid NULL display region in prepare_display_region()\n";
-
-  } else if (_current_display_region != _actual_display_region) {
-    _actual_display_region = _current_display_region;
-
 // DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::prepare_display_region\n"; DBG_E
 // DBG_S dxgsg9_cat.debug ( ) << "DXGraphicsStateGuardian9::prepare_display_region\n"; DBG_E
 
 
-    int l, u, w, h;
-    _actual_display_region->get_region_pixels_i(l, u, w, h);
-
-    DBG_S dxgsg9_cat.debug ( ) << "display_region " << l << " " << u << " "  << w << " "  << h << "\n"; DBG_E
+  int l, u, w, h;
+  _current_display_region->get_region_pixels_i(l, u, w, h);
+  
+  DBG_S dxgsg9_cat.debug ( ) << "display_region " << l << " " << u << " "  << w << " "  << h << "\n"; DBG_E
 
 
-    // Create the viewport
-    D3DVIEWPORT9 vp = { l, u, w, h, 0.0f, 1.0f };
-    HRESULT hr = _d3d_device->SetViewport(&vp);
+  // Create the viewport
+  D3DVIEWPORT9 vp = { l, u, w, h, 0.0f, 1.0f };
+  HRESULT hr = _d3d_device->SetViewport(&vp);
+  if (FAILED(hr)) {
+    dxgsg9_cat.error()
+      << "_screen->_swap_chain = " << _screen->_swap_chain << " _swap_chain = " << _swap_chain << "\n";
+    dxgsg9_cat.error()
+      << "SetViewport(" << l << ", " << u << ", " << w << ", " << h
+      << ") failed" << D3DERRORSTRING(hr);
+    
+    D3DVIEWPORT9 vp_old;
+    _d3d_device->GetViewport(&vp_old);
+    dxgsg9_cat.error()
+      << "GetViewport(" << vp_old.X << ", " << vp_old.Y << ", " << vp_old.Width << ", "
+      << vp_old.Height << ") returned: Trying to set that vp---->\n";
+    hr = _d3d_device->SetViewport(&vp_old);
+    
     if (FAILED(hr)) {
     if (FAILED(hr)) {
-      dxgsg9_cat.error()
-        << "_screen->_swap_chain = " << _screen->_swap_chain << " _swap_chain = " << _swap_chain << "\n";
-      dxgsg9_cat.error()
-        << "SetViewport(" << l << ", " << u << ", " << w << ", " << h
-        << ") failed" << D3DERRORSTRING(hr);
-
-      D3DVIEWPORT9 vp_old;
-      _d3d_device->GetViewport(&vp_old);
-      dxgsg9_cat.error()
-        << "GetViewport(" << vp_old.X << ", " << vp_old.Y << ", " << vp_old.Width << ", "
-        << vp_old.Height << ") returned: Trying to set that vp---->\n";
-      hr = _d3d_device->SetViewport(&vp_old);
-
-      if (FAILED(hr)) {
-        dxgsg9_cat.error() << "Failed again\n";
-        throw_event("panda3d-render-error");
-        nassertv(false);
-      }
+      dxgsg9_cat.error() << "Failed again\n";
+      throw_event("panda3d-render-error");
+      nassertv(false);
     }
     }
-    // Note: for DX9, also change scissor clipping state here
   }
   }
+  // Note: for DX9, also change scissor clipping state here
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -826,7 +820,7 @@ prepare_display_region() {
 //               false if it is not.
 //               false if it is not.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian9::
 bool DXGraphicsStateGuardian9::
-prepare_lens(Lens::StereoChannel stereo_channel) {
+prepare_lens() {
   if (_current_lens == (Lens *)NULL) {
   if (_current_lens == (Lens *)NULL) {
     return false;
     return false;
   }
   }
@@ -836,7 +830,7 @@ prepare_lens(Lens::StereoChannel stereo_channel) {
   }
   }
 
 
   // Start with the projection matrix from the lens.
   // Start with the projection matrix from the lens.
-  const LMatrix4f &lens_mat = _current_lens->get_projection_mat(stereo_channel);
+  const LMatrix4f &lens_mat = _current_lens->get_projection_mat(_current_stereo_channel);
 
 
   // The projection matrix must always be left-handed Y-up internally,
   // The projection matrix must always be left-handed Y-up internally,
   // to match DirectX's convention, even if our coordinate system of
   // to match DirectX's convention, even if our coordinate system of

+ 2 - 2
panda/src/dxgsg9/dxGraphicsStateGuardian9.h

@@ -102,8 +102,8 @@ public:
 
 
   virtual void do_clear(const RenderBuffer &buffer);
   virtual void do_clear(const RenderBuffer &buffer);
 
 
-  virtual void prepare_display_region();
-  virtual bool prepare_lens(Lens::StereoChannel stereo_channel);
+  virtual void prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel);
+  virtual bool prepare_lens();
 
 
   virtual bool begin_frame();
   virtual bool begin_frame();
   virtual bool begin_scene();
   virtual bool begin_scene();

+ 2 - 37
panda/src/framework/windowFramework.cxx

@@ -187,15 +187,8 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
     _display_region_3d->set_camera(camera_np);
     _display_region_3d->set_camera(camera_np);
 
 
     if (_window->is_stereo() && default_stereo_camera) {
     if (_window->is_stereo() && default_stereo_camera) {
-      // Actually, let's make a stereo camera.  That means the
-      // _display_region_3d will be the left channel, and we need to
-      // make another one to be the right channel.
-
-      _display_region_3d->set_stereo_channel(Lens::SC_left);
-
-      _display_region_right = _window->make_display_region();
-      _display_region_right->set_stereo_channel(Lens::SC_right);
-      _display_region_right->set_camera(camera_np);
+      // Actually, let's make a stereo DisplayRegion.
+      _display_region_3d->set_stereo_channel(Lens::SC_stereo);
     }
     }
 
 
     set_background_type(_background_type);
     set_background_type(_background_type);
@@ -966,12 +959,6 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_color(_window->get_clear_color());
     _display_region_3d->set_clear_color(_window->get_clear_color());
     _display_region_3d->set_clear_depth(_window->get_clear_depth());
     _display_region_3d->set_clear_depth(_window->get_clear_depth());
-    if (_display_region_right) {
-      _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());
-    }
     break;
     break;
     
     
   case BT_black:
   case BT_black:
@@ -979,12 +966,6 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
     _display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
     _display_region_3d->set_clear_depth(1.0f);
     _display_region_3d->set_clear_depth(1.0f);
-    if (_display_region_right) {
-      _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);
-    }
     break;
     break;
     
     
   case BT_gray:
   case BT_gray:
@@ -992,12 +973,6 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
     _display_region_3d->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
     _display_region_3d->set_clear_depth(1.0f);
     _display_region_3d->set_clear_depth(1.0f);
-    if (_display_region_right) {
-      _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);
-    }
     break;
     break;
     
     
   case BT_white:
   case BT_white:
@@ -1005,21 +980,11 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
     _display_region_3d->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
     _display_region_3d->set_clear_depth(1.0f);
     _display_region_3d->set_clear_depth(1.0f);
-    if (_display_region_right) {
-      _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);
-    }
     break;
     break;
 
 
   case BT_none:
   case BT_none:
     _display_region_3d->set_clear_color_active(false);
     _display_region_3d->set_clear_color_active(false);
     _display_region_3d->set_clear_depth_active(false);
     _display_region_3d->set_clear_depth_active(false);
-    if (_display_region_right) {
-      _display_region_right->set_clear_color_active(false);
-      _display_region_right->set_clear_depth_active(false);
-    }
     break;
     break;
   }
   }
 }
 }

+ 0 - 1
panda/src/framework/windowFramework.h

@@ -160,7 +160,6 @@ private:
   PT(GraphicsWindow) _window;
   PT(GraphicsWindow) _window;
   PT(DisplayRegion) _display_region_2d;
   PT(DisplayRegion) _display_region_2d;
   PT(DisplayRegion) _display_region_3d;
   PT(DisplayRegion) _display_region_3d;
-  PT(DisplayRegion) _display_region_right;
 
 
   NodePath _camera_group;
   NodePath _camera_group;
   typedef pvector< PT(Camera) > Cameras;
   typedef pvector< PT(Camera) > Cameras;

+ 20 - 30
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -961,33 +961,25 @@ do_clear(const RenderBuffer &buffer) {
 //               scissor region and viewport)
 //               scissor region and viewport)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
-prepare_display_region() {
-  if (_current_display_region == (DisplayRegion*)0L) {
-    GLCAT.error()
-      << "Invalid NULL display region in prepare_display_region()\n";
-    enable_scissor(false);
-    _viewport_width = 1;
-    _viewport_height = 1;
-
-  } else if (_current_display_region != _actual_display_region) {
-    _actual_display_region = _current_display_region;
-
-    int l, b, w, h;
-    _actual_display_region->get_region_pixels(l, b, w, h);
-    _viewport_width = w;
-    _viewport_height = h;
-    GLint x = GLint(l);
-    GLint y = GLint(b);
-    GLsizei width = GLsizei(w);
-    GLsizei height = GLsizei(h);
-
-    set_draw_buffer(get_render_buffer(_actual_display_region->get_draw_buffer_type()));
-    enable_scissor(true);
-    GLP(Scissor)(x, y, width, height);
-    GLP(Viewport)(x, y, width, height);
-  }
-  report_my_gl_errors();
+prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
+  nassertv(dr != (DisplayRegion *)NULL);
+  GraphicsStateGuardian::prepare_display_region(dr, stereo_channel);
+
+  int l, b, w, h;
+  _current_display_region->get_region_pixels(l, b, w, h);
+  _viewport_width = w;
+  _viewport_height = h;
+  GLint x = GLint(l);
+  GLint y = GLint(b);
+  GLsizei width = GLsizei(w);
+  GLsizei height = GLsizei(h);
+  
+  set_draw_buffer(get_render_buffer(_current_display_region->get_draw_buffer_type()));
+  enable_scissor(true);
+  GLP(Scissor)(x, y, width, height);
+  GLP(Viewport)(x, y, width, height);
 
 
+  report_my_gl_errors();
   do_point_size();
   do_point_size();
 }
 }
 
 
@@ -1004,7 +996,7 @@ prepare_display_region() {
 //               false if it is not.
 //               false if it is not.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
 bool CLP(GraphicsStateGuardian)::
-prepare_lens(Lens::StereoChannel stereo_channel) {
+prepare_lens() {
   if (_current_lens == (Lens *)NULL) {
   if (_current_lens == (Lens *)NULL) {
     return false;
     return false;
   }
   }
@@ -1013,7 +1005,7 @@ prepare_lens(Lens::StereoChannel stereo_channel) {
     return false;
     return false;
   }
   }
 
 
-  const LMatrix4f &lens_mat = _current_lens->get_projection_mat(stereo_channel);
+  const LMatrix4f &lens_mat = _current_lens->get_projection_mat(_current_stereo_channel);
 
 
   // The projection matrix must always be right-handed Y-up, even if
   // The projection matrix must always be right-handed Y-up, even if
   // our coordinate system of choice is otherwise, because certain GL
   // our coordinate system of choice is otherwise, because certain GL
@@ -1071,8 +1063,6 @@ begin_frame() {
   _primitive_batches_display_list_pcollector.clear_level();
   _primitive_batches_display_list_pcollector.clear_level();
 #endif
 #endif
 
 
-  _actual_display_region = NULL;
-
   report_my_gl_errors();
   report_my_gl_errors();
   return true;
   return true;
 }
 }

+ 2 - 4
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -84,8 +84,8 @@ public:
 
 
   virtual void do_clear(const RenderBuffer &buffer);
   virtual void do_clear(const RenderBuffer &buffer);
 
 
-  virtual void prepare_display_region();
-  virtual bool prepare_lens(Lens::StereoChannel stereo_channel);
+  virtual void prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel);
+  virtual bool prepare_lens();
 
 
   virtual bool begin_frame();
   virtual bool begin_frame();
   virtual void end_frame();
   virtual void end_frame();
@@ -321,8 +321,6 @@ protected:
   PT(ShaderExpansion)  _texture_binding_shader_expansion;
   PT(ShaderExpansion)  _texture_binding_shader_expansion;
   CLP(ShaderContext)  *_texture_binding_shader_context;
   CLP(ShaderContext)  *_texture_binding_shader_context;
   
   
-  CPT(DisplayRegion) _actual_display_region;
-
 #ifdef SUPPORT_IMMEDIATE_MODE
 #ifdef SUPPORT_IMMEDIATE_MODE
   CLP(ImmediateModeSender) _sender;
   CLP(ImmediateModeSender) _sender;
   bool _use_sender;
   bool _use_sender;

+ 4 - 2
panda/src/gobj/lens.cxx

@@ -1076,7 +1076,8 @@ get_projection_mat(StereoChannel channel) const {
     return _projection_mat_left;
     return _projection_mat_left;
   case SC_right:
   case SC_right:
     return _projection_mat_right;
     return _projection_mat_right;
-  case SC_both:
+  case SC_mono:
+  case SC_stereo:
     return _projection_mat;
     return _projection_mat;
   }
   }
 
 
@@ -1115,7 +1116,8 @@ get_projection_mat_inv(StereoChannel stereo_channel) const {
     }
     }
     return _projection_mat_right_inv;
     return _projection_mat_right_inv;
 
 
-  case SC_both:
+  case SC_mono:
+  case SC_stereo:
     break;
     break;
   }
   }
 
 

+ 6 - 5
panda/src/gobj/lens.h

@@ -50,9 +50,10 @@ public:
 
 
 PUBLISHED:
 PUBLISHED:
   enum StereoChannel {
   enum StereoChannel {
-    SC_left  = 0x01,
-    SC_right = 0x02,
-    SC_both  = 0x03,  // == SC_left | SC_right
+    SC_mono    = 0x00,
+    SC_left    = 0x01,
+    SC_right   = 0x02,
+    SC_stereo  = 0x03,  // == SC_left | SC_right
   };
   };
 
 
   virtual PT(Lens) make_copy() const=0;
   virtual PT(Lens) make_copy() const=0;
@@ -151,8 +152,8 @@ PUBLISHED:
 
 
   virtual PT(BoundingVolume) make_bounds() const;
   virtual PT(BoundingVolume) make_bounds() const;
 
 
-  const LMatrix4f &get_projection_mat(StereoChannel channel = SC_both) const;
-  const LMatrix4f &get_projection_mat_inv(StereoChannel channel = SC_both) const;
+  const LMatrix4f &get_projection_mat(StereoChannel channel = SC_mono) const;
+  const LMatrix4f &get_projection_mat_inv(StereoChannel channel = SC_mono) const;
 
 
   const LMatrix4f &get_film_mat() const;
   const LMatrix4f &get_film_mat() const;
   const LMatrix4f &get_film_mat_inv() const;
   const LMatrix4f &get_film_mat_inv() const;