GraphicsWindow::_unexposed_draw

This commit is contained in:
David Rose 2012-01-15 20:13:16 +00:00
parent 38a73900f1
commit 6f5fd1525d
14 changed files with 130 additions and 11 deletions

View File

@ -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

View File

@ -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

View File

@ -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, "

View File

@ -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;

View File

@ -845,8 +845,10 @@ clear_cube_map_selection() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::trigger_flip // Function: GraphicsOutput::trigger_flip
// Access: Public // Access: Protected
// Description: Set the flip_ready flag, only if legal to do so. // 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() {

View File

@ -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;

View File

@ -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

View File

@ -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);
} }

View File

@ -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;

View File

@ -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();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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);