diff --git a/panda/src/dxgsg8/dxGeomMunger8.I b/panda/src/dxgsg8/dxGeomMunger8.I index 88de8dd080..28d0d78a75 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.I +++ b/panda/src/dxgsg8/dxGeomMunger8.I @@ -27,3 +27,15 @@ DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) : ColorMunger(gsg, state, 1, qpGeomVertexDataType::NT_packed_argb) { } + +//////////////////////////////////////////////////////////////////// +// Function: DXGeomMunger8::operator new +// Access: Public +// Description: Calls up to do_operator_new() to implement the +// low-overhead allocation/deallocation for this type of +// GeomMunger. +//////////////////////////////////////////////////////////////////// +INLINE void *DXGeomMunger8:: +operator new(size_t size) { + return do_operator_new(size, _deleted_chain); +} diff --git a/panda/src/dxgsg8/dxGeomMunger8.cxx b/panda/src/dxgsg8/dxGeomMunger8.cxx index 151b44035c..50b1b252a2 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.cxx +++ b/panda/src/dxgsg8/dxGeomMunger8.cxx @@ -18,6 +18,7 @@ #include "dxGeomMunger8.h" +qpGeomMunger *DXGeomMunger8::_deleted_chain = NULL; TypeHandle DXGeomMunger8::_type_handle; //////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg8/dxGeomMunger8.h b/panda/src/dxgsg8/dxGeomMunger8.h index c0c4dd4634..d1cee0c7de 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.h +++ b/panda/src/dxgsg8/dxGeomMunger8.h @@ -40,6 +40,12 @@ protected: virtual void munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data); virtual int compare_to_impl(const qpGeomMunger *other) const; +public: + INLINE void *operator new(size_t size); + +private: + static qpGeomMunger *_deleted_chain; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/glstuff/glGeomContext_src.cxx b/panda/src/glstuff/glGeomContext_src.cxx index 0d95261799..6f39bcdb8c 100644 --- a/panda/src/glstuff/glGeomContext_src.cxx +++ b/panda/src/glstuff/glGeomContext_src.cxx @@ -28,7 +28,7 @@ CLP(GeomContext):: nassertv(_display_lists.empty()); } -//////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// // Function: CLP(GeomContext)::get_display_list // Access: Public // Description: Looks up the display list index associated with the @@ -46,7 +46,9 @@ get_display_list(GLuint &index, const CLP(GeomMunger) *munger, if (dl._index == 0) { dl._index = GLP(GenLists)(1); list_current = false; - ((CLP(GeomMunger) *)munger)->_geom_contexts.insert(this); + if (munger != (CLP(GeomMunger) *)NULL) { + ((CLP(GeomMunger) *)munger)->_geom_contexts.insert(this); + } } index = dl._index; @@ -78,7 +80,9 @@ release_display_lists() { ++dli) { CLP(GeomMunger) *munger = (*dli).first; const DisplayList &dl = (*dli).second; - munger->_geom_contexts.erase(this); + if (munger != (CLP(GeomMunger) *)NULL) { + munger->_geom_contexts.erase(this); + } if (GLCAT.is_debug()) { GLCAT.debug() diff --git a/panda/src/glstuff/glGeomMunger_src.I b/panda/src/glstuff/glGeomMunger_src.I index ed7c1cde14..3272943b32 100644 --- a/panda/src/glstuff/glGeomMunger_src.I +++ b/panda/src/glstuff/glGeomMunger_src.I @@ -41,3 +41,15 @@ INLINE GraphicsStateGuardian *CLP(GeomMunger):: get_gsg() const { return _gsg; } + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GeomMunger)::operator new +// Access: Public +// Description: Calls up to do_operator_new() to implement the +// low-overhead allocation/deallocation for this type of +// GeomMunger. +//////////////////////////////////////////////////////////////////// +INLINE void *CLP(GeomMunger):: +operator new(size_t size) { + return do_operator_new(size, _deleted_chain); +} diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index 2bea934664..67bbe549ac 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -18,6 +18,7 @@ #include "dcast.h" +qpGeomMunger *CLP(GeomMunger)::_deleted_chain = NULL; TypeHandle CLP(GeomMunger)::_type_handle; //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glGeomMunger_src.h b/panda/src/glstuff/glGeomMunger_src.h index 0a015ebed0..60bc76c304 100644 --- a/panda/src/glstuff/glGeomMunger_src.h +++ b/panda/src/glstuff/glGeomMunger_src.h @@ -43,6 +43,9 @@ protected: virtual int compare_to_impl(const qpGeomMunger *other) const; virtual int geom_compare_to_impl(const qpGeomMunger *other) const; +public: + INLINE void *operator new(size_t size); + private: PT(GraphicsStateGuardian) _gsg; CPT(TextureAttrib) _texture; @@ -51,6 +54,8 @@ private: typedef pset GeomContexts; GeomContexts _geom_contexts; + static qpGeomMunger *_deleted_chain; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 685bc6e1eb..cf5c7295d8 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2142,7 +2142,8 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger, if (_vertex_data->get_array_info(InternalName::get_color(), array_data, num_components, numeric_type, - start, stride)) { + start, stride) && + numeric_type != qpGeomVertexDataType::NT_packed_argb) { const unsigned char *client_pointer = setup_array_data(array_data); GLP(ColorPointer)(num_components, get_numeric_type(numeric_type), stride, client_pointer + start); @@ -2209,7 +2210,6 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger, void CLP(GraphicsStateGuardian):: draw_triangles(const qpGeomTriangles *primitive) { // setup_antialias_polygon(); - _vertices_tri_pcollector.add_level(primitive->get_num_vertices()); const unsigned short *client_pointer = setup_primitive(primitive); @@ -4379,9 +4379,6 @@ get_numeric_type(qpGeomVertexDataType::NumericType numeric_type) { case qpGeomVertexDataType::NT_uint8: return GL_UNSIGNED_BYTE; - case qpGeomVertexDataType::NT_packed_argb: - return GL_UNSIGNED_INT; - case qpGeomVertexDataType::NT_float: return GL_FLOAT; } diff --git a/panda/src/gobj/qpgeom.cxx b/panda/src/gobj/qpgeom.cxx index fdfcea1d04..b696605467 100644 --- a/panda/src/gobj/qpgeom.cxx +++ b/panda/src/gobj/qpgeom.cxx @@ -256,8 +256,11 @@ munge_geom(const qpGeomMunger *munger, PStatTimer timer(qpGeomMunger::_munge_pcollector); result = this; - data = munger->munge_data(get_vertex_data()); - ((qpGeomMunger *)munger)->munge_geom_impl(result, data); + data = get_vertex_data(); + if (munger != (qpGeomMunger *)NULL) { + data = munger->munge_data(data); + ((qpGeomMunger *)munger)->munge_geom_impl(result, data); + } { // Record the new result in the cache. diff --git a/panda/src/gobj/qpgeomMunger.I b/panda/src/gobj/qpgeomMunger.I index bae731e01b..70b27f635d 100644 --- a/panda/src/gobj/qpgeomMunger.I +++ b/panda/src/gobj/qpgeomMunger.I @@ -123,6 +123,49 @@ munge_data(const qpGeomVertexData *data) const { return ((qpGeomMunger *)this)->munge_data_impl(data); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::operator delete +// Access: Public +// Description: This balances do_operator_new(), below, and adds the +// deleted object to the stored deleted_chain, rather +// than returning its memory to the heap. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomMunger:: +operator delete(void *ptr) { + qpGeomMunger *obj = (qpGeomMunger *)ptr; + nassertv(obj->_deleted_chain != (qpGeomMunger **)NULL); + nassertv(obj->_next == (qpGeomMunger *)NULL); + obj->_next = (*obj->_deleted_chain); + (*obj->_deleted_chain) = obj; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::do_operator_new +// Access: Protected, Static +// Description: Intended to be called from a derived class's operator +// new method, this allocates a new object from the +// indicated deleted_chain, if there is an object +// available there, or from the heap if not. +// +// In either case, the indicated deleted_chain pointer +// is cleverly stored on the new object, even before its +// constructor is called, so that it can be returned +// there when it is deleted. +//////////////////////////////////////////////////////////////////// +INLINE void *qpGeomMunger:: +do_operator_new(size_t size, qpGeomMunger *&deleted_chain) { + qpGeomMunger *obj; + if (deleted_chain != (qpGeomMunger *)NULL) { + obj = deleted_chain; + deleted_chain = deleted_chain->_next; + } else { + obj = (qpGeomMunger *)::operator new(size); + } + obj->_deleted_chain = &deleted_chain; + + return obj; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomMunger::get_registry // Access: Private diff --git a/panda/src/gobj/qpgeomMunger.cxx b/panda/src/gobj/qpgeomMunger.cxx index 3cac6de72f..908f983528 100644 --- a/panda/src/gobj/qpgeomMunger.cxx +++ b/panda/src/gobj/qpgeomMunger.cxx @@ -35,7 +35,10 @@ qpGeomMunger:: qpGeomMunger(const GraphicsStateGuardianBase *, const RenderState *) : _is_registered(false) { +#ifndef NDEBUG _registered_key = get_registry()->_mungers.end(); + _next = NULL; +#endif } //////////////////////////////////////////////////////////////////// @@ -47,7 +50,10 @@ qpGeomMunger:: qpGeomMunger(const qpGeomMunger ©) : _is_registered(false) { +#ifndef NDEBUG _registered_key = get_registry()->_mungers.end(); + _next = NULL; +#endif } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomMunger.h b/panda/src/gobj/qpgeomMunger.h index 98de151535..bab2ec5021 100644 --- a/panda/src/gobj/qpgeomMunger.h +++ b/panda/src/gobj/qpgeomMunger.h @@ -88,6 +88,21 @@ protected: virtual int compare_to_impl(const qpGeomMunger *other) const; virtual int geom_compare_to_impl(const qpGeomMunger *other) const; +public: + // To minimize overhead, each type of GeomMunger will implement new + // and delete using their own deleted_chain. This is the base class + // implementation, which requires a pointer to deleted_chain be + // stored on each instance. + INLINE void operator delete(void *ptr); + +protected: + INLINE static void *do_operator_new(size_t size, qpGeomMunger *&_deleted_chain); + +private: + qpGeomMunger **_deleted_chain; + // This is the next pointer along the deleted_chain. + qpGeomMunger *_next; + private: class Registry; INLINE static Registry *get_registry(); diff --git a/panda/src/pgraph/cullResult.I b/panda/src/pgraph/cullResult.I index bdb93ebc6c..37dbba7b04 100644 --- a/panda/src/pgraph/cullResult.I +++ b/panda/src/pgraph/cullResult.I @@ -54,3 +54,22 @@ get_bin(int bin_index) { } return make_new_bin(bin_index); } + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::get_geom_munger +// Access: Private +// Description: Returns a suitable GeomMunger for the indicated +// state. This will ask the GSG to create a new munger +// if we haven't already created one for this state; +// otherwise, it will return the existing one. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomMunger) CullResult:: +get_geom_munger(const RenderState *state) { + Mungers::iterator mi = _mungers.find(state); + if (mi != _mungers.end()) { + return (*mi).second; + } + CPT(qpGeomMunger) munger = _gsg->get_geom_munger(state); + _mungers.insert(Mungers::value_type(state, munger)); + return munger; +} diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx index 44d2436704..9a4080a012 100644 --- a/panda/src/pgraph/cullResult.cxx +++ b/panda/src/pgraph/cullResult.cxx @@ -128,7 +128,7 @@ add_object(CullableObject *object) { get_dual_transparent_state_decals() : get_dual_transparent_state(); transparent_part->_state = state->compose(transparent_state); - transparent_part->munge_geom(_gsg); + transparent_part->munge_geom(get_geom_munger(transparent_part->_state)); CullBin *bin = get_bin(transparent_part->_state->get_bin_index()); nassertv(bin != (CullBin *)NULL); bin->add_object(transparent_part); @@ -155,7 +155,7 @@ add_object(CullableObject *object) { // Munge vertices as needed for the GSG's requirements, and the // object's current state. - object->munge_geom(_gsg); + object->munge_geom(get_geom_munger(object->_state)); CullBin *bin = get_bin(object->_state->get_bin_index()); nassertv(bin != (CullBin *)NULL); diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h index 61efdf3d13..fa4e11b6b1 100644 --- a/panda/src/pgraph/cullResult.h +++ b/panda/src/pgraph/cullResult.h @@ -23,11 +23,13 @@ #include "cullBin.h" #include "renderState.h" #include "cullableObject.h" +#include "qpgeomMunger.h" #include "referenceCount.h" #include "pointerTo.h" #include "pvector.h" #include "pset.h" +#include "pmap.h" class GraphicsStateGuardianBase; @@ -63,6 +65,7 @@ public: private: CullBin *make_new_bin(int bin_index); + INLINE CPT(qpGeomMunger) get_geom_munger(const RenderState *state); static CPT(RenderState) get_binary_state(); static CPT(RenderState) get_dual_transparent_state(); @@ -71,6 +74,9 @@ private: GraphicsStateGuardianBase *_gsg; + typedef pmap Mungers; + Mungers _mungers; + typedef pvector< PT(CullBin) > Bins; Bins _bins; }; diff --git a/panda/src/pgraph/cullableObject.I b/panda/src/pgraph/cullableObject.I index 23aad9dd03..2c50e59a47 100644 --- a/panda/src/pgraph/cullableObject.I +++ b/panda/src/pgraph/cullableObject.I @@ -103,18 +103,6 @@ has_decals() const { return (_next != (CullableObject *)NULL); } -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::munge_geom -// Access: Public -// Description: Gets a GeomMunger from the GSG to transform the -// geom and/or its vertices to meet the GSG's vertex -// requirements for the current state. -//////////////////////////////////////////////////////////////////// -INLINE void CullableObject:: -munge_geom(GraphicsStateGuardianBase *gsg) { - munge_geom(gsg->get_geom_munger(_state)); -} - //////////////////////////////////////////////////////////////////// // Function: CullableObject::draw // Access: Public diff --git a/panda/src/pgraph/cullableObject.h b/panda/src/pgraph/cullableObject.h index ffc6a32c92..7167ef170d 100644 --- a/panda/src/pgraph/cullableObject.h +++ b/panda/src/pgraph/cullableObject.h @@ -54,7 +54,6 @@ public: INLINE bool has_decals() const; - INLINE void munge_geom(GraphicsStateGuardianBase *gsg); void munge_geom(const qpGeomMunger *munger); INLINE void draw(GraphicsStateGuardianBase *gsg); diff --git a/panda/src/pgraph/drawCullHandler.cxx b/panda/src/pgraph/drawCullHandler.cxx index 724ccb35a4..44d154aab1 100644 --- a/panda/src/pgraph/drawCullHandler.cxx +++ b/panda/src/pgraph/drawCullHandler.cxx @@ -35,7 +35,7 @@ void DrawCullHandler:: record_object(CullableObject *object) { // Munge vertices as needed for the GSG's requirements, and the // object's current state. - object->munge_geom(_gsg); + object->munge_geom(_gsg->get_geom_munger(object->_state)); // And draw the object, then dispense with it. draw(object, _gsg);