2
0
Эх сурвалжийг харах

GraphicsWindow::_unexposed_draw

David Rose 14 жил өмнө
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,
     def openWindow(self, props = None, fbprops = None, pipe = None, gsg = None,
                    type = None, name = None, size = None, aspectRatio = None,
                    type = None, name = None, size = None, aspectRatio = None,
                    makeCamera = True, keepCamera = False,
                    makeCamera = True, keepCamera = False,
-                   scene = None, stereo = None, 
+                   scene = None, stereo = None, unexposedDraw = None,
                    callbackWindowDict = None, requireWindow = None):
                    callbackWindowDict = None, requireWindow = None):
         """
         """
         Creates a window and adds it to the list of windows that are
         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
         If keepCamera is false but makeCamera is true, a new camera is
         set up to render into the new window.
         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
         If callbackWindowDict is not None, a CallbackGraphicWindow is
         created instead, which allows the caller to create the actual
         created instead, which allows the caller to create the actual
         window with its own OpenGL context, and direct Panda's
         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,
             props = props, fbprops = fbprops, pipe = pipe, gsg = gsg,
             type = type, name = name, size = size, aspectRatio = aspectRatio,
             type = type, name = name, size = size, aspectRatio = aspectRatio,
             makeCamera = makeCamera, keepCamera = keepCamera,
             makeCamera = makeCamera, keepCamera = keepCamera,
-            scene = scene, stereo = stereo, 
+            scene = scene, stereo = stereo, unexposedDraw = unexposedDraw,
             callbackWindowDict = callbackWindowDict)
             callbackWindowDict = callbackWindowDict)
         
         
         if self.win:
         if self.win:
@@ -678,7 +681,7 @@ class ShowBase(DirectObject.DirectObject):
     def _doOpenWindow(self, props = None, fbprops = None, pipe = None, gsg = None,
     def _doOpenWindow(self, props = None, fbprops = None, pipe = None, gsg = None,
                       type = None, name = None, size = None, aspectRatio = None,
                       type = None, name = None, size = None, aspectRatio = None,
                       makeCamera = True, keepCamera = False,
                       makeCamera = True, keepCamera = False,
-                      scene = None, stereo = None, 
+                      scene = None, stereo = None, unexposedDraw = None,
                       callbackWindowDict = None):
                       callbackWindowDict = None):
         if pipe == None:
         if pipe == None:
             pipe = self.pipe
             pipe = self.pipe
@@ -745,6 +748,9 @@ class ShowBase(DirectObject.DirectObject):
             # Couldn't create a window!
             # Couldn't create a window!
             return None
             return None
 
 
+        if unexposedDraw is not None and hasattr(win, 'setUnexposedDraw'):
+            win.setUnexposedDraw(unexposedDraw)
+
         if callbackWindowDict:
         if callbackWindowDict:
             # If we asked for (and received) a CallbackGraphicsWindow,
             # If we asked for (and received) a CallbackGraphicsWindow,
             # we now have to assign the callbacks, before we start
             # 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.
                 # only happen on 32-bit Windows.
                 wp.setParentWindow(self.GetHandle() & 0xffffffff)
                 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)
         self.Bind(wx.EVT_SIZE, self.onSize)
 
 
         # This doesn't actually do anything, since wx won't call
         # 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 "
           "an HWND on Windows, or the NSWindow pointer or XWindow pointer "
           "converted to an integer, on OSX and X11."));
           "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
 ConfigVariableFilename subprocess_window
 ("subprocess-window", "",
 ("subprocess-window", "",
  PRC_DESC("The filename of a SubprocessWindowBuffer's temporary mmap file, "
  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 ConfigVariableEnum<WindowProperties::ZOrder> z_order;
 extern EXPCL_PANDA_DISPLAY ConfigVariableString window_title;
 extern EXPCL_PANDA_DISPLAY ConfigVariableString window_title;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt parent_window_handle;
 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 ConfigVariableFilename subprocess_window;
 
 
 extern EXPCL_PANDA_DISPLAY ConfigVariableString framebuffer_mode;
 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
 //     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::
 INLINE void GraphicsOutput::
 trigger_flip() {
 trigger_flip() {

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

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

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

@@ -40,6 +40,36 @@ is_fullscreen() const {
   return _properties.get_fullscreen();
   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
 //     Function: GraphicsWindow::get_window_handle
 //       Access: Published
 //       Access: Published

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

@@ -62,6 +62,8 @@ GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
   request_properties(win_prop);
   request_properties(win_prop);
 
 
   _window_event = "window-event";
   _window_event = "window-event";
+  _got_expose_event = false;
+  _unexposed_draw = win_unexposed_draw;
   set_pixel_zoom(pixel_zoom);
   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);
   void set_close_request_event(const string &close_request_event);
   string get_close_request_event() const;
   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;
   INLINE WindowHandle *get_window_handle() const;
   
   
   // Mouse and keyboard routines
   // Mouse and keyboard routines
@@ -151,6 +154,8 @@ protected:
   PT(WindowHandle) _window_handle;
   PT(WindowHandle) _window_handle;
   PT(WindowHandle) _parent_window_handle;
   PT(WindowHandle) _parent_window_handle;
 
 
+  bool _got_expose_event;
+
 private:
 private:
   LightReMutex _properties_lock; 
   LightReMutex _properties_lock; 
   // protects _requested_properties, _rejected_properties, and
   // protects _requested_properties, _rejected_properties, and
@@ -160,6 +165,7 @@ private:
   WindowProperties _rejected_properties;
   WindowProperties _rejected_properties;
   string _window_event;
   string _window_event;
   string _close_request_event;
   string _close_request_event;
+  bool _unexposed_draw;
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   typedef pset<PythonGraphicsWindowProc*> PythonWinProcClasses;
   typedef pset<PythonGraphicsWindowProc*> PythonWinProcClasses;

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

@@ -97,6 +97,14 @@ begin_frame(FrameMode mode, Thread *current_thread) {
     return false;
     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) {
   if (_awaiting_restore) {
     // The fullscreen window was recently restored; we can't continue
     // The fullscreen window was recently restored; we can't continue
     // until the GSG says we can.
     // until the GSG says we can.
@@ -129,7 +137,6 @@ begin_frame(FrameMode mode, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void wdxGraphicsWindow9::
 void wdxGraphicsWindow9::
 end_frame(FrameMode mode, Thread *current_thread) {
 end_frame(FrameMode mode, Thread *current_thread) {
-
   end_frame_spam(mode);
   end_frame_spam(mode);
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
 
 
@@ -160,7 +167,7 @@ end_flip() {
   if (_dxgsg != (DXGraphicsStateGuardian9 *)NULL && is_active()) {
   if (_dxgsg != (DXGraphicsStateGuardian9 *)NULL && is_active()) {
     _dxgsg->show_frame();
     _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;
     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;
   TinyGraphicsStateGuardian *tinygsg;
   DCAST_INTO_R(tinygsg, _gsg, false);
   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) {
   if (_gsg == (GraphicsStateGuardian *)NULL) {
     return false;
     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;
   wglGraphicsStateGuardian *wglgsg;
   DCAST_INTO_R(wglgsg, _gsg, false);
   DCAST_INTO_R(wglgsg, _gsg, false);
@@ -93,7 +106,6 @@ begin_frame(FrameMode mode, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::
 void wglGraphicsWindow::
 end_frame(FrameMode mode, Thread *current_thread) {
 end_frame(FrameMode mode, Thread *current_thread) {
-
   end_frame_spam(mode);
   end_frame_spam(mode);
 
 
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
   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
 //     Function: WinGraphicsWindow::close_window
@@ -1450,7 +1474,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       handle_reshape();
       handle_reshape();
     }
     }
     break;
     break;
-    
+
   case WM_EXITSIZEMOVE:
   case WM_EXITSIZEMOVE:
     handle_reshape();
     handle_reshape();
     break;
     break;
@@ -1458,6 +1482,19 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
   case WM_WINDOWPOSCHANGED:
   case WM_WINDOWPOSCHANGED:
     adjust_z_order();
     adjust_z_order();
     break;
     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:
   case WM_LBUTTONDOWN:
     if (_lost_keypresses) {
     if (_lost_keypresses) {

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

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