open_toontown_panda3d/panda/src/pgraph/renderState.h

356 lines
12 KiB
C++

// Filename: renderState.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef RENDERSTATE_H
#define RENDERSTATE_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "nodeCachedReferenceCount.h"
#include "pointerTo.h"
#include "pvector.h"
#include "updateSeq.h"
#include "pStatCollector.h"
#include "renderModeAttrib.h"
#include "texMatrixAttrib.h"
#include "geomMunger.h"
#include "weakPointerTo.h"
#include "lightReMutex.h"
#include "lightMutex.h"
#include "deletedChain.h"
#include "simpleHashMap.h"
#include "cacheStats.h"
#include "renderAttribRegistry.h"
class GraphicsStateGuardianBase;
class FactoryParams;
class ShaderAttrib;
////////////////////////////////////////////////////////////////////
// Class : RenderState
// Description : This represents a unique collection of RenderAttrib
// objects that correspond to a particular renderable
// state.
//
// You should not attempt to create or modify a
// RenderState object directly. Instead, call one of
// the make() functions to create one for you. And
// instead of modifying a RenderState object, create a
// new one.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_PGRAPH RenderState : public NodeCachedReferenceCount {
protected:
RenderState();
private:
RenderState(const RenderState &copy);
void operator = (const RenderState &copy);
public:
virtual ~RenderState();
ALLOC_DELETED_CHAIN(RenderState);
typedef RenderAttribRegistry::SlotMask SlotMask;
PUBLISHED:
bool operator < (const RenderState &other) const;
int compare_sort(const RenderState &other) const;
size_t get_hash() const;
INLINE bool is_empty() const;
INLINE bool has_cull_callback() const;
bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
static CPT(RenderState) make_empty();
static CPT(RenderState) make_full_default();
static CPT(RenderState) make(const RenderAttrib *attrib, int override = 0);
static CPT(RenderState) make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2, int override = 0);
static CPT(RenderState) make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2,
const RenderAttrib *attrib3, int override = 0);
static CPT(RenderState) make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2,
const RenderAttrib *attrib3,
const RenderAttrib *attrib4, int override = 0);
static CPT(RenderState) make(const RenderAttrib * const *attrib,
int num_attribs, int override = 0);
CPT(RenderState) compose(const RenderState *other) const;
CPT(RenderState) invert_compose(const RenderState *other) const;
CPT(RenderState) add_attrib(const RenderAttrib *attrib, int override = 0) const;
CPT(RenderState) set_attrib(const RenderAttrib *attrib) const;
CPT(RenderState) set_attrib(const RenderAttrib *attrib, int override) const;
INLINE CPT(RenderState) remove_attrib(TypeHandle type) const;
CPT(RenderState) remove_attrib(int slot) const;
CPT(RenderState) adjust_all_priorities(int adjustment) const;
INLINE bool has_attrib(TypeHandle type) const;
INLINE bool has_attrib(int slot) const;
INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
INLINE const RenderAttrib *get_attrib(int slot) const;
INLINE const RenderAttrib *get_attrib_def(int slot) const;
INLINE int get_override(TypeHandle type) const;
INLINE int get_override(int slot) const;
INLINE CPT(RenderState) get_unique() const;
bool unref() const;
INLINE void cache_ref() const;
INLINE bool cache_unref() const;
INLINE void node_ref() const;
INLINE bool node_unref() const;
INLINE int get_composition_cache_num_entries() const;
INLINE int get_invert_composition_cache_num_entries() const;
INLINE int get_composition_cache_size() const;
INLINE const RenderState *get_composition_cache_source(int n) const;
INLINE const RenderState *get_composition_cache_result(int n) const;
INLINE int get_invert_composition_cache_size() const;
INLINE const RenderState *get_invert_composition_cache_source(int n) const;
INLINE const RenderState *get_invert_composition_cache_result(int n) const;
#ifdef HAVE_PYTHON
PyObject *get_composition_cache() const;
PyObject *get_invert_composition_cache() const;
#endif // HAVE_PYTHON
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
static int get_max_priority();
static int get_num_states();
static int get_num_unused_states();
static int clear_cache();
static void clear_munger_cache();
static void list_cycles(ostream &out);
static void list_states(ostream &out);
static bool validate_states();
#ifdef HAVE_PYTHON
static PyObject *get_states();
#endif // HAVE_PYTHON
PUBLISHED:
// These methods are intended for use by low-level code, but they're
// also handy enough to expose to high-level users.
INLINE int get_draw_order() const;
INLINE int get_bin_index() const;
int get_geom_rendering(int geom_rendering) const;
const ShaderAttrib *get_generated_shader() const;
public:
static void bin_removed(int bin_index);
INLINE static void flush_level();
private:
bool validate_filled_slots() const;
INLINE bool do_cache_unref() const;
INLINE bool do_node_unref() const;
class CompositionCycleDescEntry {
public:
INLINE CompositionCycleDescEntry(const RenderState *obj,
const RenderState *result,
bool inverted);
const RenderState *_obj;
const RenderState *_result;
bool _inverted;
};
typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
static CPT(RenderState) return_new(RenderState *state);
static CPT(RenderState) return_unique(RenderState *state);
CPT(RenderState) do_compose(const RenderState *other) const;
CPT(RenderState) do_invert_compose(const RenderState *other) const;
static bool r_detect_cycles(const RenderState *start_state,
const RenderState *current_state,
int length, UpdateSeq this_seq,
CompositionCycleDesc *cycle_desc);
static bool r_detect_reverse_cycles(const RenderState *start_state,
const RenderState *current_state,
int length, UpdateSeq this_seq,
CompositionCycleDesc *cycle_desc);
void release_new();
void remove_cache_pointers();
void determine_bin_index();
void determine_cull_callback();
void fill_default();
INLINE void set_destructing();
INLINE bool is_destructing() const;
INLINE void consider_update_pstats(int old_referenced_bits) const;
static void update_pstats(int old_referenced_bits, int new_referenced_bits);
public:
static void init_states();
private:
// This mutex protects _states. It also protects any modification
// to the cache, which is encoded in _composition_cache and
// _invert_composition_cache.
static LightReMutex *_states_lock;
typedef phash_set<const RenderState *, indirect_less_hash<const RenderState *> > States;
static States *_states;
static CPT(RenderState) _empty_state;
static CPT(RenderState) _full_default_state;
// This iterator records the entry corresponding to this RenderState
// object in the above global set. We keep the iterator around so
// we can remove it when the RenderState destructs.
States::iterator _saved_entry;
// This data structure manages the job of caching the composition of
// two RenderStates. It's complicated because we have to be sure to
// remove the entry if *either* of the input RenderStates destructs.
// To implement this, we always record Composition entries in pairs,
// one in each of the two involved RenderState objects.
class Composition {
public:
INLINE Composition();
INLINE Composition(const Composition &copy);
// _result is reference counted if and only if it is not the same
// pointer as this.
const RenderState *_result;
};
// The first element of the map is the object we compose with. This
// is not reference counted within this map; instead we store a
// companion pointer in the other object, and remove the references
// explicitly when either object destructs.
typedef SimpleHashMap<const RenderState *, Composition, pointer_hash> CompositionCache;
CompositionCache _composition_cache;
CompositionCache _invert_composition_cache;
// This is here to provide a quick cache of GSG + RenderState ->
// GeomMunger for the cull phase. It is here because it is faster
// to look up the GSG in the RenderState pointer than vice-versa,
// since there are likely to be far fewer GSG's than RenderStates.
// The code to manage this map lives in
// GraphicsStateGuardian::get_geom_munger().
typedef pmap<WCPT(GraphicsStateGuardianBase), PT(GeomMunger) > Mungers;
Mungers _mungers;
Mungers::const_iterator _last_mi;
// This is used to mark nodes as we visit them to detect cycles.
UpdateSeq _cycle_detect;
static UpdateSeq _last_cycle_detect;
static PStatCollector _cache_update_pcollector;
static PStatCollector _state_compose_pcollector;
static PStatCollector _state_invert_pcollector;
static PStatCollector _node_counter;
static PStatCollector _cache_counter;
private:
// This is the actual data within the RenderState: a set of
// max_slots RenderAttribs.
class Attribute {
public:
INLINE Attribute(const RenderAttrib *attrib, int override);
INLINE Attribute(int override = 0);
INLINE Attribute(const Attribute &copy);
INLINE void operator = (const Attribute &copy);
INLINE void set(const RenderAttrib *attrib, int override);
INLINE int compare_to(const Attribute &other) const;
CPT(RenderAttrib) _attrib;
int _override;
};
Attribute *_attributes;
// We also store a bitmask of the non-NULL attributes in the above
// array. This is redundant, but it is a useful cache.
SlotMask _filled_slots;
// We cache the index to the associated CullBin, if there happens to
// be a CullBinAttrib in the state.
int _bin_index;
int _draw_order;
// If this state contains an "auto" ShaderAttrib, then an explicit
// ShaderAttrib will be synthesized by the runtime and stored here.
// I can't declare this as a ShaderAttrib because that would create
// a circular include-file dependency problem. Aaargh.
CPT(RenderAttrib) _generated_shader;
enum Flags {
F_checked_bin_index = 0x000001,
F_checked_cull_callback = 0x000002,
F_has_cull_callback = 0x000004,
F_is_destructing = 0x000008,
};
unsigned int _flags;
vector_int *_read_overrides; // Only used during bam reading.
// This mutex protects _flags, and all of the above computed values.
LightMutex _lock;
static CacheStats _cache_stats;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
virtual void finalize(BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
NodeCachedReferenceCount::init_type();
register_type(_type_handle, "RenderState",
NodeCachedReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
friend class GraphicsStateGuardian;
friend class RenderAttribRegistry;
};
INLINE ostream &operator << (ostream &out, const RenderState &state) {
state.output(out);
return out;
}
#include "renderState.I"
#endif