add GraphicsOutput::sort

This commit is contained in:
David Rose 2004-02-19 02:53:23 +00:00
parent 6039e182c0
commit c26166c9cc
7 changed files with 147 additions and 16 deletions

View File

@ -380,10 +380,10 @@ class ShowBase(DirectObject.DirectObject):
# Temporary try .. except for old Pandas. # Temporary try .. except for old Pandas.
try: try:
if type == 'onscreen': if type == 'onscreen':
win = self.graphicsEngine.makeWindow(gsg, name) win = self.graphicsEngine.makeWindow(gsg, name, 0)
elif type == 'offscreen': elif type == 'offscreen':
win = self.graphicsEngine.makeBuffer( win = self.graphicsEngine.makeBuffer(
gsg, name, props.getXSize(), props.getYSize(), 0) gsg, name, 0, props.getXSize(), props.getYSize(), 0)
except: except:
if type == 'onscreen': if type == 'onscreen':
win = self.graphicsEngine.makeWindow(pipe, gsg) win = self.graphicsEngine.makeWindow(pipe, gsg)

View File

@ -67,6 +67,8 @@ GraphicsEngine(Pipeline *pipeline) :
_pipeline = Pipeline::get_render_pipeline(); _pipeline = Pipeline::get_render_pipeline();
} }
_windows_sorted = true;
// Default frame buffer properties. // Default frame buffer properties.
_frame_buffer_properties.set_depth_bits(1); _frame_buffer_properties.set_depth_bits(1);
_frame_buffer_properties.set_color_bits(1); _frame_buffer_properties.set_color_bits(1);
@ -203,7 +205,7 @@ make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties) {
// later. // later.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
GraphicsWindow *GraphicsEngine:: GraphicsWindow *GraphicsEngine::
make_window(GraphicsStateGuardian *gsg, const string &name) { make_window(GraphicsStateGuardian *gsg, const string &name, int sort) {
GraphicsThreadingModel threading_model = get_threading_model(); GraphicsThreadingModel threading_model = get_threading_model();
nassertr(gsg != (GraphicsStateGuardian *)NULL, NULL); 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. // TODO: ask the window thread to make the window.
PT(GraphicsWindow) window = gsg->get_pipe()->make_window(gsg, name); PT(GraphicsWindow) window = gsg->get_pipe()->make_window(gsg, name);
window->_sort = sort;
do_add_window(window, gsg, threading_model); do_add_window(window, gsg, threading_model);
return window; return window;
} }
@ -232,9 +235,9 @@ make_window(GraphicsStateGuardian *gsg, const string &name) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
GraphicsOutput *GraphicsEngine:: GraphicsOutput *GraphicsEngine::
make_buffer(GraphicsStateGuardian *gsg, const string &name, 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) { if (show_buffers) {
GraphicsWindow *window = make_window(gsg, name); GraphicsWindow *window = make_window(gsg, name, sort);
if (window != (GraphicsWindow *)NULL) { if (window != (GraphicsWindow *)NULL) {
WindowProperties props; WindowProperties props;
props.set_size(x_size, y_size); 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. // TODO: ask the window thread to make the buffer.
PT(GraphicsBuffer) buffer = PT(GraphicsBuffer) buffer =
gsg->get_pipe()->make_buffer(gsg, name, x_size, y_size, want_texture); gsg->get_pipe()->make_buffer(gsg, name, x_size, y_size, want_texture);
buffer->_sort = sort;
do_add_window(buffer, gsg, threading_model); do_add_window(buffer, gsg, threading_model);
return buffer; return buffer;
} }
@ -378,6 +382,10 @@ render_frame() {
// don't do that. // don't do that.
MutexHolder holder(_lock); MutexHolder holder(_lock);
if (!_windows_sorted) {
do_resort_windows();
}
if (_flip_state != FS_flip) { if (_flip_state != FS_flip) {
do_flip_frame(); 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 // Function: GraphicsEngine::cull_and_draw_together
// Access: Private // Access: Private
@ -895,7 +920,8 @@ do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
const GraphicsThreadingModel &threading_model) { const GraphicsThreadingModel &threading_model) {
if (window != (GraphicsOutput *)NULL) { if (window != (GraphicsOutput *)NULL) {
MutexHolder holder(_lock); MutexHolder holder(_lock);
_windows.insert(window); _windows_sorted = false;
_windows.push_back(window);
WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name()); WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
WindowRenderer *draw = get_window_renderer(threading_model.get_draw_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(); PT(GraphicsPipe) pipe = window->get_pipe();
window->_pipe = (GraphicsPipe *)NULL; window->_pipe = (GraphicsPipe *)NULL;
if (!_windows_sorted) {
do_resort_windows();
}
// Now remove the window from all threads that know about it. // Now remove the window from all threads that know about it.
_app.remove_window(window); _app.remove_window(window);
Threads::const_iterator ti; Threads::const_iterator ti;
@ -950,6 +980,26 @@ do_remove_window(GraphicsOutput *window) {
_app.do_pending(this); _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 // Function: GraphicsEngine::terminate_threads
// Access: Private // Access: Private
@ -1077,7 +1127,7 @@ remove_window(GraphicsOutput *window) {
// Move it to the pending release thread so we can release the GSG // Move it to the pending release thread so we can release the GSG
// when the thread next runs. We can't do this immediately, // when the thread next runs. We can't do this immediately,
// because we might not have been called from the subthread. // because we might not have been called from the subthread.
_pending_release.insert(ptwin); _pending_release.push_back(ptwin);
_cdraw.erase(wi); _cdraw.erase(wi);
} }
@ -1089,7 +1139,7 @@ remove_window(GraphicsOutput *window) {
// Move it to the pending release thread so we can release the GSG // Move it to the pending release thread so we can release the GSG
// when the thread next runs. We can't do this immediately, // when the thread next runs. We can't do this immediately,
// because we might not have been called from the subthread. // because we might not have been called from the subthread.
_pending_release.insert(ptwin); _pending_release.push_back(ptwin);
_draw.erase(wi); _draw.erase(wi);
} }
@ -1106,13 +1156,29 @@ remove_window(GraphicsOutput *window) {
// it can be closed later. We can't close it immediately, because // it can be closed later. We can't close it immediately, because
// we might not have been called from the subthread. // we might not have been called from the subthread.
if (ptwin->is_valid()) { if (ptwin->is_valid()) {
_pending_close.insert(ptwin); _pending_close.push_back(ptwin);
} }
_window.erase(wi); _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 // Function: GraphicsEngine::WindowRenderer::do_frame
// Access: Public // Access: Public
@ -1242,7 +1308,7 @@ do_pending(GraphicsEngine *engine) {
} else { } else {
// If the GSG hasn't been released yet, we have to save the // If the GSG hasn't been released yet, we have to save the
// close operation for next frame. // close operation for next frame.
new_pending_close.insert(win); new_pending_close.push_back(win);
} }
} }
_pending_close.swap(new_pending_close); _pending_close.swap(new_pending_close);

View File

@ -29,8 +29,10 @@
#include "thread.h" #include "thread.h"
#include "pmutex.h" #include "pmutex.h"
#include "conditionVar.h" #include "conditionVar.h"
#include "pset.h"
#include "pStatCollector.h" #include "pStatCollector.h"
#include "pset.h"
#include "ordered_vector.h"
#include "indirectLess.h"
class Pipeline; class Pipeline;
class DisplayRegion; class DisplayRegion;
@ -71,8 +73,10 @@ PUBLISHED:
PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe, PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe,
const FrameBufferProperties &properties); 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, GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg, const string &name,
int sort,
int x_size, int y_size, bool want_texture); int x_size, int y_size, bool want_texture);
bool remove_window(GraphicsOutput *window); bool remove_window(GraphicsOutput *window);
@ -97,17 +101,19 @@ public:
}; };
private: private:
typedef pset< PT(GraphicsOutput) > Windows; typedef ov_multiset< PT(GraphicsOutput), IndirectLess<GraphicsOutput> > Windows;
typedef pset< PT(GraphicsStateGuardian) > GSGs; 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(const Windows &wlist);
void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr); void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
void cull_bin_draw(const Windows &wlist); void cull_bin_draw(const Windows &wlist);
void cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr); void cull_bin_draw(GraphicsStateGuardian *gsg, DisplayRegion *dr);
void process_events(const GraphicsEngine::Windows &wlist); void process_events(const Windows &wlist);
void flip_windows(const GraphicsEngine::Windows &wlist); void flip_windows(const Windows &wlist);
void do_sync_frame(); void do_sync_frame();
void do_flip_frame(); void do_flip_frame();
INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
@ -124,6 +130,7 @@ private:
void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg, void do_add_window(GraphicsOutput *window, GraphicsStateGuardian *gsg,
const GraphicsThreadingModel &threading_model); const GraphicsThreadingModel &threading_model);
void do_remove_window(GraphicsOutput *window); void do_remove_window(GraphicsOutput *window);
void do_resort_windows();
void terminate_threads(); void terminate_threads();
// The WindowRenderer class records the stages of the pipeline that // The WindowRenderer class records the stages of the pipeline that
@ -134,6 +141,7 @@ private:
void add_gsg(GraphicsStateGuardian *gsg); void add_gsg(GraphicsStateGuardian *gsg);
void add_window(Windows &wlist, GraphicsOutput *window); void add_window(Windows &wlist, GraphicsOutput *window);
void remove_window(GraphicsOutput *window); void remove_window(GraphicsOutput *window);
void resort_windows();
void do_frame(GraphicsEngine *engine); void do_frame(GraphicsEngine *engine);
void do_flip(GraphicsEngine *engine); void do_flip(GraphicsEngine *engine);
void do_release(GraphicsEngine *engine); void do_release(GraphicsEngine *engine);
@ -145,8 +153,11 @@ private:
Windows _cdraw; // cull-and-draw-together stage Windows _cdraw; // cull-and-draw-together stage
Windows _draw; // draw stage Windows _draw; // draw stage
Windows _window; // window stage, i.e. process windowing events 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_release; // moved from _draw, pending release_gsg.
Windows _pending_close; // moved from _window, pending close. Windows _pending_close; // moved from _window, pending close.
GSGs _gsgs; // draw stage GSGs _gsgs; // draw stage
Mutex _wl_lock; Mutex _wl_lock;
}; };
@ -166,6 +177,7 @@ private:
Pipeline *_pipeline; Pipeline *_pipeline;
Windows _windows; Windows _windows;
bool _windows_sorted;
WindowRenderer _app; WindowRenderer _app;
typedef pmap<string, PT(RenderThread) > Threads; typedef pmap<string, PT(RenderThread) > Threads;
@ -192,7 +204,9 @@ private:
static PStatCollector _transform_states_unused_pcollector; static PStatCollector _transform_states_unused_pcollector;
static PStatCollector _render_states_pcollector; static PStatCollector _render_states_pcollector;
static PStatCollector _render_states_unused_pcollector; static PStatCollector _render_states_unused_pcollector;
friend class WindowRenderer; friend class WindowRenderer;
friend class GraphicsOutput;
}; };
#include "graphicsEngine.I" #include "graphicsEngine.I"

View File

@ -160,6 +160,19 @@ is_valid() const {
return _is_valid; 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 // Function: GraphicsOutput::win_display_regions_changed
// Access: Public // Access: Public
@ -173,6 +186,19 @@ win_display_regions_changed() {
_display_regions_stale = true; _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 // Function: GraphicsOutput::determine_display_regions

View File

@ -18,6 +18,7 @@
#include "graphicsOutput.h" #include "graphicsOutput.h"
#include "graphicsPipe.h" #include "graphicsPipe.h"
#include "graphicsEngine.h"
#include "config_display.h" #include "config_display.h"
#include "mutexHolder.h" #include "mutexHolder.h"
#include "hardwareChannel.h" #include "hardwareChannel.h"
@ -49,6 +50,7 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
_has_size = false; _has_size = false;
_is_valid = false; _is_valid = false;
_copy_texture = false; _copy_texture = false;
_sort = 0;
_display_regions_stale = false; _display_regions_stale = false;
@ -112,6 +114,22 @@ is_active() const {
return is_valid(); 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 // Function: GraphicsOutput::get_channel
// Access: Public // Access: Public

View File

@ -83,6 +83,9 @@ PUBLISHED:
virtual bool is_active() const; virtual bool is_active() const;
INLINE int get_sort() const;
void set_sort(int sort);
GraphicsChannel *get_channel(int index); GraphicsChannel *get_channel(int index);
void remove_channel(int index); void remove_channel(int index);
@ -104,6 +107,8 @@ public:
// These are not intended to be called directly by the user. // These are not intended to be called directly by the user.
INLINE void win_display_regions_changed(); INLINE void win_display_regions_changed();
INLINE bool operator < (const GraphicsOutput &other) const;
virtual void request_open(); virtual void request_open();
virtual void request_close(); virtual void request_close();
@ -146,6 +151,8 @@ private:
INLINE void determine_display_regions() const; INLINE void determine_display_regions() const;
void do_determine_display_regions(); void do_determine_display_regions();
int _sort;
protected: protected:
Mutex _lock; Mutex _lock;
// protects _channels, _display_regions. // protects _channels, _display_regions.

View File

@ -117,7 +117,7 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
next_window_index++; next_window_index++;
string name = stream.str(); string name = stream.str();
_window = engine->make_window(ptgsg, name); _window = engine->make_window(ptgsg, name, 0);
if (_window != (GraphicsWindow *)NULL) { if (_window != (GraphicsWindow *)NULL) {
_window->request_properties(props); _window->request_properties(props);
set_background_type(_background_type); set_background_type(_background_type);