mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
explicit sync_frame and flip_frame
This commit is contained in:
parent
8c6e59f6a9
commit
8b9c2ae9c6
@ -57,6 +57,12 @@ const bool pstats_unused_states = config_display.GetBool("pstats-unused-states",
|
||||
// system!
|
||||
const string threading_model = config_display.GetString("threading-model", "");
|
||||
|
||||
// This indicates the initial setting of the auto-flip flag. Set it
|
||||
// true (the default) to cause render_frame() to flip all the windows
|
||||
// before it returns (in single-threaded mode only), or false to wait
|
||||
// until an explicit call to flip_frame() or the next render_frame().
|
||||
const bool auto_flip = config_display.GetBool("auto-flip", true);
|
||||
|
||||
// Use the variable load-display to specifiy the name of the default
|
||||
// graphics display library or GraphicsPipe to load. It is the name
|
||||
// of a shared library (or * for all libraries named in aux-display),
|
||||
|
@ -34,6 +34,7 @@ extern const bool view_frustum_cull;
|
||||
extern const bool pstats_unused_states;
|
||||
|
||||
extern const string threading_model;
|
||||
extern const bool auto_flip;
|
||||
|
||||
extern EXPCL_PANDA void init_libdisplay();
|
||||
|
||||
|
@ -17,6 +17,44 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::set_auto_flip
|
||||
// Access: Published
|
||||
// Description: Set this flag true to indicate the GraphicsEngine
|
||||
// should automatically cause windows to sync and flip
|
||||
// at the end of render_frame().
|
||||
//
|
||||
// This only applies to a single-threaded rendering
|
||||
// model. In the presence of threading, the windows are
|
||||
// never auto-flipped, regardless of this flag.
|
||||
//
|
||||
// This only affects the timing of when the flip occurs.
|
||||
// If this is true (the default), the flip occurs before
|
||||
// render_frame() returns. If this is false, the flip
|
||||
// occurs whenever flip_frame() is called, or at the
|
||||
// beginning of the next call to render_frame(), if
|
||||
// flip_frame() is never called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsEngine::
|
||||
set_auto_flip(bool auto_flip) {
|
||||
// We don't bother with the mutex here. It's just a bool, after
|
||||
// all.
|
||||
_auto_flip = auto_flip;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::get_auto_flip
|
||||
// Access: Published
|
||||
// Description: Returns the current setting for the auto-flip flag.
|
||||
// See set_auto_flip.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsEngine::
|
||||
get_auto_flip() const {
|
||||
// We don't bother with the mutex here. It's just a bool, after
|
||||
// all.
|
||||
return _auto_flip;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::make_window
|
||||
// Access: Published
|
||||
|
@ -55,7 +55,8 @@ GraphicsEngine(Pipeline *pipeline) :
|
||||
display_cat.info()
|
||||
<< "Using threading model " << _threading_model << "\n";
|
||||
}
|
||||
_needs_sync = false;
|
||||
_auto_flip = auto_flip;
|
||||
_flip_state = FS_flip;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -280,9 +281,8 @@ render_frame() {
|
||||
// don't do that.
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
if (_needs_sync) {
|
||||
// Flip the windows from the previous frame, if necessary.
|
||||
do_sync_frame();
|
||||
if (_flip_state != FS_flip) {
|
||||
do_flip_frame();
|
||||
}
|
||||
|
||||
// Grab each thread's mutex again after all windows have flipped.
|
||||
@ -310,12 +310,12 @@ render_frame() {
|
||||
|
||||
// Some threads may still be drawing, so indicate that we have to
|
||||
// wait for those threads before we can flip.
|
||||
_needs_sync = true;
|
||||
_flip_state = FS_draw;
|
||||
|
||||
// But if we don't have any threads, go ahead and flip the frame
|
||||
// now. No point in waiting if we're single-threaded.
|
||||
if (_threads.empty()) {
|
||||
do_sync_frame();
|
||||
if (_threads.empty() && _auto_flip) {
|
||||
do_flip_frame();
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,20 +323,35 @@ render_frame() {
|
||||
// Function: GraphicsEngine::sync_frame
|
||||
// Access: Published
|
||||
// Description: Waits for all the threads that started drawing their
|
||||
// last frame to finish drawing. The windows are not
|
||||
// yet flipped when this returns; see also flip_frame().
|
||||
// It is not usually necessary to call this explicitly,
|
||||
// unless you need to see the previous frame right away.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::
|
||||
sync_frame() {
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
if (_flip_state == FS_draw) {
|
||||
do_sync_frame();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::flip_frame
|
||||
// Access: Published
|
||||
// Description: Waits for all the threads that started drawing their
|
||||
// last frame to finish drawing, and then flips all the
|
||||
// windows. It is not usually necessary to call this
|
||||
// explicitly, unless you need to see the previous frame
|
||||
// right away.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::
|
||||
sync_frame() {
|
||||
// We hold the GraphicsEngine mutex while we wait for all of the
|
||||
// threads. Doing this puts us at risk for deadlock if any of the
|
||||
// threads tries to call any methods on the GraphicsEngine. So
|
||||
// don't do that.
|
||||
flip_frame() {
|
||||
MutexHolder holder(_lock);
|
||||
if (_needs_sync) {
|
||||
do_sync_frame();
|
||||
|
||||
if (_flip_state != FS_flip) {
|
||||
do_flip_frame();
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,8 +545,32 @@ flip_windows(const GraphicsEngine::Windows &wlist) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::
|
||||
do_sync_frame() {
|
||||
// First, wait for all the threads to finish their current frame.
|
||||
// Grabbing the mutex should achieve that.
|
||||
nassertv(_flip_state == FS_draw);
|
||||
|
||||
// Wait for all the threads to finish their current frame. Grabbing
|
||||
// and releasing the mutex should achieve that.
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
|
||||
_flip_state = FS_sync;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::do_flip_frame
|
||||
// Access: Private
|
||||
// Description: The implementation of flip_frame(). We assume _lock
|
||||
// is already held before this method is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::
|
||||
do_flip_frame() {
|
||||
nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
|
||||
|
||||
// First, wait for all the threads to finish their current frame, if
|
||||
// necessary. Grabbing the mutex should achieve that.
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
@ -549,7 +588,7 @@ do_sync_frame() {
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
|
||||
_needs_sync = false;
|
||||
_flip_state = FS_flip;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -56,6 +56,9 @@ PUBLISHED:
|
||||
void set_threading_model(const string &threading_model);
|
||||
string get_threading_model() const;
|
||||
|
||||
INLINE void set_auto_flip(bool auto_flip);
|
||||
INLINE bool get_auto_flip() const;
|
||||
|
||||
INLINE GraphicsWindow *make_window(GraphicsPipe *pipe);
|
||||
GraphicsWindow *make_window(GraphicsPipe *pipe,
|
||||
const string &threading_model);
|
||||
@ -64,6 +67,7 @@ PUBLISHED:
|
||||
|
||||
void render_frame();
|
||||
void sync_frame();
|
||||
void flip_frame();
|
||||
|
||||
void render_subframe(GraphicsStateGuardian *gsg, DisplayRegion *dr,
|
||||
bool cull_sorting);
|
||||
@ -80,6 +84,7 @@ private:
|
||||
void process_events(const GraphicsEngine::Windows &wlist);
|
||||
void flip_windows(const GraphicsEngine::Windows &wlist);
|
||||
void do_sync_frame();
|
||||
void do_flip_frame();
|
||||
|
||||
PT(SceneSetup) setup_scene(const NodePath &camera,
|
||||
GraphicsStateGuardian *gsg);
|
||||
@ -143,8 +148,14 @@ private:
|
||||
typedef pmap<string, PT(RenderThread) > Threads;
|
||||
Threads _threads;
|
||||
string _threading_model;
|
||||
bool _auto_flip;
|
||||
|
||||
bool _needs_sync;
|
||||
enum FlipState {
|
||||
FS_draw, // Still drawing.
|
||||
FS_sync, // All windows are done drawing.
|
||||
FS_flip, // All windows are done drawing and have flipped.
|
||||
};
|
||||
FlipState _flip_state;
|
||||
Mutex _lock;
|
||||
|
||||
static PStatCollector _cull_pcollector;
|
||||
|
@ -110,8 +110,12 @@ project(const LPoint3f &point3d, LPoint3f &point2d) const {
|
||||
// Access: Published
|
||||
// Description: Sets the name of the event that will be generated
|
||||
// whenever any properties of the Lens have
|
||||
// changed. This can be used to automatically track
|
||||
// changes to camera fov, etc. in the simulation.
|
||||
// changed. If this is not set for a particular lens,
|
||||
// no event will be generated.
|
||||
//
|
||||
// The event is thrown with one parameter, the lens
|
||||
// itself. This can be used to automatically track
|
||||
// changes to camera fov, etc. in the application.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Lens::
|
||||
set_change_event(const string &event) {
|
||||
@ -122,7 +126,7 @@ set_change_event(const string &event) {
|
||||
// Function: Lens::get_change_event
|
||||
// Access: Published
|
||||
// Description: Returns the name of the event that will be generated
|
||||
// whenever any properties of the Lens have
|
||||
// whenever any properties of this particular Lens have
|
||||
// changed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &Lens::
|
||||
|
@ -998,7 +998,7 @@ throw_change_event() {
|
||||
++_last_change;
|
||||
|
||||
if (!_change_event.empty()) {
|
||||
throw_event(_change_event);
|
||||
throw_event(_change_event, this);
|
||||
}
|
||||
|
||||
// Also update the _geom_coords, if it is in use.
|
||||
|
Loading…
x
Reference in New Issue
Block a user