first pass at cheesy pipelining
This commit is contained in:
parent
ad72a2b2fd
commit
629a2f087a
|
|
@ -33,6 +33,8 @@
|
|||
#include "cullFaceAttrib.h"
|
||||
#include "string_utils.h"
|
||||
#include "geomCacheManager.h"
|
||||
#include "thread.h"
|
||||
#include "pipeline.h"
|
||||
#include "throw_event.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
|
|
@ -1413,6 +1415,9 @@ get_window_renderer(const string &name) {
|
|||
}
|
||||
|
||||
PT(RenderThread) thread = new RenderThread(name, this);
|
||||
thread->set_pipeline_stage(1);
|
||||
Pipeline::get_render_pipeline()->set_num_stages(2);
|
||||
|
||||
thread->start(TP_normal, true, true);
|
||||
_threads[name] = thread;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "config_express.h"
|
||||
#include "datagram.h"
|
||||
#include "mainThread.h"
|
||||
#include "externalThread.h"
|
||||
#include "referenceCount.h"
|
||||
#include "textEncoder.h"
|
||||
#include "thread.h"
|
||||
|
|
@ -169,6 +170,7 @@ init_libexpress() {
|
|||
|
||||
Datagram::init_type();
|
||||
MainThread::init_type();
|
||||
ExternalThread::init_type();
|
||||
ReferenceCount::init_type();
|
||||
TextEncoder::init_type();
|
||||
Thread::init_type();
|
||||
|
|
|
|||
|
|
@ -23,12 +23,29 @@ TypeHandle ExternalThread::_type_handle;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ExternalThread::Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
// Description: This constructor is used to create the one global
|
||||
// ExternalThread object that is shared by all
|
||||
// externally-created threads that are not specifically
|
||||
// bound to a particular Thread object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ExternalThread::
|
||||
ExternalThread() : Thread("External", "External") {
|
||||
_started = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ExternalThread::Constructor
|
||||
// Access: Private
|
||||
// Description: This constructor is used to create the particular
|
||||
// Thread object for each external thread that is bound
|
||||
// via Thread::bind_thread().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ExternalThread::
|
||||
ExternalThread(const string &name, const string &sync_name) :
|
||||
Thread(name, sync_name)
|
||||
{
|
||||
_started = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ExternalThread::thread_main
|
||||
|
|
|
|||
|
|
@ -31,12 +31,14 @@
|
|||
class EXPCL_PANDAEXPRESS ExternalThread : public Thread {
|
||||
private:
|
||||
ExternalThread();
|
||||
ExternalThread(const string &name, const string &sync_name);
|
||||
virtual void thread_main();
|
||||
|
||||
public:
|
||||
PUBLISHED:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
public:
|
||||
static void init_type() {
|
||||
Thread::init_type();
|
||||
register_type(_type_handle, "ExternalThread",
|
||||
|
|
|
|||
|
|
@ -33,10 +33,11 @@ private:
|
|||
MainThread();
|
||||
virtual void thread_main();
|
||||
|
||||
public:
|
||||
PUBLISHED:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
public:
|
||||
static void init_type() {
|
||||
Thread::init_type();
|
||||
register_type(_type_handle, "MainThread",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::Constructor
|
||||
// Access: Public
|
||||
// Access: Protected
|
||||
// Description: Creates a new Thread object, but does not
|
||||
// immediately start executing it. This gives the
|
||||
// caller a chance to store it in a PT(Thread) object,
|
||||
|
|
@ -43,6 +43,7 @@ Thread(const string &name, const string &sync_name) :
|
|||
{
|
||||
_started = false;
|
||||
_pstats_index = -1;
|
||||
_pipeline_stage = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -67,7 +68,7 @@ operator = (const Thread ©) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_name
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the name of the thread. Each thread should
|
||||
// probably have a unique name, but this is not enforced
|
||||
// (and not strictly required).
|
||||
|
|
@ -79,7 +80,7 @@ get_name() const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_sync_name
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the sync name of the thread. This name
|
||||
// collects threads into "sync groups", which are
|
||||
// expected to run synchronously. This is mainly used
|
||||
|
|
@ -94,7 +95,7 @@ get_sync_name() const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_pstats_index
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the PStats index associated with this thread,
|
||||
// or -1 if no index has yet been associated with this
|
||||
// thread. This is used internally by the PStatClient;
|
||||
|
|
@ -107,7 +108,7 @@ get_pstats_index() const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::set_pstats_index
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Stores a PStats index to be associated with this
|
||||
// thread. This is used internally by the PStatClient;
|
||||
// you should not need to call this directly.
|
||||
|
|
@ -117,6 +118,120 @@ set_pstats_index(int pstats_index) {
|
|||
_pstats_index = pstats_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_pipeline_stage
|
||||
// Access: Published
|
||||
// Description: Returns the Pipeline stage number associated with
|
||||
// this thread. The default stage is 0 if no stage is
|
||||
// specified otherwise. See set_pipeline_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Thread::
|
||||
get_pipeline_stage() const {
|
||||
return _pipeline_stage;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::set_pipeline_stage
|
||||
// Access: Published
|
||||
// Description: Specifies the Pipeline stage number associated with
|
||||
// this thread. The default stage is 0 if no stage is
|
||||
// specified otherwise.
|
||||
//
|
||||
// This must be a value in the range [0
|
||||
// .. pipeline->get_num_stages() - 1]. It specifies the
|
||||
// values that this thread observes for all pipelined
|
||||
// data. Typically, an application thread will leave
|
||||
// this at 0, but a render thread may set it to 1 or 2
|
||||
// (to operate on the previous frame's data, or the
|
||||
// second previous frame's data).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Thread::
|
||||
set_pipeline_stage(int pipeline_stage) {
|
||||
_pipeline_stage = pipeline_stage;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_main_thread
|
||||
// Access: Published, Static
|
||||
// Description: Returns a pointer to the "main" Thread object--this
|
||||
// is the Thread that started the whole process.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_main_thread() {
|
||||
if (_main_thread == (Thread *)NULL) {
|
||||
init_main_thread();
|
||||
}
|
||||
return _main_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_external_thread
|
||||
// Access: Published, Static
|
||||
// Description: Returns a pointer to the "external" Thread
|
||||
// object--this is a special Thread object that
|
||||
// corresponds to any thread spawned outside of Panda's
|
||||
// threading interface. Note that multiple different
|
||||
// threads may share this same pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_external_thread() {
|
||||
if (_external_thread == (Thread *)NULL) {
|
||||
init_external_thread();
|
||||
}
|
||||
return _external_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_current_thread
|
||||
// Access: Published, Static
|
||||
// Description: Returns a pointer to the currently-executing Thread
|
||||
// object. If this is called from the main thread, this
|
||||
// will return the same value as get_main_thread().
|
||||
//
|
||||
// This will always return some valid Thread pointer.
|
||||
// It will never return NULL, even if the current thread
|
||||
// was spawned outside of Panda's threading system,
|
||||
// although all non-Panda threads will return the exact
|
||||
// same Thread pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_current_thread() {
|
||||
#ifndef HAVE_THREADS
|
||||
return get_main_thread();
|
||||
#else // HAVE_THREADS
|
||||
Thread *thread = ThreadImpl::get_current_thread();
|
||||
if (thread == (Thread *)NULL) {
|
||||
return Thread::get_external_thread();
|
||||
}
|
||||
return thread;
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::is_threading_supported
|
||||
// Access: Published, Static
|
||||
// Description: Returns true if a real threading library is available
|
||||
// that supports threads, or false if no threading
|
||||
// library is available (and Thread::start() will always
|
||||
// fail).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Thread::
|
||||
is_threading_supported() {
|
||||
return ThreadImpl::is_threading_supported();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::sleep
|
||||
// Access: Published, Static
|
||||
// Description: Suspends the current thread for at least the
|
||||
// indicated amount of time. It might be suspended for
|
||||
// longer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Thread::
|
||||
sleep(double seconds) {
|
||||
ThreadImpl::sleep(seconds);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::start
|
||||
// Access: Public
|
||||
|
|
@ -187,88 +302,6 @@ prepare_for_exit() {
|
|||
ThreadImpl::prepare_for_exit();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_main_thread
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the "main" Thread object--this
|
||||
// is the Thread that started the whole process.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_main_thread() {
|
||||
if (_main_thread == (Thread *)NULL) {
|
||||
init_main_thread();
|
||||
}
|
||||
return _main_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_external_thread
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the "external" Thread
|
||||
// object--this is a special Thread object that
|
||||
// corresponds to any thread spawned outside of Panda's
|
||||
// threading interface. Note that multiple different
|
||||
// threads may share this same pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_external_thread() {
|
||||
if (_external_thread == (Thread *)NULL) {
|
||||
init_external_thread();
|
||||
}
|
||||
return _external_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_current_thread
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the currently-executing Thread
|
||||
// object. If this is called from the main thread, this
|
||||
// will return the same value as get_main_thread().
|
||||
//
|
||||
// This will always return some valid Thread pointer.
|
||||
// It will never return NULL, even if the current thread
|
||||
// was spawned outside of Panda's threading system,
|
||||
// although all non-Panda threads will return the exact
|
||||
// same Thread pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_current_thread() {
|
||||
#ifndef HAVE_THREADS
|
||||
return get_main_thread();
|
||||
#else // HAVE_THREADS
|
||||
Thread *thread = ThreadImpl::get_current_thread();
|
||||
if (thread == (Thread *)NULL) {
|
||||
return Thread::get_external_thread();
|
||||
}
|
||||
return thread;
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::is_threading_supported
|
||||
// Access: Public, Static
|
||||
// Description: Returns true if a real threading library is available
|
||||
// that supports threads, or false if no threading
|
||||
// library is available (and Thread::start() will always
|
||||
// fail).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Thread::
|
||||
is_threading_supported() {
|
||||
return ThreadImpl::is_threading_supported();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::sleep
|
||||
// Access: Public, Static
|
||||
// Description: Suspends the current thread for at least the
|
||||
// indicated amount of time. It might be suspended for
|
||||
// longer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Thread::
|
||||
sleep(double seconds) {
|
||||
ThreadImpl::sleep(seconds);
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const Thread &thread) {
|
||||
thread.output(out);
|
||||
|
|
|
|||
|
|
@ -26,16 +26,57 @@ TypeHandle Thread::_type_handle;
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Thread::
|
||||
~Thread() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::bind_thread
|
||||
// Access: Published, Static
|
||||
// Description: Returns a new Panda Thread object associated with the
|
||||
// current thread (which has been created externally).
|
||||
// This can be used to bind a unique Panda Thread object
|
||||
// with an external thread, such as a new Python thread.
|
||||
//
|
||||
// It is particularly useful to bind a Panda Thread
|
||||
// object to an external thread for the purposes of
|
||||
// PStats monitoring. Without this call, each external
|
||||
// thread will be assigned the same global
|
||||
// ExternalThread object, which means they will all
|
||||
// appear in the same PStats graph.
|
||||
//
|
||||
// It is the caller's responsibility to save the
|
||||
// returned Thread pointer for the lifetime of the
|
||||
// external thread. It is an error for the Thread
|
||||
// pointer to destruct while the external thread is
|
||||
// still in the system.
|
||||
//
|
||||
// It is also an error to call this method from the main
|
||||
// thread, or twice within a given thread, unless it is
|
||||
// given the same name each time (in which case the same
|
||||
// pointer will be returned each time).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Thread) Thread::
|
||||
bind_thread(const string &name, const string &sync_name) {
|
||||
Thread *current_thread = get_current_thread();
|
||||
if (current_thread != get_external_thread()) {
|
||||
// This thread already has an associated thread.
|
||||
nassertr(current_thread->get_name() == name &&
|
||||
current_thread->get_sync_name() == sync_name, current_thread);
|
||||
return current_thread;
|
||||
}
|
||||
|
||||
PT(Thread) thread = new ExternalThread(name, sync_name);
|
||||
ThreadImpl::bind_thread(thread);
|
||||
return thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::output
|
||||
// Access: Public, Virtual
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Thread::
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
#include "threadPriority.h"
|
||||
#include "threadImpl.h"
|
||||
#include "notify.h"
|
||||
|
|
@ -38,8 +39,10 @@
|
|||
// are referencing it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS Thread : public TypedReferenceCount {
|
||||
public:
|
||||
protected:
|
||||
INLINE Thread(const string &name, const string &sync_name);
|
||||
|
||||
PUBLISHED:
|
||||
virtual ~Thread();
|
||||
|
||||
private:
|
||||
|
|
@ -49,18 +52,17 @@ private:
|
|||
protected:
|
||||
virtual void thread_main()=0;
|
||||
|
||||
public:
|
||||
PUBLISHED:
|
||||
static PT(Thread) bind_thread(const string &name, const string &sync_name);
|
||||
|
||||
INLINE const string &get_name() const;
|
||||
INLINE const string &get_sync_name() const;
|
||||
|
||||
INLINE int get_pstats_index() const;
|
||||
INLINE void set_pstats_index(int pstats_index);
|
||||
|
||||
INLINE bool start(ThreadPriority priority, bool global, bool joinable);
|
||||
INLINE void interrupt();
|
||||
INLINE void join();
|
||||
|
||||
INLINE static void prepare_for_exit();
|
||||
INLINE int get_pipeline_stage() const;
|
||||
INLINE void set_pipeline_stage(int pipeline_stage);
|
||||
|
||||
INLINE static Thread *get_main_thread();
|
||||
INLINE static Thread *get_external_thread();
|
||||
|
|
@ -70,6 +72,13 @@ public:
|
|||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
public:
|
||||
INLINE bool start(ThreadPriority priority, bool global, bool joinable);
|
||||
INLINE void interrupt();
|
||||
INLINE void join();
|
||||
|
||||
INLINE static void prepare_for_exit();
|
||||
|
||||
private:
|
||||
static void init_main_thread();
|
||||
static void init_external_thread();
|
||||
|
|
@ -80,6 +89,7 @@ protected:
|
|||
string _sync_name;
|
||||
ThreadImpl _impl;
|
||||
int _pstats_index;
|
||||
int _pipeline_stage;
|
||||
|
||||
private:
|
||||
static Thread *_main_thread;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,19 @@ INLINE void ThreadDummyImpl::
|
|||
prepare_for_exit() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadDummyImpl::bind_thread
|
||||
// Access: Public, Static
|
||||
// Description: Associates the indicated Thread object with the
|
||||
// currently-executing thread. You should not call this
|
||||
// directly; use Thread::bind_thread() instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ThreadDummyImpl::
|
||||
bind_thread(Thread *thread) {
|
||||
// This method shouldn't be called in the non-threaded case.
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadDummyImpl::is_threading_supported
|
||||
// Access: Public, Static
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ public:
|
|||
INLINE static void prepare_for_exit();
|
||||
|
||||
static Thread *get_current_thread();
|
||||
INLINE static void bind_thread(Thread *thread);
|
||||
INLINE static bool is_threading_supported();
|
||||
INLINE static void sleep(double seconds);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ prepare_for_exit() {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadNsprImpl::Constructor
|
||||
// Function: ThreadNsprImpl::get_current_thread
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -53,6 +53,22 @@ get_current_thread() {
|
|||
return (Thread *)PR_GetThreadPrivate(_pt_ptr_index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadNsprImpl::bind_thread
|
||||
// Access: Public, Static
|
||||
// Description: Associates the indicated Thread object with the
|
||||
// currently-executing thread. You should not call this
|
||||
// directly; use Thread::bind_thread() instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ThreadNsprImpl::
|
||||
bind_thread(Thread *thread) {
|
||||
if (!_got_pt_ptr_index) {
|
||||
init_pt_ptr_index();
|
||||
}
|
||||
PRStatus result = PR_SetThreadPrivate(_pt_ptr_index, thread);
|
||||
nassertv(result == PR_SUCCESS);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadNsprImpl::is_threading_supported
|
||||
// Access: Public, Static
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public:
|
|||
INLINE static void prepare_for_exit();
|
||||
|
||||
INLINE static Thread *get_current_thread();
|
||||
INLINE static void bind_thread(Thread *thread);
|
||||
INLINE static bool is_threading_supported();
|
||||
INLINE static void sleep(double seconds);
|
||||
|
||||
|
|
|
|||
|
|
@ -799,7 +799,7 @@ Registry() {
|
|||
(InternalName::get_vertex(), 3,
|
||||
NT_float32, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_float32, C_point,
|
||||
NT_float32, C_vector,
|
||||
InternalName::get_color(), 1,
|
||||
NT_packed_dabc, C_color));
|
||||
|
||||
|
|
@ -815,7 +815,7 @@ Registry() {
|
|||
(InternalName::get_vertex(), 3,
|
||||
NT_float32, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_float32, C_point,
|
||||
NT_float32, C_vector,
|
||||
InternalName::get_color(), 1,
|
||||
NT_packed_dabc, C_color,
|
||||
InternalName::get_texcoord(), 2,
|
||||
|
|
@ -834,7 +834,7 @@ Registry() {
|
|||
(InternalName::get_vertex(), 3,
|
||||
NT_float32, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_float32, C_point,
|
||||
NT_float32, C_vector,
|
||||
InternalName::get_color(), 4,
|
||||
NT_uint8, C_color));
|
||||
|
||||
|
|
@ -850,7 +850,7 @@ Registry() {
|
|||
(InternalName::get_vertex(), 3,
|
||||
NT_float32, C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
NT_float32, C_point,
|
||||
NT_float32, C_vector,
|
||||
InternalName::get_color(), 4,
|
||||
NT_uint8, C_color,
|
||||
InternalName::get_texcoord(), 2,
|
||||
|
|
|
|||
|
|
@ -125,33 +125,6 @@ CData() {
|
|||
_fixed_internal_bound = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PandaNode::CData::
|
||||
CData(const PandaNode::CData ©) :
|
||||
_down(copy._down),
|
||||
_stashed(copy._stashed),
|
||||
_up(copy._up),
|
||||
_paths(copy._paths),
|
||||
_state(copy._state),
|
||||
_effects(copy._effects),
|
||||
_transform(copy._transform),
|
||||
_prev_transform(copy._prev_transform),
|
||||
_tag_data(copy._tag_data),
|
||||
_draw_mask(copy._draw_mask),
|
||||
_into_collide_mask(copy._into_collide_mask),
|
||||
_fixed_internal_bound(copy._fixed_internal_bound)
|
||||
{
|
||||
_net_collide_mask = CollideMask::all_off();
|
||||
|
||||
// Note that this copy constructor is not used by the PandaNode copy
|
||||
// constructor! Any elements that must be copied between nodes
|
||||
// should also be explicitly copied there.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::Children::Constructor
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -55,6 +55,53 @@ TypeHandle PandaNode::_type_handle;
|
|||
//
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode::CData::
|
||||
CData(const PandaNode::CData ©) :
|
||||
_down(copy._down),
|
||||
_stashed(copy._stashed),
|
||||
_up(copy._up),
|
||||
_paths(copy._paths),
|
||||
_state(copy._state),
|
||||
_effects(copy._effects),
|
||||
_transform(copy._transform),
|
||||
_prev_transform(copy._prev_transform),
|
||||
_tag_data(copy._tag_data),
|
||||
_draw_mask(copy._draw_mask),
|
||||
_into_collide_mask(copy._into_collide_mask),
|
||||
_net_collide_mask(copy._net_collide_mask),
|
||||
_off_clip_planes(copy._off_clip_planes),
|
||||
_fixed_internal_bound(copy._fixed_internal_bound)
|
||||
{
|
||||
// Note that this copy constructor is not used by the PandaNode copy
|
||||
// constructor! Any elements that must be copied between nodes
|
||||
// should also be explicitly copied there.
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
// Copy and increment all of the Python objects held by the other
|
||||
// node.
|
||||
_python_tag_data = _python_tag_data;
|
||||
inc_py_refs();
|
||||
#endif // HAVE_PYTHON
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode::CData::
|
||||
~CData() {
|
||||
#ifdef HAVE_PYTHON
|
||||
// Free all of the Python objects held by this node.
|
||||
dec_py_refs();
|
||||
#endif // HAVE_PYTHON
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::make_copy
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -160,9 +207,47 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::inc_py_refs
|
||||
// Access: Public
|
||||
// Description: Increments the reference counts on all held Python
|
||||
// objects.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaNode::CData::
|
||||
inc_py_refs() {
|
||||
PythonTagData::const_iterator ti;
|
||||
for (ti = _python_tag_data.begin();
|
||||
ti != _python_tag_data.end();
|
||||
++ti) {
|
||||
PyObject *value = (*ti).second;
|
||||
Py_XINCREF(value);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::dec_py_refs
|
||||
// Access: Public
|
||||
// Description: Decrements the reference counts on all held Python
|
||||
// objects.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaNode::CData::
|
||||
dec_py_refs() {
|
||||
PythonTagData::const_iterator ti;
|
||||
for (ti = _python_tag_data.begin();
|
||||
ti != _python_tag_data.end();
|
||||
++ti) {
|
||||
PyObject *value = (*ti).second;
|
||||
Py_XDECREF(value);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::write_up_list
|
||||
// Access: Private
|
||||
// Access: Public
|
||||
// Description: Writes the indicated list of parent node pointers to
|
||||
// the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -198,7 +283,7 @@ write_up_list(const PandaNode::Up &up_list,
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::write_down_list
|
||||
// Access: Private
|
||||
// Access: Public
|
||||
// Description: Writes the indicated list of child node pointers to
|
||||
// the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -222,7 +307,7 @@ write_down_list(const PandaNode::Down &down_list,
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::complete_up_list
|
||||
// Access: Private
|
||||
// Access: Public
|
||||
// Description: Calls complete_pointers() on the list of parent node
|
||||
// pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -254,7 +339,7 @@ complete_up_list(PandaNode::Up &up_list,
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::complete_down_list
|
||||
// Access: Private
|
||||
// Access: Public
|
||||
// Description: Calls complete_pointers() on the list of child node
|
||||
// pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -279,7 +364,7 @@ complete_down_list(PandaNode::Down &down_list,
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::fillin_up_list
|
||||
// Access: Private
|
||||
// Access: Public
|
||||
// Description: Reads the indicated list parent node pointers from
|
||||
// the datagram (or at least calls read_pointer() for
|
||||
// each one).
|
||||
|
|
@ -298,7 +383,7 @@ fillin_up_list(PandaNode::Up &up_list,
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::CData::fillin_down_list
|
||||
// Access: Private
|
||||
// Access: Public
|
||||
// Description: Reads the indicated list child node pointers from
|
||||
// the datagram (or at least calls read_pointer() for
|
||||
// each one).
|
||||
|
|
@ -370,20 +455,6 @@ PandaNode::
|
|||
#endif // NDEBUG
|
||||
|
||||
remove_all_children();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
{
|
||||
// Free all of the Python objects held by this node.
|
||||
CDReader cdata(_cycler);
|
||||
PythonTagData::const_iterator ti;
|
||||
for (ti = cdata->_python_tag_data.begin();
|
||||
ti != cdata->_python_tag_data.end();
|
||||
++ti) {
|
||||
PyObject *value = (*ti).second;
|
||||
Py_XDECREF(value);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -418,21 +489,16 @@ PandaNode(const PandaNode ©) :
|
|||
cdata->_tag_data = copy_cdata->_tag_data;
|
||||
cdata->_draw_mask = copy_cdata->_draw_mask;
|
||||
cdata->_into_collide_mask = copy_cdata->_into_collide_mask;
|
||||
cdata->_net_collide_mask = CollideMask::all_off();
|
||||
cdata->_off_clip_planes = NULL;
|
||||
cdata->_fixed_internal_bound = copy_cdata->_fixed_internal_bound;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
// Copy and increment all of the Python objects held by the other
|
||||
// node.
|
||||
cdata->_python_tag_data = copy_cdata->_python_tag_data;
|
||||
PythonTagData::const_iterator ti;
|
||||
for (ti = cdata->_python_tag_data.begin();
|
||||
ti != cdata->_python_tag_data.end();
|
||||
++ti) {
|
||||
PyObject *value = (*ti).second;
|
||||
Py_XINCREF(value);
|
||||
}
|
||||
cdata->inc_py_refs();
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -315,12 +315,19 @@ private:
|
|||
class EXPCL_PANDA CData : public CycleData {
|
||||
public:
|
||||
INLINE CData();
|
||||
INLINE CData(const CData ©);
|
||||
CData(const CData ©);
|
||||
virtual ~CData();
|
||||
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
void inc_py_refs();
|
||||
void dec_py_refs();
|
||||
#endif
|
||||
|
||||
void write_up_list(const Up &up_list,
|
||||
BamWriter *manager, Datagram &dg) const;
|
||||
void write_down_list(const Down &down_list,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
// Description: Returns the Panda Thread object associated with this
|
||||
// particular PStatThread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *PStatThread::
|
||||
Thread *PStatThread::
|
||||
get_thread() const {
|
||||
return _client->get_thread_object(_index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,10 @@
|
|||
nodePointerTo.h nodePointerTo.I \
|
||||
pipeline.h pipeline.I \
|
||||
pipelineCycler.h pipelineCycler.I \
|
||||
pipelineCyclerBase.h pipelineCyclerBase.I \
|
||||
pipelineCyclerBase.h \
|
||||
pipelineCyclerDummyImpl.h pipelineCyclerDummyImpl.I \
|
||||
pipelineCyclerTrivialImpl.h pipelineCyclerTrivialImpl.I \
|
||||
pipelineCyclerTrueImpl.h pipelineCyclerTrueImpl.I \
|
||||
pta_double.h \
|
||||
pta_float.h pta_int.h \
|
||||
string_utils.I string_utils.N string_utils.h \
|
||||
|
|
@ -88,7 +91,9 @@
|
|||
nodePointerTo.cxx \
|
||||
pipeline.cxx \
|
||||
pipelineCycler.cxx \
|
||||
pipelineCyclerBase.cxx \
|
||||
pipelineCyclerDummyImpl.cxx \
|
||||
pipelineCyclerTrivialImpl.cxx \
|
||||
pipelineCyclerTrueImpl.cxx \
|
||||
pta_double.cxx pta_float.cxx \
|
||||
pta_int.cxx pta_ushort.cxx \
|
||||
string_utils.cxx timedCycle.cxx typedWritable.cxx \
|
||||
|
|
@ -138,7 +143,10 @@
|
|||
nodePointerTo.h nodePointerTo.I \
|
||||
pipeline.h pipeline.I \
|
||||
pipelineCycler.h pipelineCycler.I \
|
||||
pipelineCyclerBase.h pipelineCyclerBase.I \
|
||||
pipelineCyclerBase.h \
|
||||
pipelineCyclerDummyImpl.h pipelineCyclerDummyImpl.I \
|
||||
pipelineCyclerTrivialImpl.h pipelineCyclerTrivialImpl.I \
|
||||
pipelineCyclerTrueImpl.h pipelineCyclerTrueImpl.I \
|
||||
pta_double.h \
|
||||
pta_float.h pta_int.h pta_ushort.h \
|
||||
string_utils.I \
|
||||
|
|
|
|||
|
|
@ -32,11 +32,10 @@
|
|||
#include "pset.h"
|
||||
#include "pmap.h"
|
||||
#include "dcast.h"
|
||||
#include "pipelineCyclerBase.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
struct PipelineCyclerBase;
|
||||
|
||||
|
||||
// A handy macro for reading PointerToArrays.
|
||||
#define READ_PTA(Manager, source, Read_func, array) \
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@
|
|||
#include "pset.h"
|
||||
#include "pmap.h"
|
||||
#include "vector_int.h"
|
||||
#include "pipelineCyclerBase.h"
|
||||
|
||||
struct PipelineCyclerBase;
|
||||
|
||||
// A handy macro for writing PointerToArrays.
|
||||
#define WRITE_PTA(Manager, dest, Write_func, array) \
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pipeline.h"
|
||||
#include "pipelineCyclerTrueImpl.h"
|
||||
|
||||
Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
|
||||
|
||||
|
|
@ -29,26 +30,100 @@ Pipeline::
|
|||
Pipeline(const string &name) :
|
||||
Namable(name)
|
||||
{
|
||||
_num_stages = 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Pipeline::
|
||||
~Pipeline() {
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
nassertv(_cyclers.empty());
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::cycle
|
||||
// Access: Public, Virtual
|
||||
// Access: Public
|
||||
// Description: Flows all the pipeline data down to the next stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
cycle() {
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
Cyclers::iterator ci;
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->cycle();
|
||||
}
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::set_num_stages
|
||||
// Access: Public
|
||||
// Description: Specifies the number of stages required for the
|
||||
// pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
set_num_stages(int num_stages) {
|
||||
nassertv(num_stages >= 1);
|
||||
if (num_stages != _num_stages) {
|
||||
_num_stages = num_stages;
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
Cyclers::iterator ci;
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->set_num_stages(num_stages);
|
||||
}
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::get_num_stages
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages required for the
|
||||
// pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Pipeline::
|
||||
get_num_stages() const {
|
||||
return _num_stages;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::add_cycler
|
||||
// Access: Public
|
||||
// Description: Adds the indicated cycler to the list of cyclers
|
||||
// associated with the pipeline. This method only
|
||||
// exists when true pipelining is configured on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
add_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
bool inserted = _cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
}
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::remove_cycler
|
||||
// Access: Public
|
||||
// Description: Removes the indicated cycler from the list of cyclers
|
||||
// associated with the pipeline. This method only
|
||||
// exists when true pipelining is configured on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
Cyclers::iterator ci = _cyclers.find(cycler);
|
||||
nassertv(ci != _cyclers.end());
|
||||
_cyclers.erase(ci);
|
||||
}
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::make_render_pipeline
|
||||
// Access: Private, Static
|
||||
|
|
@ -59,4 +134,3 @@ make_render_pipeline() {
|
|||
nassertv(_render_pipeline == (Pipeline *)NULL);
|
||||
_render_pipeline = new Pipeline("render");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
#include "namable.h"
|
||||
#include "pset.h"
|
||||
|
||||
class PipelineCyclerTrueImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : Pipeline
|
||||
|
|
@ -38,15 +41,30 @@
|
|||
class EXPCL_PANDA Pipeline : public Namable {
|
||||
public:
|
||||
Pipeline(const string &name);
|
||||
virtual ~Pipeline();
|
||||
~Pipeline();
|
||||
|
||||
INLINE static Pipeline *get_render_pipeline();
|
||||
|
||||
virtual void cycle();
|
||||
void cycle();
|
||||
|
||||
void set_num_stages(int num_stages);
|
||||
int get_num_stages() const;
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
void add_cycler(PipelineCyclerTrueImpl *cycler);
|
||||
void remove_cycler(PipelineCyclerTrueImpl *cycler);
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
|
||||
private:
|
||||
int _num_stages;
|
||||
|
||||
static void make_render_pipeline();
|
||||
static Pipeline *_render_pipeline;
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
typedef pset<PipelineCyclerTrueImpl *> Cyclers;
|
||||
Cyclers _cyclers;
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
};
|
||||
|
||||
#include "pipeline.I"
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@
|
|||
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
// The following implementations are to support compiled-in pipeline
|
||||
// sanity checks.
|
||||
// The following implementations are to support the
|
||||
// PipelineCyclerDummyImpl or the PipelineCyclerTrueImpl.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Constructor (sanity-check)
|
||||
// Function: PipelineCycler::Constructor (dummy or true)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -34,20 +34,19 @@ PipelineCycler(Pipeline *pipeline) :
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Copy Constructor (sanity-check)
|
||||
// Function: PipelineCycler::Copy Constructor (dummy or true)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE PipelineCycler<CycleDataType>::
|
||||
PipelineCycler(const PipelineCycler<CycleDataType> ©) :
|
||||
// In the DO_PIPELINING copy constructor, the pointer value is ignored.
|
||||
PipelineCyclerBase(NULL, copy)
|
||||
PipelineCyclerBase(copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Copy Assignment (sanity-check)
|
||||
// Function: PipelineCycler::Copy Assignment (dummy or true)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -58,7 +57,7 @@ operator = (const PipelineCycler<CycleDataType> ©) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read (sanity-check)
|
||||
// Function: PipelineCycler::read (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -69,7 +68,7 @@ read() const {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write (sanity-check)
|
||||
// Function: PipelineCycler::write (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -80,7 +79,7 @@ write() {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::elevate_read (sanity-check)
|
||||
// Function: PipelineCycler::elevate_read (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::elevate_read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -91,7 +90,7 @@ elevate_read(const CycleDataType *pointer) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write_stage (sanity-check)
|
||||
// Function: PipelineCycler::write_stage (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -102,7 +101,7 @@ write_stage(int n) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::cheat (sanity-check)
|
||||
// Function: PipelineCycler::cheat (dummy or true)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
|
|
@ -142,7 +141,7 @@ PipelineCycler(Pipeline *pipeline) :
|
|||
template<class CycleDataType>
|
||||
INLINE PipelineCycler<CycleDataType>::
|
||||
PipelineCycler(const PipelineCycler<CycleDataType> ©) :
|
||||
PipelineCyclerBase(&_typed_data, copy),
|
||||
PipelineCyclerBase(&_typed_data),
|
||||
_typed_data(copy._typed_data)
|
||||
{
|
||||
}
|
||||
|
|
@ -155,7 +154,6 @@ PipelineCycler(const PipelineCycler<CycleDataType> ©) :
|
|||
template<class CycleDataType>
|
||||
INLINE void PipelineCycler<CycleDataType>::
|
||||
operator = (const PipelineCycler<CycleDataType> ©) {
|
||||
PipelineCyclerBase::operator = (copy);
|
||||
_typed_data = copy._typed_data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,527 +0,0 @@
|
|||
// Filename: pipelineCyclerBase.I
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
// The following implementations are to support compiled-in pipeline
|
||||
// sanity checks.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Constructor (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerBase::
|
||||
PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline) :
|
||||
_data(initial_data),
|
||||
_pipeline(pipeline),
|
||||
_read_count(0),
|
||||
_write_count(0)
|
||||
{
|
||||
if (_pipeline == (Pipeline *)NULL) {
|
||||
_pipeline = Pipeline::get_render_pipeline();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Copy Constructor (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerBase::
|
||||
PipelineCyclerBase(CycleData *, const PipelineCyclerBase ©) :
|
||||
_data(copy._data->make_copy()),
|
||||
_pipeline(copy._pipeline),
|
||||
_read_count(0),
|
||||
_write_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Copy Assignment (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
operator = (const PipelineCyclerBase ©) {
|
||||
nassertv(_read_count == 0 && _write_count == 0);
|
||||
_data = copy._data->make_copy();
|
||||
_pipeline = copy._pipeline;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Destructor (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerBase::
|
||||
~PipelineCyclerBase() {
|
||||
nassertv(_read_count == 0 && _write_count == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
//
|
||||
// There should be no outstanding write pointers on the
|
||||
// data when this function is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerBase::
|
||||
read() const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
((PipelineCyclerBase *)this)->_read_count++;
|
||||
|
||||
// It's not an error to grab a read pointer while someone else holds
|
||||
// a read or a write pointer.
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::increment_read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
increment_read(const CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_read_count > 0);
|
||||
((PipelineCyclerBase *)this)->_read_count++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::release_read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
release_read(const CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_read_count > 0);
|
||||
((PipelineCyclerBase *)this)->_read_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::write (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagate to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
write() {
|
||||
_write_count++;
|
||||
|
||||
// It's an error to grab a write pointer while someone else holds a
|
||||
// read pointer, because doing so may invalidate the read pointer.
|
||||
nassertr(_read_count == 0, _data);
|
||||
|
||||
// It's not an error to do this while someone else holds a write
|
||||
// pointer, however.
|
||||
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::elevate_read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
elevate_read(const CycleData *pointer) {
|
||||
release_read(pointer);
|
||||
return write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::release_write (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
release_write(CycleData *pointer) {
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_write_count > 0);
|
||||
_write_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::get_num_stages (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerBase::
|
||||
get_num_stages() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::is_stage_unique (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth stage is a different pointer
|
||||
// than the previous stage, or false if its pointer is
|
||||
// shared with the previous one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PipelineCyclerBase::
|
||||
is_stage_unique(int n) const {
|
||||
nassertr(n == 0, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::write_stage (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
write_stage(int n) {
|
||||
nassertr(n == 0, (CycleData *)NULL);
|
||||
_write_count++;
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::release_write_stage (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
release_write_stage(int n, CycleData *pointer) {
|
||||
nassertv(n == 0 && pointer == _data);
|
||||
nassertv(_write_count > 0);
|
||||
_write_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::cheat (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
cheat() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::get_read_count (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerBase::
|
||||
get_read_count() const {
|
||||
return _read_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::get_write_count (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerBase::
|
||||
get_write_count() const {
|
||||
return _write_count;
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// The following implementations are provided for when pipelining is
|
||||
// not compiled in. They are trivial functions that do as little as
|
||||
// possible.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerBase::
|
||||
PipelineCyclerBase(CycleData *initial_data, Pipeline *) {
|
||||
// In the trivial implementation, a derived class (the
|
||||
// PipelineCycler template class) stores the CycleData object
|
||||
// directly within itself, and since we have no data members or
|
||||
// virtual functions, we get away with assuming the pointer is the
|
||||
// same as the 'this' pointer.
|
||||
|
||||
// If this turns out not to be true on a particular platform, we
|
||||
// will have to store the pointer in this class, for a little bit of
|
||||
// extra overhead.
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
nassertv(initial_data == (CycleData *)this);
|
||||
#else
|
||||
_data = initial_data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerBase::
|
||||
PipelineCyclerBase(CycleData *initial_data, const PipelineCyclerBase &) {
|
||||
// The copy constructor for the DO_PIPELINING case is
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
nassertv(initial_data == (CycleData *)this);
|
||||
#else
|
||||
_data = initial_data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Copy Assignment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
operator = (const PipelineCyclerBase &) {
|
||||
// We don't reassign the _data pointer here; we assume it was set
|
||||
// correctly previously.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerBase::
|
||||
~PipelineCyclerBase() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::read (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerBase::
|
||||
read() const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (const CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::increment_read (trivial)
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
increment_read(const CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::release_read (trivial)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
release_read(const CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::write (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagate to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
write() {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::elevate_read (trivial)
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
elevate_read(const CycleData *) {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::release_write (trivial)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
release_write(CycleData *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::get_num_stages (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerBase::
|
||||
get_num_stages() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::is_stage_unique (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth stage is a different pointer
|
||||
// than the previous stage, or false if its pointer is
|
||||
// shared with the previous one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PipelineCyclerBase::
|
||||
is_stage_unique(int n) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::write_stage (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
write_stage(int) {
|
||||
return (CycleData *)this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::release_write_stage (trivial)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerBase::
|
||||
release_write_stage(int, CycleData *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::cheat (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerBase::
|
||||
cheat() const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::get_read_count (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerBase::
|
||||
get_read_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerBase::get_write_count (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerBase::
|
||||
get_write_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -21,68 +21,32 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipeline.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerBase
|
||||
// Description : This is the non-template part of the implementation
|
||||
// of PipelineCycler. See PipelineCycler.
|
||||
//
|
||||
// We define this as a struct instead of a class to
|
||||
// guarantee byte placement within the object, so that
|
||||
// (particularly for the trivial implementation) the
|
||||
// inherited struct's data is likely to be placed by the
|
||||
// compiler at the "this" pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
struct EXPCL_PANDA PipelineCyclerBase {
|
||||
public:
|
||||
INLINE PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline = NULL);
|
||||
INLINE PipelineCyclerBase(CycleData *initial_data, const PipelineCyclerBase ©);
|
||||
INLINE void operator = (const PipelineCyclerBase ©);
|
||||
INLINE ~PipelineCyclerBase();
|
||||
|
||||
INLINE const CycleData *read() const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
||||
INLINE CycleData *write();
|
||||
INLINE CycleData *elevate_read(const CycleData *pointer);
|
||||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE bool is_stage_unique(int n) const;
|
||||
INLINE CycleData *write_stage(int n);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
// This private data is only stored here if we have pipelining
|
||||
// compiled in. Actually, this particular data is only used for
|
||||
// sanity checking the pipelining code; it doesn't do anything
|
||||
// useful.
|
||||
private:
|
||||
PT(CycleData) _data;
|
||||
Pipeline *_pipeline;
|
||||
short _read_count, _write_count;
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// In a trivial implementation, we only need to store the CycleData
|
||||
// pointer. Actually, we don't even need to do that, if we're lucky
|
||||
// and the compiler doesn't do anything funny with the struct
|
||||
// layout.
|
||||
#ifndef SIMPLE_STRUCT_POINTERS
|
||||
CycleData *_data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
#ifdef HAVE_THREADS
|
||||
|
||||
// With DO_PIPELINING and threads available, we want the true cycler
|
||||
// implementation.
|
||||
#include "pipelineCyclerTrueImpl.h"
|
||||
typedef PipelineCyclerTrueImpl PipelineCyclerBase;
|
||||
|
||||
#else // HAVE_THREADS
|
||||
|
||||
// With DO_PIPELINING but no threads available, we want the dummy,
|
||||
// self-validating cycler implementation.
|
||||
#include "pipelineCyclerDummyImpl.h"
|
||||
typedef PipelineCyclerDummyImpl PipelineCyclerBase;
|
||||
|
||||
#endif // HAVE_THREADS
|
||||
|
||||
#else // DO_PIPELINING
|
||||
|
||||
// Without DO_PIPELINING, we only want the trivial, do-nothing
|
||||
// implementation.
|
||||
#include "pipelineCyclerTrivialImpl.h"
|
||||
typedef PipelineCyclerTrivialImpl PipelineCyclerBase;
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
};
|
||||
|
||||
#include "pipelineCyclerBase.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,275 @@
|
|||
// Filename: pipelineCyclerDummyImpl.I
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::Constructor (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerDummyImpl::
|
||||
PipelineCyclerDummyImpl(CycleData *initial_data, Pipeline *pipeline) :
|
||||
_data(initial_data),
|
||||
_pipeline(pipeline),
|
||||
_read_count(0),
|
||||
_write_count(0)
|
||||
{
|
||||
if (_pipeline == (Pipeline *)NULL) {
|
||||
_pipeline = Pipeline::get_render_pipeline();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::Copy Constructor (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerDummyImpl::
|
||||
PipelineCyclerDummyImpl(const PipelineCyclerDummyImpl ©) :
|
||||
_data(copy._data->make_copy()),
|
||||
_pipeline(copy._pipeline),
|
||||
_read_count(0),
|
||||
_write_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::Copy Assignment (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
operator = (const PipelineCyclerDummyImpl ©) {
|
||||
nassertv(_read_count == 0 && _write_count == 0);
|
||||
_data = copy._data->make_copy();
|
||||
_pipeline = copy._pipeline;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::Destructor (sanity-check)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerDummyImpl::
|
||||
~PipelineCyclerDummyImpl() {
|
||||
nassertv(_read_count == 0 && _write_count == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
//
|
||||
// There should be no outstanding write pointers on the
|
||||
// data when this function is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerDummyImpl::
|
||||
read() const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count++;
|
||||
|
||||
// It's not an error to grab a read pointer while someone else holds
|
||||
// a read or a write pointer.
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::increment_read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
increment_read(const CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_read_count > 0);
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release_read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release_read(const CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_read_count > 0);
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::write (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagated to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
write() {
|
||||
_write_count++;
|
||||
|
||||
// It's an error to grab a write pointer while someone else holds a
|
||||
// read pointer, because doing so may invalidate the read pointer.
|
||||
nassertr(_read_count == 0, _data);
|
||||
|
||||
// It's not an error to do this while someone else holds a write
|
||||
// pointer, however.
|
||||
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::elevate_read (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
elevate_read(const CycleData *pointer) {
|
||||
release_read(pointer);
|
||||
return write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release_write (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release_write(CycleData *pointer) {
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_write_count > 0);
|
||||
_write_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_num_stages (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerDummyImpl::
|
||||
get_num_stages() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::is_stage_unique (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth stage is a different pointer
|
||||
// than the previous stage, or false if its pointer is
|
||||
// shared with the previous one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PipelineCyclerDummyImpl::
|
||||
is_stage_unique(int n) const {
|
||||
nassertr(n == 0, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::write_stage (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
write_stage(int n) {
|
||||
nassertr(n == 0, (CycleData *)NULL);
|
||||
_write_count++;
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release_write_stage (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release_write_stage(int n, CycleData *pointer) {
|
||||
nassertv(n == 0 && pointer == _data);
|
||||
nassertv(_write_count > 0);
|
||||
_write_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::cheat (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
cheat() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_read_count (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerDummyImpl::
|
||||
get_read_count() const {
|
||||
return _read_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_write_count (sanity-check)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerDummyImpl::
|
||||
get_write_count() const {
|
||||
return _write_count;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Filename: pipelineCyclerBase.cxx
|
||||
// Created by: drose (21Feb02)
|
||||
// Filename: pipelineCyclerDummyImpl.cxx
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
@ -16,17 +16,4 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pipelineCyclerBase.h"
|
||||
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
// The following implementations are to support compiled-in pipeline
|
||||
// sanity checks.
|
||||
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// The following implementations are provided for when pipelining is
|
||||
// not compiled in. They are trivial functions that do as little as
|
||||
// possible.
|
||||
|
||||
#endif
|
||||
#include "pipelineCyclerDummyImpl.h"
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// Filename: pipelineCyclerDummyImpl.h
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PIPELINECYCLERDUMMYIMPL_H
|
||||
#define PIPELINECYCLERDUMMYIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#if defined(DO_PIPELINING) && !defined(HAVE_THREADS)
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipeline.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerDummyImpl
|
||||
// Description : This is a simple, single-threaded-only implementation
|
||||
// of PipelineCyclerBase. It is only compiled when
|
||||
// DO_PIPELINING is defined, but threading is not
|
||||
// available, which is usually the case only in
|
||||
// development mode.
|
||||
//
|
||||
// This implmentation is similar in principle to
|
||||
// PipelineCyclerTrivialImpl, except it does basic
|
||||
// sanity checking to ensure that you use the interface
|
||||
// in a reasonable way consistent with its design (e.g.,
|
||||
// read() is balanced with release_read(), etc.).
|
||||
//
|
||||
// This is defined as a struct instead of a class,
|
||||
// mainly to be consistent with
|
||||
// PipelineCyclerTrivialImpl.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
struct EXPCL_PANDA PipelineCyclerDummyImpl {
|
||||
public:
|
||||
INLINE PipelineCyclerDummyImpl(CycleData *initial_data, Pipeline *pipeline = NULL);
|
||||
INLINE PipelineCyclerDummyImpl(const PipelineCyclerDummyImpl ©);
|
||||
INLINE void operator = (const PipelineCyclerDummyImpl ©);
|
||||
INLINE ~PipelineCyclerDummyImpl();
|
||||
|
||||
INLINE const CycleData *read() const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
||||
INLINE CycleData *write();
|
||||
INLINE CycleData *elevate_read(const CycleData *pointer);
|
||||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE bool is_stage_unique(int n) const;
|
||||
INLINE CycleData *write_stage(int n);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
||||
private:
|
||||
PT(CycleData) _data;
|
||||
Pipeline *_pipeline;
|
||||
short _read_count, _write_count;
|
||||
};
|
||||
|
||||
#include "pipelineCyclerDummyImpl.I"
|
||||
|
||||
#endif // DO_PIPELINING && !HAVE_THREADS
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
// Filename: pipelineCyclerTrivialImpl.I
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerTrivialImpl::
|
||||
PipelineCyclerTrivialImpl(CycleData *initial_data, Pipeline *) {
|
||||
// In the trivial implementation, a derived class (the
|
||||
// PipelineCycler template class) stores the CycleData object
|
||||
// directly within itself, and since we have no data members or
|
||||
// virtual functions, we get away with assuming the pointer is the
|
||||
// same as the 'this' pointer.
|
||||
|
||||
// If this turns out not to be true on a particular platform, we
|
||||
// will have to store the pointer in this class, for a little bit of
|
||||
// extra overhead.
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
nassertv(initial_data == (CycleData *)this);
|
||||
#else
|
||||
_data = initial_data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::Copy Constructor (trivial)
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerTrivialImpl::
|
||||
PipelineCyclerTrivialImpl(const PipelineCyclerTrivialImpl &) {
|
||||
// The copy constructor for the PipelineCyclerTrivialImpl case
|
||||
// doesn't work. Don't try to use it. The PipelineCycler template
|
||||
// class is #ifdeffed appropriately to call the normal constructor
|
||||
// instead.
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::Copy Assignment (trivial)
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
operator = (const PipelineCyclerTrivialImpl &) {
|
||||
// The copy assignment operator for the PipelineCyclerTrivialImpl
|
||||
// case doesn't work. Don't try to use it. The PipelineCycler
|
||||
// template class is #ifdeffed appropriately not to call this
|
||||
// method.
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerTrivialImpl::
|
||||
~PipelineCyclerTrivialImpl() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::read (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrivialImpl::
|
||||
read() const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (const CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::increment_read (trivial)
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
increment_read(const CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release_read (trivial)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release_read(const CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::write (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagated to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
write() {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::elevate_read (trivial)
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
elevate_read(const CycleData *) {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release_write (trivial)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release_write(CycleData *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_num_stages (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrivialImpl::
|
||||
get_num_stages() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::is_stage_unique (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth stage is a different pointer
|
||||
// than the previous stage, or false if its pointer is
|
||||
// shared with the previous one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PipelineCyclerTrivialImpl::
|
||||
is_stage_unique(int n) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::write_stage (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
write_stage(int) {
|
||||
return (CycleData *)this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release_write_stage (trivial)
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release_write_stage(int, CycleData *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::cheat (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
cheat() const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_read_count (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrivialImpl::
|
||||
get_read_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_write_count (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrivialImpl::
|
||||
get_write_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: pipelineCyclerTrivialImpl.cxx
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pipelineCyclerTrivialImpl.h"
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
// Filename: pipelineCyclerTrivialImpl.h
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PIPELINECYCLERTRIVIALIMPL_H
|
||||
#define PIPELINECYCLERTRIVIALIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifndef DO_PIPELINING
|
||||
|
||||
class CycleData;
|
||||
class Pipeline;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerTrivialImpl
|
||||
// Description : This is the trivial, non-threaded implementation of
|
||||
// PipelineCyclerBase. It is only compiled when
|
||||
// DO_PIPELINING is not defined (which usually implies
|
||||
// that threading is not available).
|
||||
//
|
||||
// This implementation is designed to do as little as
|
||||
// possible, and to compile to nothing, or almost
|
||||
// nothing. It doesn't actually support pipelining in
|
||||
// any way. It doesn't even perform any sanity checks
|
||||
// to speak of. It's designed for a strictly
|
||||
// single-threaded application, and its purpose is to be
|
||||
// as low-overhead as possible.
|
||||
//
|
||||
// We define this as a struct instead of a class to
|
||||
// emphasize the importance of byte placement within the
|
||||
// object, so that the inherited struct's data is likely
|
||||
// to be placed by the compiler at the "this" pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
struct EXPCL_PANDA PipelineCyclerTrivialImpl {
|
||||
public:
|
||||
INLINE PipelineCyclerTrivialImpl(CycleData *initial_data, Pipeline *pipeline = NULL);
|
||||
private:
|
||||
INLINE PipelineCyclerTrivialImpl(const PipelineCyclerTrivialImpl ©);
|
||||
INLINE void operator = (const PipelineCyclerTrivialImpl ©);
|
||||
public:
|
||||
INLINE ~PipelineCyclerTrivialImpl();
|
||||
|
||||
INLINE const CycleData *read() const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
||||
INLINE CycleData *write();
|
||||
INLINE CycleData *elevate_read(const CycleData *pointer);
|
||||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE bool is_stage_unique(int n) const;
|
||||
INLINE CycleData *write_stage(int n);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
||||
// In a trivial implementation, we only need to store the CycleData
|
||||
// pointer. Actually, we don't even need to do that, if we're lucky
|
||||
// and the compiler doesn't do anything funny with the struct
|
||||
// layout.
|
||||
#ifndef SIMPLE_STRUCT_POINTERS
|
||||
CycleData *_data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
};
|
||||
|
||||
#include "pipelineCyclerTrivialImpl.I"
|
||||
|
||||
#endif // !DO_PIPELINING
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
// Filename: pipelineCyclerTrueImpl.I
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::read
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
//
|
||||
// There should be no outstanding write pointers on the
|
||||
// data when this function is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrueImpl::
|
||||
read() const {
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
return _data[pipeline_stage]._cycle_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::increment_read
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
increment_read(const CycleData *pointer) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release_read
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_read(const CycleData *pointer) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::write
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagated to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
write() {
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
return _data[pipeline_stage]._cycle_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::elevate_read
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
elevate_read(const CycleData *pointer) {
|
||||
return (CycleData *)pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release_write
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_write(CycleData *pointer) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_num_stages
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_num_stages() {
|
||||
return _num_stages;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::is_stage_unique
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth stage is a different pointer
|
||||
// than the previous stage, or false if its pointer is
|
||||
// shared with the previous one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PipelineCyclerTrueImpl::
|
||||
is_stage_unique(int n) const {
|
||||
nassertr(n >= 0 && n < _num_stages, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::write_stage
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
write_stage(int n) {
|
||||
nassertr(n >= 0 && n < _num_stages, (CycleData *)NULL);
|
||||
return _data[n]._cycle_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release_write_stage
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_write_stage(int n, CycleData *pointer) {
|
||||
nassertv(n >= 0 && n < _num_stages);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cheat
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
cheat() const {
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
return _data[pipeline_stage]._cycle_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_read_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_read_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_write_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_write_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
// Filename: pipelineCyclerTrueImpl.cxx
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pipelineCyclerTrueImpl.h"
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
|
||||
#include "pipeline.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PipelineCyclerTrueImpl::
|
||||
PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
||||
_pipeline(pipeline)
|
||||
{
|
||||
if (_pipeline == (Pipeline *)NULL) {
|
||||
_pipeline = Pipeline::get_render_pipeline();
|
||||
}
|
||||
_pipeline->add_cycler(this);
|
||||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
_data = new StageData[_num_stages];
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i]._cycle_data = initial_data->make_copy();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PipelineCyclerTrueImpl::
|
||||
PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
||||
_pipeline(copy._pipeline)
|
||||
{
|
||||
_pipeline->add_cycler(this);
|
||||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
_data = new StageData[_num_stages];
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i]._cycle_data = copy._data[i]._cycle_data->make_copy();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
operator = (const PipelineCyclerTrueImpl ©) {
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i]._cycle_data = copy._data[i]._cycle_data->make_copy();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PipelineCyclerTrueImpl::
|
||||
~PipelineCyclerTrueImpl() {
|
||||
_pipeline->remove_cycler(this);
|
||||
|
||||
delete[] _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cycle
|
||||
// Access: Private
|
||||
// Description: Cycles the data between frames. This is only called
|
||||
// from Pipeline::cycle().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
cycle() {
|
||||
for (int i = _num_stages - 1; i > 0; --i) {
|
||||
_data[i] = _data[i - 1];
|
||||
}
|
||||
_data[0]._cycle_data = _data[0]._cycle_data->make_copy();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::set_num_stages
|
||||
// Access: Private
|
||||
// Description: Changes the number of stages in the cycler. This is
|
||||
// only called from Pipeline::set_num_stages();
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
set_num_stages(int num_stages) {
|
||||
if (num_stages <= _num_stages) {
|
||||
// Don't bother to reallocate the array.
|
||||
for (int i = _num_stages; i < num_stages; ++i) {
|
||||
_data[i]._cycle_data.clear();
|
||||
}
|
||||
|
||||
_num_stages = num_stages;
|
||||
|
||||
|
||||
} else {
|
||||
// Increase the array.
|
||||
StageData *new_data = new StageData[num_stages];
|
||||
int i;
|
||||
for (i = 0; i < _num_stages; ++i) {
|
||||
new_data[i] = _data[i];
|
||||
}
|
||||
for (i = _num_stages; i < num_stages; ++i) {
|
||||
new_data[i]._cycle_data = _data[_num_stages - 1]._cycle_data->make_copy();
|
||||
}
|
||||
delete[] _data;
|
||||
|
||||
_num_stages = num_stages;
|
||||
_data = new_data;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// Filename: pipelineCyclerTrueImpl.h
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PIPELINECYCLERTRUEIMPL_H
|
||||
#define PIPELINECYCLERTRUEIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pointerTo.h"
|
||||
#include "thread.h"
|
||||
|
||||
class Pipeline;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerTrueImpl
|
||||
// Description : This is the true, threaded implementation of
|
||||
// PipelineCyclerBase. It is only compiled when
|
||||
// threading is available and DO_PIPELINING is defined.
|
||||
//
|
||||
// This implementation is designed to do the actual work
|
||||
// of cycling the data through a pipeline, and returning
|
||||
// the actual CycleData appropriate to the current
|
||||
// thread's pipeline stage.
|
||||
//
|
||||
// This is defined as a struct instead of a class,
|
||||
// mainly to be consistent with
|
||||
// PipelineCyclerTrivialImpl.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
struct EXPCL_PANDA PipelineCyclerTrueImpl {
|
||||
public:
|
||||
PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline = NULL);
|
||||
PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©);
|
||||
void operator = (const PipelineCyclerTrueImpl ©);
|
||||
~PipelineCyclerTrueImpl();
|
||||
|
||||
INLINE const CycleData *read() const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
||||
INLINE CycleData *write();
|
||||
INLINE CycleData *elevate_read(const CycleData *pointer);
|
||||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE bool is_stage_unique(int n) const;
|
||||
INLINE CycleData *write_stage(int n);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
||||
private:
|
||||
void cycle();
|
||||
void set_num_stages(int num_stages);
|
||||
|
||||
private:
|
||||
Pipeline *_pipeline;
|
||||
|
||||
class StageData {
|
||||
public:
|
||||
PT(CycleData) _cycle_data;
|
||||
};
|
||||
|
||||
StageData *_data;
|
||||
int _num_stages;
|
||||
|
||||
friend class Pipeline;
|
||||
};
|
||||
|
||||
#include "pipelineCyclerTrueImpl.I"
|
||||
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -6,7 +6,9 @@
|
|||
#include "nodePointerTo.cxx"
|
||||
#include "pipeline.cxx"
|
||||
#include "pipelineCycler.cxx"
|
||||
#include "pipelineCyclerBase.cxx"
|
||||
#include "pipelineCyclerDummyImpl.cxx"
|
||||
#include "pipelineCyclerTrivialImpl.cxx"
|
||||
#include "pipelineCyclerTrueImpl.cxx"
|
||||
#include "pta_double.cxx"
|
||||
#include "pta_float.cxx"
|
||||
#include "pta_int.cxx"
|
||||
|
|
|
|||
Loading…
Reference in New Issue