From f2eddac535ac517a0a7444f072569793cb4b2eb6 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 12 Jun 2001 18:56:57 +0000 Subject: [PATCH] changed CircBuffer to use STL-like interface --- panda/src/char/computedVertices.cxx | 4 +- panda/src/display/Sources.pp | 8 +- panda/src/display/display_composite1.cxx | 2 + panda/src/display/display_composite2.cxx | 1 + panda/src/display/geomContext.I | 27 ++ panda/src/display/geomContext.cxx | 21 ++ panda/src/display/geomContext.h | 75 ++++ panda/src/display/geomNodeContext.I | 29 ++ panda/src/display/geomNodeContext.cxx | 21 ++ panda/src/display/geomNodeContext.h | 75 ++++ panda/src/display/graphicsStateGuardian.cxx | 320 +++++++++++++++--- panda/src/display/graphicsStateGuardian.h | 36 +- panda/src/display/savedContext.I | 26 ++ panda/src/display/savedContext.cxx | 21 ++ panda/src/display/savedContext.h | 56 +++ panda/src/display/textureContext.h | 8 +- panda/src/downloader/asyncDownloader.cxx | 15 +- panda/src/dxgsg/dxGraphicsStateGuardian.cxx | 23 +- panda/src/dxgsg/dxGraphicsStateGuardian.h | 22 +- panda/src/event/eventQueue.cxx | 10 +- panda/src/express/circBuffer.I | 158 +++++++-- panda/src/express/circBuffer.h | 28 +- panda/src/express/tokenBoard.I | 10 +- panda/src/glgsg/glGraphicsStateGuardian.cxx | 21 +- panda/src/glgsg/glGraphicsStateGuardian.h | 22 +- panda/src/gobj/drawable.cxx | 32 ++ panda/src/gobj/drawable.h | 10 +- panda/src/gobj/geom.cxx | 119 ++++++- panda/src/gobj/geom.h | 90 ++--- panda/src/gobj/geomLine.cxx | 4 +- panda/src/gobj/geomLine.h | 2 +- panda/src/gobj/geomLinestrip.cxx | 4 +- panda/src/gobj/geomLinestrip.h | 2 +- panda/src/gobj/geomPoint.cxx | 4 +- panda/src/gobj/geomPoint.h | 2 +- panda/src/gobj/geomPolygon.cxx | 4 +- panda/src/gobj/geomPolygon.h | 2 +- panda/src/gobj/geomQuad.cxx | 4 +- panda/src/gobj/geomQuad.h | 2 +- panda/src/gobj/geomSphere.cxx | 4 +- panda/src/gobj/geomSphere.h | 2 +- panda/src/gobj/geomSprite.cxx | 4 +- panda/src/gobj/geomSprite.h | 2 +- panda/src/gobj/geomTri.cxx | 4 +- panda/src/gobj/geomTri.h | 2 +- panda/src/gobj/geomTrifan.cxx | 4 +- panda/src/gobj/geomTrifan.h | 2 +- panda/src/gobj/geomTristrip.cxx | 4 +- panda/src/gobj/geomTristrip.h | 2 +- panda/src/gsgbase/graphicsStateGuardianBase.h | 33 +- panda/src/loader/loader.cxx | 15 +- panda/src/pstatclient/pStatProperties.cxx | 4 + panda/src/sgattrib/drawBoundsTransition.cxx | 4 +- panda/src/sgraph/geomNode.cxx | 98 +++++- panda/src/sgraph/geomNode.h | 12 + panda/src/sgraph/geomTransformer.cxx | 1 + 56 files changed, 1264 insertions(+), 253 deletions(-) create mode 100644 panda/src/display/geomContext.I create mode 100644 panda/src/display/geomContext.cxx create mode 100644 panda/src/display/geomContext.h create mode 100644 panda/src/display/geomNodeContext.I create mode 100644 panda/src/display/geomNodeContext.cxx create mode 100644 panda/src/display/geomNodeContext.h create mode 100644 panda/src/display/savedContext.I create mode 100644 panda/src/display/savedContext.cxx create mode 100644 panda/src/display/savedContext.h diff --git a/panda/src/char/computedVertices.cxx b/panda/src/char/computedVertices.cxx index d37948397e..227e32126a 100644 --- a/panda/src/char/computedVertices.cxx +++ b/panda/src/char/computedVertices.cxx @@ -213,8 +213,8 @@ update(Character *character) { DCAST_INTO_V(joint, character->get_part(vt._joint_index)); mat = - joint->_initial_net_transform_inverse * - joint->_net_transform; + joint->_initial_net_transform_inverse * + joint->_net_transform; } Vertices::const_iterator vi; diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index 55c97c6944..9d24be387f 100644 --- a/panda/src/display/Sources.pp +++ b/panda/src/display/Sources.pp @@ -11,6 +11,7 @@ #define SOURCES \ config_display.h displayRegion.I displayRegion.h \ + geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ graphicsChannel.I graphicsChannel.h graphicsLayer.I \ graphicsLayer.h graphicsPipe.I graphicsPipe.N graphicsPipe.h \ graphicsStateGuardian.I graphicsStateGuardian.N \ @@ -20,21 +21,25 @@ hardwareChannel.h interactiveGraphicsPipe.I \ interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \ noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h \ + savedContext.I savedContext.h \ savedFrameBuffer.I savedFrameBuffer.h textureContext.I \ textureContext.h #define INCLUDED_SOURCES \ - config_display.cxx displayRegion.cxx graphicsChannel.cxx \ + config_display.cxx displayRegion.cxx \ + geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \ graphicsLayer.cxx graphicsPipe.cxx graphicsStateGuardian.cxx \ graphicsWindow.cxx graphicsWindowInputDevice.cxx \ hardwareChannel.cxx interactiveGraphicsPipe.cxx \ noninteractiveGraphicsPipe.cxx pipeSpec.cxx \ + savedContext.cxx \ savedFrameBuffer.cxx textureContext.cxx #define INSTALL_HEADERS \ config_display.h \ displayRegion.I displayRegion.h displayRegionStack.I \ displayRegionStack.h frameBufferStack.I frameBufferStack.h \ + geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ graphicsChannel.I graphicsChannel.h graphicsLayer.I graphicsLayer.h \ graphicsPipe.I graphicsPipe.h graphicsStateGuardian.I \ graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \ @@ -42,6 +47,7 @@ hardwareChannel.I hardwareChannel.h interactiveGraphicsPipe.I \ interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \ noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h renderBuffer.h \ + savedContext.I savedContext.h \ savedFrameBuffer.I savedFrameBuffer.h textureContext.I \ textureContext.h diff --git a/panda/src/display/display_composite1.cxx b/panda/src/display/display_composite1.cxx index 4f200062e5..1549237758 100644 --- a/panda/src/display/display_composite1.cxx +++ b/panda/src/display/display_composite1.cxx @@ -1,5 +1,7 @@ #include "displayRegion.cxx" +#include "geomContext.cxx" +#include "geomNodeContext.cxx" #include "graphicsChannel.cxx" #include "graphicsLayer.cxx" #include "graphicsPipe.cxx" diff --git a/panda/src/display/display_composite2.cxx b/panda/src/display/display_composite2.cxx index e066eec7ce..0dfb7b9c62 100644 --- a/panda/src/display/display_composite2.cxx +++ b/panda/src/display/display_composite2.cxx @@ -4,5 +4,6 @@ #include "interactiveGraphicsPipe.cxx" #include "noninteractiveGraphicsPipe.cxx" #include "pipeSpec.cxx" +#include "savedContext.cxx" #include "savedFrameBuffer.cxx" #include "textureContext.cxx" diff --git a/panda/src/display/geomContext.I b/panda/src/display/geomContext.I new file mode 100644 index 0000000000..ec07b0909c --- /dev/null +++ b/panda/src/display/geomContext.I @@ -0,0 +1,27 @@ +// Filename: geomContext.I +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: GeomContext::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeomContext:: +GeomContext(Geom *geom) : _geom(geom) { +} diff --git a/panda/src/display/geomContext.cxx b/panda/src/display/geomContext.cxx new file mode 100644 index 0000000000..05b5e30bd9 --- /dev/null +++ b/panda/src/display/geomContext.cxx @@ -0,0 +1,21 @@ +// Filename: geomContext.cxx +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "geomContext.h" + +TypeHandle GeomContext::_type_handle; diff --git a/panda/src/display/geomContext.h b/panda/src/display/geomContext.h new file mode 100644 index 0000000000..5cf30564ca --- /dev/null +++ b/panda/src/display/geomContext.h @@ -0,0 +1,75 @@ +// Filename: geomContext.h +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef GEOMCONTEXT_H +#define GEOMCONTEXT_H + +#include + +#include "savedContext.h" + +class Geom; + +//////////////////////////////////////////////////////////////////// +// Class : GeomContext +// Description : This is a special class object, similar to a +// TextureContext, that holds all the information +// returned by a particular GSG to cache the rendering +// information associated with one or more Geoms. This +// is similar to, but different from, a GeomNode +// context, which is associated with the containing +// GeomNode class; a GSG might prefer to associate data +// with either the Geom or the GeomNode or both. +// +// This allows the GSG to precompute some information +// necessary for drawing the Geoms as quickly as +// possible and reuse that information across multiple +// frames. Typically, only static Geoms +// (e.g. nonindexed) will be assigned GeomContexts. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA GeomContext : public SavedContext { +public: + INLINE GeomContext(Geom *geom); + + // This cannot be a PT(Geom), because the geom and the GSG + // both own their GeomContexts! That would create a circular + // reference count. + Geom *_geom; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + SavedContext::init_type(); + register_type(_type_handle, "GeomContext", + SavedContext::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; +}; + +#include "geomContext.I" + +#endif + diff --git a/panda/src/display/geomNodeContext.I b/panda/src/display/geomNodeContext.I new file mode 100644 index 0000000000..ab10ebd808 --- /dev/null +++ b/panda/src/display/geomNodeContext.I @@ -0,0 +1,29 @@ +// Filename: geomNodeContext.I +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: GeomNodeContext::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeomNodeContext:: +GeomNodeContext(GeomNode *node) : + _node(node) +{ +} diff --git a/panda/src/display/geomNodeContext.cxx b/panda/src/display/geomNodeContext.cxx new file mode 100644 index 0000000000..1467f24af5 --- /dev/null +++ b/panda/src/display/geomNodeContext.cxx @@ -0,0 +1,21 @@ +// Filename: geomNodeContext.cxx +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "geomNodeContext.h" + +TypeHandle GeomNodeContext::_type_handle; diff --git a/panda/src/display/geomNodeContext.h b/panda/src/display/geomNodeContext.h new file mode 100644 index 0000000000..b3a6e1869e --- /dev/null +++ b/panda/src/display/geomNodeContext.h @@ -0,0 +1,75 @@ +// Filename: geomNodeContext.h +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef GEOMNODECONTEXT_H +#define GEOMNODECONTEXT_H + +#include + +#include "savedContext.h" + +class GeomNode; + +//////////////////////////////////////////////////////////////////// +// Class : GeomNodeContext +// Description : This is a special class object, similar to a +// TextureContext, that holds all the information +// returned by a particular GSG to cache the rendering +// information associated with one or more GeomNodes. +// This is similar to, but different from, a Geom +// context, which is associated with the containing Geom +// class; a GSG might prefer to associate data with +// either the Geom or the GeomNode or both. +// +// This allows the GSG to precompute some information +// necessary for drawing the Geoms as quickly as +// possible and reuse that information across multiple +// frames. Typically, only static Geoms +// (e.g. nonindexed) will be assigned GeomContexts. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA GeomNodeContext : public SavedContext { +public: + INLINE GeomNodeContext(GeomNode *node); + + // This cannot be a PT(GeomNode), because the geomNode and the GSG + // both own their GeomNodeContexts! That would create a circular + // reference count. + GeomNode *_node; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + SavedContext::init_type(); + register_type(_type_handle, "GeomNodeContext", + SavedContext::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; +}; + +#include "geomNodeContext.I" + +#endif + diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 286f555ab7..8ae28143db 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -29,6 +29,10 @@ #ifndef CPPPARSER PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage"); PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active"); +PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms"); +PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active"); +PStatCollector GraphicsStateGuardian::_total_geom_node_pcollector("Prepared GeomNodes"); +PStatCollector GraphicsStateGuardian::_active_geom_node_pcollector("Prepared GeomNodes:Active"); PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory"); PStatCollector GraphicsStateGuardian::_used_texmem_pcollector("Texture memory:In use"); PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager"); @@ -93,52 +97,6 @@ GraphicsStateGuardian:: ~GraphicsStateGuardian() { } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::release_all_textures -// Access: Public -// Description: Frees the resources for all textures associated with -// this GSG. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -release_all_textures() { - // We must get a copy of the _prepared_textures list first, because - // each call to release_texture() will remove that texture from the - // list, and we don't want to traverse a list while we're modifying - // it! - - Textures temp = _prepared_textures; - for (Textures::const_iterator ti = temp.begin(); - ti != temp.end(); - ++ti) { - release_texture(*ti); - } - - // Now that we've released all of the textures, the - // _prepared_textures list should have completely emptied itself. - nassertv(_prepared_textures.empty()); -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::clear_attribute -// Access: Public -// Description: Explicitly clear the indicated attribute, specified -// by the TypeHandle of its associated transition. If -// the attribute is not set already, this does nothing; -// if it is set, it resets it to its default value. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -clear_attribute(TypeHandle type) { - NodeAttributes::iterator ai = _state.find(type); - if (ai != _state.end()) { - // The state is already set; get the initial value and reset it. - PT(NodeAttribute) initial = (*ai).second->make_initial(); - initial->issue(this); - - // Now remove the state entry from the set. - _state.erase(ai); - } -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::reset // Access: Public, Virtual @@ -421,6 +379,163 @@ enable_frame_clear(bool clear_color, bool clear_depth) { } } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::release_all_textures +// Access: Public +// Description: Frees the resources for all textures associated with +// this GSG. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +release_all_textures() { + // We must get a copy of the _prepared_textures list first, because + // each call to release_texture() will remove that texture from the + // list, and we don't want to traverse a list while we're modifying + // it! + + Textures temp = _prepared_textures; + for (Textures::const_iterator ti = temp.begin(); + ti != temp.end(); + ++ti) { + release_texture(*ti); + } + + // Now that we've released all of the textures, the + // _prepared_textures list should have completely emptied itself. + nassertv(_prepared_textures.empty()); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::release_all_geoms +// Access: Public +// Description: Frees the resources for all Geoms and GeomNodes +// associated with this GSG. Warning! This may make +// the Geoms unrenderable, if the Panda-level +// information has been deleted. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +release_all_geoms() { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::clear_attribute +// Access: Public +// Description: Explicitly clear the indicated attribute, specified +// by the TypeHandle of its associated transition. If +// the attribute is not set already, this does nothing; +// if it is set, it resets it to its default value. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +clear_attribute(TypeHandle type) { + NodeAttributes::iterator ai = _state.find(type); + if (ai != _state.end()) { + // The state is already set; get the initial value and reset it. + PT(NodeAttribute) initial = (*ai).second->make_initial(); + initial->issue(this); + + // Now remove the state entry from the set. + _state.erase(ai); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::prepare_texture +// Access: Public, Virtual +// Description: Prepares the indicated texture for retained-mode +// rendering. In the future, this texture may be +// applied simply by calling apply_texture() with the +// value returned by this function. +//////////////////////////////////////////////////////////////////// +TextureContext *GraphicsStateGuardian:: +prepare_texture(Texture *) { + return (TextureContext *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::apply_texture +// Access: Public, Virtual +// Description: Applies the texture previously indicated via a call +// to prepare_texture() to the graphics state, so that +// geometry rendered in the future will be rendered with +// the given texture. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +apply_texture(TextureContext *) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::release_texture +// Access: Public, Virtual +// Description: Frees the resources previously allocated via a call +// to prepare_texture(), including deleting the +// TextureContext itself, if necessary. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +release_texture(TextureContext *) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::prepare_geom_node +// Access: Public, Virtual +// Description: Prepares the indicated GeomNode for retained-mode +// rendering. If this function returns non-NULL, the +// value returned will be passed back to a future call +// to draw_geom_node(), which is expected to draw the +// contents of the node. +//////////////////////////////////////////////////////////////////// +GeomNodeContext *GraphicsStateGuardian:: +prepare_geom_node(GeomNode *) { + return (GeomNodeContext *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::draw_geom_node +// Access: Public, Virtual +// Description: Draws a GeomNode previously indicated by a call to +// prepare_geom_node(). +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +draw_geom_node(GeomNode *node, GeomNodeContext *) { + int num_geoms = node->get_num_geoms(); + for (int i = 0; i < num_geoms; i++) { + node->get_geom(i)->draw(this); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::release_geom_node +// Access: Public, Virtual +// Description: Frees the resources previously allocated via a call +// to prepare_geom_node(), including deleting the +// GeomNodeContext itself, if necessary. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +release_geom_node(GeomNodeContext *) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::prepare_geom +// Access: Public, Virtual +// Description: Prepares the indicated Geom for retained-mode +// rendering. The value returned by this function will +// be passed back into future calls to draw_tristrip(), +// etc., along with the Geom pointer. +//////////////////////////////////////////////////////////////////// +GeomContext *GraphicsStateGuardian:: +prepare_geom(Geom *) { + return (GeomContext *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::release_geom +// Access: Public, Virtual +// Description: Frees the resources previously allocated via a call +// to prepare_geom(), including deleting the GeomContext +// itself, if necessary. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +release_geom(GeomContext *) { +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::wants_normals // Access: Public, Virtual @@ -517,6 +632,86 @@ unmark_prepared_texture(TextureContext *tc) { return removed; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::mark_prepared_geom +// Access: Protected +// Description: This is intended to be called from within +// prepare_geom(). It adds the indicated GeomContext +// pointer to the _prepared_geoms set, and returns true +// if it was successfully added (i.e. it was not already +// in the set). +//////////////////////////////////////////////////////////////////// +bool GraphicsStateGuardian:: +mark_prepared_geom(GeomContext *gc) { + bool prepared = _prepared_geoms.insert(gc).second; +#ifdef DO_PSTATS + if (prepared) { + _total_geom_pcollector.add_level(1); + } +#endif + return prepared; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::unmark_prepared_geom +// Access: Protected +// Description: This is intended to be called from within +// release_geom(). It removes the indicated GeomContext +// pointer from the _prepared_geoms set, and returns +// true if it was successfully removed (i.e. it had been +// in the set). +//////////////////////////////////////////////////////////////////// +bool GraphicsStateGuardian:: +unmark_prepared_geom(GeomContext *gc) { + bool removed = (_prepared_geoms.erase(gc) != 0); +#ifdef DO_PSTATS + if (removed) { + _total_geom_pcollector.sub_level(1); + } +#endif + return removed; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::mark_prepared_geom_node +// Access: Protected +// Description: This is intended to be called from within +// prepare_geom_node(). It adds the indicated +// GeomNodeContext pointer to the _prepared_geom_nodes +// set, and returns true if it was successfully added +// (i.e. it was not already in the set). +//////////////////////////////////////////////////////////////////// +bool GraphicsStateGuardian:: +mark_prepared_geom_node(GeomNodeContext *gnc) { + bool prepared = _prepared_geom_nodes.insert(gnc).second; +#ifdef DO_PSTATS + if (prepared) { + _total_geom_node_pcollector.add_level(1); + } +#endif + return prepared; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::unmark_prepared_geom_node +// Access: Protected +// Description: This is intended to be called from within +// release_geom_node(). It removes the indicated +// GeomNodeContext pointer from the _prepared_geom_nodes +// set, and returns true if it was successfully removed +// (i.e. it had been in the set). +//////////////////////////////////////////////////////////////////// +bool GraphicsStateGuardian:: +unmark_prepared_geom_node(GeomNodeContext *gnc) { + bool removed = (_prepared_geom_nodes.erase(gnc) != 0); +#ifdef DO_PSTATS + if (removed) { + _total_geom_node_pcollector.sub_level(1); + } +#endif + return removed; +} + #ifdef DO_PSTATS //////////////////////////////////////////////////////////////////// @@ -529,6 +724,8 @@ void GraphicsStateGuardian:: init_frame_pstats() { _current_textures.clear(); _active_texusage_pcollector.clear_level(); + _total_geom_pcollector.clear_level(); + _total_geom_node_pcollector.clear_level(); // Also clear out our other counters while we're here. _vertices_tristrip_pcollector.clear_level(); @@ -560,6 +757,37 @@ add_to_texture_record(TextureContext *tc) { } } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::add_to_geom_record +// Access: Protected +// Description: Records that the indicated Geom has been drawn this +// frame. This function is only used to update the +// PStats current_texmem collector; it gets compiled out +// if we aren't using PStats. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +add_to_geom_record(GeomContext *gc) { + if (gc != (GeomContext *)NULL && _current_geoms.insert(gc).second) { + _active_geom_pcollector.add_level(1); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::add_to_geom_node_record +// Access: Protected +// Description: Records that the indicated GeomNode has been drawn +// this frame. This function is only used to update the +// PStats current_texmem collector; it gets compiled out +// if we aren't using PStats. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +add_to_geom_node_record(GeomNodeContext *gnc) { + if (gnc != (GeomNodeContext *)NULL && + _current_geom_nodes.insert(gnc).second) { + _active_geom_node_pcollector.add_level(1); + } +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::record_state_change // Access: Protected diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index bfb52eadd6..cc48688d10 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -79,10 +79,22 @@ PUBLISHED: void enable_frame_clear(bool clear_color, bool clear_depth); void release_all_textures(); + void release_all_geoms(); void clear_attribute(TypeHandle type); public: + virtual TextureContext *prepare_texture(Texture *tex); + virtual void apply_texture(TextureContext *tc); + virtual void release_texture(TextureContext *tc); + + virtual GeomNodeContext *prepare_geom_node(GeomNode *node); + virtual void draw_geom_node(GeomNode *node, GeomNodeContext *gnc); + virtual void release_geom_node(GeomNodeContext *gnc); + + virtual GeomContext *prepare_geom(Geom *geom); + virtual void release_geom(GeomContext *gc); + virtual void clear(const RenderBuffer &buffer)=0; virtual void clear(const RenderBuffer &buffer, const DisplayRegion* region)=0; @@ -148,18 +160,28 @@ protected: bool mark_prepared_texture(TextureContext *tc); bool unmark_prepared_texture(TextureContext *tc); + bool mark_prepared_geom(GeomContext *gc); + bool unmark_prepared_geom(GeomContext *gc); + bool mark_prepared_geom_node(GeomNodeContext *gnc); + bool unmark_prepared_geom_node(GeomNodeContext *gnc); #ifdef DO_PSTATS // These functions are used to update the active texture memory // usage record (and other frame-based measurements) in Pstats. void init_frame_pstats(); void add_to_texture_record(TextureContext *tc); + void add_to_geom_record(GeomContext *gc); + void add_to_geom_node_record(GeomNodeContext *gnc); void record_state_change(TypeHandle type); pset _current_textures; + pset _current_geoms; + pset _current_geom_nodes; #else INLINE void init_frame_pstats() { } INLINE void add_to_texture_record(TextureContext *) { } - INLINE void record_state_change(TypeHandle type) { } + INLINE void add_to_geom_record(GeomContext *) { } + INLINE void add_to_geom_node_record(GeomNodeContext *) { } + INLINE void record_state_change(TypeHandle) { } INLINE void count_node(Node *) { } #endif @@ -192,6 +214,10 @@ public: // Statistics static PStatCollector _total_texusage_pcollector; static PStatCollector _active_texusage_pcollector; + static PStatCollector _total_geom_pcollector; + static PStatCollector _active_geom_pcollector; + static PStatCollector _total_geom_node_pcollector; + static PStatCollector _active_geom_node_pcollector; static PStatCollector _total_texmem_pcollector; static PStatCollector _used_texmem_pcollector; static PStatCollector _texmgrmem_total_pcollector; @@ -208,8 +234,14 @@ public: static PStatCollector _geom_nodes_pcollector; private: + // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access + // these sets directly due to exported template issue typedef pset Textures; - Textures _prepared_textures; // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access set directly due to exported template issue + Textures _prepared_textures; + typedef pset Geoms; + Geoms _prepared_geoms; + typedef pset GeomNodes; + GeomNodes _prepared_geom_nodes; public: void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg); diff --git a/panda/src/display/savedContext.I b/panda/src/display/savedContext.I new file mode 100644 index 0000000000..9a9d7605a1 --- /dev/null +++ b/panda/src/display/savedContext.I @@ -0,0 +1,26 @@ +// Filename: savedContext.I +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: SavedContext::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE SavedContext:: +SavedContext() { +} diff --git a/panda/src/display/savedContext.cxx b/panda/src/display/savedContext.cxx new file mode 100644 index 0000000000..8e453690c3 --- /dev/null +++ b/panda/src/display/savedContext.cxx @@ -0,0 +1,21 @@ +// Filename: savedContext.cxx +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "savedContext.h" + +TypeHandle SavedContext::_type_handle; diff --git a/panda/src/display/savedContext.h b/panda/src/display/savedContext.h new file mode 100644 index 0000000000..a35c900d09 --- /dev/null +++ b/panda/src/display/savedContext.h @@ -0,0 +1,56 @@ +// Filename: savedContext.h +// Created by: drose (11Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef SAVEDCONTEXT_H +#define SAVEDCONTEXT_H + +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Class : SavedContext +// Description : This is the base class for both a TextureContext and +// a GeomContext. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA SavedContext : public TypedObject { +public: + INLINE SavedContext(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedObject::init_type(); + register_type(_type_handle, "SavedContext", + TypedObject::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; +}; + +#include "savedContext.I" + +#endif + diff --git a/panda/src/display/textureContext.h b/panda/src/display/textureContext.h index f898709818..e3d9aa8793 100644 --- a/panda/src/display/textureContext.h +++ b/panda/src/display/textureContext.h @@ -21,7 +21,7 @@ #include -#include +#include "savedContext.h" class Texture; @@ -38,7 +38,7 @@ class Texture; // internal handle for the texture and store it here. // The texture stores all of these handles internally. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA TextureContext : public TypedObject { +class EXPCL_PANDA TextureContext : public SavedContext { public: INLINE TextureContext(Texture *tex); @@ -54,9 +54,9 @@ public: return _type_handle; } static void init_type() { - TypedObject::init_type(); + SavedContext::init_type(); register_type(_type_handle, "TextureContext", - TypedObject::get_class_type()); + SavedContext::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/downloader/asyncDownloader.cxx b/panda/src/downloader/asyncDownloader.cxx index b513ae32b7..b6a54de0b4 100644 --- a/panda/src/downloader/asyncDownloader.cxx +++ b/panda/src/downloader/asyncDownloader.cxx @@ -324,7 +324,7 @@ request_download(const string &file_name, const Filename &file_dest, _lock.lock(); #endif - if (_token_board->_waiting.is_full()) { + if (_token_board->_waiting.full()) { downloader_cat.error() << "Downloader::request_download() - Too many pending requests\n"; return 0; @@ -338,7 +338,7 @@ request_download(const string &file_name, const Filename &file_dest, tok = new DownloaderToken(_next_token++, file_name, file_dest, event_name, first_byte, last_byte, total_bytes, partial_content, sync); - _token_board->_waiting.insert(tok); + _token_board->_waiting.push_back(tok); #ifdef HAVE_IPC _request_cond->signal(); @@ -348,7 +348,7 @@ request_download(const string &file_name, const Filename &file_dest, } else { // If we're not running asynchronously, process the load request // directly now. - if (_token_board->_waiting.is_full()) { + if (_token_board->_waiting.full()) { downloader_cat.error() << "Downloader::request_download() - Too many pending requests\n"; return 0; @@ -361,7 +361,7 @@ request_download(const string &file_name, const Filename &file_dest, tok = new DownloaderToken(_next_token++, file_name, file_dest, event_name, first_byte, last_byte, total_bytes, partial_content, sync); - _token_board->_waiting.insert(tok); + _token_board->_waiting.push_back(tok); process_request(); } @@ -384,8 +384,9 @@ process_request() { } // If there is actually a request token - process it - while (!_token_board->_waiting.is_empty()) { - PT(DownloaderToken) tok = _token_board->_waiting.extract(); + while (!_token_board->_waiting.empty()) { + PT(DownloaderToken) tok = _token_board->_waiting.front(); + _token_board->_waiting.pop_front(); int ret = download(tok->_file_name, tok->_file_dest, tok->_event_name, tok->_first_byte, tok->_last_byte, tok->_total_bytes, tok->_partial_content, tok->_sync, tok->_id); @@ -393,7 +394,7 @@ process_request() { PT_Event return_event = new Event(tok->_event_name); return_event->add_parameter(EventParameter((int)tok->_id)); if (ret == DS_success) { - _token_board->_done.insert(tok); + _token_board->_done.push_back(tok); return_event->add_parameter(EventParameter(DS_success)); // Throw a "done" event now. diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx index 5c680e5adc..83b41e52ce 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx @@ -1170,7 +1170,7 @@ draw_prim_inner_loop(int nVerts, const Geom *geom, DWORD perFlags) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_point(const GeomPoint *geom) { +draw_point(GeomPoint *geom, GeomContext *gc) { activate(); #ifdef GSG_VERBOSE @@ -1314,7 +1314,7 @@ draw_point(const GeomPoint *geom) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_line(const GeomLine* geom) { +draw_line(GeomLine* geom, GeomContext *gc) { activate(); #ifdef GSG_VERBOSE @@ -1425,7 +1425,7 @@ draw_line(const GeomLine* geom) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_linestrip(const GeomLinestrip* geom) { +draw_linestrip(GeomLinestrip* geom, GeomContext *gc) { activate(); #ifdef GSG_VERBOSE @@ -1585,7 +1585,7 @@ struct draw_sprite_vertex_less { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_sprite(const GeomSprite *geom) { +draw_sprite(GeomSprite *geom, GeomContext *gc) { // this is a little bit of a mess, but it's ok. Here's the deal: // we want to draw, and draw quickly, an arbitrarily large number @@ -1909,7 +1909,7 @@ draw_sprite(const GeomSprite *geom) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_polygon(const GeomPolygon *geom) { +draw_polygon(GeomPolygon *geom, GeomContext *gc) { activate(); #ifdef GSG_VERBOSE @@ -1990,7 +1990,7 @@ draw_polygon(const GeomPolygon *geom) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_tri(const GeomTri *geom) { +draw_tri(GeomTri *geom, GeomContext *gc) { // activate(); #ifdef GSG_VERBOSE @@ -2290,7 +2290,7 @@ draw_tri(const GeomTri *geom) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_quad(const GeomQuad *geom) { +draw_quad(GeomQuad *geom, GeomContext *gc) { activate(); #if 1 @@ -2359,7 +2359,7 @@ draw_quad(const GeomQuad *geom) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_tristrip(const GeomTristrip *geom) { +draw_tristrip(GeomTristrip *geom, GeomContext *gc) { #ifdef GSG_VERBOSE dxgsg_cat.debug() << "draw_tristrip()" << endl; @@ -2375,7 +2375,7 @@ draw_tristrip(const GeomTristrip *geom) { // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_trifan(const GeomTrifan *geom) { +draw_trifan(GeomTrifan *geom, GeomContext *gc) { #ifdef GSG_VERBOSE dxgsg_cat.debug() << "draw_trifan()" << endl; @@ -2391,7 +2391,7 @@ draw_trifan(const GeomTrifan *geom) { // Description: handles trifans and tristrips //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_multitri(const Geom *geom, D3DPRIMITIVETYPE trilisttype) { +draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { int nPrims = geom->get_num_prims(); const int *pLengthArr = geom->get_lengths(); @@ -3000,7 +3000,7 @@ GenerateSphere(void *pVertexSpace,DWORD dwVertSpaceByteSize, // Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_sphere(const GeomSphere *geom) { +draw_sphere(GeomSphere *geom, GeomContext *gc) { #define SPHERE_NUMSLICES 16 #define SPHERE_NUMSTACKS 10 @@ -5340,6 +5340,7 @@ void DXGraphicsStateGuardian:: dx_cleanup() { release_all_textures(); + release_all_geoms(); // Do a safe check for releasing the D3DDEVICE. RefCount should be zero. if (_d3dDevice!=NULL) { diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.h b/panda/src/dxgsg/dxGraphicsStateGuardian.h index 9d1f69cc09..a6f885506b 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.h +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.h @@ -103,16 +103,16 @@ public: const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans); - virtual void draw_point(const GeomPoint *geom); - virtual void draw_line(const GeomLine *geom); - virtual void draw_linestrip(const GeomLinestrip *geom); - virtual void draw_sprite(const GeomSprite *geom); - virtual void draw_polygon(const GeomPolygon *geom); - virtual void draw_quad(const GeomQuad *geom); - virtual void draw_tri(const GeomTri *geom); - virtual void draw_tristrip(const GeomTristrip *geom); - virtual void draw_trifan(const GeomTrifan *geom); - virtual void draw_sphere(const GeomSphere *geom); + virtual void draw_point(GeomPoint *geom, GeomContext *gc); + virtual void draw_line(GeomLine *geom, GeomContext *gc); + virtual void draw_linestrip(GeomLinestrip *geom, GeomContext *gc); + virtual void draw_sprite(GeomSprite *geom, GeomContext *gc); + virtual void draw_polygon(GeomPolygon *geom, GeomContext *gc); + virtual void draw_quad(GeomQuad *geom, GeomContext *gc); + virtual void draw_tri(GeomTri *geom, GeomContext *gc); + virtual void draw_tristrip(GeomTristrip *geom, GeomContext *gc); + virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc); + virtual void draw_sphere(GeomSphere *geom, GeomContext *gc); virtual TextureContext *prepare_texture(Texture *tex); virtual void apply_texture(TextureContext *tc); @@ -264,7 +264,7 @@ protected: void draw_prim_inner_loop(int nVerts, const Geom *geom, DWORD perFlags); size_t draw_prim_setup(const Geom *geom) ; - void draw_multitri(const Geom *geom, D3DPRIMITIVETYPE tri_id); + void draw_multitri(Geom *geom, D3DPRIMITIVETYPE tri_id); #ifdef DO_PSTATS void report_texmgr_stats(); diff --git a/panda/src/event/eventQueue.cxx b/panda/src/event/eventQueue.cxx index b1e1c8a2a7..f653aff29e 100644 --- a/panda/src/event/eventQueue.cxx +++ b/panda/src/event/eventQueue.cxx @@ -50,11 +50,11 @@ queue_event(CPT_Event event) { #ifdef HAVE_IPC mutex_lock lock(_lock); #endif - if (_queue.is_full()) { + if (_queue.full()) { event_cat.error() << "Ignoring event " << *event << "; event queue full.\n"; } else { - _queue.insert(event); + _queue.push_back(event); if (event_cat.is_spam() || event_cat.is_debug()) { if (event->get_name() == "NewFrame") { // Don't bother us with this particularly spammy event. @@ -75,7 +75,7 @@ queue_event(CPT_Event event) { //////////////////////////////////////////////////////////////////// bool EventQueue:: is_queue_empty() const { - return _queue.is_empty(); + return _queue.empty(); } @@ -88,7 +88,9 @@ CPT_Event EventQueue:: dequeue_event() { // We need no mutex protection here, as long as there is only one // thread extracting events. The magic of circular buffers. - return _queue.extract(); + CPT_Event result = _queue.front(); + _queue.pop_front(); + return result; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/express/circBuffer.I b/panda/src/express/circBuffer.I index 515dd11b18..a688a1a31e 100644 --- a/panda/src/express/circBuffer.I +++ b/panda/src/express/circBuffer.I @@ -33,54 +33,130 @@ CircBuffer() { _in = _out = 0; } - //////////////////////////////////////////////////////////////////// -// Function: CircBuffer::is_empty +// Function: CircBuffer::Destructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// template +INLINE CircBuffer:: +~CircBuffer() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CircBuffer::size +// Access: Public +// Description: Returns the number of items currently in the buffer. +// This can safely be called without synchronization +// from either the reader or the writer thread, but the +// size may of course vary without warning after the +// call. +//////////////////////////////////////////////////////////////////// +template +INLINE int CircBuffer:: +size() const { + int diff = _in - _out; + return (diff >= 0) ? diff : max_size + 1 - diff; +} + +//////////////////////////////////////////////////////////////////// +// Function: CircBuffer::empty +// Access: Public +// Description: Returns true if the buffer is empty. It is safe to +// call this without synchronization primitives from +// either the reader or the writer thread, but the +// result may vary without warning after the call. +//////////////////////////////////////////////////////////////////// +template INLINE bool CircBuffer:: -is_empty() const { +empty() const { return _in == _out; } - //////////////////////////////////////////////////////////////////// -// Function: CircBuffer::is_full +// Function: CircBuffer::full // Access: Public -// Description: +// Description: Returns true if the buffer is full; if this is true, +// push_back() will fail. It is safe to call this +// without synchronization primitives from either the +// reader or the writer thread, but the result may vary +// without warning after the call. //////////////////////////////////////////////////////////////////// template INLINE bool CircBuffer:: -is_full() const { - return _in == _out-1 || (_in==max_size && _out==0); +full() const { + // return _in == _out-1 || (_in==max_size && _out==0); + return ((_in + 1) % (max_size + 1)) == _out; } - //////////////////////////////////////////////////////////////////// -// Function: CircBuffer::peek +// Function: CircBuffer::front // Access: Public -// Description: +// Description: Returns a reference to the first item in the queue. +// It is invalid to call this if empty() is true. It is +// safe to call this without synchronization only from +// the reading thread: the thread that calls pop_front(). //////////////////////////////////////////////////////////////////// template INLINE const Thing &CircBuffer:: -peek() const { - nassertr(!is_empty(), *(new Thing)); +front() const { + nassertr(!empty(), _array[0]); return _array[_out]; } +//////////////////////////////////////////////////////////////////// +// Function: CircBuffer::front +// Access: Public +// Description: Returns a reference to the first item in the queue. +// It is invalid to call this if empty() is true. It is +// safe to call this without synchronization only from +// the reading thread: the thread that calls pop_front(). +//////////////////////////////////////////////////////////////////// +template +INLINE Thing &CircBuffer:: +front() { + nassertr(!empty(), _array[0]); + return _array[_out]; +} + +//////////////////////////////////////////////////////////////////// +// Function: CircBuffer::operator [] +// Access: Public +// Description: Returns the nth element in the buffer. It is safe to +// call this without synchronization only from the +// reading thread: the thread that calls pop_front(). +//////////////////////////////////////////////////////////////////// +template +INLINE const Thing &CircBuffer:: +operator[] (int n) const { + nassertr(!empty(), _array[0]); + return _array[(_out + n) % (max_size + 1)]; +} + +//////////////////////////////////////////////////////////////////// +// Function: CircBuffer::operator [] +// Access: Public +// Description: Returns the nth element in the buffer. It is safe to +// call this without synchronization only from the +// reading thread: the thread that calls pop_front(). +//////////////////////////////////////////////////////////////////// +template +INLINE Thing &CircBuffer:: +operator[] (int n) { + nassertr(!empty(), _array[0]); + return _array[(_out + n) % (max_size + 1)]; +} + //////////////////////////////////////////////////////////////////// -// Function: CircBuffer::extract +// Function: CircBuffer::pop_front // Access: Public -// Description: +// Description: Removes the first item from the buffer. //////////////////////////////////////////////////////////////////// template -INLINE Thing CircBuffer:: -extract() { - nassertr(!is_empty(), Thing()); - Thing temp = _array[_out]; +INLINE void CircBuffer:: +pop_front() { + nassertv(!empty()); // We need to clear out the old element to force its destructor to // be called; it might be important. This will generate yet another @@ -89,19 +165,53 @@ extract() { _array[_out] = Thing(); _out = (_out+1)%(max_size+1); - return temp; } + + //////////////////////////////////////////////////////////////////// -// Function: CircBuffer::insert +// Function: CircBuffer::back // Access: Public -// Description: +// Description: Returns a reference to the last item in the queue. +// It is invalid to call this if empty() is true. It is +// safe to call this without synchronization primitives +// only from the writing thread: the thread that calls +// push_back(). +//////////////////////////////////////////////////////////////////// +template +INLINE const Thing &CircBuffer:: +back() const { + nassertr(!empty(), _array[0]); + return _array[(_in + max_size) % (max_size + 1)]; +} + +//////////////////////////////////////////////////////////////////// +// Function: CircBuffer::back +// Access: Public +// Description: Returns a reference to the last item in the queue. +// It is invalid to call this if empty() is true. It is +// safe to call this without synchronization primitives +// only from the writing thread: the thread that calls +// push_back(). +//////////////////////////////////////////////////////////////////// +template +INLINE Thing &CircBuffer:: +back() { + nassertr(!empty(), _array[0]); + return _array[(_in + max_size) % (max_size + 1)]; +} + +//////////////////////////////////////////////////////////////////// +// Function: CircBuffer::push_back +// Access: Public +// Description: Adds an item to the end of the buffer. This may fail +// if full() is true. //////////////////////////////////////////////////////////////////// template INLINE void CircBuffer:: -insert(const Thing &t) { - if (is_full()) { +push_back(const Thing &t) { + if (full()) { express_cat.error() << "Circular buffer is full; cannot add requests.\n"; } else { diff --git a/panda/src/express/circBuffer.h b/panda/src/express/circBuffer.h index 22a230cfe8..a58a89d760 100644 --- a/panda/src/express/circBuffer.h +++ b/panda/src/express/circBuffer.h @@ -35,16 +35,32 @@ template class CircBuffer { public: INLINE CircBuffer(); + INLINE ~CircBuffer(); - INLINE bool is_empty() const; - INLINE bool is_full() const; + // Methods that are safe to call without synchronization primitives + // from either thread. + INLINE int size() const; - INLINE const Thing &peek() const; - INLINE Thing extract(); + // Methods that are safe to call without synchronization primitives + // only from the reader thread. + INLINE bool empty() const; - INLINE void insert(const Thing &t); + INLINE const Thing &front() const; + INLINE Thing &front(); + INLINE void pop_front(); -protected: + INLINE const Thing &operator[] (int n) const; + INLINE Thing &operator[] (int n); + + // Methods that are safe to call without synchronization primitives + // only from the writer thread. + INLINE bool full() const; + + INLINE const Thing &back() const; + INLINE Thing &back(); + INLINE void push_back(const Thing &t); + +private: Thing _array[max_size+1]; int _in, _out; }; diff --git a/panda/src/express/tokenBoard.I b/panda/src/express/tokenBoard.I index de71736f06..20f0ecc091 100644 --- a/panda/src/express/tokenBoard.I +++ b/panda/src/express/tokenBoard.I @@ -29,8 +29,9 @@ is_done_token(int id) { // to do this since we can only examine tokens on the head of the // done list, and the token we're looking for might not be at the // head. - while (!_done.is_empty()) { - _really_done.push_back(_done.extract()); + while (!_done.empty()) { + _really_done.push_back(_done.front()); + _done.pop_front(); } // Now we can search really_done for our desired id. @@ -57,8 +58,9 @@ get_done_token(int id) { // to do this since we can only examine tokens on the head of the // done list, and the token we're looking for might not be at the // head. - while (!_done.is_empty()) { - _really_done.push_back(_done.extract()); + while (!_done.empty()) { + _really_done.push_back(_done.front()); + _done.pop_front(); } // Now we can search really_done for our desired id. diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 68ded92666..dae913fa57 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -190,6 +190,7 @@ GLGraphicsStateGuardian:: ~GLGraphicsStateGuardian() { free_pointers(); release_all_textures(); + release_all_geoms(); } //////////////////////////////////////////////////////////////////// @@ -720,7 +721,7 @@ render_subgraph(RenderTraverser *traverser, Node *subgraph, // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_point(const GeomPoint *geom) { +draw_point(GeomPoint *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -779,7 +780,7 @@ draw_point(const GeomPoint *geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_line(const GeomLine* geom) { +draw_line(GeomLine *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -840,7 +841,7 @@ draw_line(const GeomLine* geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_linestrip(const GeomLinestrip* geom) { +draw_linestrip(GeomLinestrip *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -940,7 +941,7 @@ struct draw_sprite_vertex_less { }; void GLGraphicsStateGuardian:: -draw_sprite(const GeomSprite *geom) { +draw_sprite(GeomSprite *geom, GeomContext *) { // this is a little bit of a mess, but it's ok. Here's the deal: // we want to draw, and draw quickly, an arbitrarily large number // of sprites all facing the screen. Performing the billboard math @@ -1226,7 +1227,7 @@ draw_sprite(const GeomSprite *geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_polygon(const GeomPolygon *geom) { +draw_polygon(GeomPolygon *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -1299,7 +1300,7 @@ draw_polygon(const GeomPolygon *geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_tri(const GeomTri *geom) { +draw_tri(GeomTri *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -1367,7 +1368,7 @@ draw_tri(const GeomTri *geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_quad(const GeomQuad *geom) { +draw_quad(GeomQuad *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -1435,7 +1436,7 @@ draw_quad(const GeomQuad *geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_tristrip(const GeomTristrip *geom) { +draw_tristrip(GeomTristrip *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -1525,7 +1526,7 @@ draw_tristrip(const GeomTristrip *geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_trifan(const GeomTrifan *geom) { +draw_trifan(GeomTrifan *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE @@ -1616,7 +1617,7 @@ draw_trifan(const GeomTrifan *geom) { // Description: //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: -draw_sphere(const GeomSphere *geom) { +draw_sphere(GeomSphere *geom, GeomContext *) { // activate(); #ifdef GSG_VERBOSE diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index 327dc38679..fa48b0e398 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -87,16 +87,16 @@ public: const AllAttributesWrapper &initial_state, const AllTransitionsWrapper &net_trans); - virtual void draw_point(const GeomPoint *geom); - virtual void draw_line(const GeomLine *geom); - virtual void draw_linestrip(const GeomLinestrip *geom); - virtual void draw_sprite(const GeomSprite *geom); - virtual void draw_polygon(const GeomPolygon *geom); - virtual void draw_quad(const GeomQuad *geom); - virtual void draw_tri(const GeomTri *geom); - virtual void draw_tristrip(const GeomTristrip *geom); - virtual void draw_trifan(const GeomTrifan *geom); - virtual void draw_sphere(const GeomSphere *geom); + virtual void draw_point(GeomPoint *geom, GeomContext *gc); + virtual void draw_line(GeomLine *geom, GeomContext *gc); + virtual void draw_linestrip(GeomLinestrip *geom, GeomContext *gc); + virtual void draw_sprite(GeomSprite *geom, GeomContext *gc); + virtual void draw_polygon(GeomPolygon *geom, GeomContext *gc); + virtual void draw_quad(GeomQuad *geom, GeomContext *gc); + virtual void draw_tri(GeomTri *geom, GeomContext *gc); + virtual void draw_tristrip(GeomTristrip *geom, GeomContext *gc); + virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc); + virtual void draw_sphere(GeomSphere *geom, GeomContext *gc); virtual TextureContext *prepare_texture(Texture *tex); virtual void apply_texture(TextureContext *tc); @@ -111,7 +111,7 @@ public: virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb); virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr); + const DisplayRegion *dr); virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, diff --git a/panda/src/gobj/drawable.cxx b/panda/src/gobj/drawable.cxx index d0cf5dc100..56c7ba487c 100644 --- a/panda/src/gobj/drawable.cxx +++ b/panda/src/gobj/drawable.cxx @@ -20,6 +20,38 @@ TypeHandle dDrawable::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: Drawable::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +dDrawable:: +dDrawable() : WritableConfigurable() { + MemoryUsage::update_type(this, this); +} + +//////////////////////////////////////////////////////////////////// +// Function: Drawable::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +dDrawable:: +~dDrawable() { +} + +//////////////////////////////////////////////////////////////////// +// Function: Drawable::draw +// Access: Public, Virtual +// Description: Actually draws the Drawable with the indicated GSG. +// At this level, this doesn't do very much. +//////////////////////////////////////////////////////////////////// +void dDrawable:: +draw(GraphicsStateGuardianBase *) { + if (is_dirty()) { + config(); + } +} + //////////////////////////////////////////////////////////////////// // Function: Drawable::propagate_stale_bound // Access: Protected, Virtual diff --git a/panda/src/gobj/drawable.h b/panda/src/gobj/drawable.h index 8b82e7233c..cc83d877dd 100644 --- a/panda/src/gobj/drawable.h +++ b/panda/src/gobj/drawable.h @@ -46,15 +46,13 @@ class BamWriter; // to their variable names //////////////////////////////////////////////////////////////////// class EXPCL_PANDA dDrawable : public ReferenceCount, public WritableConfigurable, - public BoundedObject { + public BoundedObject { public: - dDrawable() : WritableConfigurable() { - MemoryUsage::update_type(this, this); - } - virtual ~dDrawable() { } + dDrawable(); + virtual ~dDrawable(); - virtual void draw(GraphicsStateGuardianBase *) { if (is_dirty()) config(); } + virtual void draw(GraphicsStateGuardianBase *); protected: virtual void propagate_stale_bound(); diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index f4a3bb8993..8045d64001 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -142,6 +142,8 @@ ostream &operator << (ostream &out, GeomAttrType t) { //////////////////////////////////////////////////////////////////// Geom:: Geom(void) : dDrawable() { + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomContext *)NULL; init(); } @@ -152,6 +154,8 @@ Geom(void) : dDrawable() { //////////////////////////////////////////////////////////////////// Geom:: Geom(const Geom& copy) : dDrawable() { + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomContext *)NULL; *this = copy; } @@ -161,7 +165,8 @@ Geom(const Geom& copy) : dDrawable() { // Description: //////////////////////////////////////////////////////////////////// Geom:: -~Geom(void) { +~Geom() { + unprepare(); } //////////////////////////////////////////////////////////////////// @@ -192,8 +197,8 @@ operator = (const Geom ©) { _get_color = copy._get_color; _get_texcoord = copy._get_texcoord; - if (copy.is_dirty()) - make_dirty(); + mark_bound_stale(); + make_dirty(); } //////////////////////////////////////////////////////////////////// @@ -376,13 +381,30 @@ get_tris() const { return PTA_ushort(); } +//////////////////////////////////////////////////////////////////// +// Function: Geom::draw +// Access: Public, Virtual +// Description: Actually draws the Geom with the indicated GSG. +//////////////////////////////////////////////////////////////////// +void Geom:: +draw(GraphicsStateGuardianBase *gsg) { + if (is_dirty()) { + config(); + } + if (_prepared_gsg == gsg) { + draw_immediate(gsg, _prepared_context); + } else { + draw_immediate(gsg, (GeomContext *)NULL); + } +} + //////////////////////////////////////////////////////////////////// // Function: Geom::config -// Access: Public +// Access: Public, Virtual // Description: Configure rendering based on current settings //////////////////////////////////////////////////////////////////// void Geom:: -config(void) { +config() { WritableConfigurable::config(); // Only per vertex binding makes any sense @@ -417,6 +439,9 @@ config(void) { } else { _get_color = get_color_noop; } + + // Mark the Geom as needing to be prepared again. + unprepare(); } //////////////////////////////////////////////////////////////////// @@ -448,12 +473,86 @@ output(ostream &out) const { } //////////////////////////////////////////////////////////////////// -// Function: Geom::init +// Function: Geom::prepare // Access: Public +// Description: Creates a context for the Geom on the particular +// GSG, if it does not already exist. Returns the new +// (or old) GeomContext. +// +// If the given GeomContext pointer is non-NULL, it will +// be passed to the GSG, which may or may not choose to +// extend the existing GeomContext, or create a totally +// new one. +//////////////////////////////////////////////////////////////////// +GeomContext *Geom:: +prepare(GraphicsStateGuardianBase *gsg) { + if (gsg != _prepared_gsg) { + GeomContext *gc = gsg->prepare_geom(this); + if (gc != (GeomContext *)NULL) { + unprepare(); + _prepared_context = gc; + _prepared_gsg = gsg; + } + return gc; + } + + return _prepared_context; +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::unprepare +// Access: Public +// Description: Frees the context allocated on all GSG's for which +// the geom has been declared. +//////////////////////////////////////////////////////////////////// +void Geom:: +unprepare() { + if (_prepared_gsg != (GraphicsStateGuardianBase *)NULL) { + _prepared_gsg->release_geom(_prepared_context); + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomContext *)NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::unprepare +// Access: Public +// Description: Frees the geom context only on the indicated GSG, +// if it exists there. +//////////////////////////////////////////////////////////////////// +void Geom:: +unprepare(GraphicsStateGuardianBase *gsg) { + if (_prepared_gsg == gsg) { + _prepared_gsg->release_geom(_prepared_context); + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomContext *)NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::clear_gsg +// Access: Public +// Description: Removes the indicated GSG from the Geom's known +// GSG's, without actually releasing the geom on that +// GSG. This is intended to be called only from +// GSG::release_geom(); it should never be called by +// user code. +//////////////////////////////////////////////////////////////////// +void Geom:: +clear_gsg(GraphicsStateGuardianBase *gsg) { + if (_prepared_gsg == gsg) { + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomContext *)NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::init +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// void Geom:: -init(void) { +init() { int i; _coords.clear(); @@ -779,10 +878,12 @@ write_verbose(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// // Function: Geom::get_min_max // Access: Public -// Description: +// Description: Expands min and max, if necessary, to include the +// complete bounding rectangle that encloses all the +// vertices. //////////////////////////////////////////////////////////////////// void Geom:: -get_min_max(Vertexf& min, Vertexf& max) const { +get_min_max(Vertexf &min, Vertexf &max) const { int numv = _coords.size(); for (int i = 0; i < numv; i++) { diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index f8a16e4807..934ac4a6b0 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -113,11 +113,11 @@ public: typedef const Colorf &GetNextColor(ColorIterator &); - Geom( void ); - Geom( const Geom& copy ); - ~Geom( void ); + Geom(); + Geom(const Geom ©); + ~Geom(); - void operator = ( const Geom © ); + void operator = (const Geom ©); virtual Geom *make_copy() const=0; PUBLISHED: @@ -127,51 +127,49 @@ PUBLISHED: public: // From parent dDrawable - virtual void draw(GraphicsStateGuardianBase *gsg) { - dDrawable::draw(gsg); draw_immediate(gsg); - } + virtual void draw(GraphicsStateGuardianBase *gsg); // From parent Configurable - virtual void config( void ); + virtual void config(); // Immediate mode drawing functions - issue graphics commands - virtual void draw_immediate(GraphicsStateGuardianBase *) const = 0; - virtual void print_draw_immediate( void ) const = 0; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) = 0; + virtual void print_draw_immediate() const = 0; public: - void get_min_max( Vertexf& min, Vertexf& max ) const; + void get_min_max(Vertexf &min, Vertexf &max) const; - void set_coords( const PTA_Vertexf &coords, + void set_coords(const PTA_Vertexf &coords, + GeomBindType bind, + const PTA_ushort &vindex = + PTA_ushort()); + void set_normals(const PTA_Normalf &norms, GeomBindType bind, - const PTA_ushort &vindex = - PTA_ushort() ); - void set_normals( const PTA_Normalf &norms, - GeomBindType bind, - const PTA_ushort &nindex = - PTA_ushort() ); - void set_colors( const PTA_Colorf &colors, - GeomBindType bind, - const PTA_ushort &cindex = - PTA_ushort() ); - void set_texcoords( const PTA_TexCoordf &texcoords, - GeomBindType bind, - const PTA_ushort &tindex = - PTA_ushort() ); + const PTA_ushort &nindex = + PTA_ushort()); + void set_colors(const PTA_Colorf &colors, + GeomBindType bind, + const PTA_ushort &cindex = + PTA_ushort()); + void set_texcoords(const PTA_TexCoordf &texcoords, + GeomBindType bind, + const PTA_ushort &tindex = + PTA_ushort()); - void get_coords( PTA_Vertexf &coords, + void get_coords(PTA_Vertexf &coords, + GeomBindType &bind, + PTA_ushort &vindex) const; + void get_normals(PTA_Normalf &norms, GeomBindType &bind, - PTA_ushort &vindex) const; - void get_normals( PTA_Normalf &norms, - GeomBindType &bind, - PTA_ushort &nindex) const; - void get_colors( PTA_Colorf &colors, - GeomBindType &bind, - PTA_ushort &cindex) const; - void get_texcoords( PTA_TexCoordf &texcoords, - GeomBindType &bind, - PTA_ushort &tindex) const; + PTA_ushort &nindex) const; + void get_colors(PTA_Colorf &colors, + GeomBindType &bind, + PTA_ushort &cindex) const; + void get_texcoords(PTA_TexCoordf &texcoords, + GeomBindType &bind, + PTA_ushort &tindex) const; PUBLISHED: INLINE GeomBindType get_binding(int attr) const; @@ -186,7 +184,7 @@ PUBLISHED: public: INLINE void set_num_prims(int num); - INLINE int get_num_prims(void) const; + INLINE int get_num_prims() const; INLINE void set_lengths(const PTA_int &lengths); INLINE PTA_int get_lengths() const; @@ -219,9 +217,13 @@ public: INLINE ColorIterator make_color_iterator() const; INLINE const Colorf &get_next_color(ColorIterator &citerator) const; -protected: + GeomContext *prepare(GraphicsStateGuardianBase *gsg); + void unprepare(); + void unprepare(GraphicsStateGuardianBase *gsg); + void clear_gsg(GraphicsStateGuardianBase *gsg); - void init( void ); +protected: + void init(); virtual void recompute_bound(); protected: @@ -246,6 +248,14 @@ protected: GetNextTexCoord *_get_texcoord; GetNextColor *_get_color; + // Unlike a Texture, a Geom only stores the pointer to one GSG that + // it has been prepared into. If it is prepared into another GSG, + // it automatically unprepares itself from the first one. This is + // intended to reduce memory overhead that would otherwise be + // required to support a little-used feature (having two + // simultaneous GSG's). + GraphicsStateGuardianBase *_prepared_gsg; + GeomContext *_prepared_context; public: //static void register_with_read_factory(void); diff --git a/panda/src/gobj/geomLine.cxx b/panda/src/gobj/geomLine.cxx index 4119b27b3f..8c86ab1f93 100644 --- a/panda/src/gobj/geomLine.cxx +++ b/panda/src/gobj/geomLine.cxx @@ -48,8 +48,8 @@ make_copy() const { // Description: //////////////////////////////////////////////////////////////////// void GeomLine:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_line(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_line(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomLine.h b/panda/src/gobj/geomLine.h index b314d0b4f4..d94112ba4f 100644 --- a/panda/src/gobj/geomLine.h +++ b/panda/src/gobj/geomLine.h @@ -31,7 +31,7 @@ public: GeomLine( void ) : Geom() { _width = 1.0; } virtual Geom *make_copy() const; virtual void print_draw_immediate( void ) const { } - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 2; diff --git a/panda/src/gobj/geomLinestrip.cxx b/panda/src/gobj/geomLinestrip.cxx index 2941cb2acf..63b86beaf0 100644 --- a/panda/src/gobj/geomLinestrip.cxx +++ b/panda/src/gobj/geomLinestrip.cxx @@ -49,8 +49,8 @@ make_copy() const { // Description: //////////////////////////////////////////////////////////////////// void GeomLinestrip:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_linestrip(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_linestrip(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomLinestrip.h b/panda/src/gobj/geomLinestrip.h index 0415fd9296..63d661e0c9 100644 --- a/panda/src/gobj/geomLinestrip.h +++ b/panda/src/gobj/geomLinestrip.h @@ -31,7 +31,7 @@ public: GeomLinestrip(void) : Geom() { _width = 1.0; } virtual Geom *make_copy() const; virtual void print_draw_immediate( void ) const { } - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); // Undefined for this type of primitive virtual int get_num_vertices_per_prim() const { diff --git a/panda/src/gobj/geomPoint.cxx b/panda/src/gobj/geomPoint.cxx index ed59338630..618a803bc8 100644 --- a/panda/src/gobj/geomPoint.cxx +++ b/panda/src/gobj/geomPoint.cxx @@ -57,8 +57,8 @@ print_draw_immediate(void) const { // Description: //////////////////////////////////////////////////////////////////// void GeomPoint:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_point(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_point(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomPoint.h b/panda/src/gobj/geomPoint.h index 4db33e3306..7b13922f0b 100644 --- a/panda/src/gobj/geomPoint.h +++ b/panda/src/gobj/geomPoint.h @@ -31,7 +31,7 @@ public: virtual Geom *make_copy() const; virtual void print_draw_immediate() const; - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 1; diff --git a/panda/src/gobj/geomPolygon.cxx b/panda/src/gobj/geomPolygon.cxx index d576729f91..a5fe24de8a 100644 --- a/panda/src/gobj/geomPolygon.cxx +++ b/panda/src/gobj/geomPolygon.cxx @@ -57,8 +57,8 @@ print_draw_immediate(void) const { // Description: //////////////////////////////////////////////////////////////////// void GeomPolygon:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_polygon(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_polygon(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomPolygon.h b/panda/src/gobj/geomPolygon.h index 01ef6d2dcb..112f44ca80 100644 --- a/panda/src/gobj/geomPolygon.h +++ b/panda/src/gobj/geomPolygon.h @@ -30,7 +30,7 @@ public: GeomPolygon() : Geom() { } virtual Geom *make_copy() const; virtual void print_draw_immediate() const; - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 0; diff --git a/panda/src/gobj/geomQuad.cxx b/panda/src/gobj/geomQuad.cxx index 0283be107a..1c93f87c6e 100644 --- a/panda/src/gobj/geomQuad.cxx +++ b/panda/src/gobj/geomQuad.cxx @@ -58,8 +58,8 @@ print_draw_immediate(void) const { // Description: //////////////////////////////////////////////////////////////////// void GeomQuad:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_quad(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_quad(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomQuad.h b/panda/src/gobj/geomQuad.h index dd40e50edc..821c9e27da 100644 --- a/panda/src/gobj/geomQuad.h +++ b/panda/src/gobj/geomQuad.h @@ -30,7 +30,7 @@ public: GeomQuad() { } virtual Geom *make_copy() const; virtual void print_draw_immediate() const; - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 4; diff --git a/panda/src/gobj/geomSphere.cxx b/panda/src/gobj/geomSphere.cxx index 4f827c5a94..4f5db73282 100644 --- a/panda/src/gobj/geomSphere.cxx +++ b/panda/src/gobj/geomSphere.cxx @@ -40,8 +40,8 @@ make_copy() const { } void GeomSphere:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_sphere(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_sphere(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomSphere.h b/panda/src/gobj/geomSphere.h index 816b3d2fe1..399b51bf58 100644 --- a/panda/src/gobj/geomSphere.h +++ b/panda/src/gobj/geomSphere.h @@ -42,7 +42,7 @@ public: GeomSphere() : Geom() { } virtual Geom *make_copy() const; virtual void print_draw_immediate() const { } - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 2; diff --git a/panda/src/gobj/geomSprite.cxx b/panda/src/gobj/geomSprite.cxx index efdefadf35..de648921e7 100644 --- a/panda/src/gobj/geomSprite.cxx +++ b/panda/src/gobj/geomSprite.cxx @@ -75,8 +75,8 @@ print_draw_immediate(void) const { // Description: //////////////////////////////////////////////////////////////////// void GeomSprite:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_sprite(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_sprite(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomSprite.h b/panda/src/gobj/geomSprite.h index 2acec7eca4..1c3b532194 100644 --- a/panda/src/gobj/geomSprite.h +++ b/panda/src/gobj/geomSprite.h @@ -33,7 +33,7 @@ public: virtual Geom *make_copy() const; virtual void print_draw_immediate() const; - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 1; } virtual int get_num_more_vertices_than_components() const { return 0; } diff --git a/panda/src/gobj/geomTri.cxx b/panda/src/gobj/geomTri.cxx index 4aa576f7fa..25aacfef28 100644 --- a/panda/src/gobj/geomTri.cxx +++ b/panda/src/gobj/geomTri.cxx @@ -183,8 +183,8 @@ print_draw_immediate(void) const // Description: //////////////////////////////////////////////////////////////////// void GeomTri:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_tri(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_tri(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomTri.h b/panda/src/gobj/geomTri.h index db6f17dd41..9d2eae2812 100644 --- a/panda/src/gobj/geomTri.h +++ b/panda/src/gobj/geomTri.h @@ -30,7 +30,7 @@ public: GeomTri() { } virtual Geom *make_copy() const; virtual void print_draw_immediate() const; - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 3; diff --git a/panda/src/gobj/geomTrifan.cxx b/panda/src/gobj/geomTrifan.cxx index 5d1c325e1c..30c795ff0f 100644 --- a/panda/src/gobj/geomTrifan.cxx +++ b/panda/src/gobj/geomTrifan.cxx @@ -199,8 +199,8 @@ print_draw_immediate( void ) const // Description: //////////////////////////////////////////////////////////////////// void GeomTrifan:: -draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_trifan(this); +draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_trifan(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomTrifan.h b/panda/src/gobj/geomTrifan.h index a6baacbe8d..bc0a1172ff 100644 --- a/panda/src/gobj/geomTrifan.h +++ b/panda/src/gobj/geomTrifan.h @@ -32,7 +32,7 @@ public: virtual Geom *make_copy() const; virtual void print_draw_immediate( void ) const; int get_num_tris( void ) const; - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 0; diff --git a/panda/src/gobj/geomTristrip.cxx b/panda/src/gobj/geomTristrip.cxx index 859afde300..dee42b2488 100644 --- a/panda/src/gobj/geomTristrip.cxx +++ b/panda/src/gobj/geomTristrip.cxx @@ -272,8 +272,8 @@ void GeomTristrip::print_draw_immediate( void ) const // Access: // Description: //////////////////////////////////////////////////////////////////// -void GeomTristrip::draw_immediate(GraphicsStateGuardianBase *gsg) const { - gsg->draw_tristrip(this); +void GeomTristrip::draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) { + gsg->draw_tristrip(this, gc); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomTristrip.h b/panda/src/gobj/geomTristrip.h index 66ca574369..0dc00ace44 100644 --- a/panda/src/gobj/geomTristrip.h +++ b/panda/src/gobj/geomTristrip.h @@ -31,7 +31,7 @@ public: virtual Geom *make_copy() const; virtual void print_draw_immediate() const; int get_num_tris() const; - virtual void draw_immediate(GraphicsStateGuardianBase *gsg) const; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); virtual int get_num_vertices_per_prim() const { return 0; diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 846bfd78fe..aaaba163a9 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -30,6 +30,10 @@ class RenderBuffer; class GraphicsWindow; +class GeomContext; +class GeomNodeContext; +class GeomNode; +class Geom; class GeomPoint; class GeomLine; class GeomLinestrip; @@ -111,21 +115,28 @@ public: // inconvenient to declare each of those types to be friends of this // class. - virtual void draw_point(const GeomPoint *geom)=0; - virtual void draw_line(const GeomLine *geom)=0; - virtual void draw_linestrip(const GeomLinestrip *geom)=0; - virtual void draw_sprite(const GeomSprite *geom)=0; - virtual void draw_polygon(const GeomPolygon *geom)=0; - virtual void draw_quad(const GeomQuad *geom)=0; - virtual void draw_tri(const GeomTri *geom)=0; - virtual void draw_tristrip(const GeomTristrip *geom)=0; - virtual void draw_trifan(const GeomTrifan *geom)=0; - virtual void draw_sphere(const GeomSphere *geom)=0; - virtual TextureContext *prepare_texture(Texture *tex)=0; virtual void apply_texture(TextureContext *tc)=0; virtual void release_texture(TextureContext *tc)=0; + virtual GeomNodeContext *prepare_geom_node(GeomNode *node)=0; + virtual void draw_geom_node(GeomNode *node, GeomNodeContext *gnc)=0; + virtual void release_geom_node(GeomNodeContext *gnc)=0; + + virtual GeomContext *prepare_geom(Geom *geom)=0; + virtual void release_geom(GeomContext *gc)=0; + + virtual void draw_point(GeomPoint *geom, GeomContext *gc)=0; + virtual void draw_line(GeomLine *geom, GeomContext *gc)=0; + virtual void draw_linestrip(GeomLinestrip *geom, GeomContext *gc)=0; + virtual void draw_sprite(GeomSprite *geom, GeomContext *gc)=0; + virtual void draw_polygon(GeomPolygon *geom, GeomContext *gc)=0; + virtual void draw_quad(GeomQuad *geom, GeomContext *gc)=0; + virtual void draw_tri(GeomTri *geom, GeomContext *gc)=0; + virtual void draw_tristrip(GeomTristrip *geom, GeomContext *gc)=0; + virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc)=0; + virtual void draw_sphere(GeomSphere *geom, GeomContext *gc)=0; + virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr)=0; virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb)=0; diff --git a/panda/src/loader/loader.cxx b/panda/src/loader/loader.cxx index d421e9d40a..ca8fce44da 100644 --- a/panda/src/loader/loader.cxx +++ b/panda/src/loader/loader.cxx @@ -149,7 +149,7 @@ request_load(const Filename &filename, const string &event_name) { _lock.lock(); #endif - if (_token_board->_waiting.is_full()) { + if (_token_board->_waiting.full()) { loader_cat.error() << "Loader::request_load() - Too many pending requests\n"; return 0; @@ -161,7 +161,7 @@ request_load(const Filename &filename, const string &event_name) { } tok = new LoaderToken(_next_token++, filename, event_name); - _token_board->_waiting.insert(tok); + _token_board->_waiting.push_back(tok); #ifdef HAVE_IPC _request_cond->signal(); @@ -171,7 +171,7 @@ request_load(const Filename &filename, const string &event_name) { } else { // If we're not running asynchronously, process the load request // directly now. - if (_token_board->_waiting.is_full()) { + if (_token_board->_waiting.full()) { loader_cat.error() << "Loader::request_load() - Too many pending requests\n"; return 0; @@ -183,7 +183,7 @@ request_load(const Filename &filename, const string &event_name) { } tok = new LoaderToken(_next_token++, filename, event_name); - _token_board->_waiting.insert(tok); + _token_board->_waiting.push_back(tok); process_request(); } @@ -264,15 +264,16 @@ process_request() { } // If there is actually a request token - process it - while (!_token_board->_waiting.is_empty()) { - PT(LoaderToken) tok = _token_board->_waiting.extract(); + while (!_token_board->_waiting.empty()) { + PT(LoaderToken) tok = _token_board->_waiting.front(); + _token_board->_waiting.pop_front(); tok->_node = load_file(tok->_path); if (tok->_node == NULL) { loader_cat.error() << "Loader::callback() - couldn't find file: " << tok->_path << "\n"; } else { - _token_board->_done.insert(tok); + _token_board->_done.push_back(tok); // Throw a "done" event now. if (!tok->_event_name.empty()) { diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index e255fd9071..49779f8e13 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -137,6 +137,10 @@ static LevelCollectorProperties level_properties[] = { { 1, "Texture memory:In use", { 0.0, 1.0, 1.0 } }, { 1, "Texture manager", { 1.0, 0.0, 0.0 }, "MB", 12, 1048576 }, { 1, "Texture manager:Resident", { 1.0, 1.0, 0.0 } }, + { 1, "Prepared Geoms", { 1.0, 0.0, 0.5 }, "", 500 }, + { 1, "Prepared Geoms:Active", { 0.5, 1.0, 0.8 } }, + { 1, "Prepared GeomNodes", { 1.0, 0.0, 0.5 }, "", 500 }, + { 1, "Prepared GeomNodes:Active", { 0.5, 1.0, 0.8 } }, { 1, "Vertices", { 0.5, 0.2, 0.0 }, "K", 10, 1000 }, { 1, "Vertices:Other", { 0.2, 0.2, 0.2 } }, { 1, "Vertices:Triangles", { 0.8, 0.8, 0.8 } }, diff --git a/panda/src/sgattrib/drawBoundsTransition.cxx b/panda/src/sgattrib/drawBoundsTransition.cxx index c1175c7acf..be2aaa4892 100644 --- a/panda/src/sgattrib/drawBoundsTransition.cxx +++ b/panda/src/sgattrib/drawBoundsTransition.cxx @@ -124,9 +124,9 @@ sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, geom.set_coords(verts, G_PER_VERTEX); geom.set_num_prims(1); - gsg->draw_sphere(&geom); + gsg->draw_sphere(&geom, NULL); gsg->set_state(_inside_attrib, false); - gsg->draw_sphere(&geom); + gsg->draw_sphere(&geom, NULL); } else { sgattrib_cat.warning() diff --git a/panda/src/sgraph/geomNode.cxx b/panda/src/sgraph/geomNode.cxx index b3c1ef58a0..10a30d9592 100644 --- a/panda/src/sgraph/geomNode.cxx +++ b/panda/src/sgraph/geomNode.cxx @@ -35,6 +35,8 @@ TypeHandle GeomNode::_type_handle; //////////////////////////////////////////////////////////////////// GeomNode:: GeomNode(const string &name) : NamedNode(name), _num_geoms(0) { + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomNodeContext *)NULL; } //////////////////////////////////////////////////////////////////// @@ -48,6 +50,8 @@ GeomNode(const GeomNode ©) : _geoms(copy._geoms), _num_geoms(0) { + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomNodeContext *)NULL; } //////////////////////////////////////////////////////////////////// @@ -57,6 +61,7 @@ GeomNode(const GeomNode ©) : //////////////////////////////////////////////////////////////////// void GeomNode:: operator = (const GeomNode ©) { + unprepare(); NamedNode::operator = (copy); _geoms = copy._geoms; _num_geoms = 0; @@ -69,6 +74,7 @@ operator = (const GeomNode ©) { //////////////////////////////////////////////////////////////////// GeomNode:: ~GeomNode() { + unprepare(); } //////////////////////////////////////////////////////////////////// @@ -146,9 +152,87 @@ write_verbose(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// void GeomNode:: draw(GraphicsStateGuardianBase *gsg) { - Geoms::const_iterator gi; - for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) { - (*gi)->draw(gsg); + if (_prepared_gsg == gsg) { + gsg->draw_geom_node(this, _prepared_context); + } else { + Geoms::const_iterator gi; + for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) { + (*gi)->draw(gsg); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::prepare +// Access: Public +// Description: Creates a context for the GeomNode on the particular +// GSG, if it does not already exist. Returns the new +// (or old) GeomNodeContext. +// +// If the given GeomNodeContext pointer is non-NULL, it will +// be passed to the GSG, which may or may not choose to +// extend the existing GeomNodeContext, or create a totally +// new one. +//////////////////////////////////////////////////////////////////// +GeomNodeContext *GeomNode:: +prepare(GraphicsStateGuardianBase *gsg) { + if (gsg != _prepared_gsg) { + GeomNodeContext *gc = gsg->prepare_geom_node(this); + if (gc != (GeomNodeContext *)NULL) { + unprepare(); + _prepared_context = gc; + _prepared_gsg = gsg; + } + return gc; + } + + return _prepared_context; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::unprepare +// Access: Public +// Description: Frees the context allocated on all GSG's for which +// the geom has been declared. +//////////////////////////////////////////////////////////////////// +void GeomNode:: +unprepare() { + if (_prepared_gsg != (GraphicsStateGuardianBase *)NULL) { + _prepared_gsg->release_geom_node(_prepared_context); + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomNodeContext *)NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::unprepare +// Access: Public +// Description: Frees the geom context only on the indicated GSG, +// if it exists there. +//////////////////////////////////////////////////////////////////// +void GeomNode:: +unprepare(GraphicsStateGuardianBase *gsg) { + if (_prepared_gsg == gsg) { + _prepared_gsg->release_geom_node(_prepared_context); + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomNodeContext *)NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::clear_gsg +// Access: Public +// Description: Removes the indicated GSG from the Geom's known +// GSG's, without actually releasing the geom on that +// GSG. This is intended to be called only from +// GSG::release_geom_node(); it should never be called by +// user code. +//////////////////////////////////////////////////////////////////// +void GeomNode:: +clear_gsg(GraphicsStateGuardianBase *gsg) { + if (_prepared_gsg == gsg) { + _prepared_gsg = (GraphicsStateGuardianBase *)NULL; + _prepared_context = (GeomNodeContext *)NULL; } } @@ -189,10 +273,10 @@ remove_geom(int n) { } else { // Copy-on-write. - size_t num_geoms = _geoms.size(); + int num_geoms = _geoms.size(); Geoms new_geoms; new_geoms.reserve(num_geoms - 1); - size_t i; + int i; for (i = 0; i < n; i++) { new_geoms.push_back(_geoms[i]); } @@ -204,6 +288,7 @@ remove_geom(int n) { nassertv(_geoms.get_ref_count() == 1); } + unprepare(); mark_bound_stale(); } @@ -215,6 +300,7 @@ remove_geom(int n) { void GeomNode:: clear() { _geoms.clear(); + unprepare(); mark_bound_stale(); } @@ -239,6 +325,7 @@ add_geom(dDrawable *geom) { _geoms.push_back(geom); } + unprepare(); mark_bound_stale(); return _geoms.size() - 1; } @@ -268,6 +355,7 @@ add_geoms_from(const GeomNode *other) { _geoms.v().insert(_geoms.end(), geoms_begin, geoms_end); } + unprepare(); mark_bound_stale(); } diff --git a/panda/src/sgraph/geomNode.h b/panda/src/sgraph/geomNode.h index 87ae249052..976f522375 100644 --- a/panda/src/sgraph/geomNode.h +++ b/panda/src/sgraph/geomNode.h @@ -30,6 +30,7 @@ class GraphicsStateGuardianBase; class AllAttributesWrapper; +class GeomNodeContext; //////////////////////////////////////////////////////////////////// // Class : GeomNode @@ -56,6 +57,11 @@ PUBLISHED: public: void draw(GraphicsStateGuardianBase *gsg); + GeomNodeContext *prepare(GraphicsStateGuardianBase *gsg); + void unprepare(); + void unprepare(GraphicsStateGuardianBase *gsg); + void clear_gsg(GraphicsStateGuardianBase *gsg); + PUBLISHED: int get_num_geoms() const; dDrawable *get_geom(int n) const; @@ -71,6 +77,12 @@ private: typedef PTA(PT(dDrawable)) Geoms; Geoms _geoms; + // These are essentially similar to the same fields in Geom. They + // are used only if the GSG supports a node-level Geom context, as + // opposed to strictly a Geom-level context. + GraphicsStateGuardianBase *_prepared_gsg; + GeomNodeContext *_prepared_context; + public: static void register_with_read_factory(void); virtual void write_datagram(BamWriter* manager, Datagram &me); diff --git a/panda/src/sgraph/geomTransformer.cxx b/panda/src/sgraph/geomTransformer.cxx index 770e305a4e..140e87ed65 100644 --- a/panda/src/sgraph/geomTransformer.cxx +++ b/panda/src/sgraph/geomTransformer.cxx @@ -148,6 +148,7 @@ transform_vertices(GeomNode *node, const LMatrix4f &mat) { if (any_changed) { node->_geoms = new_geoms; + node->unprepare(); node->mark_bound_stale(); return true; }