Browse Source

GraphicsWindow::_unexposed_draw

David Rose 14 years ago
parent
commit
6f5fd1525d

+ 9 - 3
direct/src/showbase/ShowBase.py

@@ -585,7 +585,7 @@ class ShowBase(DirectObject.DirectObject):
     def openWindow(self, props = None, fbprops = None, pipe = None, gsg = None,
                    type = None, name = None, size = None, aspectRatio = None,
                    makeCamera = True, keepCamera = False,
-                   scene = None, stereo = None, 
+                   scene = None, stereo = None, unexposedDraw = None,
                    callbackWindowDict = None, requireWindow = None):
         """
         Creates a window and adds it to the list of windows that are
@@ -601,6 +601,9 @@ class ShowBase(DirectObject.DirectObject):
         If keepCamera is false but makeCamera is true, a new camera is
         set up to render into the new window.
 
+        If unexposedDraw is not None, it specifies the initial value
+        of GraphicsWindow.setUnexposedDraw().
+
         If callbackWindowDict is not None, a CallbackGraphicWindow is
         created instead, which allows the caller to create the actual
         window with its own OpenGL context, and direct Panda's
@@ -618,7 +621,7 @@ class ShowBase(DirectObject.DirectObject):
             props = props, fbprops = fbprops, pipe = pipe, gsg = gsg,
             type = type, name = name, size = size, aspectRatio = aspectRatio,
             makeCamera = makeCamera, keepCamera = keepCamera,
-            scene = scene, stereo = stereo, 
+            scene = scene, stereo = stereo, unexposedDraw = unexposedDraw,
             callbackWindowDict = callbackWindowDict)
         
         if self.win:
@@ -678,7 +681,7 @@ class ShowBase(DirectObject.DirectObject):
     def _doOpenWindow(self, props = None, fbprops = None, pipe = None, gsg = None,
                       type = None, name = None, size = None, aspectRatio = None,
                       makeCamera = True, keepCamera = False,
-                      scene = None, stereo = None, 
+                      scene = None, stereo = None, unexposedDraw = None,
                       callbackWindowDict = None):
         if pipe == None:
             pipe = self.pipe
@@ -745,6 +748,9 @@ class ShowBase(DirectObject.DirectObject):
             # Couldn't create a window!
             return None
 
+        if unexposedDraw is not None and hasattr(win, 'setUnexposedDraw'):
+            win.setUnexposedDraw(unexposedDraw)
+
         if callbackWindowDict:
             # If we asked for (and received) a CallbackGraphicsWindow,
             # we now have to assign the callbacks, before we start

+ 2 - 1
direct/src/wxwidgets/WxPandaWindow.py

@@ -40,7 +40,8 @@ class EmbeddedPandaWindow(wx.Window):
                 # only happen on 32-bit Windows.
                 wp.setParentWindow(self.GetHandle() & 0xffffffff)
 
-        self.win = base.openWindow(props = wp, gsg = gsg, type = 'onscreen')
+        self.win = base.openWindow(props = wp, gsg = gsg, type = 'onscreen',
+                                   unexposedDraw = False)
         self.Bind(wx.EVT_SIZE, self.onSize)
 
         # This doesn't actually do anything, since wx won't call

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

@@ -336,6 +336,11 @@ ConfigVariableInt parent_window_handle
           "an HWND on Windows, or the NSWindow pointer or XWindow pointer "
           "converted to an integer, on OSX and X11."));
 
+ConfigVariableBool win_unexposed_draw
+("win-unexposed-draw", true,
+ PRC_DESC("Specifies the default setting of GraphicsWindow::set_unexposed_draw().  "
+          "See that method for more information."));
+
 ConfigVariableFilename subprocess_window
 ("subprocess-window", "",
  PRC_DESC("The filename of a SubprocessWindowBuffer's temporary mmap file, "

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

@@ -78,6 +78,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableFilename cursor_filename;
 extern EXPCL_PANDA_DISPLAY ConfigVariableEnum<WindowProperties::ZOrder> z_order;
 extern EXPCL_PANDA_DISPLAY ConfigVariableString window_title;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt parent_window_handle;
+extern EXPCL_PANDA_DISPLAY ConfigVariableBool win_unexposed_draw;
 extern EXPCL_PANDA_DISPLAY ConfigVariableFilename subprocess_window;
 
 extern EXPCL_PANDA_DISPLAY ConfigVariableString framebuffer_mode;

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

@@ -845,8 +845,10 @@ clear_cube_map_selection() {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::trigger_flip
-//       Access: Public
-//  Description: Set the flip_ready flag, only if legal to do so.
+//       Access: Protected
+//  Description: To be called at the end of the frame, after the
+//               window has successfully been drawn and is ready to be
+//               flipped (if appropriate).
 ////////////////////////////////////////////////////////////////////
 INLINE void GraphicsOutput::
 trigger_flip() {

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

@@ -92,12 +92,13 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
   _creation_flags = flags;
   _x_size = _y_size = 0;
   _has_size = win_prop.has_size();
+  _is_nonzero_size = false;
   if (_has_size) {
     _x_size = win_prop.get_x_size();
     _y_size = win_prop.get_y_size();
+    _is_nonzero_size = (_x_size > 0 && _y_size > 0);
   }
   _is_valid = false;
-  _is_nonzero_size = false;
   _flip_ready = false;
   _cube_map_index = -1;
   _cube_map_dr = NULL;

+ 30 - 0
panda/src/display/graphicsWindow.I

@@ -40,6 +40,36 @@ is_fullscreen() const {
   return _properties.get_fullscreen();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::set_unexposed_draw
+//       Access: Published
+//  Description: If this flag is false, the window is redrawn only
+//               after it has received a recent "unexpose" or "draw"
+//               event from the underlying windowing systme.  If this
+//               flag is true, the window is redrawn every frame
+//               regardless.  Setting this false may prevent the
+//               window from redrawing unnecessarily when it is
+//               hidden, and may play nicer with other windows on the
+//               desktop, but may adversely affect frame rate even
+//               when the window is fully visible; setting it true will
+//               ensure that the window contents are always current.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+set_unexposed_draw(bool unexposed_draw) {
+  _unexposed_draw = unexposed_draw;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::get_unexposed_draw
+//       Access: Published
+//  Description: See set_unexposed_draw().
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsWindow::
+get_unexposed_draw() const {
+  return _unexposed_draw;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_window_handle
 //       Access: Published

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

@@ -62,6 +62,8 @@ GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
   request_properties(win_prop);
 
   _window_event = "window-event";
+  _got_expose_event = false;
+  _unexposed_draw = win_unexposed_draw;
   set_pixel_zoom(pixel_zoom);
 }
 

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

@@ -71,6 +71,9 @@ PUBLISHED:
   void set_close_request_event(const string &close_request_event);
   string get_close_request_event() const;
 
+  INLINE void set_unexposed_draw(bool unexposed_draw);
+  INLINE bool get_unexposed_draw() const;
+
   INLINE WindowHandle *get_window_handle() const;
   
   // Mouse and keyboard routines
@@ -151,6 +154,8 @@ protected:
   PT(WindowHandle) _window_handle;
   PT(WindowHandle) _parent_window_handle;
 
+  bool _got_expose_event;
+
 private:
   LightReMutex _properties_lock; 
   // protects _requested_properties, _rejected_properties, and
@@ -160,6 +165,7 @@ private:
   WindowProperties _rejected_properties;
   string _window_event;
   string _close_request_event;
+  bool _unexposed_draw;
 
 #ifdef HAVE_PYTHON
   typedef pset<PythonGraphicsWindowProc*> PythonWinProcClasses;

+ 9 - 2
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -97,6 +97,14 @@ begin_frame(FrameMode mode, Thread *current_thread) {
     return false;
   }
 
+  if (!get_unexposed_draw() && !_got_expose_event) {
+    if (wdxdisplay9_cat.is_spam()) {
+      wdxdisplay9_cat.spam()
+        << "Not drawing " << this << ": unexposed.\n";
+    }
+    return false;
+  }
+
   if (_awaiting_restore) {
     // The fullscreen window was recently restored; we can't continue
     // until the GSG says we can.
@@ -129,7 +137,6 @@ begin_frame(FrameMode mode, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 void wdxGraphicsWindow9::
 end_frame(FrameMode mode, Thread *current_thread) {
-
   end_frame_spam(mode);
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
 
@@ -160,7 +167,7 @@ end_flip() {
   if (_dxgsg != (DXGraphicsStateGuardian9 *)NULL && is_active()) {
     _dxgsg->show_frame();
   }
-  GraphicsWindow::end_flip();
+  WinGraphicsWindow::end_flip();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 8 - 0
panda/src/tinydisplay/tinyWinGraphicsWindow.cxx

@@ -72,6 +72,14 @@ begin_frame(FrameMode mode, Thread *current_thread) {
     return false;
   }
 
+  if (!get_unexposed_draw() && !_got_expose_event) {
+    if (tinydisplay_cat.is_spam()) {
+      tinydisplay_cat.spam()
+        << "Not drawing " << this << ": unexposed.\n";
+    }
+    return false;
+  }
+
   TinyGraphicsStateGuardian *tinygsg;
   DCAST_INTO_R(tinygsg, _gsg, false);
 

+ 13 - 1
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -66,6 +66,19 @@ begin_frame(FrameMode mode, Thread *current_thread) {
   if (_gsg == (GraphicsStateGuardian *)NULL) {
     return false;
   }
+
+  if (!get_unexposed_draw() && !_got_expose_event) {
+    if (wgldisplay_cat.is_spam()) {
+      wgldisplay_cat.spam()
+        << "Not drawing " << this << ": unexposed.\n";
+    }
+    return false;
+  }
+
+  if (wgldisplay_cat.is_spam()) {
+    wgldisplay_cat.spam()
+      << "Drawing " << this << ": exposed.\n";
+  }
   
   wglGraphicsStateGuardian *wglgsg;
   DCAST_INTO_R(wglgsg, _gsg, false);
@@ -93,7 +106,6 @@ begin_frame(FrameMode mode, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::
 end_frame(FrameMode mode, Thread *current_thread) {
-
   end_frame_spam(mode);
 
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);

+ 38 - 1
panda/src/windisplay/winGraphicsWindow.cxx

@@ -364,6 +364,30 @@ set_properties_now(WindowProperties &properties) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::trigger_flip
+//       Access: Protected
+//  Description: To be called at the end of the frame, after the
+//               window has successfully been drawn and is ready to be
+//               flipped (if appropriate).
+////////////////////////////////////////////////////////////////////
+void WinGraphicsWindow::
+trigger_flip() {
+  GraphicsWindow::trigger_flip();
+
+  if (!get_unexposed_draw()) {
+    // Now that we've drawn or whatever, invalidate the rectangle so
+    // we won't redraw again until we get the WM_PAINT message.
+
+    InvalidateRect(_hWnd, NULL, FALSE);
+    _got_expose_event = false;
+
+    if (windisplay_cat.is_spam()) {
+      windisplay_cat.spam()
+        << "InvalidateRect: " << this << "\n";
+    }
+  }
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: WinGraphicsWindow::close_window
@@ -1450,7 +1474,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       handle_reshape();
     }
     break;
-    
+
   case WM_EXITSIZEMOVE:
     handle_reshape();
     break;
@@ -1458,6 +1482,19 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
   case WM_WINDOWPOSCHANGED:
     adjust_z_order();
     break;
+
+  case WM_PAINT:
+    // In response to WM_PAINT, we check to see if there are any
+    // update regions at all; if there are, we declare the window
+    // exposed.  This is used to implement !_unexposed_draw.
+    if (GetUpdateRect(_hWnd, NULL, false)) {
+      if (windisplay_cat.is_spam()) {
+        windisplay_cat.spam()
+          << "Got update regions: " << this << "\n";
+      }
+      _got_expose_event = true;
+    }
+    break;
     
   case WM_LBUTTONDOWN:
     if (_lost_keypresses) {

+ 1 - 0
panda/src/windisplay/winGraphicsWindow.h

@@ -88,6 +88,7 @@ public:
   virtual TouchInfo get_touch_info(int index);
 
 protected:
+  void trigger_flip();
   virtual void close_window();
   virtual bool open_window();
   virtual void fullscreen_minimized(WindowProperties &properties);