diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index 5c260c98f8..20e7dc72fa 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -92,6 +92,14 @@ ConfigVariableBool yield_timeslice PRC_DESC("Set this true to yield the timeslice at the end of the frame to be " "more polite to other applications that are trying to run.")); +ConfigVariableDouble subprocess_window_max_wait +("subprocess-window-max-wait", 0.2, + PRC_DESC("This is the amount of time, in seconds, that the SubprocessWindow will " + "wait in begin_flip for the parent process to remove the previously-rendered " + "frame. When this time is exceeded, the next frame will be rendered without " + "having flipped the previous one. This is designed to allow the Python " + "process some time to run even when the parent window is offscreen or minimized.")); + ConfigVariableString screenshot_filename ("screenshot-filename", "%~p-%a-%b-%d-%H-%M-%S-%Y-%~f.%~e", PRC_DESC("This specifies the filename pattern to be used to generate " diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index 38c9427cde..bb704748ca 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -41,6 +41,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool allow_nonpipeline_threads; extern EXPCL_PANDA_DISPLAY ConfigVariableBool auto_flip; extern EXPCL_PANDA_DISPLAY ConfigVariableBool sync_flip; extern EXPCL_PANDA_DISPLAY ConfigVariableBool yield_timeslice; +extern EXPCL_PANDA_DISPLAY ConfigVariableDouble subprocess_window_max_wait; extern EXPCL_PANDA_DISPLAY ConfigVariableString screenshot_filename; extern EXPCL_PANDA_DISPLAY ConfigVariableString screenshot_extension; diff --git a/panda/src/display/subprocessWindow.cxx b/panda/src/display/subprocessWindow.cxx index 97b58cccc9..4535ccf319 100644 --- a/panda/src/display/subprocessWindow.cxx +++ b/panda/src/display/subprocessWindow.cxx @@ -17,6 +17,7 @@ #ifdef SUPPORT_SUBPROCESS_WINDOW #include "graphicsEngine.h" +#include "config_display.h" TypeHandle SubprocessWindow::_type_handle; @@ -153,13 +154,6 @@ begin_frame(FrameMode mode, Thread *current_thread) { return false; } - if (!_swbuffer->ready_for_write()) { - // The other end hasn't removed a frame lately; don't bother to - // render. - Thread::force_yield(); - return false; - } - bool result = _buffer->begin_frame(mode, current_thread); return result; } @@ -212,7 +206,25 @@ begin_flip() { size_t framebuffer_size = _swbuffer->get_framebuffer_size(); nassertv(image.size() == framebuffer_size); - // Now copy the image to our shared framebuffer. + if (!_swbuffer->ready_for_write()) { + // We have to wait for the other end to remove the last frame we + // rendered. We only wait so long before we give up, so we + // don't completely starve the Python process just because the + // render window is offscreen or something. + + ClockObject *clock = ClockObject::get_global_clock(); + double start = clock->get_real_time(); + while (!_swbuffer->ready_for_write()) { + Thread::force_yield(); + double now = clock->get_real_time(); + if (now - start > subprocess_window_max_wait) { + // Never mind. + return; + } + } + } + + // We're ready to go. Copy the image to our shared framebuffer. void *target = _swbuffer->open_write_framebuffer(); memcpy(target, image.p(), framebuffer_size); _swbuffer->close_write_framebuffer();