Browse Source

merge dev_slots_2008: slot-based RenderState implementation

David Rose 17 years ago
parent
commit
26754b86ca
100 changed files with 2531 additions and 3159 deletions
  1. 1 1
      panda/src/collide/collisionEntry.cxx
  2. 1 1
      panda/src/collide/collisionPolygon.cxx
  3. 8 21
      panda/src/cull/cullBinStateSorted.I
  4. 69 64
      panda/src/display/graphicsStateGuardian.cxx
  5. 26 6
      panda/src/display/graphicsStateGuardian.h
  6. 7 7
      panda/src/display/standardMunger.cxx
  7. 2 2
      panda/src/dxgsg8/dxGeomMunger8.I
  8. 188 139
      panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx
  9. 1 0
      panda/src/dxgsg8/dxGraphicsStateGuardian8.h
  10. 2 2
      panda/src/dxgsg9/dxGeomMunger9.I
  11. 202 146
      panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx
  12. 1 0
      panda/src/dxgsg9/dxGraphicsStateGuardian9.h
  13. 6 6
      panda/src/dxgsg9/dxShaderContext9.cxx
  14. 2 2
      panda/src/glstuff/glGeomMunger_src.cxx
  15. 1 1
      panda/src/glstuff/glGraphicsBuffer_src.cxx
  16. 2 2
      panda/src/glstuff/glGraphicsStateGuardian_src.I
  17. 274 207
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  18. 1 0
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  19. 6 6
      panda/src/glstuff/glShaderContext_src.cxx
  20. 15 14
      panda/src/grutil/multitexReducer.cxx
  21. 4 0
      panda/src/grutil/pipeOcclusionCullTraverser.cxx
  22. 1 1
      panda/src/osxdisplay/Sources.pp
  23. 3 0
      panda/src/osxdisplay/osxGraphicsStateGuardian.cxx
  24. 3 6
      panda/src/pgraph/Sources.pp
  25. 22 22
      panda/src/pgraph/accumulatedAttribs.cxx
  26. 13 28
      panda/src/pgraph/alphaTestAttrib.cxx
  27. 12 2
      panda/src/pgraph/alphaTestAttrib.h
  28. 13 28
      panda/src/pgraph/antialiasAttrib.cxx
  29. 11 2
      panda/src/pgraph/antialiasAttrib.h
  30. 0 74
      panda/src/pgraph/attribSlots.I
  31. 0 217
      panda/src/pgraph/attribSlots.cxx
  32. 0 109
      panda/src/pgraph/attribSlots.h
  33. 14 29
      panda/src/pgraph/audioVolumeAttrib.cxx
  34. 11 2
      panda/src/pgraph/audioVolumeAttrib.h
  35. 13 28
      panda/src/pgraph/auxBitplaneAttrib.cxx
  36. 11 2
      panda/src/pgraph/auxBitplaneAttrib.h
  37. 13 28
      panda/src/pgraph/clipPlaneAttrib.cxx
  38. 11 2
      panda/src/pgraph/clipPlaneAttrib.h
  39. 13 28
      panda/src/pgraph/colorAttrib.cxx
  40. 11 2
      panda/src/pgraph/colorAttrib.h
  41. 13 28
      panda/src/pgraph/colorBlendAttrib.cxx
  42. 11 2
      panda/src/pgraph/colorBlendAttrib.h
  43. 13 28
      panda/src/pgraph/colorScaleAttrib.cxx
  44. 11 2
      panda/src/pgraph/colorScaleAttrib.h
  45. 13 28
      panda/src/pgraph/colorWriteAttrib.cxx
  46. 11 2
      panda/src/pgraph/colorWriteAttrib.h
  47. 0 3
      panda/src/pgraph/config_pgraph.cxx
  48. 13 28
      panda/src/pgraph/cullBinAttrib.cxx
  49. 11 2
      panda/src/pgraph/cullBinAttrib.h
  50. 13 30
      panda/src/pgraph/cullFaceAttrib.cxx
  51. 11 2
      panda/src/pgraph/cullFaceAttrib.h
  52. 2 2
      panda/src/pgraph/cullPlanes.cxx
  53. 10 10
      panda/src/pgraph/cullResult.cxx
  54. 1 1
      panda/src/pgraph/cullTraverser.cxx
  55. 1 1
      panda/src/pgraph/cullTraverserData.cxx
  56. 4 4
      panda/src/pgraph/cullableObject.cxx
  57. 13 28
      panda/src/pgraph/depthOffsetAttrib.cxx
  58. 11 2
      panda/src/pgraph/depthOffsetAttrib.h
  59. 13 28
      panda/src/pgraph/depthTestAttrib.cxx
  60. 11 2
      panda/src/pgraph/depthTestAttrib.h
  61. 13 28
      panda/src/pgraph/depthWriteAttrib.cxx
  62. 11 2
      panda/src/pgraph/depthWriteAttrib.h
  63. 0 92
      panda/src/pgraph/drawMaskAttrib.I
  64. 0 226
      panda/src/pgraph/drawMaskAttrib.cxx
  65. 0 98
      panda/src/pgraph/drawMaskAttrib.h
  66. 13 28
      panda/src/pgraph/fogAttrib.cxx
  67. 11 2
      panda/src/pgraph/fogAttrib.h
  68. 9 15
      panda/src/pgraph/geomNode.cxx
  69. 5 5
      panda/src/pgraph/geomTransformer.cxx
  70. 13 28
      panda/src/pgraph/lightAttrib.cxx
  71. 11 2
      panda/src/pgraph/lightAttrib.h
  72. 1 28
      panda/src/pgraph/lightRampAttrib.cxx
  73. 10 2
      panda/src/pgraph/lightRampAttrib.h
  74. 13 28
      panda/src/pgraph/materialAttrib.cxx
  75. 11 2
      panda/src/pgraph/materialAttrib.h
  76. 122 122
      panda/src/pgraph/nodePath.cxx
  77. 45 7
      panda/src/pgraph/pandaNode.I
  78. 3 3
      panda/src/pgraph/pandaNode.cxx
  79. 4 1
      panda/src/pgraph/pandaNode.h
  80. 0 1
      panda/src/pgraph/pgraph_composite1.cxx
  81. 0 1
      panda/src/pgraph/pgraph_composite2.cxx
  82. 1 0
      panda/src/pgraph/pgraph_composite4.cxx
  83. 14 14
      panda/src/pgraph/renderAttrib.I
  84. 0 17
      panda/src/pgraph/renderAttrib.cxx
  85. 7 3
      panda/src/pgraph/renderAttrib.h
  86. 162 0
      panda/src/pgraph/renderAttribRegistry.I
  87. 175 0
      panda/src/pgraph/renderAttribRegistry.cxx
  88. 107 0
      panda/src/pgraph/renderAttribRegistry.h
  89. 13 28
      panda/src/pgraph/renderModeAttrib.cxx
  90. 11 2
      panda/src/pgraph/renderModeAttrib.h
  91. 110 338
      panda/src/pgraph/renderState.I
  92. 369 383
      panda/src/pgraph/renderState.cxx
  93. 35 93
      panda/src/pgraph/renderState.h
  94. 1 28
      panda/src/pgraph/rescaleNormalAttrib.cxx
  95. 10 2
      panda/src/pgraph/rescaleNormalAttrib.h
  96. 2 2
      panda/src/pgraph/sceneGraphAnalyzer.cxx
  97. 2 0
      panda/src/pgraph/sceneSetup.h
  98. 13 28
      panda/src/pgraph/scissorAttrib.cxx
  99. 11 2
      panda/src/pgraph/scissorAttrib.h
  100. 13 28
      panda/src/pgraph/shadeModelAttrib.cxx

+ 1 - 1
panda/src/collide/collisionEntry.cxx

@@ -300,6 +300,6 @@ write(ostream &out, int indent_level) const {
 ////////////////////////////////////////////////////////////////////
 void CollisionEntry::
 check_clip_planes() {
-  _into_clip_planes = _into_node_path.get_net_state()->get_clip_plane();
+  _into_clip_planes = DCAST(ClipPlaneAttrib, _into_node_path.get_net_state()->get_attrib(ClipPlaneAttrib::get_class_slot()));
   _flags |= F_checked_clip_planes;
 }

+ 1 - 1
panda/src/collide/collisionPolygon.cxx

@@ -253,7 +253,7 @@ get_collision_origin() const {
 PT(PandaNode) CollisionPolygon::
 get_viz(const CullTraverser *trav, const CullTraverserData &data, 
         bool bounds_only) const {
-  const ClipPlaneAttrib *cpa = data._state->get_clip_plane();
+  const ClipPlaneAttrib *cpa = DCAST(ClipPlaneAttrib, data._state->get_attrib(ClipPlaneAttrib::get_class_slot()));
   if (cpa == (const ClipPlaneAttrib *)NULL) {
     // Fortunately, the polygon is not clipped.  This is the normal,
     // easy case.

+ 8 - 21
panda/src/cull/cullBinStateSorted.I

@@ -45,29 +45,16 @@ ObjectData(CullableObject *object) :
 ////////////////////////////////////////////////////////////////////
 INLINE bool CullBinStateSorted::ObjectData::
 operator < (const ObjectData &other) const {
-  const RenderState *sa = _object->_state;
-  const RenderState *sb = other._object->_state;
-
-  if (sa != sb) {
-    // First, group objects by texture, since conventional wisdom is
-    // that texture changes are the most expensive state changes in a
-    // graphics context.
-    const TextureAttrib *ta = sa->get_texture();
-    const TextureAttrib *tb = sb->get_texture();
-    if (ta != tb) {
-      return ta < tb;
-    }
-  }
-
-  // Then group objects by transform, since these are supposed to be
-  // expensive too.
+  // First group objects by transform, since transform changes are
+  // supposed to be expensive.
   if (_object->_modelview_transform != other._object->_modelview_transform) {
     return _object->_modelview_transform < other._object->_modelview_transform;
   }
-      
-  // Then, sort by all the other states, in no particular order,
-  // just as long as objects with identical state are all grouped
-  // together.
-  return sa < sb;
+
+  // Then group by other state changes, in approximate order from
+  // heaviest change to lightest change.
+  const RenderState *sa = _object->_state;
+  const RenderState *sb = other._object->_state;
+  return sa->compare_sort(*sb) < 0;
 }
 

+ 69 - 64
panda/src/display/graphicsStateGuardian.cxx

@@ -18,7 +18,6 @@
 #include "vertexBufferContext.h"
 #include "indexBufferContext.h"
 #include "renderBuffer.h"
-#include "attribSlots.h"
 #include "light.h"
 #include "planeNode.h"
 #include "ambientLight.h"
@@ -41,6 +40,11 @@
 #include "pointLight.h"
 #include "spotlight.h"
 #include "textureReloadRequest.h"
+#include "shaderAttrib.h"
+#include "materialAttrib.h"
+#include "depthWriteAttrib.h"
+#include "lightAttrib.h"
+#include "texGenAttrib.h"
 
 #include <algorithm>
 #include <limits.h>
@@ -810,7 +814,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_texpad_x: {
-    Texture *tex = _target._shader->get_shader_input_texture(name);
+    Texture *tex = _target_shader->get_shader_input_texture(name);
     nassertr(tex != 0, &LMatrix4f::zeros_mat());
     int sx = tex->get_x_size() - tex->get_pad_x_size();
     int sy = tex->get_y_size() - tex->get_pad_y_size();
@@ -822,7 +826,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_texpix_x: {
-    Texture *tex = _target._shader->get_shader_input_texture(name);
+    Texture *tex = _target_shader->get_shader_input_texture(name);
     nassertr(tex != 0, &LMatrix4f::zeros_mat());
     double px = 1.0 / tex->get_x_size();
     double py = 1.0 / tex->get_y_size();
@@ -831,12 +835,13 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_attr_material: {
+    const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
     // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
-    if (_target._material->is_off()) {
+    if (target_material->is_off()) {
       t = LMatrix4f(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0);
       return &t;
     }
-    Material *m = _target._material->get_material();
+    Material *m = target_material->get_material();
     LVecBase4f const &amb = m->get_ambient();
     LVecBase4f const &dif = m->get_diffuse();
     LVecBase4f const &emm = m->get_emission();
@@ -849,15 +854,16 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_attr_color: {
-    if (_target._color->get_color_type() != ColorAttrib::T_flat) {
+    const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot()));
+    if (target_color->get_color_type() != ColorAttrib::T_flat) {
       return &LMatrix4f::ones_mat();
     }
-    LVecBase4f c = _target._color->get_color();
+    LVecBase4f c = target_color->get_color();
     t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
     return &t;
   }
   case Shader::SMO_alight_x: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::zeros_mat());
     AmbientLight *lt;
     DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat());
@@ -866,7 +872,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_satten_x: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ones_mat());
     Spotlight *lt;
     DCAST_INTO_R(lt, np.node(), &LMatrix4f::ones_mat());
@@ -877,7 +883,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
   }
   case Shader::SMO_dlight_x: {
     // The dlight matrix contains COLOR, SPECULAR, DIRECTION, PSEUDOHALFANGLE
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::zeros_mat());
     DirectionalLight *lt;
     DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat());
@@ -894,7 +900,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
   }
   case Shader::SMO_plight_x: {
     // The plight matrix contains COLOR, SPECULAR, POINT, ATTENUATION
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ones_mat());
     PointLight *lt;
     DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat());
@@ -909,7 +915,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
   }
   case Shader::SMO_slight_x: {
     // The slight matrix contains COLOR, SPECULAR, POINT, DIRECTION
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::zeros_mat());
     Spotlight *lt;
     DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat());
@@ -926,12 +932,12 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_mat_constant_x: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ident_mat());
     return &(np.node()->get_transform()->get_mat());
   }
   case Shader::SMO_vec_constant_x: {
-    const LVector4f &input = _target._shader->get_shader_input_vector(name);
+    const LVector4f &input = _target_shader->get_shader_input_vector(name);
     const float *data = input.get_data();
     t = LMatrix4f(data[0],data[1],data[2],data[3],
                   data[0],data[1],data[2],data[3],
@@ -987,21 +993,21 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_view_x_to_view: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ident_mat());
     t = np.get_net_transform()->get_mat() *
       get_scene()->get_world_transform()->get_mat();
     return &t;
   }
   case Shader::SMO_view_to_view_x: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ident_mat());
     t = get_scene()->get_camera_transform()->get_mat() *
       invert(np.get_net_transform()->get_mat());
     return &t;
   }
   case Shader::SMO_apiview_x_to_view: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ident_mat());
     t = LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system) *
       np.get_net_transform()->get_mat() *
@@ -1009,7 +1015,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_view_to_apiview_x: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ident_mat());
     t = (get_scene()->get_camera_transform()->get_mat() *
          invert(np.get_net_transform()->get_mat()) *
@@ -1017,7 +1023,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_clip_x_to_view: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ident_mat());
     Lens *lens = DCAST(LensNode, np.node())->get_lens();
     t = lens->get_projection_mat_inv(_current_stereo_channel) *
@@ -1027,7 +1033,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
     return &t;
   }
   case Shader::SMO_view_to_clip_x: {
-    const NodePath &np = _target._shader->get_shader_input_nodepath(name);
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4f::ident_mat());
     Lens *lens = DCAST(LensNode, np.node())->get_lens();
     t = get_scene()->get_camera_transform()->get_mat() *
@@ -1151,8 +1157,8 @@ begin_frame(Thread *current_thread) {
   // have changed properties since last time without changing
   // attribute pointers--like textures, lighting, or fog--will still
   // be accurately updated.
-  _state_rs = 0;
-  _state.clear_to_zero();
+  _state_rs = RenderState::make_empty();
+  _state_mask.clear();
 
   return true;
 }
@@ -1210,8 +1216,8 @@ end_scene() {
   _num_clip_planes_enabled = 0;
 
   // Put the state into the 'unknown' state, forcing a reload.
-  _state_rs = 0;
-  _state.clear_to_zero();
+  _state_rs = RenderState::make_empty();
+  _state_mask.clear();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1452,10 +1458,9 @@ reset() {
   _needs_reset = false;
   _is_valid = false;
 
-  _state_rs = NULL;
+  _state_rs = RenderState::make_empty();
   _target_rs = NULL;
-  _state.clear_to_zero();
-  _target.clear_to_defaults();
+  _state_mask.clear();
   _internal_transform = _cs_transform;
   _scene_null = new SceneSetup;
   _scene_setup = _scene_null;
@@ -1568,8 +1573,9 @@ do_issue_clip_plane() {
   int num_enabled = 0;
   int num_on_planes = 0;
 
-  if (_target._clip_plane != (ClipPlaneAttrib *)NULL) {
-    CPT(ClipPlaneAttrib) new_plane = _target._clip_plane->filter_to_max(_max_clip_planes);
+  const ClipPlaneAttrib *target_clip_plane = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
+  if (target_clip_plane != (ClipPlaneAttrib *)NULL) {
+    CPT(ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes);
 
     num_on_planes = new_plane->get_num_on_planes();
     for (int li = 0; li < num_on_planes; li++) {
@@ -1627,12 +1633,12 @@ do_issue_clip_plane() {
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 do_issue_color() {
-  const ColorAttrib *attrib = _target._color;
-  switch (attrib->get_color_type()) {
+  const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot()));
+  switch (target_color->get_color_type()) {
   case ColorAttrib::T_flat:
     // Color attribute flat: it specifies a scene graph color that
     // overrides the vertex color.
-    _scene_graph_color = attrib->get_color();
+    _scene_graph_color = target_color->get_color();
     _has_scene_graph_color = true;
     _vertex_colors_enabled = false;
     break;
@@ -1655,9 +1661,8 @@ do_issue_color() {
   }
 
   if (_color_scale_via_lighting) {
-    _state_rs = 0;
-    _state._light = 0;
-    _state._material = 0;
+    _state_mask.clear_bit(LightAttrib::get_class_slot());
+    _state_mask.clear_bit(MaterialAttrib::get_class_slot());
 
     determine_light_color_scale();
   }
@@ -1673,36 +1678,33 @@ do_issue_color_scale() {
   // If the previous color scale had set a special texture, clear the
   // texture now.
   if (_has_texture_alpha_scale) {
-    _state._texture = 0;
+    _state_mask.clear_bit(TextureAttrib::get_class_slot());
   }
 
-  const ColorScaleAttrib *attrib = _target._color_scale;
-  _color_scale_enabled = attrib->has_scale();
-  _current_color_scale = attrib->get_scale();
+  const ColorScaleAttrib *target_color_scale = DCAST(ColorScaleAttrib, _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot()));
+  _color_scale_enabled = target_color_scale->has_scale();
+  _current_color_scale = target_color_scale->get_scale();
   _has_texture_alpha_scale = false;
 
   if (_color_blend_involves_color_scale) {
-    _state_rs = 0;
-    _state._transparency = 0;
+    _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
   }
   if (_texture_involves_color_scale) {
-    _state_rs = 0;
-    _state._texture = 0;
+    _state_mask.clear_bit(TextureAttrib::get_class_slot());
   }
   if (_color_scale_via_lighting) {
-    _state_rs = 0;
-    _state._light = 0;
-    _state._material = 0;
+    _state_mask.clear_bit(LightAttrib::get_class_slot());
+    _state_mask.clear_bit(MaterialAttrib::get_class_slot());
 
     determine_light_color_scale();
   }
 
   if (_alpha_scale_via_texture && !_has_scene_graph_color &&
-      attrib->has_alpha_scale()) {
+      target_color_scale->has_alpha_scale()) {
     // This color scale will set a special texture--so again, clear
     // the texture.
-    _state._texture = 0;
-    _state._tex_matrix = 0;
+    _state_mask.clear_bit(TextureAttrib::get_class_slot());
+    _state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
 
     _has_texture_alpha_scale = true;
   }
@@ -1738,12 +1740,13 @@ do_issue_light() {
   int num_enabled = 0;
   int num_on_lights = 0;
 
+  const LightAttrib *target_light = DCAST(LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot()));
   if (display_cat.is_spam()) {
     display_cat.spam()
-      << "do_issue_light: " << _target._light << "\n";
+      << "do_issue_light: " << target_light << "\n";
   }
-  if (_target._light != (LightAttrib *)NULL) {
-    CPT(LightAttrib) new_light = _target._light->filter_to_max(_max_lights);
+  if (target_light != (LightAttrib *)NULL) {
+    CPT(LightAttrib) new_light = target_light->filter_to_max(_max_lights);
     if (display_cat.is_spam()) {
       new_light->write(display_cat.spam(false), 2);
     }
@@ -2063,30 +2066,32 @@ end_bind_clip_planes() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::determine_effective_texture
+//     Function: GraphicsStateGuardian::determine_target_texture
 //       Access: Protected
-//  Description: Assigns _effective_texture and _effective_tex_gen
-//               based on the current settings of _target._texture and
-//               _target._color_scale.
+//  Description: Assigns _target_texture and _target_tex_gen
+//               based on the _target_rs.
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
-determine_effective_texture() {
-  nassertv(_target._texture != (TextureAttrib *)NULL &&
-           _target._tex_gen != (TexGenAttrib *)NULL);
+determine_target_texture() {
+  const TextureAttrib *target_texture = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
+  const TexGenAttrib *target_tex_gen = DCAST(TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()));
+
+  nassertv(target_texture != (TextureAttrib *)NULL &&
+           target_tex_gen != (TexGenAttrib *)NULL);
   int max_texture_stages = get_max_texture_stages();
-  _effective_texture = _target._texture->filter_to_max(max_texture_stages);
-  _effective_tex_gen = _target._tex_gen;
+  _target_texture = target_texture->filter_to_max(max_texture_stages);
+  _target_tex_gen = target_tex_gen;
   
   if (_has_texture_alpha_scale) {
     PT(TextureStage) stage = get_alpha_scale_texture_stage();
     PT(Texture) texture = TexturePool::get_alpha_scale_map();
     
-    _effective_texture = DCAST(TextureAttrib, _effective_texture->add_on_stage(stage, texture));
-    _effective_tex_gen = DCAST(TexGenAttrib, _effective_tex_gen->add_stage
+    _target_texture = DCAST(TextureAttrib, _target_texture->add_on_stage(stage, texture));
+    _target_tex_gen = DCAST(TexGenAttrib, _target_tex_gen->add_stage
                                (stage, TexGenAttrib::M_constant, TexCoord3f(_current_color_scale[3], 0.0f, 0.0f)));
   }
 
-  nassertv(_effective_texture->get_num_on_stages() <= max_texture_stages);
+  nassertv(_target_texture->get_num_on_stages() <= max_texture_stages);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 26 - 6
panda/src/display/graphicsStateGuardian.h

@@ -38,13 +38,15 @@
 #include "geomVertexData.h"
 #include "pnotify.h"
 #include "pvector.h"
-#include "attribSlots.h"
 #include "shaderContext.h"
 #include "bitMask.h"
 #include "texture.h"
 #include "occlusionQueryContext.h"
 #include "stencilRenderStates.h"
 #include "loader.h"
+#include "textureAttrib.h"
+#include "texGenAttrib.h"
+#include "shaderAttrib.h"
 
 class DrawableRegion;
 class GraphicsEngine;
@@ -291,7 +293,7 @@ protected:
   virtual void bind_clip_plane(const NodePath &plane, int plane_id);
   virtual void end_bind_clip_planes();
 
-  void determine_effective_texture();
+  void determine_target_texture();
 
   virtual void free_pointers();
   virtual void close_gsg();
@@ -309,18 +311,36 @@ protected:
   PT(SceneSetup) _scene_null;
   PT(SceneSetup) _scene_setup;
 
-  AttribSlots _state;
-  AttribSlots _target;
+  // The current state of the graphics context, as of the last call to
+  // set_state_and_transform().
   CPT(RenderState) _state_rs;
+
+  // The desired state of the graphics context, during processing of
+  // set_state_and_transform().
   CPT(RenderState) _target_rs;
+
+  // This bitmask contains a 1 bit everywhere that _state_rs has a
+  // known value.  If a bit is 0, the corresponding state must be
+  // re-sent.
+  RenderState::SlotMask _state_mask;
+
+  // The current transform, as of the last call to
+  // set_state_and_transform().
   CPT(TransformState) _internal_transform;
 
   // The current TextureAttrib is a special case; we may further
   // restrict it (according to graphics cards limits) or extend it
   // (according to ColorScaleAttribs in effect) beyond what is
   // specifically requested in the scene graph.
-  CPT(TextureAttrib) _effective_texture;
-  CPT(TexGenAttrib) _effective_tex_gen;
+  CPT(TextureAttrib) _target_texture;
+  CPT(TextureAttrib) _state_texture;
+  CPT(TexGenAttrib) _target_tex_gen;
+  CPT(TexGenAttrib) _state_tex_gen;
+
+  // Also, the shader might be the explicitly-requested shader, or it
+  // might be an auto-generated one.
+  CPT(ShaderAttrib) _state_shader;
+  CPT(ShaderAttrib) _target_shader;
 
   // These are set by begin_draw_primitives(), and are only valid
   // between begin_draw_primitives() and end_draw_primitives().

+ 7 - 7
panda/src/display/standardMunger.cxx

@@ -39,15 +39,15 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
   _numeric_type(numeric_type),
   _contents(contents)
 {
-  _render_mode = state->get_render_mode();
+  _render_mode = DCAST(RenderModeAttrib, state->get_attrib(RenderModeAttrib::get_class_slot()));
 
   _munge_color = false;
   _munge_color_scale = false;
 
   if (!get_gsg()->get_runtime_color_scale()) {
     // We might need to munge the colors.
-    CPT(ColorAttrib) color_attrib = state->get_color();
-    CPT(ColorScaleAttrib) color_scale_attrib = state->get_color_scale();
+    CPT(ColorAttrib) color_attrib = DCAST(ColorAttrib, state->get_attrib(ColorAttrib::get_class_slot()));
+    CPT(ColorScaleAttrib) color_scale_attrib = DCAST(ColorScaleAttrib, state->get_attrib(ColorScaleAttrib::get_class_slot()));
 
     if (color_attrib != (ColorAttrib *)NULL && 
         color_attrib->get_color_type() == ColorAttrib::T_flat) {
@@ -72,7 +72,7 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
                color_scale_attrib->has_scale()) {
       _color_scale = color_scale_attrib->get_scale();
       
-      CPT(TextureAttrib) tex_attrib = state->get_texture();
+      CPT(TextureAttrib) tex_attrib = DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()));
       
       // If the GSG says it can't cheat this RGB or alpha scale, we have
       // to apply the color scale directly.
@@ -339,10 +339,10 @@ munge_state_impl(const RenderState *state) {
   CPT(RenderState) munged_state = state;
 
   if (_munge_color) {
-    munged_state = munged_state->remove_attrib(ColorAttrib::get_class_type());
-    munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_type());
+    munged_state = munged_state->remove_attrib(ColorAttrib::get_class_slot());
+    munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
   } else if (_munge_color_scale) {
-    munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_type());
+    munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
   }
 
   return munged_state;

+ 2 - 2
panda/src/dxgsg8/dxGeomMunger8.I

@@ -21,8 +21,8 @@
 INLINE DXGeomMunger8::
 DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) :
   StandardMunger(gsg, state, 1, NT_packed_dabc, C_color),
-  _texture(state->get_texture()),
-  _tex_gen(state->get_tex_gen())
+  _texture(DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()))),
+  _tex_gen(DCAST(TexGenAttrib, state->get_attrib(TexGenAttrib::get_class_slot())))
 {
   _filtered_texture = (TextureAttrib *)NULL;
   _reffed_filtered_texture = false;

+ 188 - 139
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -39,6 +39,9 @@
 #include "rescaleNormalAttrib.h"
 #include "fogAttrib.h"
 #include "depthOffsetAttrib.h"
+#include "lightAttrib.h"
+#include "stencilAttrib.h"
+#include "scissorAttrib.h"
 #include "fog.h"
 #include "throw_event.h"
 #include "geomVertexFormat.h"
@@ -970,7 +973,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian8::
 draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
   _vertices_tri_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_tri_pcollector.add_level(1);
   if (reader->is_indexed()) {
@@ -1039,7 +1042,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian8::
 draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
   if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
     // One long triangle strip, connected by the degenerate vertices
     // that have already been set up within the primitive.
@@ -1214,7 +1217,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian8::
 draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
   CPTA_int ends = reader->get_ends();
   _primitive_batches_trifan_pcollector.add_level(ends.size());
 
@@ -1325,7 +1328,7 @@ draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian8::
 draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
 
@@ -1406,7 +1409,7 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian8::
 draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
 
@@ -2102,15 +2105,15 @@ do_issue_transform() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_alpha_test() {
-  const AlphaTestAttrib *attrib = _target._alpha_test;
-  AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
+  const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
+  AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode();
   if (mode == AlphaTestAttrib::M_none) {
     _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
 
   } else {
     //  AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC
     _d3d_device->SetRenderState(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode);
-    _d3d_device->SetRenderState(D3DRS_ALPHAREF, (UINT) (attrib->get_reference_alpha()*255.0f));  //d3d uses 0x0-0xFF, not a float
+    _d3d_device->SetRenderState(D3DRS_ALPHAREF, (UINT) (target_alpha_test->get_reference_alpha()*255.0f));  //d3d uses 0x0-0xFF, not a float
     _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
   }
 }
@@ -2122,8 +2125,8 @@ do_issue_alpha_test() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_render_mode() {
-  const RenderModeAttrib *attrib = _target._render_mode;
-  RenderModeAttrib::Mode mode = attrib->get_mode();
+  const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()));
+  RenderModeAttrib::Mode mode = target_render_mode->get_mode();
 
   switch (mode) {
   case RenderModeAttrib::M_unchanged:
@@ -2146,10 +2149,10 @@ do_issue_render_mode() {
   }
 
   // This might also specify the point size.
-  float point_size = attrib->get_thickness();
+  float point_size = target_render_mode->get_thickness();
   _d3d_device->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&point_size));
 
-  if (attrib->get_perspective()) {
+  if (target_render_mode->get_perspective()) {
     _d3d_device->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
 
     LVector3f height(0.0f, point_size, 1.0f);
@@ -2176,8 +2179,8 @@ do_issue_render_mode() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_rescale_normal() {
-  const RescaleNormalAttrib *attrib = _target._rescale_normal;
-  RescaleNormalAttrib::Mode mode = attrib->get_mode();
+  const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()));
+  RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
 
   _auto_rescale_normal = false;
 
@@ -2209,8 +2212,8 @@ do_issue_rescale_normal() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_depth_test() {
-  const DepthTestAttrib *attrib = _target._depth_test;
-  DepthTestAttrib::PandaCompareFunc mode = attrib->get_mode();
+  const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
+  DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode();
   if (mode == DepthTestAttrib::M_none) {
     _d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
   } else {
@@ -2226,8 +2229,8 @@ do_issue_depth_test() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_depth_write() {
-  const DepthWriteAttrib *attrib = _target._depth_write;
-  if (attrib->get_mode() == DepthWriteAttrib::M_on) {
+  const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
+  if (target_depth_write->get_mode() == DepthWriteAttrib::M_on) {
     _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
   } else {
     _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
@@ -2241,8 +2244,8 @@ do_issue_depth_write() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_cull_face() {
-  const CullFaceAttrib *attrib = _target._cull_face;
-  _cull_face_mode = attrib->get_effective_mode();
+  const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()));
+  _cull_face_mode = target_cull_face->get_effective_mode();
 
   switch (_cull_face_mode) {
   case CullFaceAttrib::M_cull_none:
@@ -2268,10 +2271,10 @@ do_issue_cull_face() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_fog() {
-  const FogAttrib *attrib = _target._fog;
-  if (!attrib->is_off()) {
+  const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
+  if (!target_fog->is_off()) {
     _d3d_device->SetRenderState(D3DRS_FOGENABLE, TRUE);
-    Fog *fog = attrib->get_fog();
+    Fog *fog = target_fog->get_fog();
     nassertv(fog != (Fog *)NULL);
     apply_fog(fog);
   } else {
@@ -2286,8 +2289,8 @@ do_issue_fog() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_depth_offset() {
-  const DepthOffsetAttrib *attrib = _target._depth_offset;
-  int offset = attrib->get_offset();
+  const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
+  int offset = target_depth_offset->get_offset();
   _d3d_device->SetRenderState(D3DRS_ZBIAS, offset);
 }
 
@@ -2298,8 +2301,8 @@ do_issue_depth_offset() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_shade_model() {
-  const ShadeModelAttrib *attrib = _target._shade_model;
-  switch (attrib->get_mode()) {
+  const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()));
+  switch (target_shade_model->get_mode()) {
   case ShadeModelAttrib::M_smooth:
     _d3d_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
     break;
@@ -2337,8 +2340,10 @@ set_state_and_transform(const RenderState *target,
   }
 #endif
   _state_pcollector.add_level(1);
+  PStatTimer timer1(_draw_set_state_pcollector);
 
   if (transform != _internal_transform) {
+    //PStatTimer timer(_draw_set_state_transform_pcollector);
     _state_pcollector.add_level(1);
     _internal_transform = transform;
     do_issue_transform();
@@ -2348,95 +2353,127 @@ set_state_and_transform(const RenderState *target,
     return;
   }
   _target_rs = target;
-  _target.clear_to_defaults();
-  target->store_into_slots(&_target);
-  _state_rs = 0;
 
-  if (_target._alpha_test != _state._alpha_test) {
+  int alpha_test_slot = AlphaTestAttrib::get_class_slot();
+  if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
+      !_state_mask.get_bit(alpha_test_slot)) {
+    //PStatTimer timer(_draw_set_state_alpha_test_pcollector);
     do_issue_alpha_test();
-    _state._alpha_test = _target._alpha_test;
+    _state_mask.set_bit(alpha_test_slot);
   }
 
-  if (_target._antialias != _state._antialias) {
-    // Antialias not implemented under DX8
-    _state._antialias = _target._antialias;
-  }
-
-  if (_target._clip_plane != _state._clip_plane) {
+  int clip_plane_slot = ClipPlaneAttrib::get_class_slot();
+  if (_target_rs->get_attrib(clip_plane_slot) != _state_rs->get_attrib(clip_plane_slot) ||
+      !_state_mask.get_bit(clip_plane_slot)) {
+    //PStatTimer timer(_draw_set_state_clip_plane_pcollector);
     do_issue_clip_plane();
-    _state._clip_plane = _target._clip_plane;
+    _state_mask.set_bit(clip_plane_slot);
   }
 
-  if (_target._color != _state._color ||
-      _target._color_scale != _state._color_scale) {
+  int color_slot = ColorAttrib::get_class_slot();
+  int color_scale_slot = ColorScaleAttrib::get_class_slot();
+  if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
+      _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
+      !_state_mask.get_bit(color_slot) ||
+      !_state_mask.get_bit(color_scale_slot)) {
+    //PStatTimer timer(_draw_set_state_color_pcollector);
     do_issue_color();
     do_issue_color_scale();
-    _state._color = _target._color;
-    _state._color_scale = _target._color_scale;
+    _state_mask.set_bit(color_slot);
+    _state_mask.set_bit(color_scale_slot);
   }
 
-  if (_target._cull_face != _state._cull_face) {
+  int cull_face_slot = CullFaceAttrib::get_class_slot();
+  if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
+      !_state_mask.get_bit(cull_face_slot)) {
+    //PStatTimer timer(_draw_set_state_cull_face_pcollector);
     do_issue_cull_face();
-    _state._cull_face = _target._cull_face;
+    _state_mask.set_bit(cull_face_slot);
   }
 
-  if (_target._depth_offset != _state._depth_offset) {
+  int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
+      !_state_mask.get_bit(depth_offset_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_offset_pcollector);
     do_issue_depth_offset();
-    _state._depth_offset = _target._depth_offset;
+    _state_mask.set_bit(depth_offset_slot);
   }
 
-  if (_target._depth_test != _state._depth_test) {
+  int depth_test_slot = DepthTestAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_test_slot) != _state_rs->get_attrib(depth_test_slot) ||
+      !_state_mask.get_bit(depth_test_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_test_pcollector);
     do_issue_depth_test();
-    _state._depth_test = _target._depth_test;
+    _state_mask.set_bit(depth_test_slot);
   }
 
-  if (_target._depth_write != _state._depth_write) {
+  int depth_write_slot = DepthWriteAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_write_slot) != _state_rs->get_attrib(depth_write_slot) ||
+      !_state_mask.get_bit(depth_write_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_write_pcollector);
     do_issue_depth_write();
-    _state._depth_write = _target._depth_write;
+    _state_mask.set_bit(depth_write_slot);
   }
-
-  if (_target._fog != _state._fog) {
+     
+  int fog_slot = FogAttrib::get_class_slot();
+  if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) ||
+      !_state_mask.get_bit(fog_slot)) {
+    //PStatTimer timer(_draw_set_state_fog_pcollector);
     do_issue_fog();
-    _state._fog = _target._fog;
+    _state_mask.set_bit(fog_slot);
   }
 
-  if (_target._render_mode != _state._render_mode) {
+  int render_mode_slot = RenderModeAttrib::get_class_slot();
+  if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
+      !_state_mask.get_bit(render_mode_slot)) {
+    //PStatTimer timer(_draw_set_state_render_mode_pcollector);
     do_issue_render_mode();
-    _state._render_mode = _target._render_mode;
+    _state_mask.set_bit(render_mode_slot);
   }
 
-  if (_target._rescale_normal != _state._rescale_normal) {
+  int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
+  if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
+      !_state_mask.get_bit(rescale_normal_slot)) {
+    //PStatTimer timer(_draw_set_state_rescale_normal_pcollector);
     do_issue_rescale_normal();
-    _state._rescale_normal = _target._rescale_normal;
+    _state_mask.set_bit(rescale_normal_slot);
   }
 
-  if (_target._shade_model != _state._shade_model) {
+  int shade_model_slot = ShadeModelAttrib::get_class_slot();
+  if (_target_rs->get_attrib(shade_model_slot) != _state_rs->get_attrib(shade_model_slot) ||
+      !_state_mask.get_bit(shade_model_slot)) {
+    //PStatTimer timer(_draw_set_state_shade_model_pcollector);
     do_issue_shade_model();
-    _state._shade_model = _target._shade_model;
-  }
-
-  // Shaders not implemented under DX8
-  if (_target._shader != _state._shader) {
-    _state._shader = _target._shader;
-  }
-
-  if ((_target._transparency != _state._transparency)||
-      (_target._color_write != _state._color_write)||
-      (_target._color_blend != _state._color_blend)) {
+    _state_mask.set_bit(shade_model_slot);
+  }
+
+  int transparency_slot = TransparencyAttrib::get_class_slot();
+  int color_write_slot = ColorWriteAttrib::get_class_slot();
+  int color_blend_slot = ColorBlendAttrib::get_class_slot();
+  if (_target_rs->get_attrib(transparency_slot) != _state_rs->get_attrib(transparency_slot) ||
+      _target_rs->get_attrib(color_write_slot) != _state_rs->get_attrib(color_write_slot) ||
+      _target_rs->get_attrib(color_blend_slot) != _state_rs->get_attrib(color_blend_slot) ||
+      !_state_mask.get_bit(transparency_slot) ||
+      !_state_mask.get_bit(color_write_slot) ||
+      !_state_mask.get_bit(color_blend_slot)) {
+    //PStatTimer timer(_draw_set_state_blending_pcollector);
     do_issue_blending();
-    _state._transparency = _target._transparency;
-    _state._color_write = _target._color_write;
-    _state._color_blend = _target._color_blend;
-  }
-
-  if (_target._tex_matrix != _state._tex_matrix) {
-    _state._texture = 0;
-    _state._tex_matrix = _target._tex_matrix;
-  }
-
-  if (_target._texture != _state._texture ||
-      _target._tex_gen != _state._tex_gen) {
-    determine_effective_texture();
+    _state_mask.set_bit(transparency_slot);
+    _state_mask.set_bit(color_write_slot);
+    _state_mask.set_bit(color_blend_slot);
+  }
+
+  int texture_slot = TextureAttrib::get_class_slot();
+  int tex_matrix_slot = TexMatrixAttrib::get_class_slot();
+  int tex_gen_slot = TexGenAttrib::get_class_slot();
+  if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
+      _target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) ||
+      _target_rs->get_attrib(tex_gen_slot) != _state_rs->get_attrib(tex_gen_slot) ||
+      !_state_mask.get_bit(texture_slot) ||
+      !_state_mask.get_bit(tex_matrix_slot) ||
+      !_state_mask.get_bit(tex_gen_slot)) {
+    //PStatTimer timer(_draw_set_state_texture_pcollector);
+    determine_target_texture();
 
     // For some mysterious and disturbing reason, making this call
     // here--which should have no effect--actually prevents the DX
@@ -2444,31 +2481,46 @@ set_state_and_transform(const RenderState *target,
     // context goes foobar when switching states and refuses to draw
     // anything at all.  I strongly suspect memory corruption
     // somewhere, but can't locate it.
-    _target._texture->filter_to_max(_max_texture_stages);
+    //    _target_texture->filter_to_max(_max_texture_stages);
 
     do_issue_texture();
-    _state._texture = _target._texture;
-    _state._tex_gen = _target._tex_gen;
+
+    _state_texture = _target_texture;
+    _state_mask.set_bit(texture_slot);
+    _state_mask.set_bit(tex_matrix_slot);
+    _state_mask.set_bit(tex_gen_slot);
   }
 
-  if (_target._material != _state._material) {
+  int material_slot = MaterialAttrib::get_class_slot();
+  if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
+      !_state_mask.get_bit(material_slot)) {
+    //PStatTimer timer(_draw_set_state_material_pcollector);
     do_issue_material();
-    _state._material = _target._material;
+    _state_mask.set_bit(material_slot);
   }
 
-  if (_target._light != _state._light) {
+  int light_slot = LightAttrib::get_class_slot();
+  if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
+      !_state_mask.get_bit(light_slot)) {
+    //PStatTimer timer(_draw_set_state_light_pcollector);
     do_issue_light();
-    _state._light = _target._light;
+    _state_mask.set_bit(light_slot);
   }
 
-  if (_target._stencil != _state._stencil) {
+  int stencil_slot = StencilAttrib::get_class_slot();
+  if (_target_rs->get_attrib(stencil_slot) != _state_rs->get_attrib(stencil_slot) ||
+      !_state_mask.get_bit(stencil_slot)) {
+    //PStatTimer timer(_draw_set_state_stencil_pcollector);
     do_issue_stencil();
-    _state._stencil = _target._stencil;
+    _state_mask.set_bit(stencil_slot);
   }
 
-  if (_target._scissor != _state._scissor) {
+  int scissor_slot = ScissorAttrib::get_class_slot();
+  if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
+      !_state_mask.get_bit(scissor_slot)) {
+    //PStatTimer timer(_draw_set_state_scissor_pcollector);
     do_issue_scissor();
-    _state._scissor = _target._scissor;
+    _state_mask.set_bit(scissor_slot);
   }
 
   _state_rs = _target_rs;
@@ -2531,7 +2583,7 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
 void DXGraphicsStateGuardian8::
 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
   static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
-  PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
+  //PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
 
   pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT8()));
   D3DLIGHT8 &fdata = (*lookup.first).second;
@@ -2663,11 +2715,11 @@ void DXGraphicsStateGuardian8::
 do_issue_material() {
   static Material empty;
   const Material *material;
-  if (_target._material == (MaterialAttrib *)NULL ||
-      _target._material->is_off()) {
+  const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
+  if (target_material->is_off()) {
     material = &empty;
   } else {
-    material = _target._material->get_material();
+    material = target_material->get_material();
   }
 
   D3DMATERIAL8 cur_material;
@@ -2726,7 +2778,7 @@ void DXGraphicsStateGuardian8::
 do_issue_texture() {
   DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
 
-  int num_stages = _effective_texture->get_num_on_ff_stages();
+  int num_stages = _target_texture->get_num_on_ff_stages();
   nassertv(num_stages <= _max_texture_stages &&
            _num_active_texture_stages <= _max_texture_stages);
 
@@ -2738,10 +2790,10 @@ do_issue_texture() {
 
   int si;
   for (si = 0; si < num_stages; si++) {
-    TextureStage *stage = _effective_texture->get_on_ff_stage(si);
-    int texcoord_index = _effective_texture->get_ff_tc_index(si);
+    TextureStage *stage = _target_texture->get_on_ff_stage(si);
+    int texcoord_index = _target_texture->get_ff_tc_index(si);
 
-    Texture *texture = _effective_texture->get_on_texture(stage);
+    Texture *texture = _target_texture->get_on_texture(stage);
     nassertv(texture != (Texture *)NULL);
 
     // We always reissue every stage in DX, just in case the texcoord
@@ -2753,12 +2805,13 @@ do_issue_texture() {
     int texcoord_dimensions = 2;
 
     CPT(TransformState) tex_mat = TransformState::make_identity();
-    if (_state._tex_matrix->has_stage(stage)) {
-      tex_mat = _state._tex_matrix->get_transform(stage);
+    const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
+    if (target_tex_matrix->has_stage(stage)) {
+      tex_mat = target_tex_matrix->get_transform(stage);
     }
 
     // Issue the texgen mode.
-    TexGenAttrib::Mode mode = _effective_tex_gen->get_mode(stage);
+    TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage);
     bool any_point_sprite = false;
 
     switch (mode) {
@@ -2867,7 +2920,7 @@ do_issue_texture() {
                                           texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
         texcoord_dimensions = 3;
 
-        const TexCoord3f &v = _effective_tex_gen->get_constant_value(stage);
+        const TexCoord3f &v = _target_tex_gen->get_constant_value(stage);
         CPT(TransformState) squash = 
           TransformState::make_pos_hpr_scale(v, LVecBase3f::zero(),
                                              LVecBase3f::zero());
@@ -3032,31 +3085,30 @@ do_issue_blending() {
   // all the other blending-related stuff doesn't matter.  If the
   // device doesn't support color-write, we use blending tricks
   // to effectively disable color write.
+  const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
   unsigned int color_channels =
-    _target._color_write->get_channels() & _color_write_mask;
+    target_color_write->get_channels() & _color_write_mask;
   if (color_channels == ColorWriteAttrib::C_off) {
-    if (_target._color_write != _state._color_write) {
-      if (_screen->_can_direct_disable_color_writes) {
-        _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
-        _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)0x0);
-      } else {
-        _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
-        _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
-        _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
-      }
+    if (_screen->_can_direct_disable_color_writes) {
+      _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+      _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)0x0);
+    } else {
+      _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+      _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+      _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
     }
     return;
-  } else {
-    if (_target._color_write != _state._color_write) {
-      if (_screen->_can_direct_disable_color_writes) {
-        _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, color_channels);
-      }
-    }
   }
 
-  CPT(ColorBlendAttrib) color_blend = _target._color_blend;
-  ColorBlendAttrib::Mode color_blend_mode = _target._color_blend->get_mode();
-  TransparencyAttrib::Mode transparency_mode = _target._transparency->get_mode();
+  if (_screen->_can_direct_disable_color_writes) {
+    _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, color_channels);
+  }
+
+  const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
+  ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode();
+
+  const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
+  TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode();
 
   // Is there a color blend set?
   if (color_blend_mode != ColorBlendAttrib::M_none) {
@@ -3085,9 +3137,9 @@ do_issue_blending() {
     }
 
     _d3d_device->SetRenderState(D3DRS_SRCBLEND,
-                                get_blend_func(color_blend->get_operand_a()));
+                                get_blend_func(target_color_blend->get_operand_a()));
     _d3d_device->SetRenderState(D3DRS_DESTBLEND,
-                                get_blend_func(color_blend->get_operand_b()));
+                                get_blend_func(target_color_blend->get_operand_b()));
     return;
   }
 
@@ -3161,8 +3213,9 @@ free_nondx_resources() {
 void DXGraphicsStateGuardian8::
 free_d3d_device() {
   // dont want a full reset of gsg, just a state clear
-  _state_rs = 0;
-  _state.clear_to_zero();
+  _state_rs = RenderState::make_empty();
+  _state_mask.clear();
+
   // want gsg to pass all state settings through
 
   _dx_is_ready = false;
@@ -4207,8 +4260,7 @@ void dx_stencil_function (StencilRenderStates::StencilRenderState stencil_render
 
   render_state_value = stencil_render_states -> get_stencil_render_state (stencil_render_state);
 
-  // DEBUG
-  if (false) {
+  if (dxgsg8_cat.is_debug()) {
     dxgsg8_cat.debug()
       << "SRS: " <<  StencilAttrib::stencil_render_state_name_array [stencil_render_state] << ", " << render_state_value << "\n";
   }
@@ -4283,15 +4335,12 @@ void dx_set_stencil_functions (StencilRenderStates *stencil_render_states) {
 void DXGraphicsStateGuardian8::
 do_issue_stencil() {
 
-  const StencilAttrib *stencil;
   StencilRenderStates *stencil_render_states;
-
-  stencil = _target._stencil;
+  const StencilAttrib *stencil = DCAST(StencilAttrib, _target_rs->get_attrib_def(StencilAttrib::get_class_slot()));
   stencil_render_states = this -> _stencil_render_states;
   if (stencil && stencil_render_states) {
 
-    // DEBUG
-    if (false) {
+    if (dxgsg8_cat.is_debug()) {
       dxgsg8_cat.debug() << "STENCIL STATE CHANGE\n";
       dxgsg8_cat.debug() << "\n"
         << "SRS_front_enable " << stencil -> get_render_state (StencilAttrib::SRS_front_enable) << "\n"
@@ -4318,8 +4367,7 @@ do_issue_stencil() {
   }
   else {
 
-    // DEBUG
-    if (false) {
+    if (dxgsg8_cat.is_debug()) {
       dxgsg8_cat.debug() << "STENCIL STATE CHANGE TO OFF \n";
     }
 
@@ -4339,7 +4387,8 @@ get_d3d_device() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 do_issue_scissor() {
-  const LVecBase4f &frame = _target._scissor->get_frame();
+  const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
+  const LVecBase4f &frame = target_scissor->get_frame();
   set_scissor(frame[0], frame[1], frame[2], frame[3]);
 }
 

+ 1 - 0
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -26,6 +26,7 @@
 #include "depthTestAttrib.h"
 #include "cullFaceAttrib.h"
 #include "renderModeAttrib.h"
+#include "colorBlendAttrib.h"
 #include "fog.h"
 #include "pointerToArray.h"
 

+ 2 - 2
panda/src/dxgsg9/dxGeomMunger9.I

@@ -21,8 +21,8 @@
 INLINE DXGeomMunger9::
 DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state) :
   StandardMunger(gsg, state, 1, NT_packed_dabc, C_color),
-  _texture(state->get_texture()),
-  _tex_gen(state->get_tex_gen())
+  _texture(DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()))),
+  _tex_gen(DCAST(TexGenAttrib, state->get_attrib(TexGenAttrib::get_class_slot())))
 {
   _filtered_texture = (TextureAttrib *)NULL;
   _reffed_filtered_texture = false;

+ 202 - 146
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -39,6 +39,9 @@
 #include "rescaleNormalAttrib.h"
 #include "fogAttrib.h"
 #include "depthOffsetAttrib.h"
+#include "lightAttrib.h"
+#include "stencilAttrib.h"
+#include "scissorAttrib.h"
 #include "fog.h"
 #include "throw_event.h"
 #include "geomVertexFormat.h"
@@ -1471,7 +1474,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian9::
 draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
 
   _vertices_tri_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_tri_pcollector.add_level(1);
@@ -1546,7 +1549,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian9::
 draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
 
   if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
     // One long triangle strip, connected by the degenerate vertices
@@ -1731,7 +1734,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian9::
 draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
 
   CPTA_int ends = reader->get_ends();
   _primitive_batches_trifan_pcollector.add_level(ends.size());
@@ -1843,7 +1846,7 @@ draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian9::
 draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
 
@@ -1924,7 +1927,7 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool DXGraphicsStateGuardian9::
 draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector);
+  //PStatTimer timer(_draw_primitive_pcollector);
   _vertices_other_pcollector.add_level(reader->get_num_vertices());
   _primitive_batches_other_pcollector.add_level(1);
 
@@ -2878,17 +2881,17 @@ do_issue_transform() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_alpha_test() {
-  if (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
+  if (_target_shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
     set_render_state(D3DRS_ALPHATESTENABLE, FALSE);
   } else {
-    const AlphaTestAttrib *attrib = _target._alpha_test;
-    AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
+    const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
+    AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode();
     if (mode == AlphaTestAttrib::M_none) {
       set_render_state(D3DRS_ALPHATESTENABLE, FALSE);
     } else {
       //  AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC
       set_render_state(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode);
-      set_render_state(D3DRS_ALPHAREF, (UINT) (attrib->get_reference_alpha()*255.0f));  //d3d uses 0x0-0xFF, not a float
+      set_render_state(D3DRS_ALPHAREF, (UINT) (target_alpha_test->get_reference_alpha()*255.0f));  //d3d uses 0x0-0xFF, not a float
       set_render_state(D3DRS_ALPHATESTENABLE, TRUE);
     }
   }
@@ -2904,8 +2907,8 @@ do_issue_shader() {
 
   CLP(ShaderContext) *context = 0;
   Shader *shader = 0;
-  if (_target._shader) {
-    shader = (Shader *)(_target._shader->get_shader());
+  if (_target_shader) {
+    shader = (Shader *)(_target_shader->get_shader());
   }
   if (shader) {
     context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));
@@ -2948,8 +2951,8 @@ do_issue_shader() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_render_mode() {
-  const RenderModeAttrib *attrib = _target._render_mode;
-  RenderModeAttrib::Mode mode = attrib->get_mode();
+  const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()));
+  RenderModeAttrib::Mode mode = target_render_mode->get_mode();
 
   switch (mode) {
   case RenderModeAttrib::M_unchanged:
@@ -2972,10 +2975,10 @@ do_issue_render_mode() {
   }
 
   // This might also specify the point size.
-  float point_size = attrib->get_thickness();
+  float point_size = target_render_mode->get_thickness();
   set_render_state(D3DRS_POINTSIZE, *((DWORD*)&point_size));
 
-  if (attrib->get_perspective()) {
+  if (target_render_mode->get_perspective()) {
     set_render_state(D3DRS_POINTSCALEENABLE, TRUE);
 
     LVector3f height(0.0f, point_size, 1.0f);
@@ -3002,8 +3005,8 @@ do_issue_render_mode() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_rescale_normal() {
-  const RescaleNormalAttrib *attrib = _target._rescale_normal;
-  RescaleNormalAttrib::Mode mode = attrib->get_mode();
+  const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()));
+  RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
 
   _auto_rescale_normal = false;
 
@@ -3035,8 +3038,8 @@ do_issue_rescale_normal() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_depth_test() {
-  const DepthTestAttrib *attrib = _target._depth_test;
-  DepthTestAttrib::PandaCompareFunc mode = attrib->get_mode();
+  const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
+  DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode();
   if (mode == DepthTestAttrib::M_none) {
     set_render_state(D3DRS_ZENABLE, D3DZB_FALSE);
   } else {
@@ -3052,8 +3055,9 @@ do_issue_depth_test() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_depth_write() {
-  const DepthWriteAttrib *attrib = _target._depth_write;
-  if (attrib->get_mode() == DepthWriteAttrib::M_on) {
+  const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
+  DepthWriteAttrib::Mode mode = target_depth_write->get_mode();
+  if (mode == DepthWriteAttrib::M_on) {
     set_render_state(D3DRS_ZWRITEENABLE, TRUE);
   } else {
     set_render_state(D3DRS_ZWRITEENABLE, FALSE);
@@ -3067,8 +3071,8 @@ do_issue_depth_write() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_cull_face() {
-  const CullFaceAttrib *attrib = _target._cull_face;
-  _cull_face_mode = attrib->get_effective_mode();
+  const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()));
+  _cull_face_mode = target_cull_face->get_effective_mode();
 
   switch (_cull_face_mode) {
   case CullFaceAttrib::M_cull_none:
@@ -3103,10 +3107,10 @@ do_issue_cull_face() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_fog() {
-  const FogAttrib *attrib = _target._fog;
-  if (!attrib->is_off()) {
+  const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
+  if (!target_fog->is_off()) {
     set_render_state(D3DRS_FOGENABLE, TRUE);
-    Fog *fog = attrib->get_fog();
+    Fog *fog = target_fog->get_fog();
     nassertv(fog != (Fog *)NULL);
     apply_fog(fog);
   } else {
@@ -3121,8 +3125,8 @@ do_issue_fog() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_depth_offset() {
-  const DepthOffsetAttrib *attrib = _target._depth_offset;
-  int offset = attrib->get_offset();
+  const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
+  int offset = target_depth_offset->get_offset();
 
   if (_supports_depth_bias) {
     set_render_state(D3DRS_DEPTHBIAS, offset);
@@ -3146,8 +3150,8 @@ do_issue_depth_offset() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_shade_model() {
-  const ShadeModelAttrib *attrib = _target._shade_model;
-  switch (attrib->get_mode()) {
+  const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()));
+  switch (target_shade_model->get_mode()) {
   case ShadeModelAttrib::M_smooth:
     set_render_state(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
     break;
@@ -3185,8 +3189,10 @@ set_state_and_transform(const RenderState *target,
   }
 #endif
   _state_pcollector.add_level(1);
+  PStatTimer timer1(_draw_set_state_pcollector);
 
   if (transform != _internal_transform) {
+    //PStatTimer timer(_draw_set_state_transform_pcollector);
     _state_pcollector.add_level(1);
     _internal_transform = transform;
     do_issue_transform();
@@ -3196,133 +3202,184 @@ set_state_and_transform(const RenderState *target,
     return;
   }
   _target_rs = target;
-  _target.clear_to_defaults();
-  target->store_into_slots(&_target);
-  _state_rs = 0;
 
-  if (_target._shader && (_target._shader->auto_shader())) {
-    _target._shader = _target_rs->get_generated_shader();
-  }
-  
-  if ((_target._alpha_test != _state._alpha_test)||
-      (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test) != 
-       _state._shader->get_flag(ShaderAttrib::F_subsume_alpha_test))) {
-    do_issue_alpha_test();
-    _state._alpha_test = _target._alpha_test;
+  _target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()));
+  if (_target_shader->auto_shader()) {
+    _target_shader = _target_rs->get_generated_shader();
   }
 
-  if (_target._antialias != _state._antialias) {
-    // Antialias not implemented under DX8
-    _state._antialias = _target._antialias;
+  int alpha_test_slot = AlphaTestAttrib::get_class_slot();
+  if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
+      !_state_mask.get_bit(alpha_test_slot)) {
+    //PStatTimer timer(_draw_set_state_alpha_test_pcollector);
+    do_issue_alpha_test();
+    _state_mask.set_bit(alpha_test_slot);
   }
 
-  if (_target._clip_plane != _state._clip_plane) {
+  int clip_plane_slot = ClipPlaneAttrib::get_class_slot();
+  if (_target_rs->get_attrib(clip_plane_slot) != _state_rs->get_attrib(clip_plane_slot) ||
+      !_state_mask.get_bit(clip_plane_slot)) {
+    //PStatTimer timer(_draw_set_state_clip_plane_pcollector);
     do_issue_clip_plane();
-    _state._clip_plane = _target._clip_plane;
+    _state_mask.set_bit(clip_plane_slot);
   }
 
-  if (_target._color != _state._color ||
-      _target._color_scale != _state._color_scale) {
+  int color_slot = ColorAttrib::get_class_slot();
+  int color_scale_slot = ColorScaleAttrib::get_class_slot();
+  if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
+      _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
+      !_state_mask.get_bit(color_slot) ||
+      !_state_mask.get_bit(color_scale_slot)) {
+    //PStatTimer timer(_draw_set_state_color_pcollector);
     do_issue_color();
     do_issue_color_scale();
-    _state._color = _target._color;
-    _state._color_scale = _target._color_scale;
-    if (_current_shader_context) {
-      _current_shader_context->issue_parameters(this, Shader::SSD_color);
-    }
+    _state_mask.set_bit(color_slot);
+    _state_mask.set_bit(color_scale_slot);
   }
 
-  if (_target._cull_face != _state._cull_face) {
+  int cull_face_slot = CullFaceAttrib::get_class_slot();
+  if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
+      !_state_mask.get_bit(cull_face_slot)) {
+    //PStatTimer timer(_draw_set_state_cull_face_pcollector);
     do_issue_cull_face();
-    _state._cull_face = _target._cull_face;
+    _state_mask.set_bit(cull_face_slot);
   }
 
-  if (_target._depth_offset != _state._depth_offset) {
+  int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
+      !_state_mask.get_bit(depth_offset_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_offset_pcollector);
     do_issue_depth_offset();
-    _state._depth_offset = _target._depth_offset;
+    _state_mask.set_bit(depth_offset_slot);
   }
 
-  if (_target._depth_test != _state._depth_test) {
+  int depth_test_slot = DepthTestAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_test_slot) != _state_rs->get_attrib(depth_test_slot) ||
+      !_state_mask.get_bit(depth_test_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_test_pcollector);
     do_issue_depth_test();
-    _state._depth_test = _target._depth_test;
+    _state_mask.set_bit(depth_test_slot);
   }
 
-  if (_target._depth_write != _state._depth_write) {
+  int depth_write_slot = DepthWriteAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_write_slot) != _state_rs->get_attrib(depth_write_slot) ||
+      !_state_mask.get_bit(depth_write_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_write_pcollector);
     do_issue_depth_write();
-    _state._depth_write = _target._depth_write;
+    _state_mask.set_bit(depth_write_slot);
   }
 
-  if (_target._fog != _state._fog) {
-    do_issue_fog();
-    _state._fog = _target._fog;
-  }
-
-  if (_target._render_mode != _state._render_mode) {
+  int render_mode_slot = RenderModeAttrib::get_class_slot();
+  if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
+      !_state_mask.get_bit(render_mode_slot)) {
+    //PStatTimer timer(_draw_set_state_render_mode_pcollector);
     do_issue_render_mode();
-    _state._render_mode = _target._render_mode;
+    _state_mask.set_bit(render_mode_slot);
   }
 
-  if (_target._rescale_normal != _state._rescale_normal) {
+  int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
+  if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
+      !_state_mask.get_bit(rescale_normal_slot)) {
+    //PStatTimer timer(_draw_set_state_rescale_normal_pcollector);
     do_issue_rescale_normal();
-    _state._rescale_normal = _target._rescale_normal;
+    _state_mask.set_bit(rescale_normal_slot);
   }
 
-  if (_target._shade_model != _state._shade_model) {
+  int shade_model_slot = ShadeModelAttrib::get_class_slot();
+  if (_target_rs->get_attrib(shade_model_slot) != _state_rs->get_attrib(shade_model_slot) ||
+      !_state_mask.get_bit(shade_model_slot)) {
+    //PStatTimer timer(_draw_set_state_shade_model_pcollector);
     do_issue_shade_model();
-    _state._shade_model = _target._shade_model;
-  }
-
-  if ((_target._transparency != _state._transparency)||
-      (_target._color_write != _state._color_write)||
-      (_target._color_blend != _state._color_blend)||
-      (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != 
-       _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
+    _state_mask.set_bit(shade_model_slot);
+  }
+
+  int transparency_slot = TransparencyAttrib::get_class_slot();
+  int color_write_slot = ColorWriteAttrib::get_class_slot();
+  int color_blend_slot = ColorBlendAttrib::get_class_slot();
+  if (_target_rs->get_attrib(transparency_slot) != _state_rs->get_attrib(transparency_slot) ||
+      _target_rs->get_attrib(color_write_slot) != _state_rs->get_attrib(color_write_slot) ||
+      _target_rs->get_attrib(color_blend_slot) != _state_rs->get_attrib(color_blend_slot) ||
+      !_state_mask.get_bit(transparency_slot) ||
+      !_state_mask.get_bit(color_write_slot) ||
+      !_state_mask.get_bit(color_blend_slot) ||
+      (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write) != 
+       _state_shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
+    //PStatTimer timer(_draw_set_state_blending_pcollector);
     do_issue_blending();
-    _state._transparency = _target._transparency;
-    _state._color_write = _target._color_write;
-    _state._color_blend = _target._color_blend;
+    _state_mask.set_bit(transparency_slot);
+    _state_mask.set_bit(color_write_slot);
+    _state_mask.set_bit(color_blend_slot);
   }
 
-  if (_target._shader != _state._shader) {
+  if (_target_shader != _state_shader) {
+    //PStatTimer timer(_draw_set_state_shader_pcollector);
     do_issue_shader();
-    _state._shader = _target._shader;
-    _state._texture = 0;
-  }
-
-  if (_target._tex_matrix != _state._tex_matrix) {
-    _state._texture = 0;
-    _state._tex_matrix = _target._tex_matrix;
-  }
-
-  if (_target._texture != _state._texture ||
-      _target._tex_gen != _state._tex_gen) {
-    determine_effective_texture();
+    _state_shader = _target_shader;
+    _state_mask.clear_bit(TextureAttrib::get_class_slot());
+  }
+
+  int texture_slot = TextureAttrib::get_class_slot();
+  int tex_matrix_slot = TexMatrixAttrib::get_class_slot();
+  int tex_gen_slot = TexGenAttrib::get_class_slot();
+  if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
+      _target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) ||
+      _target_rs->get_attrib(tex_gen_slot) != _state_rs->get_attrib(tex_gen_slot) ||
+      !_state_mask.get_bit(texture_slot) ||
+      !_state_mask.get_bit(tex_matrix_slot) ||
+      !_state_mask.get_bit(tex_gen_slot)) {
+    //PStatTimer timer(_draw_set_state_texture_pcollector);
+    determine_target_texture();
     do_issue_texture();
-    _state._texture = _target._texture;
-    _state._tex_gen = _target._tex_gen;
+
+    _state_texture = _target_texture;
+    _state_mask.set_bit(texture_slot);
+    _state_mask.set_bit(tex_matrix_slot);
+    _state_mask.set_bit(tex_gen_slot);
   }
 
-  if (_target._material != _state._material) {
+  int material_slot = MaterialAttrib::get_class_slot();
+  if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
+      !_state_mask.get_bit(material_slot)) {
+    //PStatTimer timer(_draw_set_state_material_pcollector);
     do_issue_material();
-    _state._material = _target._material;
+    _state_mask.set_bit(material_slot);
     if (_current_shader_context) {
       _current_shader_context->issue_parameters(this, Shader::SSD_material);
     }
   }
 
-  if (_target._light != _state._light) {
+  int light_slot = LightAttrib::get_class_slot();
+  if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
+      !_state_mask.get_bit(light_slot)) {
+    //PStatTimer timer(_draw_set_state_light_pcollector);
     do_issue_light();
-    _state._light = _target._light;
+    _state_mask.set_bit(light_slot);
   }
 
-  if (_target._stencil != _state._stencil) {
+  int stencil_slot = StencilAttrib::get_class_slot();
+  if (_target_rs->get_attrib(stencil_slot) != _state_rs->get_attrib(stencil_slot) ||
+      !_state_mask.get_bit(stencil_slot)) {
+    //PStatTimer timer(_draw_set_state_stencil_pcollector);
     do_issue_stencil();
-    _state._stencil = _target._stencil;
+    _state_mask.set_bit(stencil_slot);
+  }
+     
+  if (_current_shader_context == 0) {
+    int fog_slot = FogAttrib::get_class_slot();
+    if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) ||
+        !_state_mask.get_bit(fog_slot)) {
+      //PStatTimer timer(_draw_set_state_fog_pcollector);
+      do_issue_fog();
+      _state_mask.set_bit(fog_slot);
+    }
   }
 
-  if (_target._scissor != _state._scissor) {
+  int scissor_slot = ScissorAttrib::get_class_slot();
+  if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
+      !_state_mask.get_bit(scissor_slot)) {
+    //PStatTimer timer(_draw_set_state_scissor_pcollector);
     do_issue_scissor();
-    _state._scissor = _target._scissor;
+    _state_mask.set_bit(scissor_slot);
   }
 
   _state_rs = _target_rs;
@@ -3385,7 +3442,7 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
 void DXGraphicsStateGuardian9::
 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
   static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
-  PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
+  //PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
 
   pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT9()));
   D3DLIGHT9 &fdata = (*lookup.first).second;
@@ -3517,11 +3574,11 @@ void DXGraphicsStateGuardian9::
 do_issue_material() {
   static Material empty;
   const Material *material;
-  if (_target._material == (MaterialAttrib *)NULL ||
-      _target._material->is_off()) {
+  const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
+  if (target_material->is_off()) {
     material = &empty;
   } else {
-    material = _target._material->get_material();
+    material = target_material->get_material();
   }
 
   D3DMATERIAL9 cur_material;
@@ -3634,10 +3691,10 @@ void DXGraphicsStateGuardian9::
 update_standard_texture_bindings() {
   DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
 
-  int num_stages = _effective_texture->get_num_on_ff_stages();
+  int num_stages = _target_texture->get_num_on_ff_stages();
   int num_old_stages = _max_texture_stages;
-  if (_state._texture != (TextureAttrib *)NULL) {
-    num_old_stages = _state._texture->get_num_on_ff_stages();
+  if (_state_texture != (TextureAttrib *)NULL) {
+    num_old_stages = _state_texture->get_num_on_ff_stages();
   }
 
   nassertv(num_stages <= _max_texture_stages &&
@@ -3651,10 +3708,10 @@ update_standard_texture_bindings() {
 
   int si;
   for (si = 0; si < num_stages; si++) {
-    TextureStage *stage = _effective_texture->get_on_ff_stage(si);
-    int texcoord_index = _effective_texture->get_ff_tc_index(si);
+    TextureStage *stage = _target_texture->get_on_ff_stage(si);
+    int texcoord_index = _target_texture->get_ff_tc_index(si);
 
-    Texture *texture = _effective_texture->get_on_texture(stage);
+    Texture *texture = _target_texture->get_on_texture(stage);
     nassertv(texture != (Texture *)NULL);
 
     // We always reissue every stage in DX, just in case the texcoord
@@ -3666,12 +3723,13 @@ update_standard_texture_bindings() {
     int texcoord_dimensions = 2;
 
     CPT(TransformState) tex_mat = TransformState::make_identity();
-    if (_state._tex_matrix->has_stage(stage)) {
-      tex_mat = _state._tex_matrix->get_transform(stage);
+    const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
+    if (target_tex_matrix->has_stage(stage)) {
+      tex_mat = target_tex_matrix->get_transform(stage);
     }
 
     // Issue the texgen mode.
-    TexGenAttrib::Mode mode = _effective_tex_gen->get_mode(stage);
+    TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage);
     bool any_point_sprite = false;
 
     switch (mode) {
@@ -3780,7 +3838,7 @@ update_standard_texture_bindings() {
                                 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
         texcoord_dimensions = 3;
 
-        const TexCoord3f &v = _effective_tex_gen->get_constant_value(stage);
+        const TexCoord3f &v = _target_tex_gen->get_constant_value(stage);
         CPT(TransformState) squash =
           TransformState::make_pos_hpr_scale(v, LVecBase3f::zero(),
                                              LVecBase3f::zero());
@@ -3849,36 +3907,34 @@ do_issue_blending() {
   // all the other blending-related stuff doesn't matter.  If the
   // device doesn't support color-write, we use blending tricks
   // to effectively disable color write.
+  const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
   unsigned int color_channels =
-    _target._color_write->get_channels() & _color_write_mask;
-  if (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
+    target_color_write->get_channels() & _color_write_mask;
+  if (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
     color_channels &= ~(ColorWriteAttrib::C_alpha);
   }
   if (color_channels == ColorWriteAttrib::C_off) {
-    if (_target._color_write != _state._color_write) {
-      if (_screen->_can_direct_disable_color_writes) {
-        set_render_state(D3DRS_ALPHABLENDENABLE, FALSE);
-        set_render_state(D3DRS_COLORWRITEENABLE, (DWORD)0x0);
-      } else {
-        set_render_state(D3DRS_ALPHABLENDENABLE, TRUE);
-        set_render_state(D3DRS_SRCBLEND, D3DBLEND_ZERO);
-        set_render_state(D3DRS_DESTBLEND, D3DBLEND_ONE);
-      }
+    if (_screen->_can_direct_disable_color_writes) {
+      set_render_state(D3DRS_ALPHABLENDENABLE, FALSE);
+      set_render_state(D3DRS_COLORWRITEENABLE, (DWORD)0x0);
+    } else {
+      set_render_state(D3DRS_ALPHABLENDENABLE, TRUE);
+      set_render_state(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+      set_render_state(D3DRS_DESTBLEND, D3DBLEND_ONE);
     }
     return;
   } else {
-    if ((_target._color_write != _state._color_write)||
-        (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != 
-         _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
-      if (_screen->_can_direct_disable_color_writes) {
-        set_render_state(D3DRS_COLORWRITEENABLE, color_channels);
-      }
+    if (_screen->_can_direct_disable_color_writes) {
+      set_render_state(D3DRS_COLORWRITEENABLE, color_channels);
     }
   }
 
-  CPT(ColorBlendAttrib) color_blend = _target._color_blend;
-  ColorBlendAttrib::Mode color_blend_mode = _target._color_blend->get_mode();
-  TransparencyAttrib::Mode transparency_mode = _target._transparency->get_mode();
+  const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
+  CPT(ColorBlendAttrib) color_blend = target_color_blend;
+  ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode();
+
+  const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
+  TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode();
 
   // Is there a color blend set?
   if (color_blend_mode != ColorBlendAttrib::M_none) {
@@ -4085,8 +4141,9 @@ free_nondx_resources() {
 void DXGraphicsStateGuardian9::
 free_d3d_device() {
   // dont want a full reset of gsg, just a state clear
-  _state_rs = 0;
-  _state.clear_to_zero();
+  _state_rs = RenderState::make_empty();
+  _state_mask.clear();
+
   // want gsg to pass all state settings through
 
   _dx_is_ready = false;
@@ -5286,10 +5343,8 @@ void dx_set_stencil_functions (StencilRenderStates *stencil_render_states) {
 void DXGraphicsStateGuardian9::
 do_issue_stencil() {
 
-  const StencilAttrib *stencil;
   StencilRenderStates *stencil_render_states;
-
-  stencil = _target._stencil;
+  const StencilAttrib *stencil = DCAST(StencilAttrib, _target_rs->get_attrib_def(StencilAttrib::get_class_slot()));
   stencil_render_states = this -> _stencil_render_states;
   if (stencil && stencil_render_states) {
 
@@ -5362,7 +5417,8 @@ do_issue_stencil() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 do_issue_scissor() {
-  const LVecBase4f &frame = _target._scissor->get_frame();
+  const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
+  const LVecBase4f &frame = target_scissor->get_frame();
 
   RECT r;
   r.left = _current_viewport.X + _current_viewport.Width * frame[0];

+ 1 - 0
panda/src/dxgsg9/dxGraphicsStateGuardian9.h

@@ -26,6 +26,7 @@
 #include "depthTestAttrib.h"
 #include "cullFaceAttrib.h"
 #include "renderModeAttrib.h"
+#include "colorBlendAttrib.h"
 #include "fog.h"
 #include "pointerToArray.h"
 

+ 6 - 6
panda/src/dxgsg9/dxShaderContext9.cxx

@@ -469,8 +469,8 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
           }        
           InternalName *name = _shader->_var_spec[i]._name;
           int texslot = _shader->_var_spec[i]._append_uv;
-          if (texslot >= 0 && texslot < gsg->_state._texture->get_num_on_stages()) {
-            TextureStage *stage = gsg->_state._texture->get_on_stage(texslot);
+          if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) {
+            TextureStage *stage = gsg->_state_texture->get_on_stage(texslot);
             InternalName *texname = stage->get_texcoord_name();
             if (name == InternalName::get_texcoord()) {
               name = texname;
@@ -697,14 +697,14 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg)
       Texture *tex = 0;
       InternalName *id = _shader->_tex_spec[i]._name;
       if (id != 0) {
-        const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
+        const ShaderInput *input = gsg->_target_shader->get_shader_input(id);
         tex = input->get_texture();
       } else {
-        if (_shader->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
+        if (_shader->_tex_spec[i]._stage >= gsg->_target_texture->get_num_on_stages()) {
           continue;
         }
-        TextureStage *stage = gsg->_target._texture->get_on_stage(_shader->_tex_spec[i]._stage);
-        tex = gsg->_target._texture->get_on_texture(stage);
+        TextureStage *stage = gsg->_target_texture->get_on_stage(_shader->_tex_spec[i]._stage);
+        tex = gsg->_target_texture->get_on_texture(stage);
       }
       if (_shader->_tex_spec[i]._suffix != 0) {
         // The suffix feature is inefficient. It is a temporary hack.

+ 2 - 2
panda/src/glstuff/glGeomMunger_src.cxx

@@ -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(state->get_texture()),
-  _tex_gen(state->get_tex_gen())
+  _texture(DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()))),
+  _tex_gen(DCAST(TexGenAttrib, state->get_attrib(TexGenAttrib::get_class_slot())))
 {
   // Set a callback to unregister ourselves when either the Texture or
   // the TexGen object gets deleted.

+ 1 - 1
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -523,7 +523,7 @@ generate_mipmaps() {
   for (int slot=0; slot<RTP_COUNT; slot++) {
     Texture *tex = _tex[slot];
     if ((tex != 0) && (tex->uses_mipmaps())) {
-      glgsg->_state._texture = 0;
+      glgsg->_state_texture = 0;
       TextureContext *tc = tex->prepare_now(glgsg->get_prepared_objects(), glgsg);
       nassertv(tc != (TextureContext *)NULL);
       CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);

+ 2 - 2
panda/src/glstuff/glGraphicsStateGuardian_src.I

@@ -245,7 +245,7 @@ enable_multisample_alpha_mask(bool val) {
 INLINE void CLP(GraphicsStateGuardian)::
 enable_line_smooth(bool val) {
   if (_line_smooth_enabled != val) {
-    _state._transparency = 0;
+    _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
     _line_smooth_enabled = val;
     if (val) {
       GLP(Enable)(GL_LINE_SMOOTH);
@@ -263,7 +263,7 @@ enable_line_smooth(bool val) {
 INLINE void CLP(GraphicsStateGuardian)::
 enable_point_smooth(bool val) {
   if (_point_smooth_enabled != val) {
-    _state._transparency = 0;
+    _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
     _point_smooth_enabled = val;
     if (val) {
       GLP(Enable)(GL_POINT_SMOOTH);

+ 274 - 207
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -31,7 +31,6 @@
 #include "pointLight.h"
 #include "spotlight.h"
 #include "planeNode.h"
-#include "attribSlots.h"
 #include "fog.h"
 #include "clockObject.h"
 #include "string_utils.h"
@@ -48,6 +47,18 @@
 #include "load_prc_file.h"
 #include "bamCache.h"
 #include "bamCacheRecord.h"
+#include "colorWriteAttrib.h"
+#include "depthWriteAttrib.h"
+#include "shadeModelAttrib.h"
+#include "rescaleNormalAttrib.h"
+#include "alphaTestAttrib.h"
+#include "cullFaceAttrib.h"
+#include "fogAttrib.h"
+#include "depthOffsetAttrib.h"
+#include "materialAttrib.h"
+#include "stencilAttrib.h"
+#include "lightAttrib.h"
+#include "scissorAttrib.h"
 
 #ifdef HAVE_CG
 #include "Cg/cgGL.h"
@@ -1400,16 +1411,20 @@ clear(DrawableRegion *clearable) {
       GLP(Clear)(GL_COLOR_BUFFER_BIT);
     }
   }
-  
+
   if (clearable->get_clear_color_active()) {
     Colorf v = clearable->get_clear_color();
     GLP(ClearColor)(v[0],v[1],v[2],v[3]);
+    GLP(ColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    _state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
     mask |= GL_COLOR_BUFFER_BIT;
     set_draw_buffer(clearable->get_draw_buffer_type());
   }
   
   if (clearable->get_clear_depth_active()) {
     GLP(ClearDepth)(clearable->get_clear_depth());
+    GLP(DepthMask)(GL_TRUE);
+    _state_mask.clear_bit(DepthWriteAttrib::get_class_slot());
     mask |= GL_DEPTH_BUFFER_BIT;
   }
 
@@ -1426,7 +1441,7 @@ clear(DrawableRegion *clearable) {
   // change the draw buffer.  In time, I think there will need
   // to be a draw buffer attrib.  Until then, this little hack
   // to put things back the way they were after
-  // prepare_display_region will bdo.
+  // prepare_display_region will do.
   
   set_draw_buffer(_draw_buffer_type);
 
@@ -1754,13 +1769,17 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     case GeomPrimitive::PT_none:
       break;
     }
-    if ((_target._transparency != _state._transparency)||
-        (_target._color_write != _state._color_write)||
-        (_target._color_blend != _state._color_blend)) {
+
+    int transparency_slot = TransparencyAttrib::get_class_slot();
+    int color_write_slot = ColorWriteAttrib::get_class_slot();
+    int color_blend_slot = ColorBlendAttrib::get_class_slot();
+    if (!_state_mask.get_bit(transparency_slot) ||
+        !_state_mask.get_bit(color_write_slot) ||
+        !_state_mask.get_bit(color_blend_slot)) {
       do_issue_blending();
-      _state._transparency = _target._transparency;
-      _state._color_write = _target._color_write;
-      _state._color_blend = _target._color_blend;
+      _state_mask.set_bit(transparency_slot);
+      _state_mask.set_bit(color_write_slot);
+      _state_mask.set_bit(color_blend_slot);
     }
   }
 
@@ -2011,11 +2030,11 @@ update_standard_vertex_arrays(bool force) {
     // Now set up each of the active texture coordinate stages--or at
     // least those for which we're not generating texture coordinates
     // automatically.
-    int max_stage_index = _effective_texture->get_num_on_ff_stages();
+    int max_stage_index = _target_texture->get_num_on_ff_stages();
     int stage_index = 0;
     while (stage_index < max_stage_index) {
-      TextureStage *stage = _effective_texture->get_on_ff_stage(stage_index);
-      if (!_effective_tex_gen->has_gen_texcoord_stage(stage)) {
+      TextureStage *stage = _target_texture->get_on_ff_stage(stage_index);
+      if (!_target_tex_gen->has_gen_texcoord_stage(stage)) {
         // This stage is not one of the stages that doesn't need
         // texcoords issued for it.
         const InternalName *name = stage->get_texcoord_name();
@@ -2107,12 +2126,12 @@ update_standard_vertex_arrays(bool force) {
     // Now set up each of the active texture coordinate stages--or at
     // least those for which we're not generating texture coordinates
     // automatically.
-    int max_stage_index = _effective_texture->get_num_on_ff_stages();
+    int max_stage_index = _target_texture->get_num_on_ff_stages();
     int stage_index = 0;
     while (stage_index < max_stage_index) {
       _glClientActiveTexture(GL_TEXTURE0 + stage_index);
-      TextureStage *stage = _effective_texture->get_on_ff_stage(stage_index);
-      if (!_effective_tex_gen->has_gen_texcoord_stage(stage)) {
+      TextureStage *stage = _target_texture->get_on_ff_stage(stage_index);
+      if (!_target_tex_gen->has_gen_texcoord_stage(stage)) {
         // This stage is not one of the stages that doesn't need
         // texcoords issued for it.
         const InternalName *name = stage->get_texcoord_name();
@@ -2250,7 +2269,7 @@ disable_standard_vertex_arrays()
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
 draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
+  //PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
@@ -2299,7 +2318,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
 draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
+  //PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 
   report_my_gl_errors();
 
@@ -2390,7 +2409,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
 draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
+  //PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam() << "draw_trifans: " << *(reader->get_object()) << "\n";
@@ -2451,7 +2470,7 @@ draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
 draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
+  //PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam() << "draw_lines: " << *(reader->get_object()) << "\n";
@@ -2507,7 +2526,7 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
 draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
-  PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
+  //PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam() << "draw_points: " << *(reader->get_object()) << "\n";
@@ -3366,8 +3385,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
   report_my_gl_errors();
 
   // Force reload of texture state, since we've just monkeyed with it.
-  _state_rs = 0;
-  _state._texture = 0;
+  _state_mask.clear_bit(TextureAttrib::get_class_slot());
 
   return true;
 }
@@ -3585,8 +3603,8 @@ do_issue_transform() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_shade_model() {
-  const ShadeModelAttrib *attrib = _target._shade_model;
-  switch (attrib->get_mode()) {
+  const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()));
+  switch (target_shade_model->get_mode()) {
   case ShadeModelAttrib::M_smooth:
     GLP(ShadeModel)(GL_SMOOTH);
     _flat_shade_model = false;
@@ -3607,10 +3625,7 @@ do_issue_shade_model() {
 void CLP(GraphicsStateGuardian)::
 do_issue_shader() {
   CLP(ShaderContext) *context = 0;
-  Shader *shader = 0;
-  if (_target._shader) {
-    shader = (Shader *)(_target._shader->get_shader());
-  }
+  Shader *shader = (Shader *)(_target_shader->get_shader());
   if (shader) {
     context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));
   }
@@ -3647,10 +3662,10 @@ do_issue_shader() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_render_mode() {
-  const RenderModeAttrib *attrib = _target._render_mode;
-  _render_mode = attrib->get_mode();
-  _point_size = attrib->get_thickness();
-  _point_perspective = attrib->get_perspective();
+  const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()));
+  _render_mode = target_render_mode->get_mode();
+  _point_size = target_render_mode->get_thickness();
+  _point_perspective = target_render_mode->get_perspective();
 
   switch (_render_mode) {
   case RenderModeAttrib::M_unchanged:
@@ -3687,8 +3702,8 @@ do_issue_render_mode() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_antialias() {
-  const AntialiasAttrib *attrib = _target._antialias;
-  if (attrib->get_mode_type() == AntialiasAttrib::M_auto) {
+  const AntialiasAttrib *target_antialias = DCAST(AntialiasAttrib, _target_rs->get_attrib_def(AntialiasAttrib::get_class_slot()));
+  if (target_antialias->get_mode_type() == AntialiasAttrib::M_auto) {
     // In this special mode, we must enable antialiasing on a
     // case-by-case basis, because we enable it differently for
     // polygons and for points and lines.
@@ -3700,7 +3715,7 @@ do_issue_antialias() {
     // don't use the other bits at all (they will be ignored by GL
     // anyway).
     _auto_antialias_mode = false;
-    unsigned short mode = attrib->get_mode();
+    unsigned short mode = target_antialias->get_mode();
 
     if (_supports_multisample &&
         (mode & AntialiasAttrib::M_multisample) != 0) {
@@ -3714,7 +3729,7 @@ do_issue_antialias() {
     }
   }
 
-  switch (attrib->get_mode_quality()) {
+  switch (target_antialias->get_mode_quality()) {
   case AntialiasAttrib::M_faster:
     GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_FASTEST);
     GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_FASTEST);
@@ -3744,8 +3759,8 @@ do_issue_antialias() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_rescale_normal() {
-  const RescaleNormalAttrib *attrib = _target._rescale_normal;
-  RescaleNormalAttrib::Mode mode = attrib->get_mode();
+  const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()));
+  RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
 
   _auto_rescale_normal = false;
 
@@ -3795,8 +3810,8 @@ do_issue_rescale_normal() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_depth_test() {
-  const DepthTestAttrib *attrib = _target._depth_test;
-  DepthTestAttrib::PandaCompareFunc mode = attrib->get_mode();
+  const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
+  DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode();
   if (mode == DepthTestAttrib::M_none) {
     enable_depth_test(false);
   } else {
@@ -3813,16 +3828,16 @@ do_issue_depth_test() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_alpha_test() {
-  if (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
+  if (_target_shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
     enable_alpha_test(false);
   } else {
-    const AlphaTestAttrib *attrib = _target._alpha_test;
-    AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
+    const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
+    AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode();
     if (mode == AlphaTestAttrib::M_none) {
       enable_alpha_test(false);
     } else {
-      assert(GL_NEVER==(AlphaTestAttrib::M_never-1+0x200));
-      GLP(AlphaFunc)(PANDA_TO_GL_COMPAREFUNC(mode), attrib->get_reference_alpha());
+      nassertv(GL_NEVER == (AlphaTestAttrib::M_never-1+0x200));
+      GLP(AlphaFunc)(PANDA_TO_GL_COMPAREFUNC(mode), target_alpha_test->get_reference_alpha());
       enable_alpha_test(true);
     }
   }
@@ -3835,8 +3850,8 @@ do_issue_alpha_test() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_depth_write() {
-  const DepthWriteAttrib *attrib = _target._depth_write;
-  DepthWriteAttrib::Mode mode = attrib->get_mode();
+  const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
+  DepthWriteAttrib::Mode mode = target_depth_write->get_mode();
   if (mode == DepthWriteAttrib::M_off) {
     GLP(DepthMask)(GL_FALSE);
   } else {
@@ -3852,8 +3867,8 @@ do_issue_depth_write() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_cull_face() {
-  const CullFaceAttrib *attrib = _target._cull_face;
-  CullFaceAttrib::Mode mode = attrib->get_effective_mode();
+  const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()));
+  CullFaceAttrib::Mode mode = target_cull_face->get_effective_mode();
 
   switch (mode) {
   case CullFaceAttrib::M_cull_none:
@@ -3882,10 +3897,10 @@ do_issue_cull_face() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_fog() {
-  const FogAttrib *attrib = _target._fog;
-  if (!attrib->is_off()) {
+  const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
+  if (!target_fog->is_off()) {
     enable_fog(true);
-    Fog *fog = attrib->get_fog();
+    Fog *fog = target_fog->get_fog();
     nassertv(fog != (Fog *)NULL);
     apply_fog(fog);
   } else {
@@ -3901,8 +3916,8 @@ do_issue_fog() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_depth_offset() {
-  const DepthOffsetAttrib *attrib = _target._depth_offset;
-  int offset = attrib->get_offset();
+  const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
+  int offset = target_depth_offset->get_offset();
 
   if (offset != 0) {
     // The relationship between these two parameters is a little
@@ -3926,11 +3941,14 @@ void CLP(GraphicsStateGuardian)::
 do_issue_material() {
   static Material empty;
   const Material *material;
-  if (_target._material == (MaterialAttrib *)NULL ||
-      _target._material->is_off()) {
+
+  const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
+
+  if (target_material == (MaterialAttrib *)NULL ||
+      target_material->is_off()) {
     material = &empty;
   } else {
-    material = _target._material->get_material();
+    material = target_material->get_material();
   }
 
   GLenum face = material->get_twoside() ? GL_FRONT_AND_BACK : GL_FRONT;
@@ -3995,47 +4013,46 @@ do_issue_material() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_blending() {
-
   // Handle the color_write attrib.  If color_write is off, then
   // all the other blending-related stuff doesn't matter.  If the
   // device doesn't support color-write, we use blending tricks
   // to effectively disable color write.
+  const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
+
   unsigned int color_channels =
-    _target._color_write->get_channels() & _color_write_mask;
-  if (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
+    target_color_write->get_channels() & _color_write_mask;
+  if (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
     color_channels &= ~(ColorWriteAttrib::C_alpha);
   }
   if (color_channels == ColorWriteAttrib::C_off) {
-    if (_target._color_write != _state._color_write) {
-      enable_multisample_alpha_one(false);
-      enable_multisample_alpha_mask(false);
-      if (CLP(color_mask)) {
-        enable_blend(false);
-        GLP(ColorMask)(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-      } else {
-        enable_blend(true);
-        _glBlendEquation(GL_FUNC_ADD);
-        GLP(BlendFunc)(GL_ZERO, GL_ONE);
-      }
+    int color_write_slot = ColorWriteAttrib::get_class_slot();
+    enable_multisample_alpha_one(false);
+    enable_multisample_alpha_mask(false);
+    if (CLP(color_mask)) {
+      enable_blend(false);
+      GLP(ColorMask)(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+    } else {
+      enable_blend(true);
+      _glBlendEquation(GL_FUNC_ADD);
+      GLP(BlendFunc)(GL_ZERO, GL_ONE);
     }
     return;
   } else {
-    if ((_target._color_write != _state._color_write)||
-        (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != 
-         _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
-      if (CLP(color_mask)) {
-        GLP(ColorMask)((color_channels & ColorWriteAttrib::C_red) != 0,
-                       (color_channels & ColorWriteAttrib::C_green) != 0,
-                       (color_channels & ColorWriteAttrib::C_blue) != 0,
-                       (color_channels & ColorWriteAttrib::C_alpha) != 0);
-      }
+    if (CLP(color_mask)) {
+      GLP(ColorMask)((color_channels & ColorWriteAttrib::C_red) != 0,
+                     (color_channels & ColorWriteAttrib::C_green) != 0,
+                     (color_channels & ColorWriteAttrib::C_blue) != 0,
+                     (color_channels & ColorWriteAttrib::C_alpha) != 0);
     }
   }
 
 
-  CPT(ColorBlendAttrib) color_blend = _target._color_blend;
-  ColorBlendAttrib::Mode color_blend_mode = _target._color_blend->get_mode();
-  TransparencyAttrib::Mode transparency_mode = _target._transparency->get_mode();
+  const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
+  CPT(ColorBlendAttrib) color_blend = target_color_blend;
+  ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode();
+
+  const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
+  TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode();
 
   _color_blend_involves_color_scale = color_blend->involves_color_scale();
 
@@ -4131,8 +4148,8 @@ do_issue_blending() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
-  static PStatCollector _draw_set_state_light_bind_point_pcollector("Draw:Set State:Light:Bind:Point");
-  PStatTimer timer(_draw_set_state_light_bind_point_pcollector);
+  //  static PStatCollector _draw_set_state_light_bind_point_pcollector("Draw:Set State:Light:Bind:Point");
+  //  PStatTimer timer(_draw_set_state_light_bind_point_pcollector);
   
   float light_color[4];
   GLenum id = get_light_id(light_id);
@@ -4175,8 +4192,8 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
-  static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
-  PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
+  //  static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
+  //  PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
 
   pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, DirectionalLightFrameData()));
   DirectionalLightFrameData &fdata = (*lookup.first).second;
@@ -4226,8 +4243,8 @@ bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
-  static PStatCollector _draw_set_state_light_bind_spotlight_pcollector("Draw:Set State:Light:Bind:Spotlight");
-  PStatTimer timer(_draw_set_state_light_bind_spotlight_pcollector);
+  //  static PStatCollector _draw_set_state_light_bind_spotlight_pcollector("Draw:Set State:Light:Bind:Spotlight");
+  //  PStatTimer timer(_draw_set_state_light_bind_spotlight_pcollector);
   
   Lens *lens = light_obj->get_lens();
   nassertv(lens != (Lens *)NULL);
@@ -5723,8 +5740,8 @@ get_light_color(float light_color[4], Light *light) const {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 enable_lighting(bool enable) {
-  static PStatCollector _draw_set_state_light_enable_lighting_pcollector("Draw:Set State:Light:Enable lighting");
-  PStatTimer timer(_draw_set_state_light_enable_lighting_pcollector);
+  //  static PStatCollector _draw_set_state_light_enable_lighting_pcollector("Draw:Set State:Light:Enable lighting");
+  //  PStatTimer timer(_draw_set_state_light_enable_lighting_pcollector);
   
   if (enable) {
     GLP(Enable)(GL_LIGHTING);
@@ -5743,8 +5760,8 @@ enable_lighting(bool enable) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 set_ambient_light(const Colorf &color) {
-  static PStatCollector _draw_set_state_light_ambient_pcollector("Draw:Set State:Light:Ambient");
-  PStatTimer timer(_draw_set_state_light_ambient_pcollector);
+  //  static PStatCollector _draw_set_state_light_ambient_pcollector("Draw:Set State:Light:Ambient");
+  //  PStatTimer timer(_draw_set_state_light_ambient_pcollector);
   
   Colorf c = color;
   c.set(c[0] * _light_color_scale[0],
@@ -5763,8 +5780,8 @@ set_ambient_light(const Colorf &color) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 enable_light(int light_id, bool enable) {
-  static PStatCollector _draw_set_state_light_enable_light_pcollector("Draw:Set State:Light:Enable light");
-  PStatTimer timer(_draw_set_state_light_enable_light_pcollector);
+  //  static PStatCollector _draw_set_state_light_enable_light_pcollector("Draw:Set State:Light:Enable light");
+  //  PStatTimer timer(_draw_set_state_light_enable_light_pcollector);
   
   if (enable) {
     GLP(Enable)(get_light_id(light_id));
@@ -5787,8 +5804,8 @@ enable_light(int light_id, bool enable) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 begin_bind_lights() {
-  static PStatCollector _draw_set_state_light_begin_bind_pcollector("Draw:Set State:Light:Begin bind");
-  PStatTimer timer(_draw_set_state_light_begin_bind_pcollector);
+  //  static PStatCollector _draw_set_state_light_begin_bind_pcollector("Draw:Set State:Light:Begin bind");
+  //  PStatTimer timer(_draw_set_state_light_begin_bind_pcollector);
   
   // We need to temporarily load a new matrix so we can define the
   // light in a known coordinate system.  We pick the transform of the
@@ -5816,8 +5833,8 @@ begin_bind_lights() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 end_bind_lights() {
-  static PStatCollector _draw_set_state_light_end_bind_pcollector("Draw:Set State:Light:End bind");
-  PStatTimer timer(_draw_set_state_light_end_bind_pcollector);
+  //  static PStatCollector _draw_set_state_light_end_bind_pcollector("Draw:Set State:Light:End bind");
+  //  PStatTimer timer(_draw_set_state_light_end_bind_pcollector);
   
   GLP(MatrixMode)(GL_MODELVIEW);
   GLP(PopMatrix)();
@@ -5938,7 +5955,7 @@ set_state_and_transform(const RenderState *target,
   PStatTimer timer1(_draw_set_state_pcollector);
 
   if (transform != _internal_transform) {
-    PStatTimer timer(_draw_set_state_transform_pcollector);
+    //PStatTimer timer(_draw_set_state_transform_pcollector);
     _state_pcollector.add_level(1);
     _internal_transform = transform;
     do_issue_transform();
@@ -5948,177 +5965,225 @@ set_state_and_transform(const RenderState *target,
     return;
   }
   _target_rs = target;
-  _target.clear_to_defaults();
-  target->store_into_slots(&_target);
-  _state_rs = 0;
 
-  if (_target._shader && (_target._shader->auto_shader())) {
-    _target._shader = _target_rs->get_generated_shader();
+  _target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()));
+  if (_target_shader->auto_shader()) {
+    _target_shader = _target_rs->get_generated_shader();
   }
-  
-  if ((_target._alpha_test != _state._alpha_test)||
-      (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test) != 
-       _state._shader->get_flag(ShaderAttrib::F_subsume_alpha_test))) {
-    PStatTimer timer(_draw_set_state_alpha_test_pcollector);
+
+  int alpha_test_slot = AlphaTestAttrib::get_class_slot();
+  if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
+      !_state_mask.get_bit(alpha_test_slot) ||
+      (_target_shader->get_flag(ShaderAttrib::F_subsume_alpha_test) != 
+       _state_shader->get_flag(ShaderAttrib::F_subsume_alpha_test))) {
+    //PStatTimer timer(_draw_set_state_alpha_test_pcollector);
     do_issue_alpha_test();
-    _state._alpha_test = _target._alpha_test;
+    _state_mask.set_bit(alpha_test_slot);
   }
 
-  if (_target._antialias != _state._antialias) {
-    PStatTimer timer(_draw_set_state_antialias_pcollector);
+  int antialias_slot = AntialiasAttrib::get_class_slot();
+  if (_target_rs->get_attrib(antialias_slot) != _state_rs->get_attrib(antialias_slot) ||
+      !_state_mask.get_bit(antialias_slot)) {
+    //PStatTimer timer(_draw_set_state_antialias_pcollector);
     do_issue_antialias();
-    _state._antialias = _target._antialias;
+    _state_mask.set_bit(antialias_slot);
   }
 
-  if (_target._clip_plane != _state._clip_plane) {
-    PStatTimer timer(_draw_set_state_clip_plane_pcollector);
+  int clip_plane_slot = ClipPlaneAttrib::get_class_slot();
+  if (_target_rs->get_attrib(clip_plane_slot) != _state_rs->get_attrib(clip_plane_slot) ||
+      !_state_mask.get_bit(clip_plane_slot)) {
+    //PStatTimer timer(_draw_set_state_clip_plane_pcollector);
     do_issue_clip_plane();
-    _state._clip_plane = _target._clip_plane;
+    _state_mask.set_bit(clip_plane_slot);
   }
 
-  if (_target._color != _state._color ||
-      _target._color_scale != _state._color_scale) {
-    PStatTimer timer(_draw_set_state_color_pcollector);
+  int color_slot = ColorAttrib::get_class_slot();
+  int color_scale_slot = ColorScaleAttrib::get_class_slot();
+  if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
+      _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
+      !_state_mask.get_bit(color_slot) ||
+      !_state_mask.get_bit(color_scale_slot)) {
+    //PStatTimer timer(_draw_set_state_color_pcollector);
     do_issue_color();
     do_issue_color_scale();
-    _state._color = _target._color;
-    _state._color_scale = _target._color_scale;
-    if (_current_shader_context) {
-      _current_shader_context->issue_parameters(this, Shader::SSD_color);
-    }
+    _state_mask.set_bit(color_slot);
+    _state_mask.set_bit(color_scale_slot);
   }
 
-  if (_target._cull_face != _state._cull_face) {
-    PStatTimer timer(_draw_set_state_cull_face_pcollector);
+  int cull_face_slot = CullFaceAttrib::get_class_slot();
+  if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
+      !_state_mask.get_bit(cull_face_slot)) {
+    //PStatTimer timer(_draw_set_state_cull_face_pcollector);
     do_issue_cull_face();
-    _state._cull_face = _target._cull_face;
+    _state_mask.set_bit(cull_face_slot);
   }
 
-  if (_target._depth_offset != _state._depth_offset) {
-    PStatTimer timer(_draw_set_state_depth_offset_pcollector);
+  int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
+      !_state_mask.get_bit(depth_offset_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_offset_pcollector);
     do_issue_depth_offset();
-    _state._depth_offset = _target._depth_offset;
+    _state_mask.set_bit(depth_offset_slot);
   }
 
-  if (_target._depth_test != _state._depth_test) {
-    PStatTimer timer(_draw_set_state_depth_test_pcollector);
+  int depth_test_slot = DepthTestAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_test_slot) != _state_rs->get_attrib(depth_test_slot) ||
+      !_state_mask.get_bit(depth_test_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_test_pcollector);
     do_issue_depth_test();
-    _state._depth_test = _target._depth_test;
+    _state_mask.set_bit(depth_test_slot);
   }
 
-  if (_target._depth_write != _state._depth_write) {
-    PStatTimer timer(_draw_set_state_depth_write_pcollector);
+  int depth_write_slot = DepthWriteAttrib::get_class_slot();
+  if (_target_rs->get_attrib(depth_write_slot) != _state_rs->get_attrib(depth_write_slot) ||
+      !_state_mask.get_bit(depth_write_slot)) {
+    //PStatTimer timer(_draw_set_state_depth_write_pcollector);
     do_issue_depth_write();
-    _state._depth_write = _target._depth_write;
+    _state_mask.set_bit(depth_write_slot);
   }
 
-  if (_target._render_mode != _state._render_mode) {
-    PStatTimer timer(_draw_set_state_render_mode_pcollector);
+  int render_mode_slot = RenderModeAttrib::get_class_slot();
+  if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
+      !_state_mask.get_bit(render_mode_slot)) {
+    //PStatTimer timer(_draw_set_state_render_mode_pcollector);
     do_issue_render_mode();
-    _state._render_mode = _target._render_mode;
+    _state_mask.set_bit(render_mode_slot);
   }
-  
-  if (_target._rescale_normal != _state._rescale_normal) {
-    PStatTimer timer(_draw_set_state_rescale_normal_pcollector);
+
+  int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
+  if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
+      !_state_mask.get_bit(rescale_normal_slot)) {
+    //PStatTimer timer(_draw_set_state_rescale_normal_pcollector);
     do_issue_rescale_normal();
-    _state._rescale_normal = _target._rescale_normal;
+    _state_mask.set_bit(rescale_normal_slot);
   }
 
-  if (_target._shade_model != _state._shade_model) {
-    PStatTimer timer(_draw_set_state_shade_model_pcollector);
+  int shade_model_slot = ShadeModelAttrib::get_class_slot();
+  if (_target_rs->get_attrib(shade_model_slot) != _state_rs->get_attrib(shade_model_slot) ||
+      !_state_mask.get_bit(shade_model_slot)) {
+    //PStatTimer timer(_draw_set_state_shade_model_pcollector);
     do_issue_shade_model();
-    _state._shade_model = _target._shade_model;
-  }
-
-  if ((_target._transparency != _state._transparency)||
-      (_target._color_write != _state._color_write)||
-      (_target._color_blend != _state._color_blend)||
-      (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != 
-       _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
-    PStatTimer timer(_draw_set_state_blending_pcollector);
+    _state_mask.set_bit(shade_model_slot);
+  }
+
+  int transparency_slot = TransparencyAttrib::get_class_slot();
+  int color_write_slot = ColorWriteAttrib::get_class_slot();
+  int color_blend_slot = ColorBlendAttrib::get_class_slot();
+  if (_target_rs->get_attrib(transparency_slot) != _state_rs->get_attrib(transparency_slot) ||
+      _target_rs->get_attrib(color_write_slot) != _state_rs->get_attrib(color_write_slot) ||
+      _target_rs->get_attrib(color_blend_slot) != _state_rs->get_attrib(color_blend_slot) ||
+      !_state_mask.get_bit(transparency_slot) ||
+      !_state_mask.get_bit(color_write_slot) ||
+      !_state_mask.get_bit(color_blend_slot) ||
+      (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write) != 
+       _state_shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
+    //PStatTimer timer(_draw_set_state_blending_pcollector);
     do_issue_blending();
-    _state._transparency = _target._transparency;
-    _state._color_write = _target._color_write;
-    _state._color_blend = _target._color_blend;
+    _state_mask.set_bit(transparency_slot);
+    _state_mask.set_bit(color_write_slot);
+    _state_mask.set_bit(color_blend_slot);
   }
 
-  if (_target._shader != _state._shader) {
-    PStatTimer timer(_draw_set_state_shader_pcollector);
+  if (_target_shader != _state_shader) {
+    //PStatTimer timer(_draw_set_state_shader_pcollector);
     do_issue_shader();
-    _state._shader = _target._shader;
-    _state._texture = 0;
+    _state_shader = _target_shader;
+    _state_mask.clear_bit(TextureAttrib::get_class_slot());
   }
 
-  if (_target._texture != _state._texture) {
-    PStatTimer timer(_draw_set_state_texture_pcollector);
-    determine_effective_texture();
+  int texture_slot = TextureAttrib::get_class_slot();
+  if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
+      !_state_mask.get_bit(texture_slot)) {
+    //PStatTimer timer(_draw_set_state_texture_pcollector);
+    determine_target_texture();
     int prev_active = _num_active_texture_stages;
     do_issue_texture();
 
     // Since the TexGen and TexMatrix states depend partly on the
     // particular set of textures in use, we should force both of
     // those to be reissued every time we change the texture state.
-    _state._tex_gen = 0;
-    _state._tex_matrix = 0;
+    _state_mask.clear_bit(TexGenAttrib::get_class_slot());
+    _state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
 
-    _state._texture = _target._texture;
+    _state_texture = _target_texture;
+    _state_mask.set_bit(texture_slot);
   }
   
   // If one of the previously-loaded TexGen modes modified the texture
   // matrix, then if either state changed, we have to change both of
   // them now.
   if (_tex_gen_modifies_mat) {
-    if ((_target._tex_gen != _state._tex_gen) ||
-        (_target._tex_matrix != _state._tex_matrix)) {
-      _state._tex_matrix = 0;
-      _state._tex_gen = 0;
+    int tex_gen_slot = TexGenAttrib::get_class_slot();
+    int tex_matrix_slot = TexMatrixAttrib::get_class_slot();
+    if (_target_rs->get_attrib(tex_gen_slot) != _state_rs->get_attrib(tex_gen_slot) ||
+        _target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) ||
+        !_state_mask.get_bit(tex_gen_slot) ||
+        !_state_mask.get_bit(tex_matrix_slot)) {
+      _state_mask.clear_bit(tex_gen_slot);
+      _state_mask.clear_bit(tex_matrix_slot);
     }
   }
-  
-  if (_target._tex_matrix != _state._tex_matrix) {
-    PStatTimer timer(_draw_set_state_tex_matrix_pcollector);
+
+  int tex_matrix_slot = TexMatrixAttrib::get_class_slot();
+  if (_target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) ||
+      !_state_mask.get_bit(tex_matrix_slot)) {
+    //PStatTimer timer(_draw_set_state_tex_matrix_pcollector);
     do_issue_tex_matrix();
-    _state._tex_matrix = _target._tex_matrix;
+    _state_mask.set_bit(tex_matrix_slot);
   }
 
-  if (_effective_tex_gen != _state._tex_gen) {
-    PStatTimer timer(_draw_set_state_tex_gen_pcollector);
+  int tex_gen_slot = TexGenAttrib::get_class_slot();
+  if (_target_tex_gen != _state_tex_gen ||
+      !_state_mask.get_bit(tex_gen_slot)) {
+    //PStatTimer timer(_draw_set_state_tex_gen_pcollector);
     do_issue_tex_gen();
-    _state._tex_gen = _effective_tex_gen;
+    _state_tex_gen = _target_tex_gen;
+    _state_mask.set_bit(tex_gen_slot);
   }
-  
-  if (_target._material != _state._material) {
-    PStatTimer timer(_draw_set_state_material_pcollector);
+
+  int material_slot = MaterialAttrib::get_class_slot();
+  if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
+      !_state_mask.get_bit(material_slot)) {
+    //PStatTimer timer(_draw_set_state_material_pcollector);
     do_issue_material();
-    _state._material = _target._material;
+    _state_mask.set_bit(material_slot);
     if (_current_shader_context) {
       _current_shader_context->issue_parameters(this, Shader::SSD_material);
     }
   }
 
-  if (_target._light != _state._light) {
-    PStatTimer timer(_draw_set_state_light_pcollector);
+  int light_slot = LightAttrib::get_class_slot();
+  if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
+      !_state_mask.get_bit(light_slot)) {
+    //PStatTimer timer(_draw_set_state_light_pcollector);
     do_issue_light();
-    _state._light = _target._light;
+    _state_mask.set_bit(light_slot);
   }
 
-  if (_target._stencil != _state._stencil) {
-    PStatTimer timer(_draw_set_state_stencil_pcollector);
+  int stencil_slot = StencilAttrib::get_class_slot();
+  if (_target_rs->get_attrib(stencil_slot) != _state_rs->get_attrib(stencil_slot) ||
+      !_state_mask.get_bit(stencil_slot)) {
+    //PStatTimer timer(_draw_set_state_stencil_pcollector);
     do_issue_stencil();
-    _state._stencil = _target._stencil;
+    _state_mask.set_bit(stencil_slot);
   }
      
   if (_current_shader_context == 0) {
-    if (_target._fog != _state._fog) {
-      PStatTimer timer(_draw_set_state_fog_pcollector);
+    int fog_slot = FogAttrib::get_class_slot();
+    if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) ||
+        !_state_mask.get_bit(fog_slot)) {
+      //PStatTimer timer(_draw_set_state_fog_pcollector);
       do_issue_fog();
-      _state._fog = _target._fog;
+      _state_mask.set_bit(fog_slot);
     }
   }
 
-  if (_target._scissor != _state._scissor) {
+  int scissor_slot = ScissorAttrib::get_class_slot();
+  if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
+      !_state_mask.get_bit(scissor_slot)) {
+    //PStatTimer timer(_draw_set_state_scissor_pcollector);
     do_issue_scissor();
-    _state._scissor = _target._scissor;
+    _state_mask.set_bit(scissor_slot);
   }
 
   _state_rs = _target_rs;
@@ -6226,7 +6291,7 @@ do_issue_texture() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 update_standard_texture_bindings() {
-  int num_stages = _effective_texture->get_num_on_ff_stages();
+  int num_stages = _target_texture->get_num_on_ff_stages();
 
   nassertv(num_stages <= _max_texture_stages &&
            _num_active_texture_stages <= _max_texture_stages);
@@ -6237,8 +6302,8 @@ update_standard_texture_bindings() {
   int last_stage = -1;
   int i;
   for (i = 0; i < num_stages; i++) {
-    TextureStage *stage = _effective_texture->get_on_ff_stage(i);
-    Texture *texture = _effective_texture->get_on_texture(stage);
+    TextureStage *stage = _target_texture->get_on_ff_stage(i);
+    Texture *texture = _target_texture->get_on_texture(stage);
     nassertv(texture != (Texture *)NULL);
 
     // Issue the texture on stage i.
@@ -6450,12 +6515,14 @@ do_issue_tex_matrix() {
   nassertv(_num_active_texture_stages <= _max_texture_stages);
 
   for (int i = 0; i < _num_active_texture_stages; i++) {
-    TextureStage *stage = _effective_texture->get_on_ff_stage(i);
+    TextureStage *stage = _target_texture->get_on_ff_stage(i);
     _glActiveTexture(GL_TEXTURE0 + i);
 
     GLP(MatrixMode)(GL_TEXTURE);
-    if (_target._tex_matrix->has_stage(stage)) {
-      GLP(LoadMatrixf)(_target._tex_matrix->get_mat(stage).get_data());
+
+    const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
+    if (target_tex_matrix->has_stage(stage)) {
+      GLP(LoadMatrixf)(target_tex_matrix->get_mat(stage).get_data());
     } else {
       GLP(LoadIdentity)();
 
@@ -6497,7 +6564,7 @@ do_issue_tex_gen() {
   bool got_point_sprites = false;
 
   for (int i = 0; i < _num_active_texture_stages; i++) {
-    TextureStage *stage = _effective_texture->get_on_ff_stage(i);
+    TextureStage *stage = _target_texture->get_on_ff_stage(i);
     _glActiveTexture(GL_TEXTURE0 + i);
     GLP(Disable)(GL_TEXTURE_GEN_S);
     GLP(Disable)(GL_TEXTURE_GEN_T);
@@ -6507,7 +6574,7 @@ do_issue_tex_gen() {
       GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE);
     }
 
-    TexGenAttrib::Mode mode = _effective_tex_gen->get_mode(stage);
+    TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage);
     switch (mode) {
     case TexGenAttrib::M_off:
     case TexGenAttrib::M_light_vector:
@@ -6695,7 +6762,7 @@ do_issue_tex_gen() {
       // flattens the vertex position to zero and then adds our
       // desired value.
       {
-        const TexCoord3f &v = _effective_tex_gen->get_constant_value(stage);
+        const TexCoord3f &v = _target_tex_gen->get_constant_value(stage);
 
         GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
         GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
@@ -8149,10 +8216,9 @@ void gl_set_stencil_functions (StencilRenderStates *stencil_render_states) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_stencil() {
-  const StencilAttrib *stencil;
-  StencilRenderStates *stencil_render_states;
+  const StencilAttrib *stencil = DCAST(StencilAttrib, _target_rs->get_attrib_def(StencilAttrib::get_class_slot()));
 
-  stencil = _target._stencil;
+  StencilRenderStates *stencil_render_states;
   stencil_render_states = this -> _stencil_render_states;
   if (stencil && stencil_render_states) {
 
@@ -8226,7 +8292,8 @@ do_issue_stencil() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_scissor() {
-  const LVecBase4f &frame = _target._scissor->get_frame();
+  const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
+  const LVecBase4f &frame = target_scissor->get_frame();
 
   int x = (int)(_viewport_x + _viewport_width * frame[0] + 0.5f);
   int y = (int)(_viewport_y + _viewport_height * frame[2] + 0.5f);

+ 1 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -27,6 +27,7 @@
 #include "textureStage.h"
 #include "antialiasAttrib.h"
 #include "renderModeAttrib.h"
+#include "colorBlendAttrib.h"
 #include "pointerToArray.h"
 #include "fog.h"
 #include "graphicsWindow.h"

+ 6 - 6
panda/src/glstuff/glShaderContext_src.cxx

@@ -258,8 +258,8 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg,
       if (p == 0) continue;
       InternalName *name = _shader->_var_spec[i]._name;
       int texslot = _shader->_var_spec[i]._append_uv;
-      if (texslot >= 0 && texslot < gsg->_state._texture->get_num_on_stages()) {
-        TextureStage *stage = gsg->_state._texture->get_on_stage(texslot);
+      if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) {
+        TextureStage *stage = gsg->_state_texture->get_on_stage(texslot);
         InternalName *texname = stage->get_texcoord_name();
         if (name == InternalName::get_texcoord()) {
           name = texname;
@@ -351,14 +351,14 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) {
     Texture *tex = 0;
     InternalName *id = _shader->_tex_spec[i]._name;
     if (id != 0) {
-      const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
+      const ShaderInput *input = gsg->_target_shader->get_shader_input(id);
       tex = input->get_texture();
     } else {
-      if (_shader->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
+      if (_shader->_tex_spec[i]._stage >= gsg->_target_texture->get_num_on_stages()) {
         continue;
       }
-      TextureStage *stage = gsg->_target._texture->get_on_stage(_shader->_tex_spec[i]._stage);
-      tex = gsg->_target._texture->get_on_texture(stage);
+      TextureStage *stage = gsg->_target_texture->get_on_stage(_shader->_tex_spec[i]._stage);
+      tex = gsg->_target_texture->get_on_texture(stage);
     }
     if (_shader->_tex_spec[i]._suffix != 0) {
       // The suffix feature is inefficient. It is a temporary hack.

+ 15 - 14
panda/src/grutil/multitexReducer.cxx

@@ -29,6 +29,7 @@
 #include "colorAttrib.h"
 #include "colorScaleAttrib.h"
 #include "colorBlendAttrib.h"
+#include "alphaTestAttrib.h"
 #include "textureAttrib.h"
 #include "config_grutil.h"
 #include "config_gobj.h"
@@ -99,7 +100,7 @@ scan(PandaNode *node, const RenderState *state, const TransformState *transform)
   // operation, since the flattened texture will be applied to the
   // Geoms after the flatten() operation, and we don't want to still
   // have a multitexture specified.
-  node->set_state(node->get_state()->remove_attrib(TextureAttrib::get_class_type()));
+  node->set_state(node->get_state()->remove_attrib(TextureAttrib::get_class_slot()));
 
   if (node->is_geom_node()) {
     scan_geom_node(DCAST(GeomNode, node), next_state, next_transform);
@@ -376,7 +377,7 @@ flatten(GraphicsOutput *window) {
       
       CPT(RenderState) geom_state = 
         geom_info._geom_node->get_geom_state(geom_info._index);
-      int override = geom_info._geom_net_state->get_override(TextureAttrib::get_class_type());
+      int override = geom_info._geom_net_state->get_override(TextureAttrib::get_class_slot());
       geom_state = geom_state->add_attrib(new_ta, override);
 
       if (bake_in_color) {
@@ -389,7 +390,7 @@ flatten(GraphicsOutput *window) {
         // thing as a ColorScaleAttrib::make_off(), since that would
         // prohibit any future changes to the color scale.
         const RenderAttrib *attrib = 
-          geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_type());
+          geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_slot());
 
         if (attrib != (const RenderAttrib *)NULL) {
           geom_state = geom_state->add_attrib
@@ -400,7 +401,7 @@ flatten(GraphicsOutput *window) {
       // Determine what tex matrix should be on the Geom.
       CPT(TransformState) tex_mat = TransformState::make_identity();
 
-      const RenderAttrib *ra = geom_info._state->get_attrib(TexMatrixAttrib::get_class_type());
+      const RenderAttrib *ra = geom_info._state->get_attrib(TexMatrixAttrib::get_class_slot());
       if (ra != (const RenderAttrib *)NULL) {
         // There is a texture matrix inherited from above; put an
         // inverse matrix on the Geom to compensate.
@@ -415,7 +416,7 @@ flatten(GraphicsOutput *window) {
 
       if (tex_mat->is_identity()) {
         // There should be no texture matrix on the Geom.
-        geom_state = geom_state->remove_attrib(TexMatrixAttrib::get_class_type());
+        geom_state = geom_state->remove_attrib(TexMatrixAttrib::get_class_slot());
       } else {
         // The texture matrix should be as computed.
         CPT(RenderAttrib) new_tma = TexMatrixAttrib::make
@@ -437,7 +438,7 @@ flatten(GraphicsOutput *window) {
     const GeomNodeInfo &geom_node_info = (*gni);
     AccumulatedAttribs attribs;
     attribs._texture = 
-      geom_node_info._state->get_attrib(TextureAttrib::get_class_type());
+      geom_node_info._state->get_attrib(TextureAttrib::get_class_slot());
     geom_node_info._geom_node->apply_attribs_to_vertices
       (attribs, SceneGraphReducer::TT_tex_matrix, transformer);
   }
@@ -475,7 +476,7 @@ scan_geom_node(GeomNode *node, const RenderState *state,
     const RenderAttrib *attrib;
     const TextureAttrib *ta = NULL;
 
-    attrib = geom_net_state->get_attrib(TextureAttrib::get_class_type());
+    attrib = geom_net_state->get_attrib(TextureAttrib::get_class_slot());
     if (attrib != (const RenderAttrib *)NULL) {
       ta = DCAST(TextureAttrib, attrib);
     }
@@ -483,14 +484,14 @@ scan_geom_node(GeomNode *node, const RenderState *state,
     if (ta == (TextureAttrib *)NULL) {
       // No texture should be on the Geom.
       CPT(RenderState) geom_state = node->get_geom_state(gi);
-      geom_state = geom_state->remove_attrib(TextureAttrib::get_class_type());
+      geom_state = geom_state->remove_attrib(TextureAttrib::get_class_slot());
       node->set_geom_state(gi, geom_state);
 
     } else if (ta->get_num_on_stages() < 2) {
       // Just a single texture on the Geom; we don't really need to do
       // anything to flatten the textures, then.  But we should ensure
       // that the correct TextureAttrib is applied to the Geom.
-      int override = geom_net_state->get_override(TextureAttrib::get_class_type());
+      int override = geom_net_state->get_override(TextureAttrib::get_class_slot());
       CPT(RenderState) geom_state = node->get_geom_state(gi);
       geom_state = geom_state->add_attrib(ta, override);
       node->set_geom_state(gi, geom_state);
@@ -498,7 +499,7 @@ scan_geom_node(GeomNode *node, const RenderState *state,
     } else {
       // Ok, we have multitexture.  Record the Geom.
       CPT(TexMatrixAttrib) tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
-      attrib = geom_net_state->get_attrib(TexMatrixAttrib::get_class_type());
+      attrib = geom_net_state->get_attrib(TexMatrixAttrib::get_class_slot());
       if (attrib != (const RenderAttrib *)NULL) {
         tma = DCAST(TexMatrixAttrib, attrib);
       }
@@ -963,11 +964,11 @@ transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name,
     CPT(RenderState) geom_state = RenderState::make_empty();
     if (preserve_color) {
       // Be sure to preserve whatever colors are on the geom.
-      const RenderAttrib *ca = geom_info._geom_net_state->get_attrib(ColorAttrib::get_class_type());
+      const RenderAttrib *ca = geom_info._geom_net_state->get_attrib(ColorAttrib::get_class_slot());
       if (ca != (const RenderAttrib *)NULL) {
         geom_state = geom_state->add_attrib(ca);
       }
-      const RenderAttrib *csa = geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_type());
+      const RenderAttrib *csa = geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_slot());
       if (csa != (const RenderAttrib *)NULL) {
         geom_state = geom_state->add_attrib(csa);
       }
@@ -1002,7 +1003,7 @@ scan_color(const MultitexReducer::GeomList &geom_list, Colorf &geom_color,
     bool has_vertex_color = false;
 
     Colorf color_scale(1.0f, 1.0f, 1.0f, 1.0f);
-    const RenderAttrib *csa = geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_type());
+    const RenderAttrib *csa = geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_slot());
     if (csa != (const RenderAttrib *)NULL) {
       const ColorScaleAttrib *a = DCAST(ColorScaleAttrib, csa);
       if (a->has_scale()) {
@@ -1011,7 +1012,7 @@ scan_color(const MultitexReducer::GeomList &geom_list, Colorf &geom_color,
     }
 
     ColorAttrib::Type color_type = ColorAttrib::T_vertex;
-    const RenderAttrib *ca = geom_info._geom_net_state->get_attrib(ColorAttrib::get_class_type());
+    const RenderAttrib *ca = geom_info._geom_net_state->get_attrib(ColorAttrib::get_class_slot());
     if (ca != (const RenderAttrib *)NULL) {
       color_type = DCAST(ColorAttrib, ca)->get_color_type();
     }

+ 4 - 0
panda/src/grutil/pipeOcclusionCullTraverser.cxx

@@ -22,6 +22,10 @@
 #include "geomTristrips.h"
 #include "geomTriangles.h"
 #include "pStatTimer.h"
+#include "depthWriteAttrib.h"
+#include "depthTestAttrib.h"
+#include "colorWriteAttrib.h"
+#include "colorAttrib.h"
 #include "cullBinManager.h"
 #include "configVariableInt.h"
 #include "config_grutil.h"

+ 1 - 1
panda/src/osxdisplay/Sources.pp

@@ -1,4 +1,4 @@
-#define BUILD_DIRECTORY $[IS_OSX]
+#define BUILD_DIRECTORY $[and $[IS_OSX],$[HAVE_GL]]
 
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m prc:c 

+ 3 - 0
panda/src/osxdisplay/osxGraphicsStateGuardian.cxx

@@ -13,6 +13,9 @@
 #include "osxGraphicsBuffer.h"
 #include "string_utils.h"
 #include "config_osxdisplay.h"
+#include "depthWriteAttrib.h"
+#include "depthTestAttrib.h"
+#include "textureAttrib.h"
 #include "pnmImage.h"
 
 #include <OpenGL/gl.h>

+ 3 - 6
panda/src/pgraph/Sources.pp

@@ -17,7 +17,6 @@
     alphaTestAttrib.I alphaTestAttrib.h \  
     antialiasAttrib.I antialiasAttrib.h \
     attribNodeRegistry.I attribNodeRegistry.h \
-    attribSlots.h attribSlots.I \
     audioVolumeAttrib.I audioVolumeAttrib.h \
     auxSceneData.I auxSceneData.h \
     auxBitplaneAttrib.I auxBitplaneAttrib.h \
@@ -47,7 +46,6 @@
     depthOffsetAttrib.I depthOffsetAttrib.h \
     depthTestAttrib.I depthTestAttrib.h \
     depthWriteAttrib.I depthWriteAttrib.h \
-    drawMaskAttrib.I drawMaskAttrib.h \
     eventStorePandaNode.I eventStorePandaNode.h \
     fadeLodNode.I fadeLodNode.h \
     fadeLodNodeData.h \
@@ -87,6 +85,7 @@
     portalNode.I portalNode.h \
     portalClipper.I portalClipper.h \
     renderAttrib.I renderAttrib.h \
+    renderAttribRegistry.I renderAttribRegistry.h \
     renderEffect.I renderEffect.h \
     renderEffects.I renderEffects.h \
     renderModeAttrib.I renderModeAttrib.h \
@@ -124,7 +123,6 @@
     alphaTestAttrib.cxx \  
     antialiasAttrib.cxx \
     attribNodeRegistry.cxx \
-    attribSlots.cxx \
     audioVolumeAttrib.cxx \
     auxSceneData.cxx \
     bamFile.cxx \
@@ -152,7 +150,6 @@
     depthOffsetAttrib.cxx \
     depthTestAttrib.cxx \
     depthWriteAttrib.cxx \
-    drawMaskAttrib.cxx \
     eventStorePandaNode.cxx \
     fadeLodNode.cxx \
     fadeLodNodeData.cxx \
@@ -191,6 +188,7 @@
     portalNode.cxx \
     portalClipper.cxx \
     renderAttrib.cxx \
+    renderAttribRegistry.cxx \
     renderEffect.cxx \
     renderEffects.cxx \
     renderModeAttrib.cxx \
@@ -225,7 +223,6 @@
     alphaTestAttrib.I alphaTestAttrib.h \  
     antialiasAttrib.I antialiasAttrib.h \
     attribNodeRegistry.I attribNodeRegistry.h \
-    attribSlots.h attribSlots.I \
     audioVolumeAttrib.I audioVolumeAttrib.h \
     auxSceneData.I auxSceneData.h \
     auxBitplaneAttrib.I auxBitplaneAttrib.h \
@@ -255,7 +252,6 @@
     depthOffsetAttrib.I depthOffsetAttrib.h \
     depthTestAttrib.I depthTestAttrib.h \
     depthWriteAttrib.I depthWriteAttrib.h \
-    drawMaskAttrib.I drawMaskAttrib.h \
     eventStorePandaNode.I eventStorePandaNode.h \
     fadeLodNode.I fadeLodNode.h \
     fadeLodNodeData.h \
@@ -293,6 +289,7 @@
     portalNode.I portalNode.h \
     portalClipper.I portalClipper.h \
     renderAttrib.I renderAttrib.h \
+    renderAttribRegistry.I renderAttribRegistry.h \
     renderEffect.I renderEffect.h \
     renderEffects.I renderEffects.h \
     renderModeAttrib.I renderModeAttrib.h \

+ 22 - 22
panda/src/pgraph/accumulatedAttribs.cxx

@@ -172,9 +172,9 @@ collect(const RenderState *state, int attrib_types) {
 
   if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
     const RenderAttrib *node_attrib = 
-      new_state->get_attrib(ColorAttrib::get_class_type());
+      new_state->get_attrib(ColorAttrib::get_class_slot());
     if (node_attrib != (const RenderAttrib *)NULL) {
-      int color_override = new_state->get_override(ColorAttrib::get_class_type());
+      int color_override = new_state->get_override(ColorAttrib::get_class_slot());
       if (color_override >= _color_override || 
           _color == (const RenderAttrib *)NULL) {
         // The node has a color attribute; apply it.
@@ -185,15 +185,15 @@ collect(const RenderState *state, int attrib_types) {
         }
         _color_override = color_override;
       }
-      new_state = new_state->remove_attrib(ColorAttrib::get_class_type());
+      new_state = new_state->remove_attrib(ColorAttrib::get_class_slot());
     }
   }
 
   if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
     const RenderAttrib *node_attrib = 
-      new_state->get_attrib(ColorScaleAttrib::get_class_type());
+      new_state->get_attrib(ColorScaleAttrib::get_class_slot());
     if (node_attrib != (const RenderAttrib *)NULL) {
-      int color_scale_override = new_state->get_override(ColorScaleAttrib::get_class_type());
+      int color_scale_override = new_state->get_override(ColorScaleAttrib::get_class_slot());
       if (color_scale_override >= _color_scale_override ||
           _color_scale == (const RenderAttrib *)NULL) {
         if (_color_scale == (const RenderAttrib *)NULL) {
@@ -203,15 +203,15 @@ collect(const RenderState *state, int attrib_types) {
         }
         _color_scale_override = color_scale_override;
       }
-      new_state = new_state->remove_attrib(ColorScaleAttrib::get_class_type());
+      new_state = new_state->remove_attrib(ColorScaleAttrib::get_class_slot());
     }
   }
 
   if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
     const RenderAttrib *node_attrib = 
-      new_state->get_attrib(TexMatrixAttrib::get_class_type());
+      new_state->get_attrib(TexMatrixAttrib::get_class_slot());
     if (node_attrib != (const RenderAttrib *)NULL) {
-      int tex_matrix_override = new_state->get_override(TexMatrixAttrib::get_class_type());
+      int tex_matrix_override = new_state->get_override(TexMatrixAttrib::get_class_slot());
       if (tex_matrix_override >= _tex_matrix_override ||
           _tex_matrix == (const RenderAttrib *)NULL) {
         if (_tex_matrix == (const RenderAttrib *)NULL) {
@@ -221,15 +221,15 @@ collect(const RenderState *state, int attrib_types) {
         }
         _tex_matrix_override = tex_matrix_override;
       }
-      new_state = new_state->remove_attrib(TexMatrixAttrib::get_class_type());
+      new_state = new_state->remove_attrib(TexMatrixAttrib::get_class_slot());
     }
 
     // We also need to accumulate the texture state if we are
     // accumulating texture matrix.
     const RenderAttrib *tex_attrib = 
-      new_state->get_attrib(TextureAttrib::get_class_type());
+      new_state->get_attrib(TextureAttrib::get_class_slot());
     if (tex_attrib != (const RenderAttrib *)NULL) {
-      int texture_override = new_state->get_override(TextureAttrib::get_class_type());
+      int texture_override = new_state->get_override(TextureAttrib::get_class_slot());
       if (texture_override >= _texture_override || 
           _texture == (const RenderAttrib *)NULL) {
         if (_texture == (const RenderAttrib *)NULL) {
@@ -248,9 +248,9 @@ collect(const RenderState *state, int attrib_types) {
 
   if ((attrib_types & SceneGraphReducer::TT_clip_plane) != 0) {
     const RenderAttrib *node_attrib = 
-      new_state->get_attrib(ClipPlaneAttrib::get_class_type());
+      new_state->get_attrib(ClipPlaneAttrib::get_class_slot());
     if (node_attrib != (const RenderAttrib *)NULL) {
-      int clip_plane_override = new_state->get_override(ClipPlaneAttrib::get_class_type());
+      int clip_plane_override = new_state->get_override(ClipPlaneAttrib::get_class_slot());
       if (clip_plane_override >= _clip_plane_override || 
           _clip_plane == (const RenderAttrib *)NULL) {
         if (_clip_plane == (const RenderAttrib *)NULL) {
@@ -260,15 +260,15 @@ collect(const RenderState *state, int attrib_types) {
         }
         _clip_plane_override = clip_plane_override;
       }
-      new_state = new_state->remove_attrib(ClipPlaneAttrib::get_class_type());
+      new_state = new_state->remove_attrib(ClipPlaneAttrib::get_class_slot());
     }
   }
 
   if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
     const RenderAttrib *node_attrib = 
-      new_state->get_attrib(CullFaceAttrib::get_class_type());
+      new_state->get_attrib(CullFaceAttrib::get_class_slot());
     if (node_attrib != (const RenderAttrib *)NULL) {
-      int cull_face_override = new_state->get_override(CullFaceAttrib::get_class_type());
+      int cull_face_override = new_state->get_override(CullFaceAttrib::get_class_slot());
       if (cull_face_override >= _cull_face_override ||
           _cull_face == (const RenderAttrib *)NULL) {
         if (_cull_face == (const RenderAttrib *)NULL) {
@@ -278,7 +278,7 @@ collect(const RenderState *state, int attrib_types) {
         }
         _cull_face_override = cull_face_override;
       }
-      new_state = new_state->remove_attrib(CullFaceAttrib::get_class_type());
+      new_state = new_state->remove_attrib(CullFaceAttrib::get_class_slot());
     }
   }
 
@@ -312,7 +312,7 @@ apply_to_node(PandaNode *node, int attrib_types) {
   if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
     if (_color != (RenderAttrib *)NULL) {
       const RenderAttrib *node_attrib =
-        node->get_attrib(ColorAttrib::get_class_type());
+        node->get_attrib(ColorAttrib::get_class_slot());
       if (node_attrib != (RenderAttrib *)NULL) {
         node->set_attrib(_color->compose(node_attrib));
       } else {
@@ -325,7 +325,7 @@ apply_to_node(PandaNode *node, int attrib_types) {
   if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
     if (_color_scale != (RenderAttrib *)NULL) {
       const RenderAttrib *node_attrib =
-        node->get_attrib(ColorScaleAttrib::get_class_type());
+        node->get_attrib(ColorScaleAttrib::get_class_slot());
       if (node_attrib != (RenderAttrib *)NULL) {
         node->set_attrib(_color_scale->compose(node_attrib));
       } else {
@@ -338,7 +338,7 @@ apply_to_node(PandaNode *node, int attrib_types) {
   if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
     if (_tex_matrix != (RenderAttrib *)NULL) {
       const RenderAttrib *node_attrib =
-        node->get_attrib(TexMatrixAttrib::get_class_type());
+        node->get_attrib(TexMatrixAttrib::get_class_slot());
       if (node_attrib != (RenderAttrib *)NULL) {
         node->set_attrib(_tex_matrix->compose(node_attrib));
       } else {
@@ -351,7 +351,7 @@ apply_to_node(PandaNode *node, int attrib_types) {
   if ((attrib_types & SceneGraphReducer::TT_clip_plane) != 0) {
     if (_clip_plane != (RenderAttrib *)NULL) {
       const RenderAttrib *node_attrib =
-        node->get_attrib(ClipPlaneAttrib::get_class_type());
+        node->get_attrib(ClipPlaneAttrib::get_class_slot());
       if (node_attrib != (RenderAttrib *)NULL) {
         node->set_attrib(_clip_plane->compose(node_attrib));
       } else {
@@ -364,7 +364,7 @@ apply_to_node(PandaNode *node, int attrib_types) {
   if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
     if (_cull_face != (RenderAttrib *)NULL) {
       const RenderAttrib *node_attrib =
-        node->get_attrib(CullFaceAttrib::get_class_type());
+        node->get_attrib(CullFaceAttrib::get_class_slot());
       if (node_attrib != (RenderAttrib *)NULL) {
         node->set_attrib(_cull_face->compose(node_attrib));
       } else {

+ 13 - 28
panda/src/pgraph/alphaTestAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "alphaTestAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle AlphaTestAttrib::_type_handle;
+int AlphaTestAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: AlphaTestAttrib::make
@@ -35,6 +35,18 @@ make(PandaCompareFunc mode, float reference_value) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: AlphaTestAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AlphaTestAttrib::
+make_default() {
+  return return_new(new AlphaTestAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: AlphaTestAttrib::output
 //       Access: Public, Virtual
@@ -74,33 +86,6 @@ compare_to_impl(const RenderAttrib *other) const {
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: AlphaTestAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived AlphaTestAttrib
-//               types to specify what the default property for a
-//               AlphaTestAttrib of this type should be.
-//
-//               This should return a newly-allocated AlphaTestAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of AlphaTestAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *AlphaTestAttrib::
-make_default_impl() const {
-  return new AlphaTestAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AlphaTestAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void AlphaTestAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_alpha_test = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: AlphaTestAttrib::register_with_read_factory
 //       Access: Public, Static

+ 12 - 2
panda/src/pgraph/alphaTestAttrib.h

@@ -33,21 +33,29 @@ private:
 PUBLISHED:
   static CPT(RenderAttrib) make(PandaCompareFunc mode,
                                 float reference_alpha);
+  static CPT(RenderAttrib) make_default();
+
   INLINE float get_reference_alpha() const;
   INLINE PandaCompareFunc get_mode() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   PandaCompareFunc _mode;
   float _reference_alpha;  // should be in range [0.0-1.0]
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -64,6 +72,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "AlphaTestAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -72,6 +81,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "alphaTestAttrib.I"

+ 13 - 28
panda/src/pgraph/antialiasAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "antialiasAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle AntialiasAttrib::_type_handle;
+int AntialiasAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: AntialiasAttrib::make
@@ -65,6 +65,18 @@ make(unsigned short mode) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: AntialiasAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AntialiasAttrib::
+make_default() {
+  return return_new(new AntialiasAttrib(M_none));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: AntialiasAttrib::output
 //       Access: Public, Virtual
@@ -186,33 +198,6 @@ compose_impl(const RenderAttrib *other) const {
   return make(mode_type | mode_quality);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: AntialiasAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived AntialiasAttrib
-//               types to specify what the default property for a
-//               AntialiasAttrib of this type should be.
-//
-//               This should return a newly-allocated AntialiasAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of AntialiasAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *AntialiasAttrib::
-make_default_impl() const {
-  return new AntialiasAttrib(M_none);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AntialiasAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void AntialiasAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_antialias = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: AntialiasAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/antialiasAttrib.h

@@ -48,6 +48,7 @@ private:
 
 PUBLISHED:
   static CPT(RenderAttrib) make(unsigned short mode);
+  static CPT(RenderAttrib) make_default();
 
   INLINE unsigned short get_mode() const;
   INLINE unsigned short get_mode_type() const;
@@ -55,16 +56,22 @@ PUBLISHED:
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   unsigned short _mode;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -81,6 +88,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "AntialiasAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -89,6 +97,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "antialiasAttrib.I"

+ 0 - 74
panda/src/pgraph/attribSlots.I

@@ -1,74 +0,0 @@
-// Filename: attribSlots.I
-// Created by:  jyelon (01Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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: AttribSlots::clear_to_zero
-//       Access: Private
-//  Description: clears all values to zero.
-////////////////////////////////////////////////////////////////////
-INLINE void AttribSlots::
-clear_to_zero() {
-  _alpha_test     = NULL;
-  _antialias      = NULL;
-  _audio_volume   = NULL;
-  _aux_bitplane   = NULL;
-  _clip_plane     = NULL;
-  _color          = NULL;
-  _color_blend    = NULL;
-  _color_scale    = NULL;
-  _color_write    = NULL;
-  _cull_bin       = NULL;
-  _cull_face      = NULL;
-  _depth_offset   = NULL;
-  _depth_test     = NULL;
-  _depth_write    = NULL;
-  _fog            = NULL;
-  _light          = NULL;
-  _material       = NULL;
-  _render_mode    = NULL;
-  _rescale_normal = NULL;
-  _shade_model    = NULL;
-  _shader         = NULL;
-  _stencil        = NULL;
-  _tex_gen        = NULL;
-  _tex_matrix     = NULL;
-  _texture        = NULL;
-  _transparency   = NULL;
-  _scissor        = NULL;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::get_defaults
-//       Access: Public
-//  Description: Returns a set of slots containing all the default
-//               attribute values, as defined by make_default_impl.
-////////////////////////////////////////////////////////////////////
-INLINE const AttribSlots &AttribSlots::
-get_defaults() {
-  if (_defvals._alpha_test == 0) {
-    initialize_defvals();
-  }
-  return _defvals;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::clear_to_defaults
-//       Access: Private
-//  Description: clears all values to their default values.
-////////////////////////////////////////////////////////////////////
-INLINE void AttribSlots::
-clear_to_defaults() {
-  (*this) = get_defaults();
-}

+ 0 - 217
panda/src/pgraph/attribSlots.cxx

@@ -1,217 +0,0 @@
-// Filename: attribSlots.h
-// Created by:  jyelon (01Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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 "attribSlots.h"
-#include "renderAttrib.h"
-
-AttribSlots AttribSlots::_defvals;
-
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::clear_to_defaults
-//       Access: Private
-//  Description: clears all values to their initial defaults.
-////////////////////////////////////////////////////////////////////
-void AttribSlots::
-initialize_defvals() {
-
-  // Step one. Fill slots with any object of right type.
-  // the actual value is totally irrelevant.
-
-  _defvals._alpha_test     = DCAST(AlphaTestAttrib,AlphaTestAttrib::make(AlphaTestAttrib::M_none, 0.0));
-  _defvals._antialias      = DCAST(AntialiasAttrib,AntialiasAttrib::make(AntialiasAttrib::M_none));
-  _defvals._audio_volume   = DCAST(AudioVolumeAttrib,AudioVolumeAttrib::make_identity());
-  _defvals._aux_bitplane   = DCAST(AuxBitplaneAttrib,AuxBitplaneAttrib::make());
-  _defvals._clip_plane     = DCAST(ClipPlaneAttrib,ClipPlaneAttrib::make_all_off());
-  _defvals._color          = DCAST(ColorAttrib,ColorAttrib::make_off());
-  _defvals._color_blend    = DCAST(ColorBlendAttrib,ColorBlendAttrib::make_off());
-  _defvals._color_scale    = DCAST(ColorScaleAttrib,ColorScaleAttrib::make_off());
-  _defvals._color_write    = DCAST(ColorWriteAttrib,ColorWriteAttrib::make(ColorWriteAttrib::C_all));
-  _defvals._cull_bin       = DCAST(CullBinAttrib,CullBinAttrib::make("",0));
-  _defvals._cull_face      = DCAST(CullFaceAttrib,CullFaceAttrib::make(CullFaceAttrib::M_cull_counter_clockwise));
-  _defvals._depth_offset   = DCAST(DepthOffsetAttrib,DepthOffsetAttrib::make(0));
-  _defvals._depth_test     = DCAST(DepthTestAttrib,DepthTestAttrib::make(DepthTestAttrib::M_none));
-  _defvals._depth_write    = DCAST(DepthWriteAttrib,DepthWriteAttrib::make(DepthWriteAttrib::M_on));
-  _defvals._fog            = DCAST(FogAttrib,FogAttrib::make_off());
-  _defvals._light          = DCAST(LightAttrib,LightAttrib::make_all_off());
-  _defvals._light_ramp     = DCAST(LightRampAttrib,LightRampAttrib::make_identity());
-  _defvals._material       = DCAST(MaterialAttrib,MaterialAttrib::make_off());
-  _defvals._render_mode    = DCAST(RenderModeAttrib,RenderModeAttrib::make(RenderModeAttrib::M_unchanged));
-  _defvals._rescale_normal = DCAST(RescaleNormalAttrib,RescaleNormalAttrib::make_default());
-  _defvals._shade_model    = DCAST(ShadeModelAttrib,ShadeModelAttrib::make(ShadeModelAttrib::M_smooth));
-  _defvals._shader         = DCAST(ShaderAttrib,ShaderAttrib::make_off());
-  _defvals._stencil        = DCAST(StencilAttrib,StencilAttrib::make_off());
-  _defvals._tex_gen        = DCAST(TexGenAttrib,TexGenAttrib::make());
-  _defvals._tex_matrix     = DCAST(TexMatrixAttrib,TexMatrixAttrib::make());
-  _defvals._texture        = DCAST(TextureAttrib,TextureAttrib::make_all_off());
-  _defvals._transparency   = DCAST(TransparencyAttrib,TransparencyAttrib::make(TransparencyAttrib::M_none));
-  _defvals._scissor        = DCAST(ScissorAttrib, ScissorAttrib::make_off());
-
-  // Step two. Replace each with make_default_impl.
-
-  _defvals._alpha_test     = DCAST(AlphaTestAttrib,_defvals._alpha_test->make_default());
-  _defvals._antialias      = DCAST(AntialiasAttrib,_defvals._antialias->make_default());
-  _defvals._audio_volume   = DCAST(AudioVolumeAttrib,_defvals._audio_volume->make_default());
-  _defvals._aux_bitplane   = DCAST(AuxBitplaneAttrib,_defvals._aux_bitplane->make_default());
-  _defvals._clip_plane     = DCAST(ClipPlaneAttrib,_defvals._clip_plane->make_default());
-  _defvals._color          = DCAST(ColorAttrib,_defvals._color->make_default());
-  _defvals._color_blend    = DCAST(ColorBlendAttrib,_defvals._color_blend->make_default());
-  _defvals._color_scale    = DCAST(ColorScaleAttrib,_defvals._color_scale->make_default());
-  _defvals._color_write    = DCAST(ColorWriteAttrib,_defvals._color_write->make_default());
-  _defvals._cull_bin       = DCAST(CullBinAttrib,_defvals._cull_bin->make_default());
-  _defvals._cull_face      = DCAST(CullFaceAttrib,_defvals._cull_face->make_default());
-  _defvals._depth_offset   = DCAST(DepthOffsetAttrib,_defvals._depth_offset->make_default());
-  _defvals._depth_test     = DCAST(DepthTestAttrib,_defvals._depth_test->make_default());
-  _defvals._depth_write    = DCAST(DepthWriteAttrib,_defvals._depth_write->make_default());
-  _defvals._fog            = DCAST(FogAttrib,_defvals._fog->make_default());
-  _defvals._light          = DCAST(LightAttrib,_defvals._light->make_default());
-  _defvals._light_ramp     = DCAST(LightRampAttrib,_defvals._light_ramp->make_default());
-  _defvals._material       = DCAST(MaterialAttrib,_defvals._material->make_default());
-  _defvals._render_mode    = DCAST(RenderModeAttrib,_defvals._render_mode->make_default());
-  _defvals._rescale_normal = DCAST(RescaleNormalAttrib,_defvals._rescale_normal->make_default());
-  _defvals._shade_model    = DCAST(ShadeModelAttrib,_defvals._shade_model->make_default());
-  _defvals._shader         = DCAST(ShaderAttrib,_defvals._shader->make_default());
-  _defvals._stencil        = DCAST(StencilAttrib,_defvals._stencil->make_default());
-  _defvals._tex_gen        = DCAST(TexGenAttrib,_defvals._tex_gen->make_default());
-  _defvals._tex_matrix     = DCAST(TexMatrixAttrib,_defvals._tex_matrix->make_default());
-  _defvals._texture        = DCAST(TextureAttrib,_defvals._texture->make_default());
-  _defvals._transparency   = DCAST(TransparencyAttrib,_defvals._transparency->make_default());
-  _defvals._scissor        = DCAST(ScissorAttrib,_defvals._scissor->make_default());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::Default Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-AttribSlots::
-AttribSlots() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::Copy Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-AttribSlots::
-AttribSlots(const AttribSlots &copy) :
-  _alpha_test(copy._alpha_test),
-  _antialias(copy._antialias),
-  _audio_volume(copy._audio_volume),
-  _aux_bitplane(copy._aux_bitplane),
-  _clip_plane(copy._clip_plane),
-  _color(copy._color),
-  _color_blend(copy._color_blend),
-  _color_scale(copy._color_scale),
-  _color_write(copy._color_write),
-  _cull_bin(copy._cull_bin),
-  _cull_face(copy._cull_face),
-  _depth_offset(copy._depth_offset),
-  _depth_test(copy._depth_test),
-  _depth_write(copy._depth_write),
-  _fog(copy._fog),
-  _light(copy._light),
-  _light_ramp(copy._light_ramp),
-  _material(copy._material),
-  _render_mode(copy._render_mode),
-  _rescale_normal(copy._rescale_normal),
-  _shade_model(copy._shade_model),
-  _shader(copy._shader),
-  _stencil(copy._stencil),
-  _tex_gen(copy._tex_gen),
-  _tex_matrix(copy._tex_matrix),
-  _texture(copy._texture),
-  _transparency(copy._transparency),
-  _scissor(copy._scissor)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::Copy Assignment Operator
-//       Access: Public
-//  Description: copy all the slots from source.
-////////////////////////////////////////////////////////////////////
-void AttribSlots::
-operator =(const AttribSlots &src) {
-  _alpha_test     = src._alpha_test;
-  _antialias      = src._antialias;
-  _audio_volume   = src._audio_volume;
-  _aux_bitplane   = src._aux_bitplane;
-  _clip_plane     = src._clip_plane;
-  _color          = src._color;
-  _color_blend    = src._color_blend;
-  _color_scale    = src._color_scale;
-  _color_write    = src._color_write;
-  _cull_bin       = src._cull_bin;
-  _cull_face      = src._cull_face;
-  _depth_offset   = src._depth_offset;
-  _depth_test     = src._depth_test;
-  _depth_write    = src._depth_write;
-  _fog            = src._fog;
-  _light          = src._light;
-  _light_ramp     = src._light_ramp;
-  _material       = src._material;
-  _render_mode    = src._render_mode;
-  _rescale_normal = src._rescale_normal;
-  _shade_model    = src._shade_model;
-  _shader         = src._shader;
-  _stencil        = src._stencil;
-  _tex_gen        = src._tex_gen;
-  _tex_matrix     = src._tex_matrix;
-  _texture        = src._texture;
-  _transparency   = src._transparency;
-  _scissor        = src._scissor;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::get_slot
-//       Access: Public
-//  Description: fetch the contents of the nth slot.
-////////////////////////////////////////////////////////////////////
-const RenderAttrib *AttribSlots::
-get_slot(int n) const {
-  switch(n) {
-  case  0: return _alpha_test;
-  case  1: return _antialias;
-  case  2: return _audio_volume;
-  case  3: return _aux_bitplane;
-  case  4: return _clip_plane;
-  case  5: return _color;
-  case  6: return _color_blend;
-  case  7: return _color_scale;
-  case  8: return _color_write;
-  case  9: return _cull_bin;
-  case 10: return _cull_face;
-  case 11: return _depth_offset;
-  case 12: return _depth_test;
-  case 13: return _depth_write;
-  case 14: return _fog;
-  case 15: return _light;
-  case 16: return _light_ramp;
-  case 17: return _material;
-  case 18: return _render_mode;
-  case 19: return _rescale_normal;
-  case 20: return _shade_model;
-  case 21: return _shader;
-  case 22: return _stencil;
-  case 23: return _tex_gen;
-  case 24: return _tex_matrix;
-  case 25: return _texture;
-  case 26: return _transparency;
-  case 27: return _scissor;
-  default:
-    nassertr(false, NULL);
-    return NULL;
-  }
-}
-

+ 0 - 109
panda/src/pgraph/attribSlots.h

@@ -1,109 +0,0 @@
-// Filename: attribSlots.h
-// Created by:  jyelon (01Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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 ATTRIBSLOTS_H
-#define ATTRIBSLOTS_H
-
-#include "pandabase.h"
-#include "typedWritableReferenceCount.h"
-#include "pointerTo.h"
-
-#include "renderAttrib.h"
-#include "alphaTestAttrib.h"
-#include "antialiasAttrib.h"
-#include "audioVolumeAttrib.h"
-#include "auxBitplaneAttrib.h"
-#include "clipPlaneAttrib.h"
-#include "colorAttrib.h"
-#include "colorBlendAttrib.h"
-#include "colorScaleAttrib.h"
-#include "colorWriteAttrib.h"
-#include "cullBinAttrib.h"
-#include "cullFaceAttrib.h"
-#include "depthOffsetAttrib.h"
-#include "depthTestAttrib.h"
-#include "depthWriteAttrib.h"
-#include "fogAttrib.h"
-#include "lightAttrib.h"
-#include "lightRampAttrib.h"
-#include "materialAttrib.h"
-#include "renderModeAttrib.h"
-#include "rescaleNormalAttrib.h"
-#include "scissorAttrib.h"
-#include "shadeModelAttrib.h"
-#include "shaderAttrib.h"
-#include "stencilAttrib.h"
-#include "texMatrixAttrib.h"
-#include "texGenAttrib.h"
-#include "textureAttrib.h"
-#include "transparencyAttrib.h"
-
-////////////////////////////////////////////////////////////////////
-//       Class : AttribSlots
-// Description : This is a very simple class: an object full of
-//               render attributes, one per attrib type.
-////////////////////////////////////////////////////////////////////
-
-class EXPCL_PANDA_PGRAPH AttribSlots
-{
- public:
-  CPT(AlphaTestAttrib)       _alpha_test;
-  CPT(AntialiasAttrib)       _antialias;
-  CPT(AudioVolumeAttrib)     _audio_volume;
-  CPT(AuxBitplaneAttrib)     _aux_bitplane;
-  CPT(ClipPlaneAttrib)       _clip_plane;
-  CPT(ColorAttrib)           _color;
-  CPT(ColorBlendAttrib)      _color_blend;
-  CPT(ColorScaleAttrib)      _color_scale;
-  CPT(ColorWriteAttrib)      _color_write;
-  CPT(CullBinAttrib)         _cull_bin;
-  CPT(CullFaceAttrib)        _cull_face;
-  CPT(DepthOffsetAttrib)     _depth_offset;
-  CPT(DepthTestAttrib)       _depth_test;
-  CPT(DepthWriteAttrib)      _depth_write;
-  CPT(FogAttrib)             _fog;
-  CPT(LightAttrib)           _light;
-  CPT(LightRampAttrib)       _light_ramp;
-  CPT(MaterialAttrib)        _material;
-  CPT(RenderModeAttrib)      _render_mode;
-  CPT(RescaleNormalAttrib)   _rescale_normal;
-  CPT(ShadeModelAttrib)      _shade_model;
-  CPT(ShaderAttrib)          _shader;
-  CPT(StencilAttrib)         _stencil;
-  CPT(TexGenAttrib)          _tex_gen;
-  CPT(TexMatrixAttrib)       _tex_matrix;
-  CPT(TextureAttrib)         _texture;
-  CPT(TransparencyAttrib)    _transparency;
-  CPT(ScissorAttrib)         _scissor;
-
- public:
-  AttribSlots();
-  AttribSlots(const AttribSlots &copy);
-  INLINE void clear_to_zero();
-  INLINE void clear_to_defaults();
-  void operator =(const AttribSlots &src);
-  INLINE static const AttribSlots &get_defaults();
-
- public:
-  enum { slot_count=28 };
-  const RenderAttrib *get_slot(int n) const;
-
- private:
-  static AttribSlots _defvals;
-  static void initialize_defvals();
-};
-
-#include "attribSlots.I"
-
-#endif /* ATTRIBSLOTS_H */

+ 14 - 29
panda/src/pgraph/audioVolumeAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "audioVolumeAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,8 +21,9 @@
 #include "datagramIterator.h"
 #include "config_pgraph.h"
 
-TypeHandle AudioVolumeAttrib::_type_handle;
 CPT(RenderAttrib) AudioVolumeAttrib::_identity_attrib;
+TypeHandle AudioVolumeAttrib::_type_handle;
+int AudioVolumeAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: AudioVolumeAttrib::Constructor
@@ -84,6 +84,18 @@ make_off() {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: AudioVolumeAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AudioVolumeAttrib::
+make_default() {
+  return return_new(new AudioVolumeAttrib(false, 1.0f));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: AudioVolumeAttrib::set_volume
 //       Access: Published
@@ -210,33 +222,6 @@ invert_compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: AudioVolumeAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived AudioVolumeAttrib
-//               types to specify what the default property for a
-//               AudioVolumeAttrib of this type should be.
-//
-//               This should return a newly-allocated AudioVolumeAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of AudioVolumeAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *AudioVolumeAttrib::
-make_default_impl() const {
-  return new AudioVolumeAttrib(false, 1.0f);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AudioVolumeAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void AudioVolumeAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_audio_volume = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: AudioVolumeAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/audioVolumeAttrib.h

@@ -36,6 +36,7 @@ PUBLISHED:
   static CPT(RenderAttrib) make_identity();
   static CPT(RenderAttrib) make(float volume);
   static CPT(RenderAttrib) make_off();
+  static CPT(RenderAttrib) make_default();
 
   INLINE bool is_off() const;
   INLINE bool has_volume() const;
@@ -44,13 +45,11 @@ PUBLISHED:
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   bool _off;
@@ -58,6 +57,14 @@ private:
   float _volume;
   static CPT(RenderAttrib) _identity_attrib;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -74,6 +81,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "AudioVolumeAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -82,6 +90,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "audioVolumeAttrib.I"

+ 13 - 28
panda/src/pgraph/auxBitplaneAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "auxBitplaneAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle AuxBitplaneAttrib::_type_handle;
+int AuxBitplaneAttrib::_attrib_slot;
 CPT(RenderAttrib) AuxBitplaneAttrib::_default;
 
 ////////////////////////////////////////////////////////////////////
@@ -49,6 +49,18 @@ make(int outputs) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AuxBitplaneAttrib::
+make_default() {
+  return return_new(new AuxBitplaneAttrib(0));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: AuxBitplaneAttrib::output
 //       Access: Public, Virtual
@@ -85,33 +97,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: AuxBitplaneAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived AuxBitplaneAttrib
-//               types to specify what the default property for a
-//               AuxBitplaneAttrib of this type should be.
-//
-//               This should return a newly-allocated AuxBitplaneAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of AuxBitplaneAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *AuxBitplaneAttrib::
-make_default_impl() const {
-  return new AuxBitplaneAttrib(0);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: AuxBitplaneAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void AuxBitplaneAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_aux_bitplane = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: AuxBitplaneAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/auxBitplaneAttrib.h

@@ -67,22 +67,29 @@ PUBLISHED:
   };
   static CPT(RenderAttrib) make();
   static CPT(RenderAttrib) make(int outputs);
+  static CPT(RenderAttrib) make_default();
   
   INLINE int get_outputs() const;
   
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
   
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
   
 private:
   int _outputs;
 
   static CPT(RenderAttrib) _default;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -99,6 +106,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "AuxBitplaneAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -107,6 +115,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "auxBitplaneAttrib.I"

+ 13 - 28
panda/src/pgraph/clipPlaneAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "clipPlaneAttrib.h"
-#include "attribSlots.h"
 #include "pandaNode.h"
 #include "graphicsStateGuardianBase.h"
 #include "bamReader.h"
@@ -26,6 +25,7 @@
 CPT(RenderAttrib) ClipPlaneAttrib::_empty_attrib;
 CPT(RenderAttrib) ClipPlaneAttrib::_all_off_attrib;
 TypeHandle ClipPlaneAttrib::_type_handle;
+int ClipPlaneAttrib::_attrib_slot;
 
 // This STL Function object is used in filter_to_max(), below, to sort
 // a list of PlaneNodes in reverse order by priority.
@@ -209,6 +209,18 @@ make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2,
   return make();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ClipPlaneAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ClipPlaneAttrib::
+make_default() {
+  return return_new(new ClipPlaneAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ClipPlaneAttrib::get_operation
 //       Access: Published
@@ -863,33 +875,6 @@ invert_compose_impl(const RenderAttrib *other) const {
   return other;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ClipPlaneAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived ClipPlaneAttrib
-//               types to specify what the default property for a
-//               ClipPlaneAttrib of this type should be.
-//
-//               This should return a newly-allocated ClipPlaneAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of ClipPlaneAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *ClipPlaneAttrib::
-make_default_impl() const {
-  return new ClipPlaneAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ClipPlaneAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void ClipPlaneAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_clip_plane = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ClipPlaneAttrib::sort_on_planes
 //       Access: Private

+ 11 - 2
panda/src/pgraph/clipPlaneAttrib.h

@@ -57,6 +57,7 @@ PUBLISHED:
   static CPT(RenderAttrib) make(Operation op, 
                                 PlaneNode *plane1, PlaneNode *plane2,
                                 PlaneNode *plane3, PlaneNode *plane4);
+  static CPT(RenderAttrib) make_default();
 
   Operation get_operation() const;
 
@@ -96,13 +97,11 @@ PUBLISHED:
 public:
   CPT(RenderAttrib) compose_off(const RenderAttrib *other) const;
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   INLINE void check_filtered() const;
@@ -121,6 +120,14 @@ private:
   static CPT(RenderAttrib) _empty_attrib;
   static CPT(RenderAttrib) _all_off_attrib;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -139,6 +146,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "ClipPlaneAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -147,6 +155,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "clipPlaneAttrib.I"

+ 13 - 28
panda/src/pgraph/colorAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "colorAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle ColorAttrib::_type_handle;
+int ColorAttrib::_attrib_slot;
 CPT(RenderAttrib) ColorAttrib::_off;
 CPT(RenderAttrib) ColorAttrib::_vertex;
 
@@ -71,6 +71,18 @@ make_off() {
   return _off;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ColorAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ColorAttrib::
+make_default() {
+  return return_new(new ColorAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorAttrib::output
 //       Access: Public, Virtual
@@ -122,33 +134,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ColorAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived ColorAttrib
-//               types to specify what the default property for a
-//               ColorAttrib of this type should be.
-//
-//               This should return a newly-allocated ColorAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of ColorAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *ColorAttrib::
-make_default_impl() const {
-  return new ColorAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ColorAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void ColorAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_color = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorAttrib::quantize_color
 //       Access: Private

+ 11 - 2
panda/src/pgraph/colorAttrib.h

@@ -41,17 +41,16 @@ PUBLISHED:
   static CPT(RenderAttrib) make_vertex();
   static CPT(RenderAttrib) make_flat(const Colorf &color);
   static CPT(RenderAttrib) make_off();
+  static CPT(RenderAttrib) make_default();
 
   INLINE Type get_color_type() const;
   INLINE const Colorf &get_color() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   void quantize_color();
@@ -62,6 +61,14 @@ private:
   static CPT(RenderAttrib) _off;
   static CPT(RenderAttrib) _vertex;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -78,6 +85,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "ColorAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -86,6 +94,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "colorAttrib.I"

+ 13 - 28
panda/src/pgraph/colorBlendAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "colorBlendAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle ColorBlendAttrib::_type_handle;
+int ColorBlendAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorBlendAttrib::make_off
@@ -65,6 +65,18 @@ make(ColorBlendAttrib::Mode mode,
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ColorBlendAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ColorBlendAttrib::
+make_default() {
+  return return_new(new ColorBlendAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorBlendAttrib::output
 //       Access: Public, Virtual
@@ -119,33 +131,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return _color.compare_to(ta->_color);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ColorBlendAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived ColorBlendAttrib
-//               types to specify what the default property for a
-//               ColorBlendAttrib of this type should be.
-//
-//               This should return a newly-allocated ColorBlendAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of ColorBlendAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *ColorBlendAttrib::
-make_default_impl() const {
-  return new ColorBlendAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ColorBlendAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void ColorBlendAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_color_blend = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorBlendAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/colorBlendAttrib.h

@@ -77,6 +77,7 @@ PUBLISHED:
   static CPT(RenderAttrib) make(Mode mode);
   static CPT(RenderAttrib) make(Mode mode, Operand a, Operand b,
                                 const Colorf &color = Colorf::zero());
+  static CPT(RenderAttrib) make_default();
 
   INLINE Mode get_mode() const;
   INLINE Operand get_operand_a() const;
@@ -91,11 +92,9 @@ PUBLISHED:
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   Mode _mode;
@@ -104,6 +103,14 @@ private:
   bool _involves_constant_color;
   bool _involves_color_scale;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -120,6 +127,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "ColorBlendAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -128,6 +136,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 ostream &operator << (ostream &out, ColorBlendAttrib::Mode mode);

+ 13 - 28
panda/src/pgraph/colorScaleAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "colorScaleAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -23,6 +22,7 @@
 #include "config_pgraph.h"
 
 TypeHandle ColorScaleAttrib::_type_handle;
+int ColorScaleAttrib::_attrib_slot;
 CPT(RenderAttrib) ColorScaleAttrib::_identity_attrib;
 
 ////////////////////////////////////////////////////////////////////
@@ -86,6 +86,18 @@ make_off() {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ColorScaleAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ColorScaleAttrib::
+make_default() {
+  return return_new(new ColorScaleAttrib(false, LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorScaleAttrib::set_scale
 //       Access: Published
@@ -256,33 +268,6 @@ invert_compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ColorScaleAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived ColorScaleAttrib
-//               types to specify what the default property for a
-//               ColorScaleAttrib of this type should be.
-//
-//               This should return a newly-allocated ColorScaleAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of ColorScaleAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *ColorScaleAttrib::
-make_default_impl() const {
-  return new ColorScaleAttrib(false, LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ColorScaleAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void ColorScaleAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_color_scale = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorScaleAttrib::quantize_scale
 //       Access: Private

+ 11 - 2
panda/src/pgraph/colorScaleAttrib.h

@@ -36,6 +36,7 @@ PUBLISHED:
   static CPT(RenderAttrib) make_identity();
   static CPT(RenderAttrib) make(const LVecBase4f &scale);
   static CPT(RenderAttrib) make_off();
+  static CPT(RenderAttrib) make_default();
 
   INLINE bool is_off() const;
   INLINE bool is_identity() const;
@@ -48,13 +49,11 @@ PUBLISHED:
 public:
   virtual bool lower_attrib_can_override() const;
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   void quantize_scale();
@@ -67,6 +66,14 @@ private:
   LVecBase4f _scale;
   static CPT(RenderAttrib) _identity_attrib;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -83,6 +90,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "ColorScaleAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -91,6 +99,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "colorScaleAttrib.I"

+ 13 - 28
panda/src/pgraph/colorWriteAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "colorWriteAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle ColorWriteAttrib::_type_handle;
+int ColorWriteAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorWriteAttrib::make
@@ -34,6 +34,18 @@ make(unsigned int channels) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ColorWriteAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ColorWriteAttrib::
+make_default() {
+  return return_new(new ColorWriteAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorWriteAttrib::output
 //       Access: Public, Virtual
@@ -82,33 +94,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return (int)_channels - (int)ta->_channels;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ColorWriteAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived ColorWriteAttrib
-//               types to specify what the default property for a
-//               ColorWriteAttrib of this type should be.
-//
-//               This should return a newly-allocated ColorWriteAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of ColorWriteAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *ColorWriteAttrib::
-make_default_impl() const {
-  return new ColorWriteAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ColorWriteAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void ColorWriteAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_color_write = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorWriteAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/colorWriteAttrib.h

@@ -47,16 +47,15 @@ private:
 
 PUBLISHED:
   static CPT(RenderAttrib) make(unsigned int channels);
+  static CPT(RenderAttrib) make_default();
 
   INLINE unsigned int get_channels() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   int _channels;
@@ -68,6 +67,14 @@ public:
 protected:
   static TypedWritable *make_from_bam(const FactoryParams &params);
   void fillin(DatagramIterator &scan, BamReader *manager);
+
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
   
 public:
   static TypeHandle get_class_type() {
@@ -77,6 +84,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "ColorWriteAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -85,6 +93,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "colorWriteAttrib.I"

+ 0 - 3
panda/src/pgraph/config_pgraph.cxx

@@ -36,7 +36,6 @@
 #include "depthOffsetAttrib.h"
 #include "depthTestAttrib.h"
 #include "depthWriteAttrib.h"
-#include "drawMaskAttrib.h"
 #include "eventStorePandaNode.h"
 #include "findApproxLevelEntry.h"
 #include "fadeLodNode.h"
@@ -391,7 +390,6 @@ init_libpgraph() {
   DepthOffsetAttrib::init_type();
   DepthTestAttrib::init_type();
   DepthWriteAttrib::init_type();
-  DrawMaskAttrib::init_type();
   EventStorePandaNode::init_type();
   FadeLODNode::init_type();
   FadeLODNodeData::init_type();
@@ -470,7 +468,6 @@ init_libpgraph() {
   DepthOffsetAttrib::register_with_read_factory();
   DepthTestAttrib::register_with_read_factory();
   DepthWriteAttrib::register_with_read_factory();
-  DrawMaskAttrib::register_with_read_factory();
   FadeLODNode::register_with_read_factory();
   Fog::register_with_read_factory();
   FogAttrib::register_with_read_factory();

+ 13 - 28
panda/src/pgraph/cullBinAttrib.cxx

@@ -13,13 +13,13 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "cullBinAttrib.h"
-#include "attribSlots.h"
 #include "bamReader.h"
 #include "bamWriter.h"
 #include "datagram.h"
 #include "datagramIterator.h"
 
 TypeHandle CullBinAttrib::_type_handle;
+int CullBinAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinAttrib::make
@@ -40,6 +40,18 @@ make(const string &bin_name, int draw_order) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullBinAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) CullBinAttrib::
+make_default() {
+  return return_new(new CullBinAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinAttrib::output
 //       Access: Public, Virtual
@@ -80,33 +92,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return strcmp(_bin_name.c_str(), ta->_bin_name.c_str());
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: CullBinAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived CullBinAttrib
-//               types to specify what the default property for a
-//               CullBinAttrib of this type should be.
-//
-//               This should return a newly-allocated CullBinAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of CullBinAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *CullBinAttrib::
-make_default_impl() const {
-  return new CullBinAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CullBinAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void CullBinAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_cull_bin = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/cullBinAttrib.h

@@ -33,22 +33,29 @@ private:
 
 PUBLISHED:
   static CPT(RenderAttrib) make(const string &bin_name, int draw_order);
+  static CPT(RenderAttrib) make_default();
 
   INLINE const string &get_bin_name() const;
   INLINE int get_draw_order() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   string _bin_name;
   int _draw_order;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -65,6 +72,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "CullBinAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -73,6 +81,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "cullBinAttrib.I"

+ 13 - 30
panda/src/pgraph/cullFaceAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "cullFaceAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle CullFaceAttrib::_type_handle;
+int CullFaceAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CullFaceAttrib::make
@@ -51,8 +51,6 @@ make(CullFaceAttrib::Mode mode) {
 //               the scene graph.  M_cull_clockwise will be treated as
 //               M_cull_counter_clockwise, and vice-versa.
 //               M_cull_none is unchanged.
-
-
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) CullFaceAttrib::
 make_reverse() {
@@ -60,6 +58,18 @@ make_reverse() {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullFaceAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) CullFaceAttrib::
+make_default() {
+  return return_new(new CullFaceAttrib(M_cull_clockwise, false));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CullFaceAttrib::get_effective_mode
 //       Access: Published
@@ -223,33 +233,6 @@ invert_compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: CullFaceAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived CullFaceAttrib
-//               types to specify what the default property for a
-//               CullFaceAttrib of this type should be.
-//
-//               This should return a newly-allocated CullFaceAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of CullFaceAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *CullFaceAttrib::
-make_default_impl() const {
-  return new CullFaceAttrib(M_cull_clockwise, false);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CullFaceAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void CullFaceAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_cull_face = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: CullFaceAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/cullFaceAttrib.h

@@ -41,6 +41,7 @@ private:
 PUBLISHED:
   static CPT(RenderAttrib) make(Mode mode = M_cull_clockwise);
   static CPT(RenderAttrib) make_reverse();
+  static CPT(RenderAttrib) make_default();
 
   INLINE Mode get_actual_mode() const;
   INLINE bool get_reverse() const;
@@ -48,18 +49,24 @@ PUBLISHED:
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   Mode _mode;
   bool _reverse;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -76,6 +83,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "CullFaceAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -84,6 +92,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "cullFaceAttrib.I"

+ 2 - 2
panda/src/pgraph/cullPlanes.cxx

@@ -136,7 +136,7 @@ do_cull(int &result, CPT(RenderState) &state,
   result = 
     BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some;
 
-  CPT(ClipPlaneAttrib) orig_cpa = state->get_clip_plane();
+  CPT(ClipPlaneAttrib) orig_cpa = DCAST(ClipPlaneAttrib, state->get_attrib(ClipPlaneAttrib::get_class_slot()));
   
   // If there are no clip planes in the state, the node is completely
   // in front of all zero of the clip planes.  (This can happen if
@@ -172,7 +172,7 @@ do_cull(int &result, CPT(RenderState) &state,
 
   if (new_cpa != orig_cpa) {
     if (new_cpa->is_identity()) {
-      state = state->remove_attrib(ClipPlaneAttrib::get_class_type());
+      state = state->remove_attrib(ClipPlaneAttrib::get_class_slot());
     } else {
       state = state->add_attrib(new_cpa);
     }

+ 10 - 10
panda/src/pgraph/cullResult.cxx

@@ -114,7 +114,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
   const RenderState *state = object->_state;
   nassertv(state != (const RenderState *)NULL);
 
-  const TransparencyAttrib *trans = state->get_transparency();
+  const TransparencyAttrib *trans = DCAST(TransparencyAttrib, state->get_attrib(TransparencyAttrib::get_class_slot()));
   if (trans != (const TransparencyAttrib *)NULL) {
     switch (trans->get_mode()) {
     case TransparencyAttrib::M_alpha:
@@ -163,7 +163,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
       // explicit bin already applied; otherwise, M_dual falls back
       // to M_alpha. 
       {
-        const CullBinAttrib *bin_attrib = state->get_bin();
+        const CullBinAttrib *bin_attrib = DCAST(CullBinAttrib, state->get_attrib(CullBinAttrib::get_class_slot()));
         if (bin_attrib == (CullBinAttrib *)NULL || 
             bin_attrib->get_bin_name().empty()) {
           // We make a copy of the object to draw the transparent part
@@ -397,10 +397,10 @@ check_flash_bin(CPT(RenderState) &state, CullBin *bin) {
   if (bin->has_flash_color()) {
     int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
     if ((cycle & 1) == 0) {
-      state = state->remove_attrib(TextureAttrib::get_class_type());
-      state = state->remove_attrib(LightAttrib::get_class_type());
-      state = state->remove_attrib(ColorScaleAttrib::get_class_type());
-      state = state->remove_attrib(FogAttrib::get_class_type());
+      state = state->remove_attrib(TextureAttrib::get_class_slot());
+      state = state->remove_attrib(LightAttrib::get_class_slot());
+      state = state->remove_attrib(ColorScaleAttrib::get_class_slot());
+      state = state->remove_attrib(FogAttrib::get_class_slot());
       state = state->add_attrib(ColorAttrib::make_flat(bin->get_flash_color()),
                                 RenderState::get_max_priority());
     }
@@ -419,10 +419,10 @@ check_flash_transparency(CPT(RenderState) &state, const Colorf &transparency) {
   if (show_transparency) {
     int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
     if ((cycle & 1) == 0) {
-      state = state->remove_attrib(TextureAttrib::get_class_type());
-      state = state->remove_attrib(LightAttrib::get_class_type());
-      state = state->remove_attrib(ColorScaleAttrib::get_class_type());
-      state = state->remove_attrib(FogAttrib::get_class_type());
+      state = state->remove_attrib(TextureAttrib::get_class_slot());
+      state = state->remove_attrib(LightAttrib::get_class_slot());
+      state = state->remove_attrib(ColorScaleAttrib::get_class_slot());
+      state = state->remove_attrib(FogAttrib::get_class_slot());
       state = state->add_attrib(ColorAttrib::make_flat(transparency),
                                 RenderState::get_max_priority());
     }

+ 1 - 1
panda/src/pgraph/cullTraverser.cxx

@@ -198,7 +198,7 @@ traverse(CullTraverserData &data) {
       
       data.apply_transform_and_state(this);
       
-      const FogAttrib *fog = node_reader->get_state()->get_fog();
+      const FogAttrib *fog = DCAST(FogAttrib, node_reader->get_state()->get_attrib(FogAttrib::get_class_slot()));
       if (fog != (const FogAttrib *)NULL && fog->get_fog() != (Fog *)NULL) {
         // If we just introduced a FogAttrib here, call adjust_to_camera()
         // now.  This maybe isn't the perfect time to call it, but it's

+ 1 - 1
panda/src/pgraph/cullTraverserData.cxx

@@ -116,7 +116,7 @@ apply_transform_and_state(CullTraverser *trav,
 
   if (clip_plane_cull) {
     _cull_planes = _cull_planes->apply_state(trav, this, 
-                                             node_state->get_clip_plane(),
+                                             DCAST(ClipPlaneAttrib, node_state->get_attrib(ClipPlaneAttrib::get_class_slot())),
                                              DCAST(ClipPlaneAttrib, off_clip_planes));
   }
 }

+ 4 - 4
panda/src/pgraph/cullableObject.cxx

@@ -238,7 +238,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
   bool has_aspect_ratio = (aspect_ratio.has_column());
 
   bool sprite_texcoord = false;
-  const TexGenAttrib *tex_gen = _state->get_tex_gen();
+  const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, _state->get_attrib(TexGenAttrib::get_class_slot()));
   if (tex_gen != (TexGenAttrib *)NULL) {
     if (tex_gen->get_mode(TextureStage::get_default()) == TexGenAttrib::M_point_sprite) {
       sprite_texcoord = true;
@@ -250,7 +250,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
 
   float point_size = 1.0f;
   bool perspective = false;
-  const RenderModeAttrib *render_mode = _state->get_render_mode();
+  const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, _state->get_attrib(RenderModeAttrib::get_class_slot()));
   if (render_mode != (RenderModeAttrib *)NULL) {
     point_size = render_mode->get_thickness();
     perspective = render_mode->get_perspective();
@@ -604,7 +604,7 @@ munge_texcoord_light_vector(const CullTraverser *traverser, bool force) {
     return true;
   }
 
-  CPT(TexGenAttrib) tex_gen = _state->get_tex_gen();
+  CPT(TexGenAttrib) tex_gen = DCAST(TexGenAttrib, _state->get_attrib(TexGenAttrib::get_class_slot()));
   nassertr(tex_gen != (TexGenAttrib *)NULL, false);
 
   const TexGenAttrib::LightVectors &light_vectors = tex_gen->get_light_vectors();
@@ -617,7 +617,7 @@ munge_texcoord_light_vector(const CullTraverser *traverser, bool force) {
     if (light.is_empty()) {
       // If a particular light isn't specified in the TexGenAttrib,
       // use the most important light in the current state.
-      CPT(RenderAttrib) attrib = _state->get_attrib(LightAttrib::get_class_type());
+      CPT(RenderAttrib) attrib = _state->get_attrib(LightAttrib::get_class_slot());
       if (attrib != (RenderAttrib *)NULL) {
         CPT(LightAttrib) la = DCAST(LightAttrib, attrib);
         light = la->get_most_important_light();

+ 13 - 28
panda/src/pgraph/depthOffsetAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "depthOffsetAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle DepthOffsetAttrib::_type_handle;
+int DepthOffsetAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthOffsetAttrib::make
@@ -36,6 +36,18 @@ make(int offset) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DepthOffsetAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) DepthOffsetAttrib::
+make_default() {
+  return return_new(new DepthOffsetAttrib(0));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthOffsetAttrib::output
 //       Access: Public, Virtual
@@ -114,33 +126,6 @@ invert_compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DepthOffsetAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived DepthOffsetAttrib
-//               types to specify what the default property for a
-//               DepthOffsetAttrib of this type should be.
-//
-//               This should return a newly-allocated DepthOffsetAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of DepthOffsetAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *DepthOffsetAttrib::
-make_default_impl() const {
-  return new DepthOffsetAttrib(0);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DepthOffsetAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void DepthOffsetAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_depth_offset = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthOffsetAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/depthOffsetAttrib.h

@@ -56,22 +56,29 @@ private:
 
 PUBLISHED:
   static CPT(RenderAttrib) make(int offset = 1);
+  static CPT(RenderAttrib) make_default();
 
   INLINE int get_offset() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   int _offset;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -88,6 +95,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "DepthOffsetAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -96,6 +104,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "depthOffsetAttrib.I"

+ 13 - 28
panda/src/pgraph/depthTestAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "depthTestAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle DepthTestAttrib::_type_handle;
+int DepthTestAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthTestAttrib::make
@@ -34,6 +34,18 @@ make(DepthTestAttrib::PandaCompareFunc mode) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DepthTestAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) DepthTestAttrib::
+make_default() {
+  return return_new(new DepthTestAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthTestAttrib::output
 //       Access: Public, Virtual
@@ -67,33 +79,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return (int)_mode - (int)ta->_mode;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DepthTestAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived DepthTestAttrib
-//               types to specify what the default property for a
-//               DepthTestAttrib of this type should be.
-//
-//               This should return a newly-allocated DepthTestAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of DepthTestAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *DepthTestAttrib::
-make_default_impl() const {
-  return new DepthTestAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DepthTestAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void DepthTestAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_depth_test = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthTestAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/depthTestAttrib.h

@@ -31,20 +31,27 @@ private:
 
 PUBLISHED:
   static CPT(RenderAttrib) make(PandaCompareFunc mode);
+  static CPT(RenderAttrib) make_default();
 
   INLINE PandaCompareFunc get_mode() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   PandaCompareFunc _mode;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -61,6 +68,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "DepthTestAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -69,6 +77,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "depthTestAttrib.I"

+ 13 - 28
panda/src/pgraph/depthWriteAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "depthWriteAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle DepthWriteAttrib::_type_handle;
+int DepthWriteAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthWriteAttrib::make
@@ -34,6 +34,18 @@ make(DepthWriteAttrib::Mode mode) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DepthWriteAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) DepthWriteAttrib::
+make_default() {
+  return return_new(new DepthWriteAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthWriteAttrib::output
 //       Access: Public, Virtual
@@ -74,33 +86,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return (int)_mode - (int)ta->_mode;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DepthWriteAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived DepthWriteAttrib
-//               types to specify what the default property for a
-//               DepthWriteAttrib of this type should be.
-//
-//               This should return a newly-allocated DepthWriteAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of DepthWriteAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *DepthWriteAttrib::
-make_default_impl() const {
-  return new DepthWriteAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DepthWriteAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void DepthWriteAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_depth_write = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthWriteAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/depthWriteAttrib.h

@@ -37,20 +37,27 @@ private:
 
 PUBLISHED:
   static CPT(RenderAttrib) make(Mode mode);
+  static CPT(RenderAttrib) make_default();
 
   INLINE Mode get_mode() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   Mode _mode;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -67,6 +74,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "DepthWriteAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -75,6 +83,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "depthWriteAttrib.I"

+ 0 - 92
panda/src/pgraph/drawMaskAttrib.I

@@ -1,92 +0,0 @@
-// Filename: drawMaskAttrib.I
-// Created by:  drose (28Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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: DrawMaskAttrib::Constructor
-//       Access: Protected
-//  Description: Use DrawMaskAttrib::make() to construct a new
-//               DrawMaskAttrib object.
-////////////////////////////////////////////////////////////////////
-INLINE DrawMaskAttrib::
-DrawMaskAttrib(DrawMask new_mask, DrawMask bits_to_change) :
-  _new_mask(new_mask & bits_to_change),
-  _bits_to_change(bits_to_change)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::Copy Constructor
-//       Access: Protected
-//  Description: Use DrawMaskAttrib::make() to construct a new
-//               DrawMaskAttrib object.
-////////////////////////////////////////////////////////////////////
-INLINE DrawMaskAttrib::
-DrawMaskAttrib(const DrawMaskAttrib &copy) :
-  _new_mask(copy._new_mask),
-  _bits_to_change(copy._bits_to_change)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::make_hide
-//       Access: Published, Static
-//  Description: Constructs a new DrawMaskAttrib that removes the
-//               indicated draw bits from the visibility mask.  That
-//               is, it makes any nodes invisible to cameras that have
-//               any bits in common with draw_mask.  This is similar
-//               to (but not quite identical to)
-//               NodePath.hide(draw_mask).
-////////////////////////////////////////////////////////////////////
-INLINE CPT(RenderAttrib) DrawMaskAttrib::
-make_hide(DrawMask draw_mask) {
-  return make(DrawMask::all_off(), draw_mask);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::make_show
-//       Access: Published, Static
-//  Description: Constructs a new DrawMaskAttrib that adds the
-//               indicated draw bits to the visibility mask.  That
-//               is, it makes any nodes visible to cameras that have
-//               any bits in common with draw_mask.  This is similar
-//               to (but not quite identical to)
-//               NodePath.show(draw_mask).
-////////////////////////////////////////////////////////////////////
-INLINE CPT(RenderAttrib) DrawMaskAttrib::
-make_show(DrawMask draw_mask) {
-  return make(draw_mask, draw_mask);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::get_new_mask
-//       Access: Published
-//  Description: Returns the new DrawMask that will be set after the
-//               attrib has been applied.
-////////////////////////////////////////////////////////////////////
-INLINE DrawMask DrawMaskAttrib::
-get_new_mask() const {
-  return _new_mask;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::get_bits_to_change
-//       Access: Published
-//  Description: Returns the set of bits that will be allowed to be
-//               changed by this DrawMaskAttrib.
-////////////////////////////////////////////////////////////////////
-INLINE DrawMask DrawMaskAttrib::
-get_bits_to_change() const {
-  return _bits_to_change;
-}

+ 0 - 226
panda/src/pgraph/drawMaskAttrib.cxx

@@ -1,226 +0,0 @@
-// Filename: drawMaskAttrib.cxx
-// Created by:  drose (28Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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 "drawMaskAttrib.h"
-#include "dcast.h"
-#include "bamReader.h"
-#include "bamWriter.h"
-#include "datagram.h"
-#include "datagramIterator.h"
-#include "cullTraverser.h"
-#include "config_pgraph.h"
-
-TypeHandle DrawMaskAttrib::_type_handle;
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::make
-//       Access: Published, Static
-//  Description: Constructs a new DrawMaskAttrib that changes the
-//               bits_to_change bits in the current DrawMask to the
-//               values of the corresponding bits in new_mask.  Only
-//               those bits in common with bits_to_change are
-//               affected.
-////////////////////////////////////////////////////////////////////
-CPT(RenderAttrib) DrawMaskAttrib::
-make(DrawMask new_mask, DrawMask bits_to_change) {
-  DrawMaskAttrib *attrib = new DrawMaskAttrib(new_mask, bits_to_change);
-  return return_new(attrib);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::output
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void DrawMaskAttrib::
-output(ostream &out) const {
-  out << get_type() << ":" << get_new_mask() << "/" << get_bits_to_change();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::compare_to_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived DrawMaskAttrib
-//               types to return a unique number indicating whether
-//               this DrawMaskAttrib is equivalent to the other one.
-//
-//               This should return 0 if the two DrawMaskAttrib objects
-//               are equivalent, a number less than zero if this one
-//               should be sorted before the other one, and a number
-//               greater than zero otherwise.
-//
-//               This will only be called with two DrawMaskAttrib
-//               objects whose get_type() functions return the same.
-////////////////////////////////////////////////////////////////////
-int DrawMaskAttrib::
-compare_to_impl(const RenderAttrib *other) const {
-  const DrawMaskAttrib *ta;
-  DCAST_INTO_R(ta, other, 0);
-
-  int compare = get_new_mask().compare_to(ta->get_new_mask());
-  if (compare != 0) {
-    return compare;
-  }
-  compare = get_bits_to_change().compare_to(ta->get_bits_to_change());
-  return compare;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::compose_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived RenderAttrib
-//               types to specify how two consecutive RenderAttrib
-//               objects of the same type interact.
-//
-//               This should return the result of applying the other
-//               RenderAttrib to a node in the scene graph below this
-//               RenderAttrib, which was already applied.  In most
-//               cases, the result is the same as the other
-//               RenderAttrib (that is, a subsequent RenderAttrib
-//               completely replaces the preceding one).  On the other
-//               hand, some kinds of RenderAttrib (for instance,
-//               ColorTransformAttrib) might combine in meaningful
-//               ways.
-////////////////////////////////////////////////////////////////////
-CPT(RenderAttrib) DrawMaskAttrib::
-compose_impl(const RenderAttrib *other) const {
-  const DrawMaskAttrib *ta;
-  DCAST_INTO_R(ta, other, 0);
-  
-  DrawMask mask = get_new_mask();
-  mask = (mask & ~ta->get_bits_to_change()) | ta->get_new_mask();
-
-  DrawMaskAttrib *attrib = new DrawMaskAttrib(mask, DrawMask::all_on());
-  return return_new(attrib);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived DrawMaskAttrib
-//               types to specify what the default property for a
-//               DrawMaskAttrib of this type should be.
-//
-//               This should return a newly-allocated DrawMaskAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of DrawMaskAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *DrawMaskAttrib::
-make_default_impl() const {
-  return new DrawMaskAttrib(DrawMask::all_on(), DrawMask::all_on());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void DrawMaskAttrib::
-store_into_slot(AttribSlots *) const {
-  // There's no need to store a DrawMaskAttrib at the moment, since it
-  // doesn't actually change any rendering state.
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::has_cull_callback
-//       Access: Public, Virtual
-//  Description: Should be overridden by derived classes to return
-//               true if cull_callback() has been defined.  Otherwise,
-//               returns false to indicate cull_callback() does not
-//               need to be called for this node during the cull
-//               traversal.
-////////////////////////////////////////////////////////////////////
-bool DrawMaskAttrib::
-has_cull_callback() const {
-  return (_new_mask != DrawMask::all_on());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::cull_callback
-//       Access: Public, Virtual
-//  Description: If has_cull_callback() returns true, this function
-//               will be called during the cull traversal to perform
-//               any additional operations that should be performed at
-//               cull time.
-//
-//               This is called each time the RenderAttrib is
-//               discovered applied to a Geom in the traversal.  It
-//               should return true if the Geom is visible, false if
-//               it should be omitted.
-////////////////////////////////////////////////////////////////////
-bool DrawMaskAttrib::
-cull_callback(CullTraverser *trav, const CullTraverserData &) const {
-  return (trav->get_camera_mask() & _new_mask) != 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::register_with_read_factory
-//       Access: Public, Static
-//  Description: Tells the BamReader how to create objects of type
-//               DrawMaskAttrib.
-////////////////////////////////////////////////////////////////////
-void DrawMaskAttrib::
-register_with_read_factory() {
-  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::write_datagram
-//       Access: Public, Virtual
-//  Description: Writes the contents of this object to the datagram
-//               for shipping out to a Bam file.
-////////////////////////////////////////////////////////////////////
-void DrawMaskAttrib::
-write_datagram(BamWriter *manager, Datagram &dg) {
-  RenderAttrib::write_datagram(manager, dg);
-
-  dg.add_uint32(_new_mask.get_word());
-  dg.add_uint32(_bits_to_change.get_word());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::make_from_bam
-//       Access: Protected, Static
-//  Description: This function is called by the BamReader's factory
-//               when a new object of type DrawMaskAttrib is encountered
-//               in the Bam file.  It should create the DrawMaskAttrib
-//               and extract its information from the file.
-////////////////////////////////////////////////////////////////////
-TypedWritable *DrawMaskAttrib::
-make_from_bam(const FactoryParams &params) {
-  DrawMaskAttrib *attrib = new DrawMaskAttrib(0, 0);
-  DatagramIterator scan;
-  BamReader *manager;
-
-  parse_params(params, scan, manager);
-  attrib->fillin(scan, manager);
-
-  return attrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DrawMaskAttrib::fillin
-//       Access: Protected
-//  Description: This internal function is called by make_from_bam to
-//               read in all of the relevant data from the BamFile for
-//               the new DrawMaskAttrib.
-////////////////////////////////////////////////////////////////////
-void DrawMaskAttrib::
-fillin(DatagramIterator &scan, BamReader *manager) {
-  RenderAttrib::fillin(scan, manager);
-
-  _new_mask.set_word(scan.get_uint32());
-  _bits_to_change.set_word(scan.get_uint32());
-}

+ 0 - 98
panda/src/pgraph/drawMaskAttrib.h

@@ -1,98 +0,0 @@
-// Filename: drawMaskAttrib.h
-// Created by:  drose (28Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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 DRAWMASKATTRIB_H
-#define DRAWMASKATTRIB_H
-
-#include "pandabase.h"
-
-#include "renderAttrib.h"
-#include "drawMask.h"
-
-class FactoryParams;
-
-////////////////////////////////////////////////////////////////////
-//       Class : DrawMaskAttrib
-// Description : This attrib can be used to control the visibility of
-//               certain Geoms from certain cameras.  It is similar in
-//               principle to the PandaNode::set_draw_mask()
-//               interface, except it does not cause an early prune in
-//               the cull traversal; thus, it can be used to show a
-//               node even though its parent has been hidden (if the
-//               parent was hidden using the same interface).
-//
-//               It is mainly useful for unusual circumstances in
-//               which the visibility of a node is not easy to
-//               determine from examining the static hierarchy of the
-//               graph.
-////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PGRAPH DrawMaskAttrib : public RenderAttrib {
-protected:
-  INLINE DrawMaskAttrib(DrawMask new_mask, DrawMask bits_to_change);
-  INLINE DrawMaskAttrib(const DrawMaskAttrib &copy);
-
-PUBLISHED:
-  INLINE static CPT(RenderAttrib) make_hide(DrawMask draw_mask = DrawMask::all_on());
-  INLINE static CPT(RenderAttrib) make_show(DrawMask draw_mask = DrawMask::all_on());
-  static CPT(RenderAttrib) make(DrawMask new_mask, DrawMask bits_to_change);
-
-  INLINE DrawMask get_new_mask() const;
-  INLINE DrawMask get_bits_to_change() const;
-
-public:
-  virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
-
-  virtual bool has_cull_callback() const;
-  virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
-
-protected:
-  virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
-
-private:
-  DrawMask _new_mask;
-  DrawMask _bits_to_change;
-
-public:
-  static void register_with_read_factory();
-  virtual void write_datagram(BamWriter *manager, Datagram &dg);
-
-protected:
-  static TypedWritable *make_from_bam(const FactoryParams &params);
-  void fillin(DatagramIterator &scan, BamReader *manager);
-  
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    RenderAttrib::init_type();
-    register_type(_type_handle, "DrawMaskAttrib",
-                  RenderAttrib::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-};
-
-#include "drawMaskAttrib.I"
-
-#endif
-

+ 13 - 28
panda/src/pgraph/fogAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "fogAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "bamReader.h"
 #include "bamWriter.h"
@@ -21,6 +20,7 @@
 #include "datagramIterator.h"
 
 TypeHandle FogAttrib::_type_handle;
+int FogAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FogAttrib::make
@@ -35,6 +35,18 @@ make(Fog *fog) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: FogAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) FogAttrib::
+make_default() {
+  return return_new(new FogAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: FogAttrib::make_off
 //       Access: Published, Static
@@ -91,33 +103,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: FogAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived FogAttrib
-//               types to specify what the default property for a
-//               FogAttrib of this type should be.
-//
-//               This should return a newly-allocated FogAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of FogAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *FogAttrib::
-make_default_impl() const {
-  return new FogAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FogAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void FogAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_fog = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: FogAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/fogAttrib.h

@@ -31,21 +31,28 @@ private:
 PUBLISHED:
   static CPT(RenderAttrib) make(Fog *fog);
   static CPT(RenderAttrib) make_off();
+  static CPT(RenderAttrib) make_default();
 
   INLINE bool is_off() const;
   INLINE Fog *get_fog() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   PT(Fog) _fog;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -63,6 +70,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "FogAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -71,6 +79,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "fogAttrib.I"

+ 9 - 15
panda/src/pgraph/geomNode.cxx

@@ -144,7 +144,7 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
         }
         entry._state = entry._state->add_attrib(ra, override);
 
-        ra = entry._state->get_attrib(ColorAttrib::get_class_type());
+        ra = entry._state->get_attrib(ColorAttrib::get_class_slot());
         const ColorAttrib *ca = DCAST(ColorAttrib, ra);
         if (ca->get_color_type() != ColorAttrib::T_vertex) {
           if (transformer.remove_column(new_geom, InternalName::get_color())) {
@@ -160,7 +160,7 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
             // Now, if we have an "off" or "flat" color attribute, we
             // simply modify the color attribute, and leave the
             // vertices alone.
-            const RenderAttrib *ra = entry._state->get_attrib(ColorAttrib::get_class_type());
+            const RenderAttrib *ra = entry._state->get_attrib(ColorAttrib::get_class_slot());
             if (ra != (const RenderAttrib *)NULL) {
               const ColorAttrib *ca = DCAST(ColorAttrib, ra);
               if (ca->get_color_type() == ColorAttrib::T_off) {
@@ -374,7 +374,7 @@ r_prepare_scene(const RenderState *state,
   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
     CPT(RenderState) geom_state = state->compose((*gi)._state);
     const RenderAttrib *attrib = 
-      geom_state->get_attrib(TextureAttrib::get_class_type());
+      geom_state->get_attrib(TextureAttrib::get_class_slot());
     if (attrib != (const RenderAttrib *)NULL) {
       const TextureAttrib *ta;
       DCAST_INTO_V(ta, attrib);
@@ -767,25 +767,19 @@ output(ostream &out) const {
   pset<TypeHandle> attrib_types;
 
   GeomList::const_iterator gi;
+  CPT(RenderState) common = RenderState::make_empty();
+
   CPT(GeomList) geoms = cdata->get_geoms();
   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
     const GeomEntry &entry = (*gi);
-    int num_attribs = entry._state->get_num_attribs();
-    for (int i = 0; i < num_attribs; i++) {
-      const RenderAttrib *attrib = entry._state->get_attrib(i);
-      attrib_types.insert(attrib->get_type());
-    }
+    common = common->compose(entry._state);
   }
 
   PandaNode::output(out);
   out << " (" << geoms->size() << " geoms";
 
-  if (!attrib_types.empty()) {
-    out << ":";
-    pset<TypeHandle>::const_iterator ai;
-    for (ai = attrib_types.begin(); ai != attrib_types.end(); ++ai) {
-      out << " " << (*ai);
-    }
+  if (!common->is_empty()) {
+    out << ": " << *common;    
   }
 
   out << ")";
@@ -964,7 +958,7 @@ finalize(BamReader *manager) {
         }
 
         if (vdata->has_column(color) &&
-            entry._state->get_color() == (ColorAttrib *)NULL) {
+            !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
           // We'll be reassigning the RenderState.  Therefore, save it
           // temporarily to increment its reference count.
           PT(BamAuxData) aux_data = new BamAuxData;

+ 5 - 5
panda/src/pgraph/geomTransformer.cxx

@@ -653,15 +653,15 @@ apply_texture_colors(GeomNode *node, const RenderState *state) {
     GeomNode::GeomEntry &entry = (*gi);
     CPT(RenderState) geom_state = state->compose(entry._state);
 
-    const TextureAttrib *ta = geom_state->get_texture();
+    const TextureAttrib *ta = DCAST(TextureAttrib, geom_state->get_attrib(TextureAttrib::get_class_slot()));
     if (ta != (TextureAttrib *)NULL) {
       CPT(TextureAttrib) ta2 = ta->filter_to_max(1);
       if (ta2->get_num_on_stages() > 0) {
         TextureStage *ts = ta2->get_on_stage(0);
         Texture *tex = ta2->get_on_texture(ts);
-        const TexMatrixAttrib *tma = geom_state->get_tex_matrix();
+        const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, geom_state->get_attrib(TexMatrixAttrib::get_class_slot()));
 
-        const ColorAttrib *ca = geom_state->get_color();
+        const ColorAttrib *ca = DCAST(ColorAttrib, geom_state->get_attrib(ColorAttrib::get_class_slot()));
         Colorf base_color(1.0f, 1.0f, 1.0f, 1.0f);
         bool keep_vertex_color = true;
         if (ca != (ColorAttrib *)NULL && ca->get_color_type() == ColorAttrib::T_flat) {
@@ -685,7 +685,7 @@ apply_texture_colors(GeomNode *node, const RenderState *state) {
         }
 
         // Also remove any texture references from the GeomState.
-        CPT(RenderState) no_tex_state = entry._state->remove_attrib(TextureAttrib::get_class_type());
+        CPT(RenderState) no_tex_state = entry._state->remove_attrib(TextureAttrib::get_class_slot());
         if (entry._state != no_tex_state) {
           entry._state = no_tex_state;
           any_changed = true;
@@ -889,7 +889,7 @@ make_compatible_state(GeomNode *node) {
     const RenderState *canon_state = (*si).first;
     for (int i = 0; i < (int)indices.size(); i++) {
       GeomNode::GeomEntry &entry = geoms[indices[i]];
-      const RenderAttrib *ra = entry._state->get_attrib(ColorAttrib::get_class_type());
+      const RenderAttrib *ra = entry._state->get_attrib(ColorAttrib::get_class_slot());
       if (ra == (RenderAttrib *)NULL) {
         ra = ColorAttrib::make_off();
       }

+ 13 - 28
panda/src/pgraph/lightAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "lightAttrib.h"
-#include "attribSlots.h"
 #include "pandaNode.h"
 #include "nodePath.h"
 #include "graphicsStateGuardianBase.h"
@@ -25,6 +24,7 @@
 #include "attribNodeRegistry.h"
 
 CPT(RenderAttrib) LightAttrib::_empty_attrib;
+int LightAttrib::_attrib_slot;
 CPT(RenderAttrib) LightAttrib::_all_off_attrib;
 TypeHandle LightAttrib::_type_handle;
 
@@ -214,6 +214,18 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
   return make();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LightAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) LightAttrib::
+make_default() {
+  return return_new(new LightAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LightAttrib::get_operation
 //       Access: Published
@@ -843,33 +855,6 @@ invert_compose_impl(const RenderAttrib *other) const {
   return other;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LightAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived LightAttrib
-//               types to specify what the default property for a
-//               LightAttrib of this type should be.
-//
-//               This should return a newly-allocated LightAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of LightAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *LightAttrib::
-make_default_impl() const {
-  return new LightAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LightAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void LightAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_light = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LightAttrib::sort_on_lights
 //       Access: Private

+ 11 - 2
panda/src/pgraph/lightAttrib.h

@@ -55,6 +55,7 @@ PUBLISHED:
   static CPT(RenderAttrib) make(Operation op, 
                                 Light *light1, Light *light2,
                                 Light *light3, Light *light4);
+  static CPT(RenderAttrib) make_default();
 
   Operation get_operation() const;
 
@@ -94,13 +95,11 @@ PUBLISHED:
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   INLINE void check_filtered() const;
@@ -119,6 +118,14 @@ private:
   static CPT(RenderAttrib) _empty_attrib;
   static CPT(RenderAttrib) _all_off_attrib;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -137,6 +144,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "LightAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 20, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -145,6 +153,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "lightAttrib.I"

+ 1 - 28
panda/src/pgraph/lightRampAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "lightRampAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle LightRampAttrib::_type_handle;
+int LightRampAttrib::_attrib_slot;
 CPT(RenderAttrib) LightRampAttrib::_default;
 
 ////////////////////////////////////////////////////////////////////
@@ -248,33 +248,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LightRampAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived LightRampAttrib
-//               types to specify what the default property for a
-//               LightRampAttrib of this type should be.
-//
-//               This should return a newly-allocated LightRampAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of LightRampAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *LightRampAttrib::
-make_default_impl() const {
-  return new LightRampAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LightRampAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void LightRampAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_light_ramp = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LightRampAttrib::register_with_read_factory
 //       Access: Public, Static

+ 10 - 2
panda/src/pgraph/lightRampAttrib.h

@@ -58,11 +58,9 @@ PUBLISHED:
   
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
   
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
   
 private:
   LightRampMode _mode;
@@ -71,6 +69,14 @@ private:
 
   static CPT(RenderAttrib) _default;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -87,6 +93,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "LightRampAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -95,6 +102,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "lightRampAttrib.I"

+ 13 - 28
panda/src/pgraph/materialAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "materialAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "bamReader.h"
 #include "bamWriter.h"
@@ -21,6 +20,7 @@
 #include "datagramIterator.h"
 
 TypeHandle MaterialAttrib::_type_handle;
+int MaterialAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: MaterialAttrib::make
@@ -48,6 +48,18 @@ make_off() {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: MaterialAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) MaterialAttrib::
+make_default() {
+  return return_new(new MaterialAttrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MaterialAttrib::output
 //       Access: Public, Virtual
@@ -92,33 +104,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: MaterialAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived MaterialAttrib
-//               types to specify what the default property for a
-//               MaterialAttrib of this type should be.
-//
-//               This should return a newly-allocated MaterialAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of MaterialAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *MaterialAttrib::
-make_default_impl() const {
-  return new MaterialAttrib;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: MaterialAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void MaterialAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_material = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: MaterialAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/materialAttrib.h

@@ -34,21 +34,28 @@ private:
 PUBLISHED:
   static CPT(RenderAttrib) make(Material *material);
   static CPT(RenderAttrib) make_off();
+  static CPT(RenderAttrib) make_default();
 
   INLINE bool is_off() const;
   INLINE Material *get_material() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   PT(Material) _material;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -66,6 +73,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "MaterialAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -74,6 +82,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "materialAttrib.I"

File diff suppressed because it is too large
+ 122 - 122
panda/src/pgraph/nodePath.cxx


+ 45 - 7
panda/src/pgraph/pandaNode.I

@@ -235,11 +235,22 @@ find_stashed(PandaNode *node, Thread *current_thread) const {
 INLINE const RenderAttrib *PandaNode::
 get_attrib(TypeHandle type) const {
   CDReader cdata(_cycler);
-  int index = cdata->_state->find_attrib(type);
-  if (index >= 0) {
-    return cdata->_state->get_attrib(index);
-  }
-  return NULL;
+  return cdata->_state->get_attrib(type);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaNode::get_attrib
+//       Access: Published
+//  Description: Returns the render attribute of the indicated type,
+//               if it is defined on the node, or NULL if it is not.
+//               This checks only what is set on this particular node
+//               level, and has nothing to do with what render
+//               attributes may be inherited from parent nodes.
+////////////////////////////////////////////////////////////////////
+INLINE const RenderAttrib *PandaNode::
+get_attrib(int slot) const {
+  CDReader cdata(_cycler);
+  return cdata->_state->get_attrib(slot);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -252,8 +263,35 @@ get_attrib(TypeHandle type) const {
 INLINE bool PandaNode::
 has_attrib(TypeHandle type) const {
   CDReader cdata(_cycler);
-  int index = cdata->_state->find_attrib(type);
-  return (index >= 0);
+  return cdata->_state->has_attrib(type);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaNode::has_attrib
+//       Access: Published
+//  Description: Returns true if there is a render attribute of the
+//               indicated type defined on this node, or false if
+//               there is not.
+////////////////////////////////////////////////////////////////////
+INLINE bool PandaNode::
+has_attrib(int slot) const {
+  CDReader cdata(_cycler);
+  return cdata->_state->has_attrib(slot);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaNode::clear_attrib
+//       Access: Published
+//  Description: Removes the render attribute of the given type from
+//               this node.  This node, and the subgraph below, will
+//               now inherit the indicated render attribute from the
+//               nodes above this one.
+////////////////////////////////////////////////////////////////////
+INLINE void PandaNode::
+clear_attrib(TypeHandle type) {
+  RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
+  int slot = reg->get_slot(type);
+  clear_attrib(slot);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 3
panda/src/pgraph/pandaNode.cxx

@@ -1090,14 +1090,14 @@ set_attrib(const RenderAttrib *attrib, int override) {
 //               nodes above this one.
 ////////////////////////////////////////////////////////////////////
 void PandaNode::
-clear_attrib(TypeHandle type) {
+clear_attrib(int slot) {
   bool any_changed = false;
 
   Thread *current_thread = Thread::get_current_thread();
   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
     
-    CPT(RenderState) new_state = cdata->_state->remove_attrib(type);
+    CPT(RenderState) new_state = cdata->_state->remove_attrib(slot);
     if (cdata->_state != new_state) {
       cdata->_state = new_state;
       cdata->set_fancy_bit(FB_state, !new_state->is_empty());
@@ -3644,7 +3644,7 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
         << "\nnet_draw_show_mask = " << net_draw_show_mask
         << "\n";
     }
-    CPT(RenderAttrib) off_clip_planes = cdata->_state->get_clip_plane();
+    CPT(RenderAttrib) off_clip_planes = cdata->_state->get_attrib(ClipPlaneAttrib::get_class_slot());
     if (off_clip_planes == (RenderAttrib *)NULL) {
       off_clip_planes = ClipPlaneAttrib::make();
     }

+ 4 - 1
panda/src/pgraph/pandaNode.h

@@ -157,8 +157,11 @@ PUBLISHED:
 
   void set_attrib(const RenderAttrib *attrib, int override = 0);
   INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
+  INLINE const RenderAttrib *get_attrib(int slot) const;
   INLINE bool has_attrib(TypeHandle type) const;
-  void clear_attrib(TypeHandle type);
+  INLINE bool has_attrib(int slot) const;
+  INLINE void clear_attrib(TypeHandle type);
+  void clear_attrib(int slot);
 
   void set_effect(const RenderEffect *effect);
   INLINE const RenderEffect *get_effect(TypeHandle type) const;

+ 0 - 1
panda/src/pgraph/pgraph_composite1.cxx

@@ -4,7 +4,6 @@
 #include "audioVolumeAttrib.cxx"
 #include "auxBitplaneAttrib.cxx"
 #include "auxSceneData.cxx"
-#include "attribSlots.cxx"
 #include "bamFile.cxx"
 #include "billboardEffect.cxx"
 #include "cacheStats.cxx"

+ 0 - 1
panda/src/pgraph/pgraph_composite2.cxx

@@ -13,7 +13,6 @@
 #include "depthTestAttrib.cxx"
 #include "depthWriteAttrib.cxx"
 #include "alphaTestAttrib.cxx"
-#include "drawMaskAttrib.cxx"
 #include "eventStorePandaNode.cxx"
 #include "fadeLodNode.cxx"
 #include "fadeLodNodeData.cxx"

+ 1 - 0
panda/src/pgraph/pgraph_composite4.cxx

@@ -1,4 +1,5 @@
 #include "renderAttrib.cxx"
+#include "renderAttribRegistry.cxx"
 #include "renderEffect.cxx"
 #include "renderEffects.cxx"
 #include "renderModeAttrib.cxx"

+ 14 - 14
panda/src/pgraph/renderAttrib.I

@@ -49,20 +49,6 @@ invert_compose(const RenderAttrib *other) const {
   return invert_compose_impl(other);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RenderAttrib::make_default
-//       Access: Public
-//  Description: Returns a different (or possibly the same)
-//               RenderAttrib pointer of the same type as this one
-//               that corresponds to whatever the standard default
-//               properties for render attributes of this type ought
-//               to be.
-////////////////////////////////////////////////////////////////////
-INLINE CPT(RenderAttrib) RenderAttrib::
-make_default() const {
-  return return_new(make_default_impl());
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderAttrib::always_reissue
 //       Access: Public
@@ -102,3 +88,17 @@ compare_to(const RenderAttrib &other) const {
   // We only call compare_to_impl() if they have the same type.
   return compare_to_impl(&other);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttrib::register_slot
+//       Access: Public, Static
+//  Description: Adds the indicated TypeHandle to the registry, if it
+//               is not there already, and returns a unique slot
+//               number.  See RenderAttribRegistry.
+////////////////////////////////////////////////////////////////////
+INLINE int RenderAttrib::
+register_slot(TypeHandle type_handle, int sort,
+              RenderAttribRegistry::MakeDefaultFunc *make_default_func) {
+  RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
+  return reg->register_slot(type_handle, sort, make_default_func);
+}

+ 0 - 17
panda/src/pgraph/renderAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "renderAttrib.h"
-#include "attribSlots.h"
 #include "bamReader.h"
 #include "indent.h"
 #include "config_pgraph.h"
@@ -461,22 +460,6 @@ release_new() {
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RenderAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived RenderAttrib
-//               types to specify what the default property for a
-//               RenderAttrib of this type should be.
-//
-//               This should return a newly-allocated RenderAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of RenderAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *RenderAttrib::
-make_default_impl() const {
-  return (RenderAttrib *)NULL;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderAttrib::init_attribs
 //       Access: Public, Static

+ 7 - 3
panda/src/pgraph/renderAttrib.h

@@ -18,6 +18,7 @@
 #include "pandabase.h"
 
 #include "typedWritableReferenceCount.h"
+#include "renderAttribRegistry.h"
 #include "pointerTo.h"
 #include "pset.h"
 #include "lightReMutex.h"
@@ -66,11 +67,9 @@ public:
 
   INLINE CPT(RenderAttrib) compose(const RenderAttrib *other) const;
   INLINE CPT(RenderAttrib) invert_compose(const RenderAttrib *other) const;
-  INLINE CPT(RenderAttrib) make_default() const;
   virtual bool lower_attrib_can_override() const;
 
   INLINE bool always_reissue() const;
-  virtual void store_into_slot(AttribSlots *slots) const=0;
 
   virtual bool has_cull_callback() const;
   virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
@@ -87,6 +86,8 @@ PUBLISHED:
   static void list_attribs(ostream &out);
   static bool validate_attribs();
 
+  virtual int get_slot() const=0;
+
   enum PandaCompareFunc {   // intentionally defined to match D3DCMPFUNC
     M_none=0,           // alpha-test disabled (always-draw)
     M_never,            // Never draw.
@@ -176,9 +177,12 @@ protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const=0;
   void output_comparefunc(ostream &out, PandaCompareFunc fn) const;
 
+public:
+  INLINE static int register_slot(TypeHandle type_handle, int sort,
+                                  RenderAttribRegistry::MakeDefaultFunc *make_default_func);
+
 private:
   void release_new();
 

+ 162 - 0
panda/src/pgraph/renderAttribRegistry.I

@@ -0,0 +1,162 @@
+// Filename: renderAttribRegistry.I
+// Created by:  drose (13Nov08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: RenderAttribRegistry::get_slot
+//       Access: Published
+//  Description: Returns the slot number assigned to the indicated
+//               TypeHandle, or 0 if no slot number has been assigned.
+////////////////////////////////////////////////////////////////////
+INLINE int RenderAttribRegistry::
+get_slot(TypeHandle type_handle) const {
+  int type_index = type_handle.get_index();
+  if (type_index >= (int)_slots_by_type.size()) {
+    return 0;
+  }
+  return _slots_by_type[type_index];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::get_max_slots
+//       Access: Published
+//  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
+//               puts an upper bound on the number of RenderAttrib
+//               slots that may be allocated, and allows other code to
+//               define an array of slots.
+//
+//               This number will not change during the lifetime of
+//               the application.
+////////////////////////////////////////////////////////////////////
+INLINE int RenderAttribRegistry::
+get_max_slots() const {
+  return _max_slots;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::get_num_slots
+//       Access: Published
+//  Description: Returns the number of RenderAttrib slots that have
+//               been allocated.  This is one more than the highest
+//               slot number in use.
+////////////////////////////////////////////////////////////////////
+INLINE int RenderAttribRegistry::
+get_num_slots() const {
+  return _registry.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::get_slot_type
+//       Access: Published
+//  Description: Returns the TypeHandle associated with slot n.
+////////////////////////////////////////////////////////////////////
+INLINE TypeHandle RenderAttribRegistry::
+get_slot_type(int slot) const {
+  nassertr(slot >= 0 && slot < (int)_registry.size(), TypeHandle::none());
+  return _registry[slot]._type;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::get_slot_sort
+//       Access: Published
+//  Description: Returns the sort number associated with slot n.
+////////////////////////////////////////////////////////////////////
+INLINE int RenderAttribRegistry::
+get_slot_sort(int slot) const {
+  nassertr(slot >= 0 && slot < (int)_registry.size(), 0);
+  return _registry[slot]._sort;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::get_num_sorted_slots
+//       Access: Published
+//  Description: Returns the number of entries in the sorted_slots
+//               list.
+////////////////////////////////////////////////////////////////////
+INLINE int RenderAttribRegistry::
+get_num_sorted_slots() const {
+  return _sorted_slots.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::get_sorted_slot
+//       Access: Published
+//  Description: Returns the nth slot in sorted order.  By traversing
+//               this list, you will retrieve all the slot numbers in
+//               order according to their registered sort value.
+////////////////////////////////////////////////////////////////////
+INLINE int RenderAttribRegistry::
+get_sorted_slot(int n) const {
+  nassertr(n >= 0 && n < (int)_sorted_slots.size(), 0);
+  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
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE RenderAttribRegistry *RenderAttribRegistry::
+get_global_ptr() {
+  if (_global_ptr == (RenderAttribRegistry *)NULL) {
+    init_global_ptr();
+  }
+  return _global_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::quick_get_global_ptr
+//       Access: Public, Static
+//  Description: Returns the global_ptr without first ensuring it has
+//               been initialized.  Only safe for code that knows it
+//               has already been initialized.
+////////////////////////////////////////////////////////////////////
+INLINE RenderAttribRegistry *RenderAttribRegistry::
+quick_get_global_ptr() {
+  return _global_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::SortSlots::Constructor
+//       Access: Public
+//  Description: This is an STL function object for sorting the
+//               _sorted_slots list into order by slot sort number.
+////////////////////////////////////////////////////////////////////
+INLINE RenderAttribRegistry::SortSlots::
+SortSlots(RenderAttribRegistry *reg) : _reg(reg) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::SortSlots::operator ()
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool RenderAttribRegistry::SortSlots::
+operator () (int a, int b) const {
+  return _reg->get_slot_sort(a) < _reg->get_slot_sort(b);
+}

+ 175 - 0
panda/src/pgraph/renderAttribRegistry.cxx

@@ -0,0 +1,175 @@
+// Filename: renderAttribRegistry.cxx
+// Created by:  drose (13Nov08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "renderAttribRegistry.h"
+#include "renderAttrib.h"
+#include "renderState.h"
+#include "deletedChain.h"
+
+RenderAttribRegistry *RenderAttribRegistry::_global_ptr;
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::Constructor
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+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));
+
+  // 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);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::Destructor
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+RenderAttribRegistry::
+~RenderAttribRegistry() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::register_slot
+//       Access: Public
+//  Description: Adds the indicated TypeHandle to the registry, if it
+//               is not there already, and returns a unique slot
+//               number in the range 0 < slot < get_max_slots().
+//
+//               The sort value is an arbitrary integer.  In general,
+//               the RenderAttribs will be sorted in order from lowest
+//               sort value to highest sort value, when they are
+//               traversed via the get_num_sorted_slots() /
+//               get_sorted_slot() methods.  This will be used to sort
+//               render states, so that heavier RenderAttribs are
+//               changed less frequently.  In general, you should
+//               choose sort values such that the heavier
+//               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.
+//
+//               register_slot() is intended to be called at
+//               application start for each different RenderAttrib
+//               type in the system, to assign a different integer
+//               slot number to each one.
+////////////////////////////////////////////////////////////////////
+int RenderAttribRegistry::
+register_slot(TypeHandle type_handle, int sort,
+              RenderAttribRegistry::MakeDefaultFunc *make_default_func) {
+  int type_index = type_handle.get_index();
+  while (type_index >= (int)_slots_by_type.size()) {
+    _slots_by_type.push_back(0);
+  }
+
+  if (_slots_by_type[type_index] != 0) {
+    // This type has already been registered.
+    return _slots_by_type[type_index];
+  }
+
+  int slot = (int)_registry.size();
+  if (slot >= _max_slots) {
+    pgraph_cat->error()
+      << "Too many registered RenderAttribs; not registering " 
+      << type_handle << "\n";
+    nassertr(false, 0);
+    return 0;
+  }
+
+  _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);
+
+  _sorted_slots.push_back(slot);
+  ::sort(_sorted_slots.begin(), _sorted_slots.end(), SortSlots(this));
+
+  return slot;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttribRegistry::set_slot_sort
+//       Access: Published
+//  Description: Changes the sort number associated with slot n.
+////////////////////////////////////////////////////////////////////
+void RenderAttribRegistry::
+set_slot_sort(int slot, int sort) {
+  nassertv(slot >= 0 && slot < (int)_registry.size());
+  _registry[slot]._sort = 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
+//  Description:
+////////////////////////////////////////////////////////////////////
+void RenderAttribRegistry::
+init_global_ptr() {
+  _global_ptr = new RenderAttribRegistry;
+}

+ 107 - 0
panda/src/pgraph/renderAttribRegistry.h

@@ -0,0 +1,107 @@
+// Filename: renderAttribRegistry.h
+// Created by:  drose (13Nov08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 RENDERATTRIBREGISTRY_H
+#define RENDERATTRIBREGISTRY_H
+
+#include "pandabase.h"
+#include "typeHandle.h"
+#include "vector_int.h"
+#include "pointerTo.h"
+#include "bitMask.h"
+
+class RenderAttrib;
+class DeletedBufferChain;
+
+////////////////////////////////////////////////////////////////////
+//       Class : RenderAttribRegistry
+// Description : This class is used to associate each RenderAttrib
+//               with a different slot index at runtime, so we can
+//               store a list of RenderAttribs in the RenderState
+//               object, and very quickly look them up by type.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA_PGRAPH RenderAttribRegistry {
+private:
+  RenderAttribRegistry();
+  ~RenderAttribRegistry();
+
+public:
+  typedef CPT(RenderAttrib) MakeDefaultFunc();
+
+  // This typedef defines the native bitmask type for indicating which
+  // slots are present in a RenderState.  It must be wide enough to
+  // allow room for all of the possible RenderAttribs that might
+  // register themselves.  Presently, 32 bits is wide enough, but only
+  // barely; when we exceed this limit, we will need to go to a 64-bit
+  // type instead.  It will be interesting to see whether a BitMask64
+  // or a DoubleBitMask<BitMask32> will be faster on a 32-bit machine.
+  typedef BitMask32 SlotMask;
+
+  int register_slot(TypeHandle type_handle, int sort,
+                    MakeDefaultFunc *make_default_func);
+
+PUBLISHED:
+  INLINE int get_slot(TypeHandle type_handle) const;
+  INLINE int get_max_slots() const;
+
+  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 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:
+  INLINE static RenderAttribRegistry *quick_get_global_ptr();
+
+private:
+  static void init_global_ptr();
+
+private:
+  int _max_slots;
+
+  class SortSlots {
+  public:
+    INLINE SortSlots(RenderAttribRegistry *reg);
+    INLINE bool operator () (int a, int b) const;
+    RenderAttribRegistry *_reg;
+  };
+
+  class RegistryNode {
+  public:
+    TypeHandle _type;
+    int _sort;
+    MakeDefaultFunc *_make_default_func;
+  };
+  typedef pvector<RegistryNode> Registry;
+  Registry _registry;
+
+  vector_int _slots_by_type;
+  vector_int _sorted_slots;
+
+  DeletedBufferChain *_array_chain;
+
+  static RenderAttribRegistry *_global_ptr;
+};
+
+#include "renderAttribRegistry.I"
+
+#endif
+

+ 13 - 28
panda/src/pgraph/renderModeAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "renderModeAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle RenderModeAttrib::_type_handle;
+int RenderModeAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderModeAttrib::make
@@ -51,6 +51,18 @@ make(RenderModeAttrib::Mode mode, float thickness, bool perspective) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderModeAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) RenderModeAttrib::
+make_default() {
+  return return_new(new RenderModeAttrib(M_filled, 1.0f, false));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderModeAttrib::output
 //       Access: Public, Virtual
@@ -148,33 +160,6 @@ compose_impl(const RenderAttrib *other) const {
   return make(mode, ta->get_thickness(), ta->get_perspective());
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RenderModeAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived RenderModeAttrib
-//               types to specify what the default property for a
-//               RenderModeAttrib of this type should be.
-//
-//               This should return a newly-allocated RenderModeAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of RenderModeAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *RenderModeAttrib::
-make_default_impl() const {
-  return new RenderModeAttrib(M_filled, 1.0f, false);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderModeAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void RenderModeAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_render_mode = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderModeAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/renderModeAttrib.h

@@ -53,6 +53,7 @@ private:
 PUBLISHED:
   static CPT(RenderAttrib) make(Mode mode, float thickness = 1.0f,
                                 bool perspective = false);
+  static CPT(RenderAttrib) make_default();
 
   INLINE Mode get_mode() const;
   INLINE float get_thickness() const;
@@ -62,18 +63,24 @@ PUBLISHED:
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   Mode _mode;
   float _thickness;
   bool _perspective;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -90,6 +97,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "RenderModeAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -98,6 +106,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "renderModeAttrib.I"

+ 110 - 338
panda/src/pgraph/renderState.I

@@ -20,58 +20,127 @@
 ////////////////////////////////////////////////////////////////////
 INLINE bool RenderState::
 is_empty() const {
-  return _attributes.empty();
+  return _filled_slots.is_zero();
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_num_attribs
+//     Function: RenderState::has_cull_callback
 //       Access: Published
-//  Description: Returns the number of separate attributes indicated
-//               in the state.
+//  Description: Returns true if any of the RenderAttribs in this
+//               state request a cull_callback(), false if none of
+//               them do.
 ////////////////////////////////////////////////////////////////////
-INLINE int RenderState::
-get_num_attribs() const {
-  return _attributes.size();
+INLINE bool RenderState::
+has_cull_callback() const {
+  if ((_flags & F_checked_cull_callback) == 0) {
+    // We pretend this function is const, even though it transparently
+    // modifies the internal shader cache.
+    ((RenderState *)this)->determine_cull_callback();
+  }
+  return (_flags & F_has_cull_callback) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::remove_attrib
+//       Access: Published
+//  Description: Returns a new RenderState object that represents the
+//               same as the source state, with the indicated
+//               RenderAttrib removed.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(RenderState) RenderState::
+remove_attrib(TypeHandle type) const {
+  RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
+  int slot = reg->get_slot(type);
+  return remove_attrib(slot);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::has_attrib
+//       Access: Published
+//  Description: Returns true if an attrib of the indicated type is
+//               present, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool RenderState::
+has_attrib(TypeHandle type) const {
+  return get_attrib(type) != (RenderAttrib *)NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::has_attrib
+//       Access: Published
+//  Description: Returns true if an attrib of the indicated type is
+//               present, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool RenderState::
+has_attrib(int slot) const {
+  return get_attrib(slot) != (RenderAttrib *)NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::get_attrib
 //       Access: Published
-//  Description: Returns the nth attribute in the state.
+//  Description: Looks for a RenderAttrib of the indicated type in the
+//               state, and returns it if it is found, or NULL if it
+//               is not.
 ////////////////////////////////////////////////////////////////////
 INLINE const RenderAttrib *RenderState::
-get_attrib(int n) const {
-  nassertr(n >= 0 && n < (int)_attributes.size(), NULL);
-  return _attributes[n]._attrib;
+get_attrib(TypeHandle type) const {
+  RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
+  int slot = reg->get_slot(type);
+  return _attributes[slot]._attrib;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::get_attrib
+//       Access: Published
+//  Description: Returns the RenderAttrib with the indicated slot
+//               index, or NULL if there is no such RenderAttrib in
+//               the state.
+////////////////////////////////////////////////////////////////////
+INLINE const RenderAttrib *RenderState::
+get_attrib(int slot) const {
+  return _attributes[slot]._attrib;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::get_attrib_def
+//       Access: Published
+//  Description: Returns the RenderAttrib with the indicated slot
+//               index, or the default attrib for that slot if there
+//               is no such RenderAttrib in the state.
+////////////////////////////////////////////////////////////////////
+INLINE const RenderAttrib *RenderState::
+get_attrib_def(int slot) const {
+  if (_attributes[slot]._attrib != (RenderAttrib *)NULL) {
+    return _attributes[slot]._attrib;
+  }
+  return make_full_default()->get_attrib(slot);
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::get_override
 //       Access: Published
-//  Description: Returns the override associated with the nth
-//               attribute in the state.
+//  Description: Looks for a RenderAttrib of the indicated type in the
+//               state, and returns its override value if it is found,
+//               or 0 if it is not.
 ////////////////////////////////////////////////////////////////////
 INLINE int RenderState::
-get_override(int n) const {
-  nassertr(n >= 0 && n < (int)_attributes.size(), 0);
-  return _attributes[n]._override;
+get_override(TypeHandle type) const {
+  RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
+  int slot = reg->get_slot(type);
+  return _attributes[slot]._override;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: RenderState::has_cull_callback
+//     Function: RenderState::get_override
 //       Access: Published
-//  Description: Returns true if any of the RenderAttribs in this
-//               state request a cull_callback(), false if none of
-//               them do.
+//  Description: Looks for a RenderAttrib of the indicated type in the
+//               state, and returns its override value if it is found,
+//               or 0 if it is not.
 ////////////////////////////////////////////////////////////////////
-INLINE bool RenderState::
-has_cull_callback() const {
-  if ((_flags & F_checked_cull_callback) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal shader cache.
-    ((RenderState *)this)->determine_cull_callback();
-  }
-  return (_flags & F_has_cull_callback) != 0;
+INLINE int RenderState::
+get_override(int slot) const {
+  return _attributes[slot]._override;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -157,63 +226,6 @@ get_draw_order() const {
   return _draw_order;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_fog
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a FogAttrib on this state.  It returns a
-//               pointer to the FogAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const FogAttrib *RenderState::
-get_fog() const {
-  if ((_flags & F_checked_fog) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal fog cache.
-    ((RenderState *)this)->determine_fog();
-  }
-  return _fog;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_bin
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a BinAttrib on this state.  It returns a
-//               pointer to the BinAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const CullBinAttrib *RenderState::
-get_bin() const {
-  if ((_flags & F_checked_bin) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal bin cache.
-    ((RenderState *)this)->determine_bin();
-  }
-  return _bin;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_transparency
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a TransparencyAttrib on this state.  It returns a
-//               pointer to the TransparencyAttrib, if there is one,
-//               or NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const TransparencyAttrib *RenderState::
-get_transparency() const {
-  if ((_flags & F_checked_transparency) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal transparency cache.
-    ((RenderState *)this)->determine_transparency();
-  }
-  return _transparency;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::get_bin_index
 //       Access: Published
@@ -233,218 +245,6 @@ get_bin_index() const {
   return _bin_index;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_color
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a ColorAttrib on this state.  It returns a
-//               pointer to the ColorAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const ColorAttrib *RenderState::
-get_color() const {
-  if ((_flags & F_checked_color) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal color cache.
-    ((RenderState *)this)->determine_color();
-  }
-  return _color;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_color_scale
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a ColorScaleAttrib on this state.  It returns a
-//               pointer to the ColorScaleAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const ColorScaleAttrib *RenderState::
-get_color_scale() const {
-  if ((_flags & F_checked_color_scale) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal color_scale cache.
-    ((RenderState *)this)->determine_color_scale();
-  }
-  return _color_scale;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_texture
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a TextureAttrib on this state.  It returns a
-//               pointer to the TextureAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const TextureAttrib *RenderState::
-get_texture() const {
-  if ((_flags & F_checked_texture) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal texture cache.
-    ((RenderState *)this)->determine_texture();
-  }
-  return _texture;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_tex_gen
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a TexGenAttrib on this state.  It returns a
-//               pointer to the TexGenAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const TexGenAttrib *RenderState::
-get_tex_gen() const {
-  if ((_flags & F_checked_tex_gen) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal tex_gen cache.
-    ((RenderState *)this)->determine_tex_gen();
-  }
-  return _tex_gen;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_tex_matrix
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a TexMatrixAttrib on this state.  It returns a
-//               pointer to the TexMatrixAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const TexMatrixAttrib *RenderState::
-get_tex_matrix() const {
-  if ((_flags & F_checked_tex_matrix) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal tex_matrix cache.
-    ((RenderState *)this)->determine_tex_matrix();
-  }
-  return _tex_matrix;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_render_mode
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a RenderModeAttrib on this state.  It returns a
-//               pointer to the RenderModeAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const RenderModeAttrib *RenderState::
-get_render_mode() const {
-  if ((_flags & F_checked_render_mode) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal render_mode cache.
-    ((RenderState *)this)->determine_render_mode();
-  }
-  return _render_mode;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_clip_plane
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a ClipPlaneAttrib on this state.  It returns a
-//               pointer to the ClipPlaneAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const ClipPlaneAttrib *RenderState::
-get_clip_plane() const {
-  if ((_flags & F_checked_clip_plane) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal clip_plane cache.
-    ((RenderState *)this)->determine_clip_plane();
-  }
-  return _clip_plane;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_scissor
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a ScissorAttrib on this state.  It returns a
-//               pointer to the ScissorAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const ScissorAttrib *RenderState::
-get_scissor() const {
-  if ((_flags & F_checked_scissor) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal scissor cache.
-    ((RenderState *)this)->determine_scissor();
-  }
-  return _scissor;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_shader
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of a ShaderAttrib on this state.  It returns a
-//               pointer to the ShaderAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const ShaderAttrib *RenderState::
-get_shader() const {
-  if ((_flags & F_checked_shader) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal shader cache.
-    ((RenderState *)this)->determine_shader();
-  }
-  return _shader;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_audio_volume
-//       Access: Published
-//  Description: This function is provided as an optimization, to
-//               speed up the render-time checking for the existance
-//               of an AudioVolumeAttrib on this state.  It returns a
-//               pointer to the AudioVolumeAttrib, if there is one, or
-//               NULL if there is not.
-////////////////////////////////////////////////////////////////////
-INLINE const AudioVolumeAttrib *RenderState::
-get_audio_volume() const {
-  if ((_flags & F_checked_audio_volume) == 0) {
-    // We pretend this function is const, even though it transparently
-    // modifies the internal audio_volume cache.
-    ((RenderState *)this)->determine_audio_volume();
-  }
-  return _audio_volume;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::determine_bin
-//       Access: Private
-//  Description: This is the private implementation of get_bin().
-////////////////////////////////////////////////////////////////////
-INLINE void RenderState::
-determine_bin() {
-  LightMutexHolder holder(_lock);
-  do_determine_bin();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::determine_transparency
-//       Access: Private
-//  Description: This is the private implementation of get_transparency().
-////////////////////////////////////////////////////////////////////
-INLINE void RenderState::
-determine_transparency() {
-  LightMutexHolder holder(_lock);
-  do_determine_transparency();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::set_destructing
 //       Access: Private
@@ -522,7 +322,6 @@ Composition(const RenderState::Composition &copy) :
 ////////////////////////////////////////////////////////////////////
 INLINE RenderState::Attribute::
 Attribute(const RenderAttrib *attrib, int override) :
-  _type(attrib->get_type()),
   _attrib(attrib),
   _override(override)
 {
@@ -531,9 +330,7 @@ Attribute(const RenderAttrib *attrib, int override) :
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::Attribute::Constructor
 //       Access: Public
-//  Description: This constructor is only used when reading the
-//               RenderState from a bam file.  At this point, the
-//               attribute pointer is unknown.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE RenderState::Attribute::
 Attribute(int override) :
@@ -541,22 +338,6 @@ Attribute(int override) :
 {
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::Attribute::Constructor
-//       Access: Public
-//  Description: This constructor makes an invalid Attribute with no
-//               RenderAttrib pointer; its purpose is just to make an
-//               object we can use to look up a particular type in the
-//               Attribute set.
-////////////////////////////////////////////////////////////////////
-INLINE RenderState::Attribute::
-Attribute(TypeHandle type) :
-  _type(type),
-  _attrib(NULL),
-  _override(0)
-{
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::Attribute::Copy Constructor
 //       Access: Public
@@ -564,7 +345,6 @@ Attribute(TypeHandle type) :
 ////////////////////////////////////////////////////////////////////
 INLINE RenderState::Attribute::
 Attribute(const Attribute &copy) :
-  _type(copy._type),
   _attrib(copy._attrib),
   _override(copy._override)
 {
@@ -577,45 +357,37 @@ Attribute(const Attribute &copy) :
 ////////////////////////////////////////////////////////////////////
 INLINE void RenderState::Attribute::
 operator = (const Attribute &copy) {
-  _type = copy._type;
   _attrib = copy._attrib;
   _override = copy._override;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RenderState::Attribute::operator <
-//       Access: Public
-//  Description: This is used by the Attributes set to uniquify
-//               RenderAttributes by type.  Only one RenderAttrib of a
-//               given type is allowed in the set.  This ordering must
-//               also match the ordering reported by compare_to().
-////////////////////////////////////////////////////////////////////
-INLINE bool RenderState::Attribute::
-operator < (const Attribute &other) const {
-  return _type < other._type;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::Attribute::compare_to
 //       Access: Public
 //  Description: Provides an indication of whether a particular
 //               attribute is equivalent to another one, for purposes
 //               of generating unique RenderStates.  This should
-//               compare all properties of the Attribute, but it is
-//               important that the type is compared first, to be
-//               consistent with the ordering defined by operator <.
+//               compare all properties of the Attribute.
 ////////////////////////////////////////////////////////////////////
 INLINE int RenderState::Attribute::
 compare_to(const Attribute &other) const {
-  if (_type != other._type) {
-    return _type.get_index() - other._type.get_index();
-  }
   if (_attrib != other._attrib) {
     return _attrib < other._attrib ? -1 : 1;
   }
   return _override - other._override;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::Attribute::set
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void RenderState::Attribute::
+set(const RenderAttrib *attrib, int override) {
+  _attrib = attrib;
+  _override = override;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::flush_level
 //       Access: Public, Static

File diff suppressed because it is too large
+ 369 - 383
panda/src/pgraph/renderState.cxx


+ 35 - 93
panda/src/pgraph/renderState.h

@@ -20,7 +20,7 @@
 #include "renderAttrib.h"
 #include "nodeCachedReferenceCount.h"
 #include "pointerTo.h"
-#include "ordered_vector.h"
+#include "pvector.h"
 #include "updateSeq.h"
 #include "pStatCollector.h"
 #include "renderModeAttrib.h"
@@ -32,20 +32,11 @@
 #include "deletedChain.h"
 #include "simpleHashMap.h"
 #include "cacheStats.h"
+#include "renderAttribRegistry.h"
 
 class GraphicsStateGuardianBase;
-class FogAttrib;
-class CullBinAttrib;
-class TransparencyAttrib;
-class ColorAttrib;
-class ColorScaleAttrib;
-class TextureAttrib;
-class TexGenAttrib;
-class ClipPlaneAttrib;
-class ScissorAttrib;
-class ShaderAttrib;
 class FactoryParams;
-class AudioVolumeAttrib;
+class ShaderAttrib;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : RenderState
@@ -71,21 +62,20 @@ public:
   virtual ~RenderState();
   ALLOC_DELETED_CHAIN(RenderState);
 
+  typedef RenderAttribRegistry::SlotMask SlotMask;
+
 PUBLISHED:
   bool operator < (const RenderState &other) const;
+  int compare_sort(const RenderState &other) const;
   size_t get_hash() const;
 
   INLINE bool is_empty() const;
-  INLINE int get_num_attribs() const;
-  INLINE const RenderAttrib *get_attrib(int n) const;
-  INLINE int get_override(int n) const;
 
   INLINE bool has_cull_callback() const;
   bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
 
-  int find_attrib(TypeHandle type) const;
-
   static CPT(RenderState) make_empty();
+  static CPT(RenderState) make_full_default();
   static CPT(RenderState) make(const RenderAttrib *attrib, int override = 0);
   static CPT(RenderState) make(const RenderAttrib *attrib1,
                                const RenderAttrib *attrib2, int override = 0);
@@ -98,7 +88,6 @@ PUBLISHED:
                                const RenderAttrib *attrib4, int override = 0);
   static CPT(RenderState) make(const RenderAttrib * const *attrib,
                                int num_attribs, int override = 0);
-  static CPT(RenderState) make(const AttribSlots *slots, int override = 0);
   
   CPT(RenderState) compose(const RenderState *other) const;
   CPT(RenderState) invert_compose(const RenderState *other) const;
@@ -106,12 +95,18 @@ PUBLISHED:
   CPT(RenderState) add_attrib(const RenderAttrib *attrib, int override = 0) const;
   CPT(RenderState) set_attrib(const RenderAttrib *attrib) const;
   CPT(RenderState) set_attrib(const RenderAttrib *attrib, int override) const;
-  CPT(RenderState) remove_attrib(TypeHandle type) const;
+  INLINE CPT(RenderState) remove_attrib(TypeHandle type) const;
+  CPT(RenderState) remove_attrib(int slot) const;
 
   CPT(RenderState) adjust_all_priorities(int adjustment) const;
 
-  const RenderAttrib *get_attrib(TypeHandle type) const;
-  int get_override(TypeHandle type) const;
+  INLINE bool has_attrib(TypeHandle type) const;
+  INLINE bool has_attrib(int slot) const;
+  INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
+  INLINE const RenderAttrib *get_attrib(int slot) const;
+  INLINE const RenderAttrib *get_attrib_def(int slot) const;
+  INLINE int get_override(TypeHandle type) const;
+  INLINE int get_override(int slot) const;
 
   bool unref() const;
 
@@ -137,33 +132,18 @@ PUBLISHED:
   // These methods are intended for use by low-level code, but they're
   // also handy enough to expose to high-level users.
   INLINE int get_draw_order() const;
-  INLINE const FogAttrib *get_fog() const;
-  INLINE const CullBinAttrib *get_bin() const;
-  INLINE const TransparencyAttrib *get_transparency() const;
   INLINE int get_bin_index() const;
-  INLINE const ColorAttrib *get_color() const;
-  INLINE const ColorScaleAttrib *get_color_scale() const;
-  INLINE const TextureAttrib *get_texture() const;
-  INLINE const TexGenAttrib *get_tex_gen() const;
-  INLINE const TexMatrixAttrib *get_tex_matrix() const;
-  INLINE const RenderModeAttrib *get_render_mode() const;
-  INLINE const ClipPlaneAttrib *get_clip_plane() const;
-  INLINE const ScissorAttrib *get_scissor() const;
-  INLINE const ShaderAttrib *get_shader() const;
-  INLINE const AudioVolumeAttrib *get_audio_volume() const;
-  
   int get_geom_rendering(int geom_rendering) const;
-
   const ShaderAttrib *get_generated_shader() const;
   
 public:
-  void store_into_slots(AttribSlots *slots) const;
-  
   static void bin_removed(int bin_index);
   
   INLINE static void flush_level();
 
 private:
+  void determine_filled_slots();
+  bool validate_filled_slots() const;
   INLINE bool do_cache_unref() const;
   INLINE bool do_node_unref() const;
 
@@ -191,22 +171,8 @@ private:
   void remove_cache_pointers();
 
   void determine_bin_index();
-  void determine_fog();
-  INLINE void determine_bin();
-  void do_determine_bin();
-  INLINE void determine_transparency();
-  void do_determine_transparency();
-  void determine_color();
-  void determine_color_scale();
-  void determine_texture();
-  void determine_tex_gen();
-  void determine_tex_matrix();
-  void determine_render_mode();
-  void determine_clip_plane();
-  void determine_scissor();
-  void determine_shader();
   void determine_cull_callback();
-  void determine_audio_volume();
+  void fill_default();
 
   INLINE void set_destructing();
   INLINE bool is_destructing() const;
@@ -225,6 +191,7 @@ private:
   typedef phash_set<const RenderState *, indirect_less_hash<const RenderState *> > States;
   static States *_states;
   static CPT(RenderState) _empty_state;
+  static CPT(RenderState) _full_default_state;
 
   // This iterator records the entry corresponding to this RenderState
   // object in the above global set.  We keep the iterator around so
@@ -277,23 +244,24 @@ private:
 
 private:
   // This is the actual data within the RenderState: a set of
-  // RenderAttribs.
+  // max_slots RenderAttribs.
   class Attribute {
   public:
     INLINE Attribute(const RenderAttrib *attrib, int override);
-    INLINE Attribute(int override);
-    INLINE Attribute(TypeHandle type);
+    INLINE Attribute(int override = 0);
     INLINE Attribute(const Attribute &copy);
     INLINE void operator = (const Attribute &copy);
-    INLINE bool operator < (const Attribute &other) const;
+    INLINE void set(const RenderAttrib *attrib, int override);
     INLINE int compare_to(const Attribute &other) const;
 
-    TypeHandle _type;
     CPT(RenderAttrib) _attrib;
     int _override;
   };
-  typedef ov_set<Attribute> Attributes;
-  Attributes _attributes;
+  Attribute *_attributes;
+
+  // We also store a bitmask of the non-NULL attributes in the above
+  // array.  This is redundant, but it is a useful cache.
+  SlotMask _filled_slots;
 
   // We cache the index to the associated CullBin, if there happens to
   // be a CullBinAttrib in the state.
@@ -305,44 +273,17 @@ private:
   // I can't declare this as a ShaderAttrib because that would create
   // a circular include-file dependency problem.  Aaargh.
   CPT(RenderAttrib) _generated_shader;
-  
-  // We also cache the pointer to some critical attribs stored in the
-  // state, if they exist.
-  const FogAttrib *_fog;
-  const CullBinAttrib *_bin;
-  const TransparencyAttrib *_transparency;
-  const ColorAttrib *_color;
-  const ColorScaleAttrib *_color_scale;
-  const TextureAttrib *_texture;
-  const TexGenAttrib *_tex_gen;
-  const TexMatrixAttrib *_tex_matrix;
-  const RenderModeAttrib *_render_mode;
-  const ClipPlaneAttrib *_clip_plane;
-  const ScissorAttrib *_scissor;
-  const ShaderAttrib *_shader;
-  const AudioVolumeAttrib *_audio_volume;
-  
+
   enum Flags {
     F_checked_bin_index     = 0x000001,
-    F_checked_fog           = 0x000002,
-    F_checked_bin           = 0x000004,
-    F_checked_transparency  = 0x000008,
-    F_checked_color         = 0x000010,
-    F_checked_color_scale   = 0x000020,
-    F_checked_texture       = 0x000040,
-    F_checked_tex_gen       = 0x000080,
-    F_checked_tex_matrix    = 0x000100,
-    F_checked_render_mode   = 0x000200,
-    F_checked_clip_plane    = 0x000400,
-    F_checked_shader        = 0x000800,
-    F_checked_cull_callback = 0x001000,
-    F_checked_audio_volume  = 0x002000,
-    F_has_cull_callback     = 0x004000,
-    F_is_destructing        = 0x008000,
-    F_checked_scissor       = 0x010000,
+    F_checked_cull_callback = 0x000002,
+    F_has_cull_callback     = 0x000004,
+    F_is_destructing        = 0x000008,
   };
   unsigned int _flags;
 
+  vector_int *_read_overrides;  // Only used during bam reading.
+
   // This mutex protects _flags, and all of the above computed values.
   LightMutex _lock;
 
@@ -377,6 +318,7 @@ private:
   static TypeHandle _type_handle;
 
   friend class GraphicsStateGuardian;
+  friend class RenderAttribRegistry;
 };
 
 INLINE ostream &operator << (ostream &out, const RenderState &state) {

+ 1 - 28
panda/src/pgraph/rescaleNormalAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "rescaleNormalAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "string_utils.h"
 #include "dcast.h"
@@ -24,6 +23,7 @@
 #include "configVariableEnum.h"
 
 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
@@ -96,33 +96,6 @@ compare_to_impl(const RenderAttrib *other) const {
   return (int)_mode - (int)ta->_mode;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: RescaleNormalAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived RescaleNormalAttrib
-//               types to specify what the default property for a
-//               RescaleNormalAttrib of this type should be.
-//
-//               This should return a newly-allocated RescaleNormalAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of RescaleNormalAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *RescaleNormalAttrib::
-make_default_impl() const {
-  return new RescaleNormalAttrib(M_none);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: RescaleNormalAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void RescaleNormalAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_rescale_normal = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: RescaleNormalAttrib::register_with_read_factory
 //       Access: Public, Static

+ 10 - 2
panda/src/pgraph/rescaleNormalAttrib.h

@@ -55,15 +55,21 @@ PUBLISHED:
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   Mode _mode;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -80,6 +86,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "RescaleNormalAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -88,6 +95,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 EXPCL_PANDA_PGRAPH ostream &operator << (ostream &out, RescaleNormalAttrib::Mode mode);

+ 2 - 2
panda/src/pgraph/sceneGraphAnalyzer.cxx

@@ -280,7 +280,7 @@ collect_statistics(PandaNode *node, bool under_instance) {
   if (!node->get_state()->is_empty()) {
     _num_nodes_with_attribs++;
     const RenderAttrib *attrib = 
-      node->get_attrib(TextureAttrib::get_class_type());
+      node->get_attrib(TextureAttrib::get_class_slot());
     if (attrib != (RenderAttrib *)NULL) {
       const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
       for (int i = 0; i < ta->get_num_on_stages(); i++) {
@@ -350,7 +350,7 @@ collect_statistics(GeomNode *geom_node) {
     const RenderState *geom_state = geom_node->get_geom_state(i);
 
     const RenderAttrib *attrib = 
-      geom_state->get_attrib(TextureAttrib::get_class_type());
+      geom_state->get_attrib(TextureAttrib::get_class_slot());
     if (attrib != (RenderAttrib *)NULL) {
       const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
       for (int i = 0; i < ta->get_num_on_stages(); i++) {

+ 2 - 0
panda/src/pgraph/sceneSetup.h

@@ -24,6 +24,8 @@
 #include "lens.h"
 #include "pointerTo.h"
 
+class DisplayRegion;
+
 ////////////////////////////////////////////////////////////////////
 //       Class : SceneSetup
 // Description : This object holds the camera position, etc., and

+ 13 - 28
panda/src/pgraph/scissorAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "scissorAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle ScissorAttrib::_type_handle;
+int ScissorAttrib::_attrib_slot;
 CPT(RenderAttrib) ScissorAttrib::_off;
 
 ////////////////////////////////////////////////////////////////////
@@ -71,6 +71,18 @@ make(const LVecBase4f &frame) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ScissorAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ScissorAttrib::
+make_default() {
+  return return_new(new ScissorAttrib(LVecBase4f(0.0f, 1.0f, 0.0f, 1.0f)));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ScissorAttrib::output
 //       Access: Public, Virtual
@@ -134,33 +146,6 @@ compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ScissorAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived ScissorAttrib
-//               types to specify what the default property for a
-//               ScissorAttrib of this type should be.
-//
-//               This should return a newly-allocated ScissorAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of ScissorAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *ScissorAttrib::
-make_default_impl() const {
-  return new ScissorAttrib(LVecBase4f(0.0f, 1.0f, 0.0f, 1.0f));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ScissorAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void ScissorAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_scissor = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ScissorAttrib::register_with_read_factory
 //       Access: Public, Static

+ 11 - 2
panda/src/pgraph/scissorAttrib.h

@@ -46,22 +46,29 @@ PUBLISHED:
   static CPT(RenderAttrib) make_off();
   INLINE static CPT(RenderAttrib) make(float left, float right, float bottom, float top);
   static CPT(RenderAttrib) make(const LVecBase4f &frame);
+  static CPT(RenderAttrib) make_default();
 
   INLINE const LVecBase4f &get_frame() const;
 
 public:
   virtual void output(ostream &out) const;
-  virtual void store_into_slot(AttribSlots *slots) const;
 
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
-  virtual RenderAttrib *make_default_impl() const;
 
 private:
   LVecBase4f _frame;
   static CPT(RenderAttrib) _off;
 
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
@@ -78,6 +85,7 @@ public:
     RenderAttrib::init_type();
     register_type(_type_handle, "ScissorAttrib",
                   RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, make_default);
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -86,6 +94,7 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  static int _attrib_slot;
 };
 
 #include "scissorAttrib.I"

+ 13 - 28
panda/src/pgraph/shadeModelAttrib.cxx

@@ -13,7 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "shadeModelAttrib.h"
-#include "attribSlots.h"
 #include "graphicsStateGuardianBase.h"
 #include "dcast.h"
 #include "bamReader.h"
@@ -22,6 +21,7 @@
 #include "datagramIterator.h"
 
 TypeHandle ShadeModelAttrib::_type_handle;
+int ShadeModelAttrib::_attrib_slot;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: ShadeModelAttrib::make
@@ -36,6 +36,18 @@ make(ShadeModelAttrib::Mode mode) {
   return return_new(attrib);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ShadeModelAttrib::make_default
+//       Access: Published, Static
+//  Description: Returns a RenderAttrib that corresponds to whatever
+//               the standard default properties for render attributes
+//               of this type ought to be.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShadeModelAttrib::
+make_default() {
+  return return_new(new ShadeModelAttrib(M_smooth));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ShadeModelAttrib::output
 //       Access: Public, Virtual
@@ -103,33 +115,6 @@ compose_impl(const RenderAttrib *other) const {
   return make(mode);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: ShadeModelAttrib::make_default_impl
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by derived ShadeModelAttrib
-//               types to specify what the default property for a
-//               ShadeModelAttrib of this type should be.
-//
-//               This should return a newly-allocated ShadeModelAttrib of
-//               the same type that corresponds to whatever the
-//               standard default for this kind of ShadeModelAttrib is.
-////////////////////////////////////////////////////////////////////
-RenderAttrib *ShadeModelAttrib::
-make_default_impl() const {
-  return new ShadeModelAttrib(M_smooth);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShadeModelAttrib::store_into_slot
-//       Access: Public, Virtual
-//  Description: Stores this attrib into the appropriate slot of
-//               an object of class AttribSlots.
-////////////////////////////////////////////////////////////////////
-void ShadeModelAttrib::
-store_into_slot(AttribSlots *slots) const {
-  slots->_shade_model = this;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: ShadeModelAttrib::register_with_read_factory
 //       Access: Public, Static

Some files were not shown because too many files changed in this diff