diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index b3d548f542..a52f8447b9 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -380,10 +380,10 @@ class ShowBase(DirectObject.DirectObject): # Temporary try .. except for old Pandas. try: if type == 'onscreen': - win = self.graphicsEngine.makeWindow(gsg, name) + win = self.graphicsEngine.makeWindow(gsg, name, 0) elif type == 'offscreen': win = self.graphicsEngine.makeBuffer( - gsg, name, props.getXSize(), props.getYSize(), 0) + gsg, name, 0, props.getXSize(), props.getYSize(), 0) except: if type == 'onscreen': win = self.graphicsEngine.makeWindow(pipe, gsg) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 48b2c76f3b..828185eab2 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -67,6 +67,8 @@ GraphicsEngine(Pipeline *pipeline) : _pipeline = Pipeline::get_render_pipeline(); } + _windows_sorted = true; + // Default frame buffer properties. _frame_buffer_properties.set_depth_bits(1); _frame_buffer_properties.set_color_bits(1); @@ -203,7 +205,7 @@ make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties) { // later. //////////////////////////////////////////////////////////////////// GraphicsWindow *GraphicsEngine:: -make_window(GraphicsStateGuardian *gsg, const string &name) { +make_window(GraphicsStateGuardian *gsg, const string &name, int sort) { GraphicsThreadingModel threading_model = get_threading_model(); nassertr(gsg != (GraphicsStateGuardian *)NULL, NULL); @@ -213,6 +215,7 @@ make_window(GraphicsStateGuardian *gsg, const string &name) { // TODO: ask the window thread to make the window. PT(GraphicsWindow) window = gsg->get_pipe()->make_window(gsg, name); + window->_sort = sort; do_add_window(window, gsg, threading_model); return window; } @@ -232,9 +235,9 @@ make_window(GraphicsStateGuardian *gsg, const string &name) { //////////////////////////////////////////////////////////////////// GraphicsOutput *GraphicsEngine:: make_buffer(GraphicsStateGuardian *gsg, const string &name, - int x_size, int y_size, bool want_texture) { + int sort, int x_size, int y_size, bool want_texture) { if (show_buffers) { - GraphicsWindow *window = make_window(gsg, name); + GraphicsWindow *window = make_window(gsg, name, sort); if (window != (GraphicsWindow *)NULL) { WindowProperties props; props.set_size(x_size, y_size); @@ -261,6 +264,7 @@ make_buffer(GraphicsStateGuardian *gsg, const string &name, // TODO: ask the window thread to make the buffer. PT(GraphicsBuffer) buffer = gsg->get_pipe()->make_buffer(gsg, name, x_size, y_size, want_texture); + buffer->_sort = sort; do_add_window(buffer, gsg, threading_model); return buffer; } @@ -378,6 +382,10 @@ render_frame() { // don't do that. MutexHolder holder(_lock); + if (!_windows_sorted) { + do_resort_windows(); + } + if (_flip_state != FS_flip) { do_flip_frame(); } @@ -502,6 +510,23 @@ render_subframe(GraphicsStateGuardian *gsg, DisplayRegion *dr, } } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::set_window_sort +// Access: Private +// Description: Changes the sort value of a particular window (or +// buffer) on the GraphicsEngine. This requires +// securing the mutex. +// +// Users shouldn't call this directly; use +// GraphicsOutput::set_sort() instead. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +set_window_sort(GraphicsOutput *window, int sort) { + MutexHolder holder(_lock); + window->_sort = sort; + _windows_sorted = false; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::cull_and_draw_together // Access: Private @@ -895,7 +920,8 @@ do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg, const GraphicsThreadingModel &threading_model) { if (window != (GraphicsOutput *)NULL) { MutexHolder holder(_lock); - _windows.insert(window); + _windows_sorted = false; + _windows.push_back(window); WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name()); WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name()); @@ -937,6 +963,10 @@ do_remove_window(GraphicsOutput *window) { PT(GraphicsPipe) pipe = window->get_pipe(); window->_pipe = (GraphicsPipe *)NULL; + if (!_windows_sorted) { + do_resort_windows(); + } + // Now remove the window from all threads that know about it. _app.remove_window(window); Threads::const_iterator ti; @@ -950,6 +980,26 @@ do_remove_window(GraphicsOutput *window) { _app.do_pending(this); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::do_resort_windows +// Access: Private +// Description: Resorts all of the Windows lists. This may need to +// be done if one or more of the windows' sort +// properties has changed. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +do_resort_windows() { + _windows_sorted = true; + + _app.resort_windows(); + Threads::const_iterator ti; + for (ti = _threads.begin(); ti != _threads.end(); ++ti) { + RenderThread *thread = (*ti).second; + thread->resort_windows(); + } + _windows.sort(); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::terminate_threads // Access: Private @@ -1077,7 +1127,7 @@ remove_window(GraphicsOutput *window) { // Move it to the pending release thread so we can release the GSG // when the thread next runs. We can't do this immediately, // because we might not have been called from the subthread. - _pending_release.insert(ptwin); + _pending_release.push_back(ptwin); _cdraw.erase(wi); } @@ -1089,7 +1139,7 @@ remove_window(GraphicsOutput *window) { // Move it to the pending release thread so we can release the GSG // when the thread next runs. We can't do this immediately, // because we might not have been called from the subthread. - _pending_release.insert(ptwin); + _pending_release.push_back(ptwin); _draw.erase(wi); } @@ -1106,13 +1156,29 @@ remove_window(GraphicsOutput *window) { // it can be closed later. We can't close it immediately, because // we might not have been called from the subthread. if (ptwin->is_valid()) { - _pending_close.insert(ptwin); + _pending_close.push_back(ptwin); } _window.erase(wi); } } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::WindowRenderer::resort_windows +// Access: Public +// Description: Resorts all the lists of windows, assuming they may +// have become unsorted. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine::WindowRenderer:: +resort_windows() { + MutexHolder holder(_wl_lock); + + _cull.sort(); + _cdraw.sort(); + _draw.sort(); + _window.sort(); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::WindowRenderer::do_frame // Access: Public @@ -1242,7 +1308,7 @@ do_pending(GraphicsEngine *engine) { } else { // If the GSG hasn't been released yet, we have to save the // close operation for next frame. - new_pending_close.insert(win); + new_pending_close.push_back(win); } } _pending_close.swap(new_pending_close); diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index 1badf1b7c5..9c749fc321 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -29,8 +29,10 @@ #include "thread.h" #include "pmutex.h" #include "conditionVar.h" -#include "pset.h" #include "pStatCollector.h" +#include "pset.h" +#include "ordered_vector.h" +#include "indirectLess.h" class Pipeline; class DisplayRegion; @@ -71,8 +73,10 @@ PUBLISHED: PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties); - GraphicsWindow *make_window(GraphicsStateGuardian *gsg, const string &name); + GraphicsWindow *make_window(GraphicsStateGuardian *gsg, const string &name, + int sort); GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg, const string &name, + int sort, int x_size, int y_size, bool want_texture); bool remove_window(GraphicsOutput *window); @@ -97,17 +101,19 @@ public: }; private: - typedef pset< PT(GraphicsOutput) > Windows; + typedef ov_multiset< PT(GraphicsOutput), IndirectLess > Windows; typedef pset< PT(GraphicsStateGuardian) > GSGs; + void set_window_sort(GraphicsOutput *window, int sort); + void cull_and_draw_together(const Windows &wlist); void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr); void cull_bin_draw(const Windows &wlist); void cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr); - void process_events(const GraphicsEngine::Windows &wlist); - void flip_windows(const GraphicsEngine::Windows &wlist); + void process_events(const Windows &wlist); + void flip_windows(const Windows &wlist); void do_sync_frame(); void do_flip_frame(); INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); @@ -124,6 +130,7 @@ private: void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg, const GraphicsThreadingModel &threading_model); void do_remove_window(GraphicsOutput *window); + void do_resort_windows(); void terminate_threads(); // The WindowRenderer class records the stages of the pipeline that @@ -134,6 +141,7 @@ private: void add_gsg(GraphicsStateGuardian *gsg); void add_window(Windows &wlist, GraphicsOutput *window); void remove_window(GraphicsOutput *window); + void resort_windows(); void do_frame(GraphicsEngine *engine); void do_flip(GraphicsEngine *engine); void do_release(GraphicsEngine *engine); @@ -145,8 +153,11 @@ private: Windows _cdraw; // cull-and-draw-together stage Windows _draw; // draw stage Windows _window; // window stage, i.e. process windowing events + + // These two are not kept sorted. Windows _pending_release; // moved from _draw, pending release_gsg. Windows _pending_close; // moved from _window, pending close. + GSGs _gsgs; // draw stage Mutex _wl_lock; }; @@ -166,6 +177,7 @@ private: Pipeline *_pipeline; Windows _windows; + bool _windows_sorted; WindowRenderer _app; typedef pmap Threads; @@ -192,7 +204,9 @@ private: static PStatCollector _transform_states_unused_pcollector; static PStatCollector _render_states_pcollector; static PStatCollector _render_states_unused_pcollector; + friend class WindowRenderer; + friend class GraphicsOutput; }; #include "graphicsEngine.I" diff --git a/panda/src/display/graphicsOutput.I b/panda/src/display/graphicsOutput.I index 2bb72c9d66..b3b2634e48 100644 --- a/panda/src/display/graphicsOutput.I +++ b/panda/src/display/graphicsOutput.I @@ -160,6 +160,19 @@ is_valid() const { return _is_valid; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::get_sort +// Access: Published +// Description: Returns the sorting order of this particular +// GraphicsOutput. The various GraphicsOutputs within a +// particular thread will be rendered in the indicated +// order. +//////////////////////////////////////////////////////////////////// +INLINE int GraphicsOutput:: +get_sort() const { + return _sort; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::win_display_regions_changed // Access: Public @@ -173,6 +186,19 @@ win_display_regions_changed() { _display_regions_stale = true; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::operator < +// Access: Public +// Description: The sorting operator is used to order the +// GraphicsOutput object in order by their sort number, +// so that they will render in the correct order in the +// GraphicsEngine. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsOutput:: +operator < (const GraphicsOutput &other) const { + return _sort < other._sort; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::determine_display_regions diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 1a9fe3eb64..066c68ffd3 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -18,6 +18,7 @@ #include "graphicsOutput.h" #include "graphicsPipe.h" +#include "graphicsEngine.h" #include "config_display.h" #include "mutexHolder.h" #include "hardwareChannel.h" @@ -49,6 +50,7 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, _has_size = false; _is_valid = false; _copy_texture = false; + _sort = 0; _display_regions_stale = false; @@ -112,6 +114,22 @@ is_active() const { return is_valid(); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::set_sort +// Access: Published +// Description: Adjusts the sorting order of this particular +// GraphicsOutput, relative to other GraphicsOutputs. +//////////////////////////////////////////////////////////////////// +void GraphicsOutput:: +set_sort(int sort) { + if (_sort != sort) { + if (_gsg != (GraphicsStateGuardian *)NULL && + _gsg->get_engine() != (GraphicsEngine *)NULL) { + _gsg->get_engine()->set_window_sort(this, sort); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::get_channel // Access: Public diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 48043c990a..33c03c61d7 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -83,6 +83,9 @@ PUBLISHED: virtual bool is_active() const; + INLINE int get_sort() const; + void set_sort(int sort); + GraphicsChannel *get_channel(int index); void remove_channel(int index); @@ -104,6 +107,8 @@ public: // These are not intended to be called directly by the user. INLINE void win_display_regions_changed(); + INLINE bool operator < (const GraphicsOutput &other) const; + virtual void request_open(); virtual void request_close(); @@ -146,6 +151,8 @@ private: INLINE void determine_display_regions() const; void do_determine_display_regions(); + int _sort; + protected: Mutex _lock; // protects _channels, _display_regions. diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index a5cc135f2b..717563ce20 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -117,7 +117,7 @@ open_window(const WindowProperties &props, GraphicsEngine *engine, next_window_index++; string name = stream.str(); - _window = engine->make_window(ptgsg, name); + _window = engine->make_window(ptgsg, name, 0); if (_window != (GraphicsWindow *)NULL) { _window->request_properties(props); set_background_type(_background_type);