A lot of performance changes, particularly wrt dcasts and state management
This commit is contained in:
parent
6cf2da9e56
commit
f33e450823
|
|
@ -61,7 +61,9 @@ get_type_index() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TypedObject::
|
||||
is_of_type(TypeHandle handle) const {
|
||||
return get_type().is_derived_from(handle, (TypedObject *)this);
|
||||
// Shortcut for the common case where the type matches exactly.
|
||||
TypeHandle my_type = get_type();
|
||||
return handle == my_type || my_type.is_derived_from(handle, (TypedObject *)this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -420,8 +420,7 @@ find_joint(const string &name) const {
|
|||
int num_bundles = get_num_bundles();
|
||||
for (int i = 0; i < num_bundles; ++i) {
|
||||
PartGroup *part = get_bundle(i)->find_child(name);
|
||||
if (part != (PartGroup *)NULL &&
|
||||
part->is_of_type(CharacterJoint::get_class_type())) {
|
||||
if (part != (PartGroup *)NULL && part->is_character_joint()) {
|
||||
return DCAST(CharacterJoint, part);
|
||||
}
|
||||
}
|
||||
|
|
@ -728,7 +727,7 @@ r_merge_bundles(Character::JointMap &joint_map,
|
|||
PartGroup *old_group, PartGroup *new_group) {
|
||||
joint_map[old_group] = new_group;
|
||||
|
||||
if (new_group->is_of_type(CharacterJoint::get_class_type())) {
|
||||
if (new_group->is_character_joint()) {
|
||||
CharacterJoint *new_joint;
|
||||
DCAST_INTO_V(new_joint, new_group);
|
||||
|
||||
|
|
@ -736,7 +735,7 @@ r_merge_bundles(Character::JointMap &joint_map,
|
|||
new_joint->_character = this;
|
||||
|
||||
if (old_group != new_group &&
|
||||
old_group->is_of_type(CharacterJoint::get_class_type())) {
|
||||
old_group->is_character_joint()) {
|
||||
CharacterJoint *old_joint;
|
||||
DCAST_INTO_V(old_joint, old_group);
|
||||
|
||||
|
|
@ -763,7 +762,7 @@ r_merge_bundles(Character::JointMap &joint_map,
|
|||
if (old_group == new_group) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int i = 0, j = 0;
|
||||
int old_num_children = old_group->get_num_children();
|
||||
int new_num_children = new_group->get_num_children();
|
||||
|
|
@ -809,7 +808,7 @@ r_merge_bundles(Character::JointMap &joint_map,
|
|||
// new_group. Duplicate it.
|
||||
PartGroup *new_pc = pc->make_copy();
|
||||
new_children.push_back(new_pc);
|
||||
|
||||
|
||||
r_merge_bundles(joint_map, pc, new_pc);
|
||||
i++;
|
||||
}
|
||||
|
|
@ -968,7 +967,7 @@ copy_geom(const Geom *source, const Character::JointMap &joint_map,
|
|||
void Character::
|
||||
copy_node_pointers(const Character::NodeMap &node_map,
|
||||
PartGroup *dest, const PartGroup *source) {
|
||||
if (dest->is_of_type(CharacterJoint::get_class_type())) {
|
||||
if (dest->is_character_joint()) {
|
||||
nassertv(dest != source);
|
||||
const CharacterJoint *source_joint;
|
||||
CharacterJoint *dest_joint;
|
||||
|
|
@ -1204,7 +1203,7 @@ redirect_slider(const VertexSlider *vs, Character::GeomSliderMap &gsmap) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void Character::
|
||||
r_clear_joint_characters(PartGroup *part) {
|
||||
if (part->is_of_type(CharacterJoint::get_class_type())) {
|
||||
if (part->is_character_joint()) {
|
||||
CharacterJoint *joint = DCAST(CharacterJoint, part);
|
||||
|
||||
// It is possible for the joint to reference a different Character
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ r_set_character(PartGroup *group, Character *character) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (group->is_of_type(CharacterJoint::get_class_type())) {
|
||||
DCAST(CharacterJoint, group)->set_character(character);
|
||||
if (group->is_character_joint()) {
|
||||
((CharacterJoint *)group)->set_character(character);
|
||||
}
|
||||
|
||||
Children::const_iterator ci;
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ add_object(CullableObject *object, Thread *current_thread) {
|
|||
return;
|
||||
}
|
||||
|
||||
const GeometricBoundingVolume *gbv;
|
||||
DCAST_INTO_V(gbv, volume);
|
||||
const GeometricBoundingVolume *gbv = volume->as_geometric_bounding_volume();
|
||||
nassertv(gbv != NULL);
|
||||
|
||||
LPoint3 center = gbv->get_approx_center();
|
||||
nassertv(object->_internal_transform != (const TransformState *)NULL);
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ add_object(CullableObject *object, Thread *current_thread) {
|
|||
return;
|
||||
}
|
||||
|
||||
const GeometricBoundingVolume *gbv;
|
||||
DCAST_INTO_V(gbv, volume);
|
||||
const GeometricBoundingVolume *gbv = volume->as_geometric_bounding_volume();
|
||||
nassertv(gbv != NULL);
|
||||
|
||||
LPoint3 center = gbv->get_approx_center();
|
||||
nassertv(object->_internal_transform != (const TransformState *)NULL);
|
||||
|
|
|
|||
|
|
@ -597,11 +597,16 @@ get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const {
|
|||
// to all upstream pipeline stages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DisplayRegion::
|
||||
set_cull_result(CullResult *cull_result, SceneSetup *scene_setup,
|
||||
set_cull_result(PT(CullResult) cull_result, PT(SceneSetup) scene_setup,
|
||||
Thread *current_thread) {
|
||||
CDCullWriter cdata(_cycler_cull, true, current_thread);
|
||||
cdata->_cull_result = cull_result;
|
||||
cdata->_scene_setup = scene_setup;
|
||||
#ifdef USE_MOVE_SEMANTICS
|
||||
cdata->_cull_result = std::move(cull_result);
|
||||
cdata->_scene_setup = std::move(scene_setup);
|
||||
#else
|
||||
swap(cdata->_cull_result, cull_result);
|
||||
swap(cdata->_scene_setup, scene_setup);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ public:
|
|||
|
||||
virtual bool supports_pixel_zoom() const;
|
||||
|
||||
INLINE void set_cull_result(CullResult *cull_result, SceneSetup *scene_setup,
|
||||
INLINE void set_cull_result(PT(CullResult) cull_result, PT(SceneSetup) scene_setup,
|
||||
Thread *current_thread);
|
||||
INLINE CullResult *get_cull_result(Thread *current_thread) const;
|
||||
INLINE SceneSetup *get_scene_setup(Thread *current_thread) const;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
#include "bamCache.h"
|
||||
#include "cullableObject.h"
|
||||
#include "geomVertexArrayData.h"
|
||||
#include "omniBoundingVolume.h"
|
||||
#include "vertexDataSaveFile.h"
|
||||
#include "vertexDataBook.h"
|
||||
#include "vertexDataPage.h"
|
||||
|
|
@ -1248,12 +1247,12 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
|
|||
// from the lens.
|
||||
PT(BoundingVolume) bv = scene_setup->get_cull_bounds();
|
||||
|
||||
if (bv != (BoundingVolume *)NULL &&
|
||||
bv->is_of_type(GeometricBoundingVolume::get_class_type()) &&
|
||||
!bv->is_of_type(OmniBoundingVolume::get_class_type())) {
|
||||
if (bv != (BoundingVolume *)NULL && !bv->is_infinite() &&
|
||||
bv->as_geometric_bounding_volume() != NULL) {
|
||||
// Transform it into the appropriate coordinate space.
|
||||
PT(GeometricBoundingVolume) local_frustum;
|
||||
local_frustum = DCAST(GeometricBoundingVolume, bv->make_copy());
|
||||
local_frustum = bv->make_copy()->as_geometric_bounding_volume();
|
||||
nassertv(!local_frustum.is_null());
|
||||
|
||||
NodePath scene_parent = scene_setup->get_scene_root().get_parent(current_thread);
|
||||
CPT(TransformState) cull_center_transform =
|
||||
|
|
@ -1580,7 +1579,7 @@ cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
|
|||
}
|
||||
|
||||
// Save the results for next frame.
|
||||
dr->set_cull_result(cull_result, scene_setup, current_thread);
|
||||
dr->set_cull_result(MOVE(cull_result), MOVE(scene_setup), current_thread);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "graphicsOutput.h"
|
||||
#include "texturePool.h"
|
||||
#include "geomMunger.h"
|
||||
#include "stateMunger.h"
|
||||
#include "ambientLight.h"
|
||||
#include "directionalLight.h"
|
||||
#include "pointLight.h"
|
||||
|
|
@ -814,38 +815,42 @@ dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
PT(GeomMunger) GraphicsStateGuardian::
|
||||
get_geom_munger(const RenderState *state, Thread *current_thread) {
|
||||
// Before we even look up the map, see if the _last_mi value points
|
||||
// to this GSG. This is likely because we tend to visit the same
|
||||
// state multiple times during a frame. Also, this might well be
|
||||
// the only GSG in the world anyway.
|
||||
if (!state->_mungers.empty()) {
|
||||
RenderState::Mungers::const_iterator mi = state->_last_mi;
|
||||
if (!(*mi).first.was_deleted() && (*mi).first == this) {
|
||||
if ((*mi).second->is_registered()) {
|
||||
return (*mi).second;
|
||||
RenderState::Mungers &mungers = state->_mungers;
|
||||
|
||||
if (mungers.is_empty()) {
|
||||
// Before we even look up the map, see if the _last_mi value points
|
||||
// to this GSG. This is likely because we tend to visit the same
|
||||
// state multiple times during a frame. Also, this might well be
|
||||
// the only GSG in the world anyway.
|
||||
int mi = state->_last_mi;
|
||||
if (mi >= 0 && mungers.has_element(mi) && mungers.get_key(mi) == this) {
|
||||
PT(GeomMunger) munger = mungers.get_data(mi);
|
||||
if (munger->is_registered()) {
|
||||
return munger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nope, we have to look it up in the map.
|
||||
RenderState::Mungers::iterator mi = state->_mungers.find(this);
|
||||
if (mi != state->_mungers.end() && !(*mi).first.was_deleted()) {
|
||||
if ((*mi).second->is_registered()) {
|
||||
state->_last_mi = mi;
|
||||
return (*mi).second;
|
||||
// Nope, we have to look it up in the map.
|
||||
mi = mungers.find(this);
|
||||
if (mi >= 0) {
|
||||
PT(GeomMunger) munger = mungers.get_data(mi);
|
||||
if (munger->is_registered()) {
|
||||
state->_last_mi = mi;
|
||||
return munger;
|
||||
} else {
|
||||
// This GeomMunger is no longer registered. Remove it from
|
||||
// the map.
|
||||
mungers.remove_element(mi);
|
||||
}
|
||||
}
|
||||
// This GeomMunger is no longer registered. Remove it from the
|
||||
// map.
|
||||
state->_mungers.erase(mi);
|
||||
}
|
||||
|
||||
// Nothing in the map; create a new entry.
|
||||
PT(GeomMunger) munger = make_geom_munger(state, current_thread);
|
||||
nassertr(munger != (GeomMunger *)NULL && munger->is_registered(), munger);
|
||||
nassertr(munger->is_of_type(StateMunger::get_class_type()), munger);
|
||||
|
||||
mi = state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first;
|
||||
state->_last_mi = mi;
|
||||
|
||||
state->_last_mi = mungers.store(this, munger);
|
||||
return munger;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#include "standardMunger.h"
|
||||
#include "renderState.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "dcast.h"
|
||||
#include "config_gobj.h"
|
||||
#include "displayRegion.h"
|
||||
|
||||
|
|
@ -43,16 +42,15 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
|
|||
_auto_shader(false),
|
||||
_shader_skinning(false)
|
||||
{
|
||||
_render_mode = DCAST(RenderModeAttrib, state->get_attrib(RenderModeAttrib::get_class_slot()));
|
||||
_render_mode = (const RenderModeAttrib *)
|
||||
state->get_attrib(RenderModeAttrib::get_class_slot());
|
||||
|
||||
if (!get_gsg()->get_runtime_color_scale()) {
|
||||
// We might need to munge the colors.
|
||||
const ColorAttrib *color_attrib = (const ColorAttrib *)
|
||||
state->get_attrib(ColorAttrib::get_class_slot());
|
||||
const ColorScaleAttrib *color_scale_attrib = (const ColorScaleAttrib *)
|
||||
state->get_attrib(ColorScaleAttrib::get_class_slot());
|
||||
const ColorAttrib *color_attrib;
|
||||
const ColorScaleAttrib *color_scale_attrib;
|
||||
|
||||
if (color_attrib != (ColorAttrib *)NULL &&
|
||||
if (state->get_attrib(color_attrib) &&
|
||||
color_attrib->get_color_type() == ColorAttrib::T_flat) {
|
||||
|
||||
if (!get_gsg()->get_color_scale_via_lighting()) {
|
||||
|
|
@ -60,7 +58,7 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
|
|||
// can't cheat the color via lighting (presumably, in this case,
|
||||
// by applying a material).
|
||||
_color = color_attrib->get_color();
|
||||
if (color_scale_attrib != (ColorScaleAttrib *)NULL &&
|
||||
if (state->get_attrib(color_scale_attrib) &&
|
||||
color_scale_attrib->has_scale()) {
|
||||
const LVecBase4 &cs = color_scale_attrib->get_scale();
|
||||
_color.set(_color[0] * cs[0],
|
||||
|
|
@ -70,11 +68,11 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
|
|||
}
|
||||
_munge_color = true;
|
||||
}
|
||||
|
||||
} else if (color_scale_attrib != (ColorScaleAttrib *)NULL &&
|
||||
|
||||
} else if (state->get_attrib(color_scale_attrib) &&
|
||||
color_scale_attrib->has_scale()) {
|
||||
_color_scale = color_scale_attrib->get_scale();
|
||||
|
||||
|
||||
const TextureAttrib *tex_attrib = (const TextureAttrib *)
|
||||
state->get_attrib(TextureAttrib::get_class_slot());
|
||||
|
||||
|
|
@ -106,7 +104,7 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StandardMunger::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StandardMunger::
|
||||
~StandardMunger() {
|
||||
|
|
@ -126,7 +124,7 @@ munge_data_impl(const GeomVertexData *data) {
|
|||
new_data = new_data->set_color(_color, _num_components, _numeric_type,
|
||||
_contents);
|
||||
} else if (_munge_color_scale) {
|
||||
new_data = new_data->scale_color(_color_scale, _num_components,
|
||||
new_data = new_data->scale_color(_color_scale, _num_components,
|
||||
_numeric_type, _contents);
|
||||
}
|
||||
|
||||
|
|
@ -142,9 +140,9 @@ munge_data_impl(const GeomVertexData *data) {
|
|||
const TransformBlendTable *table = new_data->get_transform_blend_table();
|
||||
if (table != (TransformBlendTable *)NULL &&
|
||||
table->get_num_transforms() != 0 &&
|
||||
table->get_max_simultaneous_transforms() <=
|
||||
table->get_max_simultaneous_transforms() <=
|
||||
get_gsg()->get_max_vertex_transforms()) {
|
||||
if (matrix_palette &&
|
||||
if (matrix_palette &&
|
||||
table->get_num_transforms() <= get_gsg()->get_max_vertex_transform_indices()) {
|
||||
|
||||
if (table->get_num_transforms() == table->get_max_simultaneous_transforms()) {
|
||||
|
|
@ -186,7 +184,7 @@ munge_data_impl(const GeomVertexData *data) {
|
|||
// Description: Converts a Geom and/or its data as necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StandardMunger::
|
||||
munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
|
||||
munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
|
||||
Thread *) {
|
||||
int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
|
||||
|
||||
|
|
@ -289,7 +287,7 @@ premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int StandardMunger::
|
||||
compare_to_impl(const GeomMunger *other) const {
|
||||
const StandardMunger *om = DCAST(StandardMunger, other);
|
||||
const StandardMunger *om = (const StandardMunger *)other;
|
||||
|
||||
if (_render_mode != om->_render_mode) {
|
||||
return _render_mode < om->_render_mode ? -1 : 1;
|
||||
|
|
@ -335,7 +333,8 @@ compare_to_impl(const GeomMunger *other) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int StandardMunger::
|
||||
geom_compare_to_impl(const GeomMunger *other) const {
|
||||
const StandardMunger *om = DCAST(StandardMunger, other);
|
||||
const StandardMunger *om = (const StandardMunger *)other;
|
||||
|
||||
if (_munge_color != om->_munge_color) {
|
||||
return (int)_munge_color - (int)om->_munge_color;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ PandaNode *CharacterMaker::
|
|||
part_to_node(PartGroup *part, const string &name) const {
|
||||
PandaNode *node = _character_node;
|
||||
|
||||
if (part->is_of_type(CharacterJoint::get_class_type())) {
|
||||
if (part->is_character_joint()) {
|
||||
CharacterJoint *joint = DCAST(CharacterJoint, part);
|
||||
if (joint->_geom_node != (PandaNode *)NULL) {
|
||||
node = joint->_geom_node;
|
||||
|
|
@ -343,7 +343,7 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part, int index) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CharacterMaker::
|
||||
parent_joint_nodes(PartGroup *part) {
|
||||
if (part->is_of_type(CharacterJoint::get_class_type())) {
|
||||
if (part->is_character_joint()) {
|
||||
CharacterJoint *joint = DCAST(CharacterJoint, part);
|
||||
PandaNode *joint_node = joint->_geom_node;
|
||||
if (joint_node != NULL) {
|
||||
|
|
|
|||
|
|
@ -57,16 +57,7 @@ prepare_node(EggNode *node) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int EggBinner::
|
||||
get_bin_number(const EggNode *node) {
|
||||
if (node->is_of_type(EggNurbsSurface::get_class_type())) {
|
||||
return (int)BN_nurbs_surface;
|
||||
|
||||
} else if (node->is_of_type(EggNurbsCurve::get_class_type())) {
|
||||
return (int)BN_nurbs_curve;
|
||||
|
||||
} else if (node->is_of_type(EggPatch::get_class_type())) {
|
||||
return (int)BN_patches;
|
||||
|
||||
} else if (node->is_of_type(EggPrimitive::get_class_type())) {
|
||||
if (node->is_of_type(EggPrimitive::get_class_type())) {
|
||||
return (int)BN_polyset;
|
||||
|
||||
} else if (node->is_of_type(EggGroup::get_class_type())) {
|
||||
|
|
@ -74,6 +65,15 @@ get_bin_number(const EggNode *node) {
|
|||
if (group->has_lod()) {
|
||||
return (int)BN_lod;
|
||||
}
|
||||
|
||||
} else if (node->is_of_type(EggNurbsSurface::get_class_type())) {
|
||||
return (int)BN_nurbs_surface;
|
||||
|
||||
} else if (node->is_of_type(EggNurbsCurve::get_class_type())) {
|
||||
return (int)BN_nurbs_curve;
|
||||
|
||||
} else if (node->is_of_type(EggPatch::get_class_type())) {
|
||||
return (int)BN_patches;
|
||||
}
|
||||
|
||||
return (int)BN_none;
|
||||
|
|
|
|||
|
|
@ -991,8 +991,8 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||
|
||||
// We get the TextureAttrib directly from the _target_rs, not the
|
||||
// filtered TextureAttrib in _target_texture.
|
||||
const TextureAttrib *texattrib = DCAST(TextureAttrib, _glgsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
|
||||
nassertv(texattrib != (TextureAttrib *)NULL);
|
||||
const TextureAttrib *texattrib;
|
||||
_glgsg->_target_rs->get_attrib_def(texattrib);
|
||||
|
||||
for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
|
||||
Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
|
||||
|
|
@ -1053,8 +1053,9 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||
continue;
|
||||
}
|
||||
|
||||
_glgsg->apply_texture(tc);
|
||||
_glgsg->apply_sampler(texunit, sampler, tc);
|
||||
CLP(TextureContext) *gtc = (CLP(TextureContext) *)tc;
|
||||
_glgsg->apply_texture(gtc);
|
||||
_glgsg->apply_sampler(texunit, sampler, gtc);
|
||||
}
|
||||
|
||||
cg_report_errors();
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ ALLOC_DELETED_CHAIN_DEF(CLP(GeomMunger));
|
|||
CLP(GeomMunger)::
|
||||
CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
|
||||
StandardMunger(gsg, state, 4, NT_uint8, C_color),
|
||||
_texture(DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()))),
|
||||
_tex_gen(DCAST(TexGenAttrib, state->get_attrib(TexGenAttrib::get_class_slot())))
|
||||
_texture((const TextureAttrib *)state->get_attrib(TextureAttrib::get_class_slot())),
|
||||
_tex_gen((const TexGenAttrib *)state->get_attrib(TexGenAttrib::get_class_slot()))
|
||||
{
|
||||
// Set a callback to unregister ourselves when either the Texture or
|
||||
// the TexGen object gets deleted.
|
||||
|
|
@ -475,7 +475,7 @@ premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int CLP(GeomMunger)::
|
||||
compare_to_impl(const GeomMunger *other) const {
|
||||
const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other);
|
||||
const CLP(GeomMunger) *om = (CLP(GeomMunger) *)other;
|
||||
if (_texture != om->_texture) {
|
||||
return _texture < om->_texture ? -1 : 1;
|
||||
}
|
||||
|
|
@ -499,7 +499,7 @@ compare_to_impl(const GeomMunger *other) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int CLP(GeomMunger)::
|
||||
geom_compare_to_impl(const GeomMunger *other) const {
|
||||
const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other);
|
||||
const CLP(GeomMunger) *om = (CLP(GeomMunger) *)other;
|
||||
#ifdef OPENGLES
|
||||
if (get_render_mode() != om->get_render_mode()) {
|
||||
return get_render_mode() < om->get_render_mode() ? -1 : 1;
|
||||
|
|
|
|||
|
|
@ -4512,13 +4512,14 @@ prepare_texture(Texture *tex, int view) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
update_texture(TextureContext *tc, bool force) {
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
CLP(TextureContext) *gtc;
|
||||
DCAST_INTO_R(gtc, tc, false);
|
||||
|
||||
if (gtc->was_image_modified() || !gtc->_has_storage) {
|
||||
PStatGPUTimer timer(this, _texture_update_pcollector);
|
||||
|
||||
// If the texture image was modified, reload the texture.
|
||||
apply_texture(tc);
|
||||
apply_texture(gtc);
|
||||
|
||||
Texture *tex = tc->get_texture();
|
||||
if (gtc->was_properties_modified()) {
|
||||
|
|
@ -4536,7 +4537,7 @@ update_texture(TextureContext *tc, bool force) {
|
|||
|
||||
// If only the properties have been modified, we don't necessarily
|
||||
// need to reload the texture.
|
||||
apply_texture(tc);
|
||||
apply_texture(gtc);
|
||||
|
||||
Texture *tex = tc->get_texture();
|
||||
if (specify_texture(gtc, tex->get_default_sampler())) {
|
||||
|
|
@ -9649,8 +9650,10 @@ update_standard_texture_bindings() {
|
|||
glDisable(target);
|
||||
continue;
|
||||
}
|
||||
apply_texture(tc);
|
||||
apply_sampler(i, _target_texture->get_on_sampler(stage), tc);
|
||||
// Don't DCAST(); we already did the verification in update_texture.
|
||||
CLP(TextureContext) *gtc = (CLP(TextureContext) *)tc;
|
||||
apply_texture(gtc);
|
||||
apply_sampler(i, _target_texture->get_on_sampler(stage), gtc);
|
||||
|
||||
if (stage->involves_color_scale() && _color_scale_enabled) {
|
||||
LColor color = stage->get_color();
|
||||
|
|
@ -10487,9 +10490,7 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) {
|
|||
// for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
apply_texture(TextureContext *tc) {
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
|
||||
apply_texture(CLP(TextureContext) *gtc) {
|
||||
gtc->set_active(true);
|
||||
GLenum target = get_texture_target(gtc->get_texture()->get_texture_type());
|
||||
if (target == GL_NONE) {
|
||||
|
|
@ -10520,9 +10521,7 @@ apply_texture(TextureContext *tc) {
|
|||
// context instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
|
||||
apply_sampler(GLuint unit, const SamplerState &sampler, CLP(TextureContext) *gtc) {
|
||||
#ifndef OPENGLES
|
||||
if (_supports_sampler_objects) {
|
||||
// We support sampler objects. Prepare the sampler object and
|
||||
|
|
@ -10547,7 +10546,7 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
|
|||
// texture and change the texture parameters if they don't match.
|
||||
if (gtc->_active_sampler != sampler) {
|
||||
_glActiveTexture(GL_TEXTURE0 + unit);
|
||||
apply_texture(tc);
|
||||
apply_texture(gtc);
|
||||
specify_texture(gtc, sampler);
|
||||
}
|
||||
}
|
||||
|
|
@ -10555,7 +10554,7 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
|
|||
if (sampler.uses_mipmaps() && !gtc->_uses_mipmaps) {
|
||||
// The texture wasn't created with mipmaps, but we are trying
|
||||
// to sample it with mipmaps. We will need to reload it.
|
||||
apply_texture(tc);
|
||||
apply_texture(gtc);
|
||||
gtc->mark_needs_reload();
|
||||
bool okflag = upload_texture(gtc, false, true);
|
||||
if (!okflag) {
|
||||
|
|
|
|||
|
|
@ -531,8 +531,8 @@ protected:
|
|||
#endif // NDEBUG
|
||||
|
||||
bool specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler);
|
||||
bool apply_texture(TextureContext *tc);
|
||||
bool apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc);
|
||||
bool apply_texture(CLP(TextureContext) *gtc);
|
||||
bool apply_sampler(GLuint unit, const SamplerState &sampler, CLP(TextureContext) *gtc);
|
||||
bool upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps);
|
||||
bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
|
||||
bool uses_mipmaps, int mipmap_bias,
|
||||
|
|
|
|||
|
|
@ -832,7 +832,7 @@ get_modified() const {
|
|||
INLINE GeomContext *GeomPipelineReader::
|
||||
prepare_now(PreparedGraphicsObjects *prepared_objects,
|
||||
GraphicsStateGuardianBase *gsg) const {
|
||||
return ((Geom *)_object.p())->prepare_now(prepared_objects, gsg);
|
||||
return ((Geom *)_object)->prepare_now(prepared_objects, gsg);
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
|
|
|
|||
|
|
@ -1897,7 +1897,7 @@ check_usage_hint() const {
|
|||
#ifdef DO_PIPELINING
|
||||
unref_delete((CycleData *)_cdata);
|
||||
#endif
|
||||
Geom::CDWriter fresh_cdata(((Geom *)_object.p())->_cycler,
|
||||
Geom::CDWriter fresh_cdata(((Geom *)_object)->_cycler,
|
||||
false, _current_thread);
|
||||
((GeomPipelineReader *)this)->_cdata = fresh_cdata;
|
||||
#ifdef DO_PIPELINING
|
||||
|
|
@ -1906,7 +1906,7 @@ check_usage_hint() const {
|
|||
if (!fresh_cdata->_got_usage_hint) {
|
||||
// The cache is still stale. We have to do the work of
|
||||
// freshening it.
|
||||
((Geom *)_object.p())->reset_usage_hint(fresh_cdata);
|
||||
((Geom *)_object)->reset_usage_hint(fresh_cdata);
|
||||
nassertv(fresh_cdata->_got_usage_hint);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -397,6 +397,10 @@ private:
|
|||
// Class : GeomPipelineReader
|
||||
// Description : Encapsulates the data from a Geom,
|
||||
// pre-fetched for one stage of the pipeline.
|
||||
//
|
||||
// Does not hold a reference to the Geom. The caller
|
||||
// must ensure that the Geom persists for at least the
|
||||
// lifetime of the GeomPipelineReader.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_GOBJ GeomPipelineReader : public GeomEnums {
|
||||
public:
|
||||
|
|
@ -434,7 +438,7 @@ public:
|
|||
bool force) const;
|
||||
|
||||
private:
|
||||
CPT(Geom) _object;
|
||||
const Geom *_object;
|
||||
Thread *_current_thread;
|
||||
const Geom::CData *_cdata;
|
||||
|
||||
|
|
|
|||
|
|
@ -107,8 +107,8 @@ is_composite() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GeomPrimitive::
|
||||
is_indexed() const {
|
||||
GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
|
||||
return reader.is_indexed();
|
||||
CDReader cdata(_cycler);
|
||||
return (!cdata->_vertices.is_null());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -84,6 +84,18 @@ write(ostream &out, int indent_level) const {
|
|||
indent(out, indent_level) << *this << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::as_geometric_bounding_volume
|
||||
// Access: Public, Virtual
|
||||
// Description: Virtual downcast method. Returns this object as a
|
||||
// pointer of the indicated type, if it is in fact that
|
||||
// type. Returns NULL if it is not that type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeometricBoundingVolume *BoundingVolume::
|
||||
as_geometric_bounding_volume() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::as_geometric_bounding_volume
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ PUBLISHED:
|
|||
};
|
||||
|
||||
public:
|
||||
virtual GeometricBoundingVolume *as_geometric_bounding_volume();
|
||||
virtual const GeometricBoundingVolume *as_geometric_bounding_volume() const;
|
||||
virtual const FiniteBoundingVolume *as_finite_bounding_volume() const;
|
||||
virtual const BoundingSphere *as_bounding_sphere() const;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,19 @@ TypeHandle GeometricBoundingVolume::_type_handle;
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeometricBoundingVolume::as_geometric_bounding_volume
|
||||
// Access: Public, Virtual
|
||||
// Access: Public, Virtual, Final
|
||||
// Description: Virtual downcast method. Returns this object as a
|
||||
// pointer of the indicated type, if it is in fact that
|
||||
// type. Returns NULL if it is not that type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeometricBoundingVolume *GeometricBoundingVolume::
|
||||
as_geometric_bounding_volume() {
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeometricBoundingVolume::as_geometric_bounding_volume
|
||||
// Access: Public, Virtual, Final
|
||||
// Description: Virtual downcast method. Returns this object as a
|
||||
// pointer of the indicated type, if it is in fact that
|
||||
// type. Returns NULL if it is not that type.
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ PUBLISHED:
|
|||
virtual void xform(const LMatrix4 &mat)=0;
|
||||
|
||||
public:
|
||||
virtual const GeometricBoundingVolume *as_geometric_bounding_volume() const;
|
||||
virtual GeometricBoundingVolume *as_geometric_bounding_volume() FINAL;
|
||||
virtual const GeometricBoundingVolume *as_geometric_bounding_volume() const FINAL;
|
||||
|
||||
protected:
|
||||
// Some virtual functions to implement fundamental bounding
|
||||
|
|
|
|||
|
|
@ -76,13 +76,13 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int AlphaTestAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const AlphaTestAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const AlphaTestAttrib *ta = (const AlphaTestAttrib *)other;
|
||||
|
||||
int compare_result = ((int)_mode - (int)ta->_mode) ;
|
||||
if (compare_result != 0) {
|
||||
return compare_result;
|
||||
}
|
||||
|
||||
|
||||
if (_reference_alpha != ta->_reference_alpha) {
|
||||
return _reference_alpha < ta->_reference_alpha ? -1 : 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public:
|
|||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
@ -74,7 +74,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "AlphaTestAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new AlphaTestAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -75,11 +75,7 @@ make(unsigned short mode) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) AntialiasAttrib::
|
||||
make_default() {
|
||||
if (default_antialias_enable) {
|
||||
return return_new(new AntialiasAttrib(M_auto));
|
||||
} else {
|
||||
return return_new(new AntialiasAttrib(M_none));
|
||||
}
|
||||
return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -146,8 +142,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int AntialiasAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const AntialiasAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const AntialiasAttrib *ta = (const AntialiasAttrib *)other;
|
||||
|
||||
if (_mode != ta->_mode) {
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
|
@ -190,8 +186,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) AntialiasAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const AntialiasAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const AntialiasAttrib *ta = (const AntialiasAttrib *)other;
|
||||
|
||||
unsigned short mode_type;
|
||||
unsigned short mode_quality;
|
||||
|
|
@ -277,3 +272,26 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
|
||||
_mode = scan.get_uint16();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AntialiasAttrib::init_type
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AntialiasAttrib::
|
||||
init_type() {
|
||||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "AntialiasAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
|
||||
// This is defined here, since we have otherwise no guarantee that
|
||||
// the config var has already been constructed by the time we call
|
||||
// init_type() at static init time.
|
||||
static ConfigVariableBool default_antialias_enable
|
||||
("default-antialias-enable", false,
|
||||
PRC_DESC("Set this true to enable the M_auto antialiasing mode for all "
|
||||
"nodes by default."));
|
||||
|
||||
_attrib_slot = register_slot(_type_handle, 100,
|
||||
new AntialiasAttrib(default_antialias_enable ? M_auto : M_none));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,17 +80,12 @@ public:
|
|||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "AntialiasAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
}
|
||||
static void init_type();
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,8 +147,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int AudioVolumeAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const AudioVolumeAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const AudioVolumeAttrib *ta = (const AudioVolumeAttrib *)other;
|
||||
|
||||
if (_off != ta->_off) {
|
||||
return (int)_off - (int)ta->_off;
|
||||
|
|
@ -198,8 +197,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) AudioVolumeAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const AudioVolumeAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const AudioVolumeAttrib *ta = (const AudioVolumeAttrib *)other;
|
||||
|
||||
if (ta->is_off()) {
|
||||
return ta;
|
||||
|
|
@ -223,8 +221,8 @@ invert_compose_impl(const RenderAttrib *other) const {
|
|||
if (is_off()) {
|
||||
return other;
|
||||
}
|
||||
const AudioVolumeAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const AudioVolumeAttrib *ta = (const AudioVolumeAttrib *)other;
|
||||
|
||||
PN_stdfloat new_volume = _volume == 0.0f ? 1.0f : ta->_volume / _volume;
|
||||
|
||||
AudioVolumeAttrib *attrib = new AudioVolumeAttrib(false, new_volume);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public:
|
|||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
@ -82,7 +82,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "AudioVolumeAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new AudioVolumeAttrib(false, 1));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int AuxBitplaneAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const AuxBitplaneAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const AuxBitplaneAttrib *ta = (const AuxBitplaneAttrib *)other;
|
||||
|
||||
int compare_result = _outputs - ta->_outputs;
|
||||
if (compare_result != 0) {
|
||||
return compare_result;
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "AuxBitplaneAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new AuxBitplaneAttrib(0));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ClipPlaneAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new ClipPlaneAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int ColorAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const ColorAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ColorAttrib *ta = (const ColorAttrib *)other;
|
||||
|
||||
if (_type != ta->_type) {
|
||||
return (int)_type - (int)ta->_type;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,8 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ColorAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100,
|
||||
new ColorAttrib(T_off, LColor(1, 1, 1, 1)));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -113,8 +113,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int ColorBlendAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const ColorBlendAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ColorBlendAttrib *ta = (const ColorBlendAttrib *)other;
|
||||
|
||||
if (_mode != ta->_mode) {
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ColorBlendAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new ColorBlendAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -186,8 +186,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int ColorScaleAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const ColorScaleAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ColorScaleAttrib *ta = (const ColorScaleAttrib *)other;
|
||||
|
||||
if (is_off() != ta->is_off()) {
|
||||
return (int)is_off() - (int)ta->is_off();
|
||||
|
|
@ -233,8 +232,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ColorScaleAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const ColorScaleAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ColorScaleAttrib *ta = (const ColorScaleAttrib *)other;
|
||||
|
||||
if (ta->is_off()) {
|
||||
return ta;
|
||||
|
|
@ -263,8 +261,8 @@ invert_compose_impl(const RenderAttrib *other) const {
|
|||
if (is_off()) {
|
||||
return other;
|
||||
}
|
||||
const ColorScaleAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ColorScaleAttrib *ta = (const ColorScaleAttrib *)other;
|
||||
|
||||
LVecBase4 new_scale(_scale[0] == 0.0f ? 1.0f : ta->_scale[0] / _scale[0],
|
||||
_scale[1] == 0.0f ? 1.0f : ta->_scale[1] / _scale[1],
|
||||
_scale[2] == 0.0f ? 1.0f : ta->_scale[2] / _scale[2],
|
||||
|
|
|
|||
|
|
@ -92,7 +92,8 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ColorScaleAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100,
|
||||
new ColorScaleAttrib(false, LVecBase4(1, 1, 1, 1)));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -89,8 +89,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int ColorWriteAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const ColorWriteAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ColorWriteAttrib *ta = (const ColorWriteAttrib *)other;
|
||||
return (int)_channels - (int)ta->_channels;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ColorWriteAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new ColorWriteAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -310,11 +310,6 @@ ConfigVariableInt max_lenses
|
|||
"this can be used as a simple sanity check. Set it larger or "
|
||||
"smaller to suit your needs."));
|
||||
|
||||
ConfigVariableBool default_antialias_enable
|
||||
("default-antialias-enable", false,
|
||||
PRC_DESC("Set this true to enable the M_auto antialiasing mode for all "
|
||||
"nodes by default."));
|
||||
|
||||
ConfigVariableBool polylight_info
|
||||
("polylight-info", false,
|
||||
PRC_DESC("Set this true to view some info statements regarding the polylight. "
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ extern EXPCL_PANDA_PGRAPH ConfigVariableBool premunge_data;
|
|||
extern ConfigVariableBool preserve_geom_nodes;
|
||||
extern ConfigVariableBool flatten_geoms;
|
||||
extern EXPCL_PANDA_PGRAPH ConfigVariableInt max_lenses;
|
||||
extern ConfigVariableBool default_antialias_enable;
|
||||
|
||||
extern ConfigVariableBool polylight_info;
|
||||
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int CullBinAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const CullBinAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const CullBinAttrib *ta = (const CullBinAttrib *)other;
|
||||
|
||||
if (_draw_order != ta->_draw_order) {
|
||||
return _draw_order - ta->_draw_order;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "CullBinAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new CullBinAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int CullFaceAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const CullFaceAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const CullFaceAttrib *ta = (const CullFaceAttrib *)other;
|
||||
|
||||
if (_mode != ta->_mode) {
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
|
@ -199,8 +199,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) CullFaceAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const CullFaceAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const CullFaceAttrib *ta = (const CullFaceAttrib *)other;
|
||||
|
||||
if (!_reverse && ta->_mode != M_cull_unchanged) {
|
||||
// The normal case (there is nothing funny going on): the second
|
||||
|
|
@ -231,8 +230,7 @@ compose_impl(const RenderAttrib *other) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) CullFaceAttrib::
|
||||
invert_compose_impl(const RenderAttrib *other) const {
|
||||
const CullFaceAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const CullFaceAttrib *ta = (const CullFaceAttrib *)other;
|
||||
|
||||
// The invert case is the same as the normal case, except that the
|
||||
// meaning of _reverse is inverted. See compose_impl(), above.
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "CullFaceAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100,
|
||||
new CullFaceAttrib(M_cull_clockwise, false));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -237,9 +237,8 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
}
|
||||
|
||||
// Check for a special wireframe setting.
|
||||
const RenderModeAttrib *rmode = (const RenderModeAttrib *)
|
||||
object->_state->get_attrib(RenderModeAttrib::get_class_slot());
|
||||
if (rmode != (const RenderModeAttrib *)NULL) {
|
||||
const RenderModeAttrib *rmode;
|
||||
if (object->_state->get_attrib(rmode)) {
|
||||
if (rmode->get_mode() == RenderModeAttrib::M_filled_wireframe) {
|
||||
CullableObject *wireframe_part = new CullableObject(*object);
|
||||
wireframe_part->_state = get_wireframe_overlay_state(rmode);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,9 @@ apply_transform_and_state(CullTraverser *trav,
|
|||
// Copy the bounding volumes for the frustums so we can
|
||||
// transform them.
|
||||
if (_view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||
_view_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy());
|
||||
_view_frustum = _view_frustum->make_copy()->as_geometric_bounding_volume();
|
||||
nassertv(_view_frustum != (GeometricBoundingVolume *)NULL);
|
||||
|
||||
_view_frustum->xform(inv_transform->get_mat());
|
||||
}
|
||||
|
||||
|
|
@ -106,9 +108,9 @@ apply_transform_and_state(CullTraverser *trav,
|
|||
|
||||
if (clip_plane_cull) {
|
||||
_cull_planes = _cull_planes->apply_state(trav, this,
|
||||
DCAST(ClipPlaneAttrib, node_state->get_attrib(ClipPlaneAttrib::get_class_slot())),
|
||||
(const ClipPlaneAttrib *)node_state->get_attrib(ClipPlaneAttrib::get_class_slot()),
|
||||
DCAST(ClipPlaneAttrib, off_clip_planes),
|
||||
DCAST(OccluderEffect, node_effects->get_effect(OccluderEffect::get_class_type())));
|
||||
(const OccluderEffect *)node_effects->get_effect(OccluderEffect::get_class_type()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +124,8 @@ is_in_view_impl() {
|
|||
const GeometricBoundingVolume *node_gbv = NULL;
|
||||
|
||||
if (_view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||
DCAST_INTO_R(node_gbv, _node_reader.get_bounds(), false)
|
||||
node_gbv = _node_reader.get_bounds()->as_geometric_bounding_volume();
|
||||
nassertr(node_gbv != (const GeometricBoundingVolume *)NULL, false);
|
||||
|
||||
int result = _view_frustum->contains(node_gbv);
|
||||
|
||||
|
|
@ -168,7 +171,8 @@ is_in_view_impl() {
|
|||
|
||||
if (!_cull_planes->is_empty()) {
|
||||
if (node_gbv == (const GeometricBoundingVolume *)NULL) {
|
||||
DCAST_INTO_R(node_gbv, _node_reader.get_bounds(), false)
|
||||
node_gbv = _node_reader.get_bounds()->as_geometric_bounding_volume();
|
||||
nassertr(node_gbv != (const GeometricBoundingVolume *)NULL, false);
|
||||
}
|
||||
|
||||
// Also cull against the current clip planes.
|
||||
|
|
|
|||
|
|
@ -140,8 +140,7 @@ munge_geom(GraphicsStateGuardianBase *gsg,
|
|||
}
|
||||
}
|
||||
|
||||
StateMunger *state_munger;
|
||||
DCAST_INTO_R(state_munger, munger, false);
|
||||
StateMunger *state_munger = (StateMunger *)munger;
|
||||
_state = state_munger->munge_state(_state);
|
||||
|
||||
// If there is any animation left in the vertex data after it
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int DepthOffsetAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const DepthOffsetAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const DepthOffsetAttrib *ta = (const DepthOffsetAttrib *)other;
|
||||
|
||||
if (_offset != ta->_offset) {
|
||||
return _offset - ta->_offset;
|
||||
}
|
||||
|
|
@ -147,8 +147,8 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) DepthOffsetAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const DepthOffsetAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const DepthOffsetAttrib *ta = (const DepthOffsetAttrib *)other;
|
||||
|
||||
int new_offset = ta->_offset + _offset;
|
||||
|
||||
DepthOffsetAttrib *attrib = new DepthOffsetAttrib(new_offset, ta->_min_value, ta->_max_value);
|
||||
|
|
@ -166,8 +166,8 @@ compose_impl(const RenderAttrib *other) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) DepthOffsetAttrib::
|
||||
invert_compose_impl(const RenderAttrib *other) const {
|
||||
const DepthOffsetAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const DepthOffsetAttrib *ta = (const DepthOffsetAttrib *)other;
|
||||
|
||||
int new_offset = ta->_offset - _offset;
|
||||
|
||||
DepthOffsetAttrib *attrib = new DepthOffsetAttrib(new_offset, ta->_min_value, ta->_max_value);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,8 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "DepthOffsetAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100,
|
||||
new DepthOffsetAttrib(0, 0, 1));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int DepthTestAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const DepthTestAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const DepthTestAttrib *ta = (const DepthTestAttrib *)other;
|
||||
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "DepthTestAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new DepthTestAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int DepthWriteAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const DepthWriteAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const DepthWriteAttrib *ta = (const DepthWriteAttrib *)other;
|
||||
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "DepthWriteAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new DepthWriteAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -91,8 +91,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int FogAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const FogAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const FogAttrib *ta = (const FogAttrib *)other;
|
||||
|
||||
// Comparing pointers by subtraction is problematic. Instead of
|
||||
// doing this, we'll just depend on the built-in != and < operators
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "FogAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new FogAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -696,8 +696,7 @@ write(ostream &out, int indent_level) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int LightAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const LightAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const LightAttrib *ta = (const LightAttrib *)other;
|
||||
|
||||
if (_off_all_lights != ta->_off_all_lights) {
|
||||
return (int)_off_all_lights - (int)ta->_off_all_lights;
|
||||
|
|
@ -803,8 +802,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const LightAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const LightAttrib *ta = (const LightAttrib *)other;
|
||||
|
||||
if (ta->_off_all_lights) {
|
||||
// If the other type turns off all lights, it doesn't matter what
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "LightAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 20, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 20, new LightAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -241,8 +241,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int LightRampAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const LightRampAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const LightRampAttrib *ta = (const LightRampAttrib *)other;
|
||||
|
||||
int compare_result = ((int)_mode - (int)ta->_mode) ;
|
||||
if (compare_result != 0) {
|
||||
return compare_result;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "LightRampAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new LightRampAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -92,8 +92,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int MaterialAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const MaterialAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const MaterialAttrib *ta = (const MaterialAttrib *)other;
|
||||
|
||||
// Comparing pointers by subtraction is problematic. Instead of
|
||||
// doing this, we'll just depend on the built-in != and < operators
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "MaterialAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new MaterialAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -49,20 +49,6 @@ invert_compose(const RenderAttrib *other) const {
|
|||
return invert_compose_impl(other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttrib::always_reissue
|
||||
// Access: Public
|
||||
// Description: Returns true if the RenderAttrib should be reissued
|
||||
// to the GSG with every state change, even if it is the
|
||||
// same pointer as it was before; or false for the
|
||||
// normal case, to reissue only when the RenderAttrib
|
||||
// pointer changes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RenderAttrib::
|
||||
always_reissue() const {
|
||||
return _always_reissue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttrib::compare_to
|
||||
// Access: Published
|
||||
|
|
@ -160,8 +146,7 @@ calc_hash() {
|
|||
// number. See RenderAttribRegistry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int RenderAttrib::
|
||||
register_slot(TypeHandle type_handle, int sort,
|
||||
RenderAttribRegistry::MakeDefaultFunc *make_default_func) {
|
||||
register_slot(TypeHandle type_handle, int sort, RenderAttrib *default_attrib) {
|
||||
RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
|
||||
return reg->register_slot(type_handle, sort, make_default_func);
|
||||
return reg->register_slot(type_handle, sort, default_attrib);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@ RenderAttrib() {
|
|||
init_attribs();
|
||||
}
|
||||
_saved_entry = -1;
|
||||
|
||||
_always_reissue = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -435,13 +433,14 @@ return_unique(RenderAttrib *attrib) {
|
|||
return attrib;
|
||||
}
|
||||
|
||||
// Save the attrib in a local PointerTo so that it will be freed at
|
||||
// the end of this function if no one else uses it.
|
||||
CPT(RenderAttrib) pt_attrib = attrib;
|
||||
|
||||
int si = _attribs->find(attrib);
|
||||
if (si != -1) {
|
||||
// There's an equivalent attrib already in the set. Return it.
|
||||
// If this is a newly created RenderAttrib, though, be sure to
|
||||
// delete it.
|
||||
if (attrib->get_ref_count() == 0) {
|
||||
delete attrib;
|
||||
}
|
||||
return _attribs->get_key(si);
|
||||
}
|
||||
|
||||
|
|
@ -456,7 +455,7 @@ return_unique(RenderAttrib *attrib) {
|
|||
|
||||
// Save the index and return the input attrib.
|
||||
attrib->_saved_entry = si;
|
||||
return pt_attrib;
|
||||
return attrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -73,8 +73,6 @@ PUBLISHED:
|
|||
virtual bool lower_attrib_can_override() const;
|
||||
|
||||
public:
|
||||
INLINE bool always_reissue() const;
|
||||
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
|
||||
|
||||
|
|
@ -190,14 +188,11 @@ protected:
|
|||
|
||||
public:
|
||||
INLINE static int register_slot(TypeHandle type_handle, int sort,
|
||||
RenderAttribRegistry::MakeDefaultFunc *make_default_func);
|
||||
RenderAttrib *default_attrib);
|
||||
|
||||
private:
|
||||
void release_new();
|
||||
|
||||
protected:
|
||||
bool _always_reissue;
|
||||
|
||||
public:
|
||||
static void init_attribs();
|
||||
|
||||
|
|
@ -218,6 +213,8 @@ private:
|
|||
|
||||
static PStatCollector _garbage_collect_pcollector;
|
||||
|
||||
friend class RenderAttribRegistry;
|
||||
|
||||
public:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ get_slot(TypeHandle type_handle) const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::get_max_slots
|
||||
// Access: Published
|
||||
// Access: Published, Static
|
||||
// Description: Returns the maximum number that any slot number is
|
||||
// allowed to grow. Actually, this number will be one
|
||||
// higher than the highest possible slot number. This
|
||||
|
|
@ -41,8 +41,8 @@ get_slot(TypeHandle type_handle) const {
|
|||
// This number will not change during the lifetime of
|
||||
// the application.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int RenderAttribRegistry::
|
||||
get_max_slots() const {
|
||||
CONSTEXPR int RenderAttribRegistry::
|
||||
get_max_slots() {
|
||||
return _max_slots;
|
||||
}
|
||||
|
||||
|
|
@ -80,6 +80,20 @@ get_slot_sort(int slot) const {
|
|||
return _registry[slot]._sort;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::get_slot_default
|
||||
// Access: Published
|
||||
// Description: Returns the default RenderAttrib object associated
|
||||
// with slot n. This is the attrib that should be
|
||||
// applied in the absence of any other attrib of this
|
||||
// type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const RenderAttrib *RenderAttribRegistry::
|
||||
get_slot_default(int slot) const {
|
||||
nassertr(slot >= 0 && slot < (int)_registry.size(), 0);
|
||||
return _registry[slot]._default_attrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::get_num_sorted_slots
|
||||
// Access: Published
|
||||
|
|
@ -104,18 +118,6 @@ get_sorted_slot(int n) const {
|
|||
return _sorted_slots[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::get_array_chain
|
||||
// Access: Published
|
||||
// Description: Returns the DeletedBufferChain object that may be
|
||||
// used to allocated appropriately-sized arrays of
|
||||
// RenderState::Attribute objects.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DeletedBufferChain *RenderAttribRegistry::
|
||||
get_array_chain() const {
|
||||
return _array_chain;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::get_global_ptr
|
||||
// Access: Published, Static
|
||||
|
|
@ -154,9 +156,21 @@ SortSlots(RenderAttribRegistry *reg) : _reg(reg) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::SortSlots::operator ()
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RenderAttribRegistry::SortSlots::
|
||||
operator () (int a, int b) const {
|
||||
return _reg->get_slot_sort(a) < _reg->get_slot_sort(b);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::RegistryNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE RenderAttribRegistry::RegistryNode::
|
||||
RegistryNode(TypeHandle type, int sort, const RenderAttrib *default_attrib) :
|
||||
_type(type),
|
||||
_sort(sort),
|
||||
_default_attrib(default_attrib) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,37 +26,12 @@ RenderAttribRegistry *RenderAttribRegistry::_global_ptr;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
RenderAttribRegistry::
|
||||
RenderAttribRegistry() {
|
||||
ConfigVariableInt max_attribs
|
||||
("max-attribs", SlotMask::get_max_num_bits(),
|
||||
PRC_DESC("This specifies the maximum number of different RenderAttrib "
|
||||
"types that may be defined at runtime. Normally you should "
|
||||
"never need to change this, but if the default value is too "
|
||||
"low for the number of attribs that Panda actually defines, "
|
||||
"you may need to raise this number."));
|
||||
|
||||
// Assign this number once, at startup, and never change it again.
|
||||
_max_slots = max((int)max_attribs, 1);
|
||||
if (_max_slots > SlotMask::get_max_num_bits()) {
|
||||
pgraph_cat->warning()
|
||||
<< "Value for max-attribs too large: cannot exceed "
|
||||
<< SlotMask::get_max_num_bits()
|
||||
<< " in this build. To raise this limit, change the typedef "
|
||||
<< "for SlotMask in renderAttribRegistry.h and recompile.\n";
|
||||
|
||||
_max_slots = SlotMask::get_max_num_bits();
|
||||
}
|
||||
|
||||
// Get a DeletedBufferChain to manage the arrays of RenderAttribs that are
|
||||
// allocated within each RenderState object.
|
||||
init_memory_hook();
|
||||
_array_chain = memory_hook->get_deleted_chain(_max_slots * sizeof(RenderState::Attribute));
|
||||
_registry.reserve(_max_slots);
|
||||
_sorted_slots.reserve(_max_slots);
|
||||
|
||||
// Reserve slot 0 for TypeHandle::none(), and for types that exceed
|
||||
// max_slots.
|
||||
RegistryNode node;
|
||||
node._sort = 0;
|
||||
node._make_default_func = NULL;
|
||||
_registry.push_back(node);
|
||||
_registry.push_back(RegistryNode(TypeHandle::none(), 0, NULL));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -86,9 +61,9 @@ RenderAttribRegistry::
|
|||
// RenderAttribs (that is, those which are more
|
||||
// expensive to change) have lower sort values.
|
||||
//
|
||||
// The make_default_func pointer is a function that may
|
||||
// be called to generate a default RenderAttrib to apply
|
||||
// in the absence of any other attrib of this type.
|
||||
// The default_attrib pointer should be a newly
|
||||
// created instance of this attribute that represents
|
||||
// the default state for this attribute.
|
||||
//
|
||||
// register_slot() is intended to be called at
|
||||
// application start for each different RenderAttrib
|
||||
|
|
@ -96,8 +71,11 @@ RenderAttribRegistry::
|
|||
// slot number to each one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int RenderAttribRegistry::
|
||||
register_slot(TypeHandle type_handle, int sort,
|
||||
RenderAttribRegistry::MakeDefaultFunc *make_default_func) {
|
||||
register_slot(TypeHandle type_handle, int sort, RenderAttrib *default_attrib) {
|
||||
// Sanity check; if this triggers, you either passed a wrong argument,
|
||||
// or you didn't use the type system correctly.
|
||||
nassertr(default_attrib->get_type() == type_handle, 0);
|
||||
|
||||
int type_index = type_handle.get_index();
|
||||
while (type_index >= (int)_slots_by_type.size()) {
|
||||
_slots_by_type.push_back(0);
|
||||
|
|
@ -111,19 +89,33 @@ register_slot(TypeHandle type_handle, int sort,
|
|||
int slot = (int)_registry.size();
|
||||
if (slot >= _max_slots) {
|
||||
pgraph_cat->error()
|
||||
<< "Too many registered RenderAttribs; not registering "
|
||||
<< "Too many registered RenderAttribs; not registering "
|
||||
<< type_handle << "\n";
|
||||
nassertr(false, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Register the default attribute. We don't use return_unique and
|
||||
// register it even if the state cache is disabled, because we can't read
|
||||
// the state_cache config variable yet at this time. It probably doesn't
|
||||
// hurt to have these 32 entries around in the attrib cache.
|
||||
if (default_attrib != (RenderAttrib *)NULL) {
|
||||
default_attrib->calc_hash();
|
||||
|
||||
if (default_attrib->_saved_entry == -1) {
|
||||
// If this attribute was already registered, something odd is going on.
|
||||
nassertr(RenderAttrib::_attribs->find(default_attrib) == -1, 0);
|
||||
default_attrib->_saved_entry =
|
||||
RenderAttrib::_attribs->store(default_attrib, RenderAttrib::Empty());
|
||||
}
|
||||
|
||||
// It effectively lives forever. Might as well make it official.
|
||||
default_attrib->local_object();
|
||||
}
|
||||
|
||||
_slots_by_type[type_index] = slot;
|
||||
|
||||
RegistryNode node;
|
||||
node._type = type_handle;
|
||||
node._sort = sort;
|
||||
node._make_default_func = make_default_func;
|
||||
_registry.push_back(node);
|
||||
_registry.push_back(RegistryNode(type_handle, sort, default_attrib));
|
||||
|
||||
_sorted_slots.push_back(slot);
|
||||
::sort(_sorted_slots.begin(), _sorted_slots.end(), SortSlots(this));
|
||||
|
|
@ -143,27 +135,12 @@ set_slot_sort(int slot, int sort) {
|
|||
|
||||
// Re-sort the slot list.
|
||||
_sorted_slots.clear();
|
||||
_sorted_slots.reserve(_registry.size() - 1);
|
||||
for (int i = 1; i < (int)_registry.size(); ++i) {
|
||||
_sorted_slots.push_back(i);
|
||||
}
|
||||
::sort(_sorted_slots.begin(), _sorted_slots.end(), SortSlots(this));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::get_slot_default
|
||||
// Access: Published
|
||||
// Description: Returns the default RenderAttrib object associated
|
||||
// with slot n. This is the attrib that should be
|
||||
// applied in the absence of any other attrib of this
|
||||
// type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) RenderAttribRegistry::
|
||||
get_slot_default(int slot) const {
|
||||
nassertr(slot >= 0 && slot < (int)_registry.size(), 0);
|
||||
return (*_registry[slot]._make_default_func)();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderAttribRegistry::init_global_ptr
|
||||
// Access: Private, Static
|
||||
|
|
|
|||
|
|
@ -48,24 +48,26 @@ public:
|
|||
// or a DoubleBitMask<BitMask32> will be faster on a 32-bit machine.
|
||||
typedef BitMask32 SlotMask;
|
||||
|
||||
// Raise this number whenever we add a new attrib. This used to be
|
||||
// determined at runtime, but it's better to have it as a constexpr.
|
||||
static const int _max_slots = 29;
|
||||
|
||||
int register_slot(TypeHandle type_handle, int sort,
|
||||
MakeDefaultFunc *make_default_func);
|
||||
RenderAttrib *default_attrib);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE int get_slot(TypeHandle type_handle) const;
|
||||
INLINE int get_max_slots() const;
|
||||
static CONSTEXPR int get_max_slots();
|
||||
|
||||
INLINE int get_num_slots() const;
|
||||
INLINE TypeHandle get_slot_type(int slot) const;
|
||||
INLINE int get_slot_sort(int slot) const;
|
||||
void set_slot_sort(int slot, int sort);
|
||||
CPT(RenderAttrib) get_slot_default(int slot) const;
|
||||
INLINE const RenderAttrib *get_slot_default(int slot) const;
|
||||
|
||||
INLINE int get_num_sorted_slots() const;
|
||||
INLINE int get_sorted_slot(int n) const;
|
||||
|
||||
INLINE DeletedBufferChain *get_array_chain() const;
|
||||
|
||||
INLINE static RenderAttribRegistry *get_global_ptr();
|
||||
|
||||
public:
|
||||
|
|
@ -75,8 +77,6 @@ private:
|
|||
static void init_global_ptr();
|
||||
|
||||
private:
|
||||
int _max_slots;
|
||||
|
||||
class SortSlots {
|
||||
public:
|
||||
INLINE SortSlots(RenderAttribRegistry *reg);
|
||||
|
|
@ -86,9 +86,12 @@ private:
|
|||
|
||||
class RegistryNode {
|
||||
public:
|
||||
INLINE RegistryNode(TypeHandle type, int sort,
|
||||
const RenderAttrib *default_attrib);
|
||||
|
||||
TypeHandle _type;
|
||||
int _sort;
|
||||
MakeDefaultFunc *_make_default_func;
|
||||
const RenderAttrib *_default_attrib;
|
||||
};
|
||||
typedef pvector<RegistryNode> Registry;
|
||||
Registry _registry;
|
||||
|
|
@ -96,12 +99,9 @@ private:
|
|||
vector_int _slots_by_type;
|
||||
vector_int _sorted_slots;
|
||||
|
||||
DeletedBufferChain *_array_chain;
|
||||
|
||||
static RenderAttribRegistry *_global_ptr;
|
||||
};
|
||||
|
||||
#include "renderAttribRegistry.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int RenderModeAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const RenderModeAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const RenderModeAttrib *ta = (const RenderModeAttrib *)other;
|
||||
|
||||
if (_mode != ta->_mode) {
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
|
@ -186,8 +186,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) RenderModeAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const RenderModeAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const RenderModeAttrib *ta = (const RenderModeAttrib *)other;
|
||||
|
||||
// The special mode M_unchanged means to keep the current mode.
|
||||
Mode mode = ta->get_mode();
|
||||
|
|
|
|||
|
|
@ -106,7 +106,8 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "RenderModeAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100,
|
||||
new RenderModeAttrib(M_filled, 1, false));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -58,35 +58,9 @@ has_cull_callback() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPT(RenderState) RenderState::
|
||||
make_empty() {
|
||||
// The empty state is asked for so often, we make it a special case
|
||||
// and store a pointer forever once we find it the first time.
|
||||
if (_empty_state == (RenderState *)NULL) {
|
||||
RenderState *state = new RenderState;
|
||||
_empty_state = return_unique(state);
|
||||
}
|
||||
|
||||
return _empty_state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::make_full_default
|
||||
// Access: Published, Static
|
||||
// Description: Returns a RenderState with all possible attributes
|
||||
// set to their default value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPT(RenderState) RenderState::
|
||||
make_full_default() {
|
||||
// The empty state is asked for so often, we make it a special case
|
||||
// and store a pointer forever once we find it the first time.
|
||||
if (_full_default_state == (RenderState *)NULL) {
|
||||
RenderState *state = new RenderState;
|
||||
state->fill_default();
|
||||
_full_default_state = return_unique(state);
|
||||
}
|
||||
|
||||
return _full_default_state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::remove_attrib
|
||||
// Access: Published
|
||||
|
|
@ -144,7 +118,7 @@ get_attrib(TypeHandle type) const {
|
|||
// index, or NULL if there is no such RenderAttrib in
|
||||
// the state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const RenderAttrib *RenderState::
|
||||
ALWAYS_INLINE const RenderAttrib *RenderState::
|
||||
get_attrib(int slot) const {
|
||||
return _attributes[slot]._attrib;
|
||||
}
|
||||
|
|
@ -161,7 +135,8 @@ get_attrib_def(int slot) const {
|
|||
if (_attributes[slot]._attrib != (RenderAttrib *)NULL) {
|
||||
return _attributes[slot]._attrib;
|
||||
}
|
||||
return make_full_default()->get_attrib(slot);
|
||||
RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
|
||||
return reg->get_slot_default(slot);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@
|
|||
|
||||
LightReMutex *RenderState::_states_lock = NULL;
|
||||
RenderState::States *RenderState::_states = NULL;
|
||||
CPT(RenderState) RenderState::_empty_state;
|
||||
CPT(RenderState) RenderState::_full_default_state;
|
||||
const RenderState *RenderState::_empty_state = NULL;
|
||||
UpdateSeq RenderState::_last_cycle_detect;
|
||||
int RenderState::_garbage_index = 0;
|
||||
|
||||
|
|
@ -72,20 +71,11 @@ RenderState() :
|
|||
_auto_shader_state(NULL),
|
||||
_lock("RenderState")
|
||||
{
|
||||
// Allocate the _attributes array.
|
||||
RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
|
||||
_attributes = (Attribute *)reg->get_array_chain()->allocate(reg->get_max_slots() * sizeof(Attribute), get_class_type());
|
||||
|
||||
// Also make sure each element gets initialized.
|
||||
for (int i = 0; i < reg->get_max_slots(); ++i) {
|
||||
new(&_attributes[i]) Attribute();
|
||||
}
|
||||
|
||||
if (_states == (States *)NULL) {
|
||||
init_states();
|
||||
}
|
||||
_saved_entry = -1;
|
||||
_last_mi = _mungers.end();
|
||||
_last_mi = -1;
|
||||
_cache_stats.add_num_states(1);
|
||||
_read_overrides = NULL;
|
||||
_generated_shader = NULL;
|
||||
|
|
@ -103,17 +93,13 @@ RenderState(const RenderState ©) :
|
|||
_auto_shader_state(NULL),
|
||||
_lock("RenderState")
|
||||
{
|
||||
// Allocate the _attributes array.
|
||||
RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
|
||||
_attributes = (Attribute *)reg->get_array_chain()->allocate(reg->get_max_slots() * sizeof(Attribute), get_class_type());
|
||||
|
||||
// Also make sure each element gets initialized, as a copy.
|
||||
for (int i = 0; i < reg->get_max_slots(); ++i) {
|
||||
new(&_attributes[i]) Attribute(copy._attributes[i]);
|
||||
// Copy over the attributes.
|
||||
for (int i = 0; i < RenderAttribRegistry::_max_slots; ++i) {
|
||||
_attributes[i] = copy._attributes[i];
|
||||
}
|
||||
|
||||
_saved_entry = -1;
|
||||
_last_mi = _mungers.end();
|
||||
_last_mi = -1;
|
||||
_cache_stats.add_num_states(1);
|
||||
_read_overrides = NULL;
|
||||
_generated_shader = NULL;
|
||||
|
|
@ -159,14 +145,6 @@ RenderState::
|
|||
// longer true now, probably we've been double-deleted.
|
||||
nassertv(get_ref_count() == 0);
|
||||
_cache_stats.add_num_states(-1);
|
||||
|
||||
// Free the _attributes array.
|
||||
RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
|
||||
for (int i = 0; i < reg->get_max_slots(); ++i) {
|
||||
_attributes[i].~Attribute();
|
||||
}
|
||||
reg->get_array_chain()->deallocate(_attributes, get_class_type());
|
||||
_attributes = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -360,7 +338,7 @@ make(const RenderAttrib *attrib1,
|
|||
CPT(RenderState) RenderState::
|
||||
make(const RenderAttrib * const *attrib, int num_attribs, int override) {
|
||||
if (num_attribs == 0) {
|
||||
return make_empty();
|
||||
return _empty_state;
|
||||
}
|
||||
RenderState *state = new RenderState;
|
||||
for (int i = 0; i < num_attribs; i++) {
|
||||
|
|
@ -490,7 +468,7 @@ invert_compose(const RenderState *other) const {
|
|||
|
||||
if (other == this) {
|
||||
// a->invert_compose(a) always produces identity.
|
||||
return make_empty();
|
||||
return _empty_state;
|
||||
}
|
||||
|
||||
if (!state_cache) {
|
||||
|
|
@ -633,7 +611,7 @@ remove_attrib(int slot) const {
|
|||
|
||||
// Will this bring us down to the empty state?
|
||||
if (_filled_slots.get_num_on_bits() == 1) {
|
||||
return make_empty();
|
||||
return _empty_state;
|
||||
}
|
||||
|
||||
RenderState *new_state = new RenderState(*this);
|
||||
|
|
@ -1110,7 +1088,7 @@ clear_munger_cache() {
|
|||
}
|
||||
RenderState *state = (RenderState *)(_states->get_key(si));
|
||||
state->_mungers.clear();
|
||||
state->_last_mi = state->_mungers.end();
|
||||
state->_last_mi = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1314,17 +1292,17 @@ validate_states() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int RenderState::
|
||||
get_geom_rendering(int geom_rendering) const {
|
||||
const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, get_attrib(RenderModeAttrib::get_class_slot()));
|
||||
const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, get_attrib(TexGenAttrib::get_class_slot()));
|
||||
const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, get_attrib(TexMatrixAttrib::get_class_slot()));
|
||||
const RenderModeAttrib *render_mode;
|
||||
const TexGenAttrib *tex_gen;
|
||||
const TexMatrixAttrib *tex_matrix;
|
||||
|
||||
if (render_mode != (const RenderModeAttrib *)NULL) {
|
||||
if (get_attrib(render_mode)) {
|
||||
geom_rendering = render_mode->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
if (tex_gen != (const TexGenAttrib *)NULL) {
|
||||
if (get_attrib(tex_gen)) {
|
||||
geom_rendering = tex_gen->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
if (tex_matrix != (const TexMatrixAttrib *)NULL) {
|
||||
if (get_attrib(tex_matrix)) {
|
||||
geom_rendering = tex_matrix->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
|
||||
|
|
@ -1507,7 +1485,7 @@ return_new(RenderState *state) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) RenderState::
|
||||
return_unique(RenderState *state) {
|
||||
nassertr(state != (RenderState *)NULL, state);
|
||||
nassertr(state != (RenderState *)NULL, NULL);
|
||||
|
||||
if (!state_cache) {
|
||||
return state;
|
||||
|
|
@ -1523,14 +1501,10 @@ return_unique(RenderState *state) {
|
|||
|
||||
if (state->_saved_entry != -1) {
|
||||
// This state is already in the cache.
|
||||
//nassertr(_states->find(state) == state->_saved_entry, state);
|
||||
//nassertr(_states->find(state) == state->_saved_entry, pt_state);
|
||||
return state;
|
||||
}
|
||||
|
||||
// Save the state in a local PointerTo so that it will be freed at
|
||||
// the end of this function if no one else uses it.
|
||||
CPT(RenderState) pt_state = state;
|
||||
|
||||
// Ensure each of the individual attrib pointers has been uniquified
|
||||
// before we add the state to the cache.
|
||||
if (!uniquify_attribs && !state->is_empty()) {
|
||||
|
|
@ -1538,7 +1512,7 @@ return_unique(RenderState *state) {
|
|||
int slot = mask.get_lowest_on_bit();
|
||||
while (slot >= 0) {
|
||||
Attribute &attrib = state->_attributes[slot];
|
||||
nassertr(attrib._attrib != (RenderAttrib *)NULL, state);
|
||||
nassertd(attrib._attrib != (RenderAttrib *)NULL) continue;
|
||||
attrib._attrib = attrib._attrib->get_unique();
|
||||
mask.clear_bit(slot);
|
||||
slot = mask.get_lowest_on_bit();
|
||||
|
|
@ -1548,6 +1522,11 @@ return_unique(RenderState *state) {
|
|||
int si = _states->find(state);
|
||||
if (si != -1) {
|
||||
// There's an equivalent state already in the set. Return it.
|
||||
// The state that was passed may be newly created and therefore
|
||||
// may not be automatically deleted. Do that if necessary.
|
||||
if (state->get_ref_count() == 0) {
|
||||
delete state;
|
||||
}
|
||||
return _states->get_key(si);
|
||||
}
|
||||
|
||||
|
|
@ -1562,7 +1541,7 @@ return_unique(RenderState *state) {
|
|||
|
||||
// Save the index and return the input state.
|
||||
state->_saved_entry = si;
|
||||
return pt_state;
|
||||
return state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1621,15 +1600,6 @@ do_compose(const RenderState *other) const {
|
|||
slot = mask.get_lowest_on_bit();
|
||||
}
|
||||
|
||||
// If we have any ShaderAttrib with auto-shader enabled,
|
||||
// remove any shader inputs on it. This is a workaround for an
|
||||
// issue that makes the shader-generator regenerate the shader
|
||||
// every time a shader input changes.
|
||||
CPT(ShaderAttrib) sattrib = DCAST(ShaderAttrib, new_state->get_attrib_def(ShaderAttrib::get_class_slot()));
|
||||
if (sattrib->auto_shader()) {
|
||||
sattrib = DCAST(ShaderAttrib, sattrib->clear_all_shader_inputs());
|
||||
}
|
||||
|
||||
return return_new(new_state);
|
||||
}
|
||||
|
||||
|
|
@ -1660,9 +1630,8 @@ do_invert_compose(const RenderState *other) const {
|
|||
|
||||
} else if (b._attrib == NULL) {
|
||||
// A wins. Invert it.
|
||||
CPT(RenderState) full_default = make_full_default();
|
||||
CPT(RenderAttrib) default_attrib = full_default->get_attrib(slot);
|
||||
result.set(a._attrib->invert_compose(default_attrib), 0);
|
||||
RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
|
||||
result.set(a._attrib->invert_compose(reg->get_slot_default(slot)), 0);
|
||||
|
||||
} else {
|
||||
// Both are good. (Overrides are not used in invert_compose.)
|
||||
|
|
@ -2162,8 +2131,14 @@ init_states() {
|
|||
_states_lock = new LightReMutex("RenderState::_states_lock");
|
||||
_cache_stats.init();
|
||||
nassertv(Thread::get_current_thread() == Thread::get_main_thread());
|
||||
}
|
||||
|
||||
// Initialize the empty state object as well. It is used so often
|
||||
// that it is declared globally, and lives forever.
|
||||
RenderState *state = new RenderState;
|
||||
state->local_object();
|
||||
state->_saved_entry = _states->store(state, Empty());
|
||||
_empty_state = state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::register_with_read_factory
|
||||
|
|
|
|||
|
|
@ -31,10 +31,11 @@
|
|||
#include "lightMutex.h"
|
||||
#include "deletedChain.h"
|
||||
#include "simpleHashMap.h"
|
||||
#include "weakKeyHashMap.h"
|
||||
#include "cacheStats.h"
|
||||
#include "renderAttribRegistry.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
|
||||
class GraphicsStateGuardianBase;
|
||||
class FactoryParams;
|
||||
class ShaderAttrib;
|
||||
|
||||
|
|
@ -76,7 +77,6 @@ PUBLISHED:
|
|||
bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
|
||||
|
||||
INLINE static CPT(RenderState) make_empty();
|
||||
INLINE static CPT(RenderState) make_full_default();
|
||||
static CPT(RenderState) make(const RenderAttrib *attrib, int override = 0);
|
||||
static CPT(RenderState) make(const RenderAttrib *attrib1,
|
||||
const RenderAttrib *attrib2, int override = 0);
|
||||
|
|
@ -104,7 +104,7 @@ PUBLISHED:
|
|||
INLINE bool has_attrib(TypeHandle type) const;
|
||||
INLINE bool has_attrib(int slot) const;
|
||||
INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
|
||||
INLINE const RenderAttrib *get_attrib(int slot) const;
|
||||
ALWAYS_INLINE const RenderAttrib *get_attrib(int slot) const;
|
||||
INLINE const RenderAttrib *get_attrib_def(int slot) const;
|
||||
INLINE int get_override(TypeHandle type) const;
|
||||
INLINE int get_override(int slot) const;
|
||||
|
|
@ -233,8 +233,7 @@ private:
|
|||
};
|
||||
typedef SimpleHashMap<const RenderState *, Empty, indirect_compare_to_hash<const RenderState *> > States;
|
||||
static States *_states;
|
||||
static CPT(RenderState) _empty_state;
|
||||
static CPT(RenderState) _full_default_state;
|
||||
static const RenderState *_empty_state;
|
||||
|
||||
// This iterator records the entry corresponding to this
|
||||
// RenderState object in the above global set. We keep the index
|
||||
|
|
@ -270,9 +269,9 @@ private:
|
|||
// since there are likely to be far fewer GSG's than RenderStates.
|
||||
// The code to manage this map lives in
|
||||
// GraphicsStateGuardian::get_geom_munger().
|
||||
typedef pmap<WCPT(GraphicsStateGuardianBase), PT(GeomMunger) > Mungers;
|
||||
typedef WeakKeyHashMap<GraphicsStateGuardianBase, PT(GeomMunger) > Mungers;
|
||||
mutable Mungers _mungers;
|
||||
mutable Mungers::const_iterator _last_mi;
|
||||
mutable int _last_mi;
|
||||
|
||||
// This is used to mark nodes as we visit them to detect cycles.
|
||||
UpdateSeq _cycle_detect;
|
||||
|
|
@ -307,7 +306,7 @@ private:
|
|||
CPT(RenderAttrib) _attrib;
|
||||
int _override;
|
||||
};
|
||||
Attribute *_attributes;
|
||||
Attribute _attributes[RenderAttribRegistry::_max_slots];
|
||||
|
||||
// We also store a bitmask of the non-NULL attributes in the above
|
||||
// array. This is redundant, but it is a useful cache.
|
||||
|
|
|
|||
|
|
@ -25,6 +25,19 @@ RescaleNormalAttrib(RescaleNormalAttrib::Mode mode) :
|
|||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RescaleNormalAttrib::make_default
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a RescaleNormalAttrib object that's
|
||||
// suitable for putting at the top of a scene graph.
|
||||
// This will contain whatever attrib was suggested by
|
||||
// the user's rescale-normals Config variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPT(RenderAttrib) RescaleNormalAttrib::
|
||||
make_default() {
|
||||
return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RescaleNormalAttrib::get_mode
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -25,18 +25,7 @@
|
|||
|
||||
TypeHandle RescaleNormalAttrib::_type_handle;
|
||||
int RescaleNormalAttrib::_attrib_slot;
|
||||
|
||||
// This variable is defined here instead of in config_pgraph.cxx,
|
||||
// because it depends on rescaleNormalAttrib.h having already been
|
||||
// included.
|
||||
static ConfigVariableEnum<RescaleNormalAttrib::Mode> rescale_normals
|
||||
("rescale-normals", RescaleNormalAttrib::M_auto,
|
||||
PRC_DESC("Specifies the kind of RescaleNormalAttrib that should be "
|
||||
"created for the top of the scene graph. This can automatically "
|
||||
"ensure that your lighting normals are unit-length, which may be "
|
||||
"particularly necessary in the presence of scales in the scene "
|
||||
"graph. Turning it off ('none') may produce a small performance "
|
||||
"benefit."));
|
||||
CPT(RenderAttrib) RescaleNormalAttrib::_attribs[RescaleNormalAttrib::M_auto + 1];
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RescaleNormalAttrib::make
|
||||
|
|
@ -47,28 +36,18 @@ static ConfigVariableEnum<RescaleNormalAttrib::Mode> rescale_normals
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) RescaleNormalAttrib::
|
||||
make(RescaleNormalAttrib::Mode mode) {
|
||||
RescaleNormalAttrib *attrib = new RescaleNormalAttrib(mode);
|
||||
return return_new(attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RescaleNormalAttrib::make_default
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a RescaleNoramlAttrib object that's
|
||||
// suitable for putting at the top of a scene graph.
|
||||
// This will contain whatever attrib was suggested by
|
||||
// the user's rescale-normals Config variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) RescaleNormalAttrib::
|
||||
make_default() {
|
||||
RescaleNormalAttrib *attrib = new RescaleNormalAttrib(rescale_normals);
|
||||
return return_new(attrib);
|
||||
if (_attribs[mode].is_null()) {
|
||||
// Don't bother with return_new, since this is the only way a
|
||||
// RescaleNormalAttrib can be made anyway.
|
||||
_attribs[mode] = new RescaleNormalAttrib(mode);
|
||||
}
|
||||
return _attribs[mode];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RescaleNormalAttrib::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RescaleNormalAttrib::
|
||||
output(ostream &out) const {
|
||||
|
|
@ -92,8 +71,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int RescaleNormalAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const RescaleNormalAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const RescaleNormalAttrib *ta = (const RescaleNormalAttrib *)other;
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
||||
|
|
@ -187,6 +165,35 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
_mode = (Mode)scan.get_int8();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RescaleNormalAttrib::init_type
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RescaleNormalAttrib::
|
||||
init_type() {
|
||||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "RescaleNormalAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
|
||||
// This is defined here, since we have otherwise no guarantee that
|
||||
// the config var has already been constructed by the time we call
|
||||
// init_type() at static init time.
|
||||
static ConfigVariableEnum<RescaleNormalAttrib::Mode> rescale_normals
|
||||
("rescale-normals", RescaleNormalAttrib::M_auto,
|
||||
PRC_DESC("Specifies the kind of RescaleNormalAttrib that should be "
|
||||
"created for the top of the scene graph. This can automatically "
|
||||
"ensure that your lighting normals are unit-length, which may be "
|
||||
"particularly necessary in the presence of scales in the scene "
|
||||
"graph. Turning it off ('none') may produce a small performance "
|
||||
"benefit."));
|
||||
|
||||
Mode mode = rescale_normals;
|
||||
RescaleNormalAttrib *attrib = new RescaleNormalAttrib(mode);
|
||||
_attrib_slot = register_slot(_type_handle, 100, attrib);
|
||||
_attribs[mode] = attrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RescaleNormalAttrib::Mode output operator
|
||||
// Description:
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ private:
|
|||
|
||||
PUBLISHED:
|
||||
static CPT(RenderAttrib) make(Mode mode);
|
||||
static CPT(RenderAttrib) make_default();
|
||||
INLINE static CPT(RenderAttrib) make_default();
|
||||
|
||||
INLINE Mode get_mode() const;
|
||||
|
||||
|
|
@ -64,6 +64,10 @@ protected:
|
|||
private:
|
||||
Mode _mode;
|
||||
|
||||
// There are so few possible combinations, and it's used fairly often, so
|
||||
// we keep an array of the possible attributes.
|
||||
static CPT(RenderAttrib) _attribs[M_auto + 1];
|
||||
|
||||
PUBLISHED:
|
||||
static int get_class_slot() {
|
||||
return _attrib_slot;
|
||||
|
|
@ -79,17 +83,12 @@ public:
|
|||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "RescaleNormalAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
}
|
||||
static void init_type();
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,8 +113,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int ScissorAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const ScissorAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ScissorAttrib *ta = (const ScissorAttrib *)other;
|
||||
|
||||
if (!_off && !ta->_off) {
|
||||
return 0;
|
||||
|
|
@ -173,8 +172,7 @@ compose_impl(const RenderAttrib *other) const {
|
|||
return other;
|
||||
}
|
||||
|
||||
const ScissorAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ScissorAttrib *ta = (const ScissorAttrib *)other;
|
||||
|
||||
if (ta->_off) {
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,10 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ScissorAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
|
||||
ScissorAttrib *attrib = new ScissorAttrib(LVecBase4(0, 1, 0, 1));
|
||||
attrib->_off = true;
|
||||
_attrib_slot = register_slot(_type_handle, 100, attrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -84,8 +84,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int ShadeModelAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const ShadeModelAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ShadeModelAttrib *ta = (const ShadeModelAttrib *)other;
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
||||
|
|
@ -125,8 +124,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ShadeModelAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const ShadeModelAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const ShadeModelAttrib *ta = (const ShadeModelAttrib *)other;
|
||||
|
||||
Mode mode = ta->get_mode();
|
||||
return make(mode);
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ShadeModelAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new ShadeModelAttrib(M_smooth));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -542,8 +542,7 @@ get_shader() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int ShaderAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const ShaderAttrib *that;
|
||||
DCAST_INTO_R(that, other, 0);
|
||||
const ShaderAttrib *that = (const ShaderAttrib *)other;
|
||||
|
||||
if (this->_shader != that->_shader) {
|
||||
return (this->_shader < that->_shader) ? -1 : 1;
|
||||
|
|
@ -643,8 +642,8 @@ get_hash_impl() const {
|
|||
CPT(RenderAttrib) ShaderAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
ShaderAttrib *attr = new ShaderAttrib(*this);
|
||||
const ShaderAttrib *over;
|
||||
DCAST_INTO_R(over, other, 0);
|
||||
const ShaderAttrib *over = (const ShaderAttrib *)other;
|
||||
|
||||
// Update the shader portion.
|
||||
if (over->_has_shader) {
|
||||
if ((attr->_has_shader == false) ||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "ShaderAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 10, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 10, new ShaderAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -32,18 +32,15 @@ StateMunger::
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) StateMunger::
|
||||
munge_state(const RenderState *state) {
|
||||
WCPT(RenderState) pt_state = state;
|
||||
|
||||
StateMap::iterator mi = _state_map.find(pt_state);
|
||||
if (mi != _state_map.end()) {
|
||||
if (!(*mi).first.was_deleted() &&
|
||||
!(*mi).second.was_deleted()) {
|
||||
return (*mi).second.p();
|
||||
int mi = _state_map.find(state);
|
||||
if (mi != -1) {
|
||||
if (!_state_map.get_data(mi).was_deleted()) {
|
||||
return _state_map.get_data(mi).p();
|
||||
}
|
||||
}
|
||||
|
||||
CPT(RenderState) result = munge_state_impl(state);
|
||||
_state_map[pt_state] = result;
|
||||
_state_map.store(state, result.p());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include "pandabase.h"
|
||||
#include "geomMunger.h"
|
||||
#include "renderState.h"
|
||||
#include "weakPointerTo.h"
|
||||
#include "weakKeyHashMap.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StateMunger
|
||||
|
|
@ -36,7 +36,7 @@ public:
|
|||
protected:
|
||||
virtual CPT(RenderState) munge_state_impl(const RenderState *state);
|
||||
|
||||
typedef pmap< WCPT(RenderState), WCPT(RenderState) > StateMap;
|
||||
typedef WeakKeyHashMap<RenderState, WCPT(RenderState) > StateMap;
|
||||
StateMap _state_map;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -311,8 +311,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int StencilAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const StencilAttrib *sa;
|
||||
DCAST_INTO_R(sa, other, 0);
|
||||
const StencilAttrib *sa = (const StencilAttrib *)other;
|
||||
|
||||
int a;
|
||||
int b;
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "StencilAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new StencilAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -297,8 +297,7 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int TexGenAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const TexGenAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TexGenAttrib *ta = (const TexGenAttrib *)other;
|
||||
|
||||
Stages::const_iterator ai, bi;
|
||||
ai = _stages.begin();
|
||||
|
|
@ -383,8 +382,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) TexGenAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const TexGenAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TexGenAttrib *ta = (const TexGenAttrib *)other;
|
||||
|
||||
// The composition is the union of the two attribs. In the case
|
||||
// when a stage is in both attribs, we compose the stages.
|
||||
|
|
@ -441,8 +439,7 @@ compose_impl(const RenderAttrib *other) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) TexGenAttrib::
|
||||
invert_compose_impl(const RenderAttrib *other) const {
|
||||
const TexGenAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TexGenAttrib *ta = (const TexGenAttrib *)other;
|
||||
|
||||
// The inverse composition works a lot like the composition, except
|
||||
// we invert the ai stages.
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "TexGenAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new TexGenAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -247,9 +247,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int TexMatrixAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const TexMatrixAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
|
||||
const TexMatrixAttrib *ta = (const TexMatrixAttrib *)other;
|
||||
|
||||
Stages::const_iterator ai, bi;
|
||||
ai = _stages.begin();
|
||||
bi = ta->_stages.begin();
|
||||
|
|
@ -326,8 +325,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) TexMatrixAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const TexMatrixAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TexMatrixAttrib *ta = (const TexMatrixAttrib *)other;
|
||||
|
||||
// The composition is the union of the two attribs. In the case
|
||||
// when a stage is in both attribs, we compose the stages.
|
||||
|
|
@ -396,8 +394,7 @@ compose_impl(const RenderAttrib *other) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) TexMatrixAttrib::
|
||||
invert_compose_impl(const RenderAttrib *other) const {
|
||||
const TexMatrixAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TexMatrixAttrib *ta = (const TexMatrixAttrib *)other;
|
||||
|
||||
// The inverse composition works a lot like the composition, except
|
||||
// we invert the ai stages.
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "TexMatrixAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new TexMatrixAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -507,8 +507,7 @@ cull_callback(CullTraverser *trav, const CullTraverserData &data) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int TextureAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const TextureAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TextureAttrib *ta = (const TextureAttrib *)other;
|
||||
|
||||
if (_off_all_stages != ta->_off_all_stages) {
|
||||
return (int)_off_all_stages - (int)ta->_off_all_stages;
|
||||
|
|
@ -664,8 +663,7 @@ get_hash_impl() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) TextureAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const TextureAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TextureAttrib *ta = (const TextureAttrib *)other;
|
||||
|
||||
if (ta->_off_all_stages) {
|
||||
// If the other type turns off all stages, it doesn't matter what
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "TextureAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 30, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 30, new TextureAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ output(ostream &out) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int TransparencyAttrib::
|
||||
compare_to_impl(const RenderAttrib *other) const {
|
||||
const TransparencyAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
const TransparencyAttrib *ta = (const TransparencyAttrib *)other;
|
||||
|
||||
return (int)_mode - (int)ta->_mode;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ public:
|
|||
RenderAttrib::init_type();
|
||||
register_type(_type_handle, "TransparencyAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100, make_default);
|
||||
_attrib_slot = register_slot(_type_handle, 100, new TransparencyAttrib);
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "vector_typedWritable.cxx"
|
||||
#include "vector_ushort.cxx"
|
||||
#include "vector_writable.cxx"
|
||||
#include "weakKeyHashMap.cxx"
|
||||
#include "writableConfigurable.cxx"
|
||||
#include "writableParam.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,714 @@
|
|||
// Filename: weakKeyHashMap.I
|
||||
// Created by: rdb (13Jul15)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE WeakKeyHashMap<Key, Value>::
|
||||
WeakKeyHashMap() :
|
||||
_table(NULL),
|
||||
_deleted_chain(NULL),
|
||||
_table_size(0),
|
||||
_num_entries(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE WeakKeyHashMap<Key, Value>::
|
||||
~WeakKeyHashMap() {
|
||||
clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::swap
|
||||
// Access: Public
|
||||
// Description: Quickly exchanges the contents of this map and the
|
||||
// other map.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE void WeakKeyHashMap<Key, Value>::
|
||||
swap(WeakKeyHashMap<Key, Value> &other) {
|
||||
TableEntry *t0 = _table;
|
||||
_table = other._table;
|
||||
other._table = t0;
|
||||
|
||||
DeletedBufferChain *t1 = _deleted_chain;
|
||||
_deleted_chain = other._deleted_chain;
|
||||
other._deleted_chain = t1;
|
||||
|
||||
size_t t2 = _table_size;
|
||||
_table_size = other._table_size;
|
||||
other._table_size = t2;
|
||||
|
||||
size_t t3 = _num_entries;
|
||||
_num_entries = other._num_entries;
|
||||
other._num_entries = t3;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::find
|
||||
// Access: Public
|
||||
// Description: Searches for the indicated key in the table. Returns
|
||||
// its index number if it is found, or -1 if it is not
|
||||
// present in the table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
int WeakKeyHashMap<Key, Value>::
|
||||
find(const Key *key) const {
|
||||
if (_table_size == 0) {
|
||||
// Special case: the table is empty.
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t index = get_hash(key);
|
||||
if (!has_element(index)) {
|
||||
return -1;
|
||||
}
|
||||
if (is_element(index, key)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// There was some other key at the hashed slot. That's a hash
|
||||
// conflict. Maybe our entry was recorded at a later slot position;
|
||||
// scan the subsequent positions until we find the entry or an
|
||||
// unused slot, indicating the end of the scan.
|
||||
size_t i = index;
|
||||
i = (i + 1) & (_table_size - 1);
|
||||
while (i != index && has_element(i)) {
|
||||
if (is_element(i, key)) {
|
||||
return i;
|
||||
}
|
||||
i = (i + 1) & (_table_size - 1);
|
||||
}
|
||||
|
||||
// The key is not in the table.
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::store
|
||||
// Access: Public
|
||||
// Description: Records the indicated key/data pair in the map. If
|
||||
// the key was already present, silently replaces it.
|
||||
// Returns the index at which it was stored.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
int WeakKeyHashMap<Key, Value>::
|
||||
store(const Key *key, const Value &data) {
|
||||
if (_table_size == 0) {
|
||||
// Special case: the first key in an empty table.
|
||||
nassertr(_num_entries == 0, -1);
|
||||
new_table();
|
||||
size_t index = get_hash(key);
|
||||
store_new_element(index, key, data);
|
||||
++_num_entries;
|
||||
#ifdef _DEBUG
|
||||
nassertr(validate(), index);
|
||||
#endif
|
||||
return index;
|
||||
}
|
||||
|
||||
size_t index = get_hash(key);
|
||||
if (!has_element(index)) {
|
||||
// This element is not already in the map; add it.
|
||||
if (consider_expand_table()) {
|
||||
return store(key, data);
|
||||
}
|
||||
store_new_element(index, key, data);
|
||||
++_num_entries;
|
||||
#ifdef _DEBUG
|
||||
nassertr(validate(), index);
|
||||
#endif
|
||||
return index;
|
||||
}
|
||||
if (is_element(index, key)) {
|
||||
// This element is already in the map; replace the data at that
|
||||
// key.
|
||||
_table[index]._data = data;
|
||||
#ifdef _DEBUG
|
||||
nassertr(validate(), index);
|
||||
#endif
|
||||
return index;
|
||||
}
|
||||
|
||||
// There was some other key at the hashed slot. That's a hash
|
||||
// conflict. Record this entry at a later position.
|
||||
size_t i = index;
|
||||
i = (i + 1) & (_table_size - 1);
|
||||
while (i != index) {
|
||||
if (!has_element(i)) {
|
||||
if (consider_expand_table()) {
|
||||
return store(key, data);
|
||||
}
|
||||
store_new_element(i, key, data);
|
||||
++_num_entries;
|
||||
#ifdef _DEBUG
|
||||
nassertr(validate(), i);
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
if (is_element(i, key)) {
|
||||
_table[i]._data = data;
|
||||
#ifdef _DEBUG
|
||||
nassertr(validate(), i);
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
i = (i + 1) & (_table_size - 1);
|
||||
}
|
||||
|
||||
// Shouldn't get here unless _num_entries == _table_size, which
|
||||
// shouldn't be possible due to consider_expand_table().
|
||||
nassertr(false, -1);
|
||||
return -1; // To satisfy compiler
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::remove
|
||||
// Access: Public
|
||||
// Description: Removes the indicated key and its associated data
|
||||
// from the table. Returns true if the key was removed,
|
||||
// false if it was not present.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE bool WeakKeyHashMap<Key, Value>::
|
||||
remove(const Key *key) {
|
||||
int index = find(key);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
remove_element(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::clear
|
||||
// Access: Public
|
||||
// Description: Completely empties the table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
void WeakKeyHashMap<Key, Value>::
|
||||
clear() {
|
||||
if (_table_size != 0) {
|
||||
for (size_t i = 0; i < _table_size; ++i) {
|
||||
if (get_exists_array()[i] != 0) {
|
||||
clear_element(i);
|
||||
}
|
||||
}
|
||||
|
||||
_deleted_chain->deallocate(_table, TypeHandle::none());
|
||||
_table = NULL;
|
||||
_deleted_chain = NULL;
|
||||
_table_size = 0;
|
||||
_num_entries = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::operator []
|
||||
// Access: Public
|
||||
// Description: Returns a modifiable reference to the data associated
|
||||
// with the indicated key, or creates a new data entry
|
||||
// and returns its reference.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE Value &WeakKeyHashMap<Key, Value>::
|
||||
operator [] (const Key *key) {
|
||||
int index = find(key);
|
||||
if (index == -1) {
|
||||
index = store(key, Value());
|
||||
}
|
||||
return modify_data(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::get_size
|
||||
// Access: Public
|
||||
// Description: Returns the total number of slots in the table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE int WeakKeyHashMap<Key, Value>::
|
||||
get_size() const {
|
||||
return _table_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::has_element
|
||||
// Access: Public
|
||||
// Description: Returns true if there is an element stored in the nth
|
||||
// slot, false otherwise.
|
||||
//
|
||||
// n should be in the range 0 <= n < get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE bool WeakKeyHashMap<Key, Value>::
|
||||
has_element(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_table_size, false);
|
||||
return (get_exists_array()[n] != 0 && !_table[n]._key.was_deleted());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::get_key
|
||||
// Access: Public
|
||||
// Description: Returns the key in the nth slot of the table.
|
||||
//
|
||||
// It is an error to call this if there is nothing
|
||||
// stored in the nth slot (use has_element() to check
|
||||
// this first). n should be in the range 0 <= n <
|
||||
// get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE const Key *WeakKeyHashMap<Key, Value>::
|
||||
get_key(int n) const {
|
||||
nassertr(has_element(n), _table[n]._key);
|
||||
return _table[n]._key;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::get_data
|
||||
// Access: Public
|
||||
// Description: Returns the data in the nth slot of the table.
|
||||
//
|
||||
// It is an error to call this if there is nothing
|
||||
// stored in the nth slot (use has_element() to check
|
||||
// this first). n should be in the range 0 <= n <
|
||||
// get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE const Value &WeakKeyHashMap<Key, Value>::
|
||||
get_data(int n) const {
|
||||
nassertr(has_element(n), _table[n]._data);
|
||||
return _table[n]._data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::modify_data
|
||||
// Access: Public
|
||||
// Description: Returns a modifiable reference to the data in the nth
|
||||
// slot of the table.
|
||||
//
|
||||
// It is an error to call this if there is nothing
|
||||
// stored in the nth slot (use has_element() to check
|
||||
// this first). n should be in the range 0 <= n <
|
||||
// get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE Value &WeakKeyHashMap<Key, Value>::
|
||||
modify_data(int n) {
|
||||
nassertr(has_element(n), _table[n]._data);
|
||||
return _table[n]._data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::set_data
|
||||
// Access: Public
|
||||
// Description: Changes the data for the nth slot of the table.
|
||||
//
|
||||
// It is an error to call this if there is nothing
|
||||
// stored in the nth slot (use has_element() to check
|
||||
// this first). n should be in the range 0 <= n <
|
||||
// get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE void WeakKeyHashMap<Key, Value>::
|
||||
set_data(int n, const Value &data) {
|
||||
nassertv(has_element(n));
|
||||
_table[n]._data = data;
|
||||
}
|
||||
|
||||
#ifdef USE_MOVE_SEMANTICS
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::set_data
|
||||
// Access: Public
|
||||
// Description: Changes the data for the nth slot of the table.
|
||||
//
|
||||
// It is an error to call this if there is nothing
|
||||
// stored in the nth slot (use has_element() to check
|
||||
// this first). n should be in the range 0 <= n <
|
||||
// get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE void WeakKeyHashMap<Key, Value>::
|
||||
set_data(int n, Value &&data) {
|
||||
nassertv(has_element(n));
|
||||
_table[n]._data = std::move(data);
|
||||
}
|
||||
#endif // USE_MOVE_SEMANTICS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::remove_element
|
||||
// Access: Public
|
||||
// Description: Removes the nth slot from the table.
|
||||
//
|
||||
// It is an error to call this if there is nothing
|
||||
// stored in the nth slot (use has_element() to check
|
||||
// this first). n should be in the range 0 <= n <
|
||||
// get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
void WeakKeyHashMap<Key, Value>::
|
||||
remove_element(int n) {
|
||||
nassertv(get_exists_array()[n] != 0);
|
||||
|
||||
clear_element(n);
|
||||
nassertv(_num_entries > 0);
|
||||
--_num_entries;
|
||||
|
||||
// Now we have put a hole in the table. If there was a hash
|
||||
// conflict in the slot following this one, we have to move it down
|
||||
// to close the hole.
|
||||
size_t i = n;
|
||||
i = (i + 1) & (_table_size - 1);
|
||||
while (get_exists_array()[i] != 0) {
|
||||
if (_table[i]._key.was_deleted()) {
|
||||
// It was deleted. Forget about it.
|
||||
clear_element(i);
|
||||
--_num_entries;
|
||||
} else {
|
||||
size_t wants_index = get_hash(_table[i]._key);
|
||||
if (wants_index != i) {
|
||||
// This one was a hash conflict; try to put it where it belongs.
|
||||
// We can't just put it in n, since maybe it belongs somewhere
|
||||
// after n.
|
||||
while (wants_index != i && has_element(wants_index)) {
|
||||
// Hash conflict; move it up.
|
||||
wants_index = (wants_index + 1) & (_table_size - 1);
|
||||
}
|
||||
if (wants_index != i) {
|
||||
store_new_element(wants_index, _table[i]._key, _table[i]._data);
|
||||
clear_element(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Continue until we encounter the next unused slot. Until we do,
|
||||
// we can't be sure we've found all of the potential hash
|
||||
// conflicts.
|
||||
i = (i + 1) & (_table_size - 1);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
nassertv(validate());
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::get_num_entries
|
||||
// Access: Public
|
||||
// Description: Returns the number of active entries in the table.
|
||||
// This is not necessarily related to the number of
|
||||
// slots in the table as reported by get_size(). Use
|
||||
// get_size() to iterate through all of the slots, not
|
||||
// get_num_entries().
|
||||
//
|
||||
// This is merely an upper bound on the number of
|
||||
// entries; it may also count false positives for
|
||||
// pointers that were recently deleted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE int WeakKeyHashMap<Key, Value>::
|
||||
get_num_entries() const {
|
||||
return _num_entries;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::is_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if the table is empty;
|
||||
// i.e. get_num_entries() == 0. This may return a
|
||||
// false negatives if a pointer was recently deleted;
|
||||
// if this returns true, though, you can be sure it's
|
||||
// empty.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE bool WeakKeyHashMap<Key, Value>::
|
||||
is_empty() const {
|
||||
return (_num_entries == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
void WeakKeyHashMap<Key, Value>::
|
||||
output(ostream &out) const {
|
||||
out << "WeakKeyHashMap (" << _num_entries << " entries): [";
|
||||
for (size_t i = 0; i < _table_size; ++i) {
|
||||
if (get_exists_array()[i] == 0) {
|
||||
out << " *";
|
||||
|
||||
} else {
|
||||
out << " " << _table[i]._key;
|
||||
size_t index = get_hash(_table[i]._key.get_orig());
|
||||
if (index != i) {
|
||||
// This was misplaced as the result of a hash conflict.
|
||||
// Report how far off it is.
|
||||
out << "(" << ((_table_size + i - index) & (_table_size - 1)) << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
out << " ]";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
void WeakKeyHashMap<Key, Value>::
|
||||
write(ostream &out) const {
|
||||
output(out);
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::validate
|
||||
// Access: Public
|
||||
// Description: Returns true if the internal table appears to be
|
||||
// consistent, false if there are some internal errors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
bool WeakKeyHashMap<Key, Value>::
|
||||
validate() const {
|
||||
size_t count = 0;
|
||||
|
||||
for (size_t i = 0; i < _table_size; ++i) {
|
||||
if (get_exists_array()[i] != 0) {
|
||||
++count;
|
||||
if (_table[i]._key.was_deleted()) {
|
||||
continue;
|
||||
}
|
||||
size_t ideal_index = get_hash(_table[i]._key.get_orig());
|
||||
size_t wants_index = ideal_index;
|
||||
while (wants_index != i && get_exists_array()[i] != 0) {
|
||||
wants_index = (wants_index + 1) & (_table_size - 1);
|
||||
}
|
||||
if (wants_index != i) {
|
||||
util_cat.error()
|
||||
<< "WeakKeyHashMap is invalid: key " << _table[i]._key
|
||||
<< " should be in slot " << wants_index << " instead of "
|
||||
<< i << " (ideal is " << ideal_index << ")\n";
|
||||
write(util_cat.error(false));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count != _num_entries) {
|
||||
util_cat.error()
|
||||
<< "WeakKeyHashMap is invalid: reports " << _num_entries
|
||||
<< " entries, actually has " << count << "\n";
|
||||
write(util_cat.error(false));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::get_hash
|
||||
// Access: Private
|
||||
// Description: Computes an appropriate index number to store the
|
||||
// given pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE size_t WeakKeyHashMap<Key, Value>::
|
||||
get_hash(const Key *key) const {
|
||||
/*
|
||||
// We want a hash constant 0 < k < 1. This one is suggested by
|
||||
// Knuth:
|
||||
static const double hash_constant = (sqrt(5.0) - 1.0) / 2.0;
|
||||
double f = ((double)(size_t)key * hash_constant);
|
||||
f -= floor(f);
|
||||
return (size_t)floor(f * _table_size);
|
||||
*/
|
||||
|
||||
return (((size_t)key * (size_t)9973) >> 8) & (_table_size - 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::is_element
|
||||
// Access: Private
|
||||
// Description: Returns true if element n matches key.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE bool WeakKeyHashMap<Key, Value>::
|
||||
is_element(int n, const Key *key) const {
|
||||
nassertr(has_element(n), false);
|
||||
return _table[n]._key == key;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::store_new_element
|
||||
// Access: Private
|
||||
// Description: Constructs a new TableEntry at position n, storing
|
||||
// the indicated key and value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE void WeakKeyHashMap<Key, Value>::
|
||||
store_new_element(int n, const Key *key, const Value &data) {
|
||||
if (get_exists_array()[n] != 0) {
|
||||
// There was already an element in this spot. This can happen
|
||||
// if it was a pointer that had already been deleted.
|
||||
nassertv(_table[n]._key.was_deleted());
|
||||
_table[n].~TableEntry();
|
||||
--_num_entries;
|
||||
}
|
||||
new(&_table[n]) TableEntry(key, data);
|
||||
get_exists_array()[n] = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::clear_element
|
||||
// Access: Private
|
||||
// Description: Destructs the TableEntry at position n.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE void WeakKeyHashMap<Key, Value>::
|
||||
clear_element(int n) {
|
||||
_table[n].~TableEntry();
|
||||
get_exists_array()[n] = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::get_exists_array
|
||||
// Access: Private
|
||||
// Description: Returns the beginning of the array of _table_size
|
||||
// unsigned chars that are the boolean flags for whether
|
||||
// each element exists (has been constructed) within the
|
||||
// table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE unsigned char *WeakKeyHashMap<Key, Value>::
|
||||
get_exists_array() const {
|
||||
return (unsigned char *)(_table + _table_size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::new_table
|
||||
// Access: Private
|
||||
// Description: Allocates a brand new table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
void WeakKeyHashMap<Key, Value>::
|
||||
new_table() {
|
||||
nassertv(_table_size == 0 && _num_entries == 0);
|
||||
|
||||
// Pick a good initial table size. For now, we make it really
|
||||
// small. Maybe that's the right answer.
|
||||
_table_size = 4;
|
||||
|
||||
// We allocate enough bytes for _table_size elements of TableEntry,
|
||||
// plus _table_size more bytes at the end (for the exists array).
|
||||
size_t alloc_size = _table_size * sizeof(TableEntry) + _table_size;
|
||||
|
||||
_deleted_chain = memory_hook->get_deleted_chain(alloc_size);
|
||||
_table = (TableEntry *)_deleted_chain->allocate(alloc_size, TypeHandle::none());
|
||||
memset(get_exists_array(), 0, _table_size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::consider_expand_table
|
||||
// Access: Private
|
||||
// Description: Expands the table if it will need it (assuming one
|
||||
// more element is about to be added). Returns true if
|
||||
// the table was modified, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
INLINE bool WeakKeyHashMap<Key, Value>::
|
||||
consider_expand_table() {
|
||||
if (_num_entries >= (_table_size >> 1)) {
|
||||
// Actually, first, we should see if there are any deleted pointers.
|
||||
// Clean those up and see how much space we save.
|
||||
for (size_t i = 0; i < _table_size; ++i) {
|
||||
if (get_exists_array()[i] != 0 && _table[i]._key.was_deleted()) {
|
||||
remove_element(i);
|
||||
}
|
||||
}
|
||||
if (_num_entries >= (_table_size >> 1)) {
|
||||
// Still not enough space.
|
||||
expand_table();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakKeyHashMap::expand_table
|
||||
// Access: Private
|
||||
// Description: Doubles the size of the existing table.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
void WeakKeyHashMap<Key, Value>::
|
||||
expand_table() {
|
||||
nassertv(_table_size != 0);
|
||||
|
||||
WeakKeyHashMap<Key, Value> old_map;
|
||||
swap(old_map);
|
||||
|
||||
// Double the table size.
|
||||
size_t old_table_size = old_map._table_size;
|
||||
_table_size = (old_table_size << 1);
|
||||
nassertv(_table == NULL);
|
||||
|
||||
// We allocate enough bytes for _table_size elements of TableEntry,
|
||||
// plus _table_size more bytes at the end (for the exists array).
|
||||
size_t alloc_size = _table_size * sizeof(TableEntry) + _table_size;
|
||||
_deleted_chain = memory_hook->get_deleted_chain(alloc_size);
|
||||
_table = (TableEntry *)_deleted_chain->allocate(alloc_size, TypeHandle::none());
|
||||
unsigned char *exists_array = get_exists_array();
|
||||
memset(exists_array, 0, _table_size);
|
||||
nassertv(_num_entries == 0);
|
||||
|
||||
// Now copy the entries from the old table into the new table.
|
||||
int num_added = 0;
|
||||
for (size_t i = 0; i < old_table_size; ++i) {
|
||||
if (old_map.has_element(i)) {
|
||||
size_t new_index = get_hash(old_map._table[i]._key.get_orig());
|
||||
|
||||
while (exists_array[new_index] != 0) {
|
||||
// Hash conflict; look for a better spot. This has to succeed.
|
||||
new_index = (new_index + 1) & (_table_size - 1);
|
||||
}
|
||||
|
||||
#ifdef USE_MOVE_SEMANTICS
|
||||
// Use C++11 rvalue references to invoke the move constructor,
|
||||
// which may be more efficient.
|
||||
new(&_table[new_index]) TableEntry(move(old_map._table[i]));
|
||||
#else
|
||||
new(&_table[new_index]) TableEntry(old_map._table[i]);
|
||||
#endif
|
||||
exists_array[new_index] = true;
|
||||
++_num_entries;
|
||||
}
|
||||
}
|
||||
|
||||
nassertv(validate());
|
||||
nassertv(old_map.validate());
|
||||
|
||||
nassertv(_num_entries == old_map._num_entries);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Filename: weakKeyHashMap.cxx
|
||||
// Created by: rdb (13Jul15)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "weakKeyHashMap.h"
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
// Filename: weakKeyHashMap.h
|
||||
// Created by: rdb (13Jul15)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WEAKKEYHASHMAP_H
|
||||
#define WEAKKEYHASHMAP_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pvector.h"
|
||||
#include "config_util.h"
|
||||
#include "weakPointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : WeakKeyHashMap
|
||||
// Description : This is a variation on WeakKeyHashMap that stores
|
||||
// weak pointers as keys, and automatically frees up
|
||||
// entries from the map when the associated key has
|
||||
// been deleted.
|
||||
//
|
||||
// This is more efficient than using a naive map of
|
||||
// WeakPointerTo keys since that would incur the cost
|
||||
// of constructing a weak reference every time a find
|
||||
// operation is used.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value>
|
||||
class WeakKeyHashMap {
|
||||
public:
|
||||
#ifndef CPPPARSER
|
||||
INLINE WeakKeyHashMap();
|
||||
INLINE ~WeakKeyHashMap();
|
||||
|
||||
INLINE void swap(WeakKeyHashMap &other);
|
||||
|
||||
int find(const Key *key) const;
|
||||
int store(const Key *key, const Value &data);
|
||||
INLINE bool remove(const Key *key);
|
||||
void clear();
|
||||
|
||||
INLINE Value &operator [] (const Key *key);
|
||||
|
||||
INLINE int get_size() const;
|
||||
INLINE bool has_element(int n) const;
|
||||
INLINE const Key *get_key(int n) const;
|
||||
INLINE const Value &get_data(int n) const;
|
||||
INLINE Value &modify_data(int n);
|
||||
INLINE void set_data(int n, const Value &data);
|
||||
#ifdef USE_MOVE_SEMANTICS
|
||||
INLINE void set_data(int n, Value &&data);
|
||||
#endif
|
||||
void remove_element(int n);
|
||||
|
||||
INLINE int get_num_entries() const;
|
||||
INLINE bool is_empty() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out) const;
|
||||
bool validate() const;
|
||||
|
||||
private:
|
||||
INLINE size_t get_hash(const Key *key) const;
|
||||
|
||||
INLINE bool is_element(int n, const Key *key) const;
|
||||
INLINE void store_new_element(int n, const Key *key, const Value &data);
|
||||
INLINE void clear_element(int n);
|
||||
INLINE unsigned char *get_exists_array() const;
|
||||
|
||||
void new_table();
|
||||
INLINE bool consider_expand_table();
|
||||
void expand_table();
|
||||
|
||||
class TableEntry {
|
||||
public:
|
||||
INLINE TableEntry(const Key *key, const Value &data) :
|
||||
_key(key),
|
||||
_data(data) {}
|
||||
INLINE TableEntry(const TableEntry ©) :
|
||||
_key(copy._key),
|
||||
_data(copy._data) {}
|
||||
#ifdef USE_MOVE_SEMANTICS
|
||||
INLINE TableEntry(TableEntry &&from) NOEXCEPT :
|
||||
_key(move(from._key)),
|
||||
_data(move(from._data)) {}
|
||||
#endif
|
||||
WCPT(Key) _key;
|
||||
Value _data;
|
||||
};
|
||||
|
||||
TableEntry *_table;
|
||||
DeletedBufferChain *_deleted_chain;
|
||||
size_t _table_size;
|
||||
size_t _num_entries;
|
||||
#endif // CPPPARSER
|
||||
};
|
||||
|
||||
template<class Key, class Value>
|
||||
inline ostream &operator << (ostream &out, const WeakKeyHashMap<Key, Value> &shm) {
|
||||
shm.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifndef CPPPARSER
|
||||
#include "weakKeyHashMap.I"
|
||||
#endif // CPPPARSER
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue