Quellcode durchsuchen

merge shader_overhaul from jyelon

David Rose vor 19 Jahren
Ursprung
Commit
1fdb425b88

+ 30 - 30
panda/src/display/graphicsStateGuardian.cxx

@@ -783,7 +783,7 @@ clear(DrawableRegion *clearable) {
 //
 ////////////////////////////////////////////////////////////////////
 const LMatrix4f *GraphicsStateGuardian::
-fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
+fetch_specified_value(ShaderExpansion::ShaderMatSpec &spec, bool altered) {
   static LMatrix4f acc;
   const LMatrix4f *val1;
   const LMatrix4f *val2;
@@ -791,26 +791,26 @@ fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
   static LMatrix4f t2;
 
   switch(spec._func) {
-  case ShaderContext::SMF_compose:
+  case ShaderExpansion::SMF_compose:
     val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
     val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
     acc.multiply(*val1, *val2);
     return &acc;
-  case ShaderContext::SMF_compose_cache_first:
+  case ShaderExpansion::SMF_compose_cache_first:
     if (altered) {
       spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1);
     }
     val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
     acc.multiply(spec._cache, *val2);
     return &acc;
-  case ShaderContext::SMF_compose_cache_second:
+  case ShaderExpansion::SMF_compose_cache_second:
     if (altered) {
       spec._cache = *fetch_specified_part(spec._part[1], spec._arg[1], t2);
     }
     val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
     acc.multiply(*val1, spec._cache);
     return &acc;
-  case ShaderContext::SMF_first:
+  case ShaderExpansion::SMF_first:
     return fetch_specified_part(spec._part[0], spec._arg[0], t1);
   default:
     // should never get here
@@ -824,24 +824,24 @@ fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
 //  Description: See fetch_specified_value
 ////////////////////////////////////////////////////////////////////
 const LMatrix4f *GraphicsStateGuardian::
-fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMatrix4f &t) {
+fetch_specified_part(ShaderExpansion::ShaderMatInput part, InternalName *name, LMatrix4f &t) {
   switch(part) {
-  case ShaderContext::SMO_identity: {
+  case ShaderExpansion::SMO_identity: {
     return &LMatrix4f::ident_mat();
   }
-  case ShaderContext::SMO_window_size: {
+  case ShaderExpansion::SMO_window_size: {
     t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
                                  _current_display_region->get_pixel_height(),
                                  0.0);
     return &t;
   }
-  case ShaderContext::SMO_pixel_size: {
+  case ShaderExpansion::SMO_pixel_size: {
     t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
                                  _current_display_region->get_pixel_height(),
                                  0.0);
     return &t;
   }
-  case ShaderContext::SMO_card_center: {
+  case ShaderExpansion::SMO_card_center: {
     int px = _current_display_region->get_pixel_width();
     int py = _current_display_region->get_pixel_height();
     t = LMatrix4f::translate_mat((px*0.5) / Texture::up_to_power_2(px),
@@ -849,14 +849,14 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
                                  0.0);
     return &t;
   }
-  case ShaderContext::SMO_mat_constant_x: {
+  case ShaderExpansion::SMO_mat_constant_x: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
     if (input->get_nodepath().is_empty()) {
       return &LMatrix4f::ident_mat();
     }
     return &(input->get_nodepath().node()->get_transform()->get_mat());
   }
-  case ShaderContext::SMO_vec_constant_x: {
+  case ShaderExpansion::SMO_vec_constant_x: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
     const float *data = input->get_vector().get_data();
     t = LMatrix4f(data[0],data[1],data[2],data[3],
@@ -865,28 +865,28 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
                   data[0],data[1],data[2],data[3]);
     return &t;
   }
-  case ShaderContext::SMO_world_to_view: {
+  case ShaderExpansion::SMO_world_to_view: {
     return &(get_scene()->get_world_transform()->get_mat());
     break;
   }
-  case ShaderContext::SMO_view_to_world: {
+  case ShaderExpansion::SMO_view_to_world: {
     return &(get_scene()->get_camera_transform()->get_mat());
   }
-  case ShaderContext::SMO_model_to_view: {
+  case ShaderExpansion::SMO_model_to_view: {
     return &(get_external_transform()->get_mat());
   }
-  case ShaderContext::SMO_view_to_model: {
+  case ShaderExpansion::SMO_view_to_model: {
     // DANGER: SLOW AND NOT CACHEABLE!
     t.invert_from(get_external_transform()->get_mat());
     return &t;
   }
-  case ShaderContext::SMO_apiview_to_view: {
+  case ShaderExpansion::SMO_apiview_to_view: {
     return &(_inv_cs_transform->get_mat());
   }
-  case ShaderContext::SMO_view_to_apiview: {
+  case ShaderExpansion::SMO_view_to_apiview: {
     return &(_cs_transform->get_mat());
   }
-  case ShaderContext::SMO_clip_to_view: {
+  case ShaderExpansion::SMO_clip_to_view: {
     if (_current_lens->get_coordinate_system() == _coordinate_system) {
       return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
     } else {
@@ -895,7 +895,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
       return &t;
     }
   }
-  case ShaderContext::SMO_view_to_clip: {
+  case ShaderExpansion::SMO_view_to_clip: {
     if (_current_lens->get_coordinate_system() == _coordinate_system) {
       return &(_current_lens->get_projection_mat(_current_stereo_channel));
     } else {
@@ -904,15 +904,15 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
       return &t;
     }
   }
-  case ShaderContext::SMO_apiclip_to_view: {
+  case ShaderExpansion::SMO_apiclip_to_view: {
     t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
     return &t;
   }
-  case ShaderContext::SMO_view_to_apiclip: {
+  case ShaderExpansion::SMO_view_to_apiclip: {
     t = _cs_transform->get_mat() * _projection_mat->get_mat();
     return &t;
   }
-  case ShaderContext::SMO_view_x_to_view: {
+  case ShaderExpansion::SMO_view_x_to_view: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
 
     if (input->get_nodepath().is_empty()) {
@@ -927,7 +927,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
       get_scene()->get_world_transform()->get_mat();
     return &t;
   }
-  case ShaderContext::SMO_view_to_view_x: {
+  case ShaderExpansion::SMO_view_to_view_x: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
 
     if (input->get_nodepath().is_empty()) {
@@ -942,7 +942,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
       invert(input->get_nodepath().get_net_transform()->get_mat());
     return &t;
   }
-  case ShaderContext::SMO_apiview_x_to_view: {
+  case ShaderExpansion::SMO_apiview_x_to_view: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
     nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
     t = LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system) *
@@ -950,7 +950,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
       get_scene()->get_world_transform()->get_mat();
     return &t;
   }
-  case ShaderContext::SMO_view_to_apiview_x: {
+  case ShaderExpansion::SMO_view_to_apiview_x: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
     nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
     t = (get_scene()->get_camera_transform()->get_mat() *
@@ -958,7 +958,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
          LMatrix4f::convert_mat(_coordinate_system, _internal_coordinate_system));
     return &t;
   }
-  case ShaderContext::SMO_clip_x_to_view: {
+  case ShaderExpansion::SMO_clip_x_to_view: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
     nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
     Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
@@ -968,7 +968,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
       get_scene()->get_world_transform()->get_mat();
     return &t;
   }
-  case ShaderContext::SMO_view_to_clip_x: {
+  case ShaderExpansion::SMO_view_to_clip_x: {
     const ShaderInput *input = _target._shader->get_shader_input(name);
     nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
     Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
@@ -978,11 +978,11 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
       lens->get_projection_mat(_current_stereo_channel);
     return &t;
   }
-  case ShaderContext::SMO_apiclip_x_to_view: {
+  case ShaderExpansion::SMO_apiclip_x_to_view: {
     // NOT IMPLEMENTED
     return &LMatrix4f::ident_mat();
   }
-  case ShaderContext::SMO_view_to_apiclip_x: {
+  case ShaderExpansion::SMO_view_to_apiclip_x: {
     // NOT IMPLEMENTED
     return &LMatrix4f::ident_mat();
   }

+ 4 - 2
panda/src/display/graphicsStateGuardian.h

@@ -194,8 +194,8 @@ public:
 
   void clear(DrawableRegion *clearable);
 
-  const LMatrix4f *fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered);
-  const LMatrix4f *fetch_specified_part(ShaderContext::ShaderMatInput input, InternalName *name, LMatrix4f &t);
+  const LMatrix4f *fetch_specified_value(ShaderExpansion::ShaderMatSpec &spec, bool altered);
+  const LMatrix4f *fetch_specified_part(ShaderExpansion::ShaderMatInput input, InternalName *name, LMatrix4f &t);
 
   virtual void prepare_display_region(DisplayRegionPipelineReader *dr,
                                       Lens::StereoChannel stereo_channel);
@@ -410,6 +410,8 @@ protected:
 
   static PT(TextureStage) _alpha_scale_texture_stage;
 
+  ShaderExpansion::ShaderCaps _shader_caps;
+
 public:
   // Statistics
   static PStatCollector _vertex_buffer_switch_pcollector;

+ 47 - 66
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -61,6 +61,9 @@
 #include "pStatTimer.h"
 #include "pStatCollector.h"
 #include "wdxGraphicsBuffer9.h"
+#ifdef HAVE_CG
+#include "Cg/cgD3D9.h"
+#endif
 
 #include <mmsystem.h>
 
@@ -147,10 +150,6 @@ DXGraphicsStateGuardian9(GraphicsPipe *pipe) :
   _vertex_shader_maximum_constants = 0;
 
   _supports_stream_offset = false;
-
-#ifdef HAVE_CGDX9
-  _cg_context = 0;
-#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -169,14 +168,6 @@ DXGraphicsStateGuardian9::
     delete _lru;
     _lru = 0;
   }
-
-#ifdef HAVE_CGDX9
-  if (_cg_context) {
-    cgD3D9SetDevice (NULL);
-    cgDestroyContext (_cg_context);
-    _cg_context = 0;
-  }
-#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -346,10 +337,9 @@ release_texture(TextureContext *tc) {
 ////////////////////////////////////////////////////////////////////
 ShaderContext *CLP(GraphicsStateGuardian)::
 prepare_shader(ShaderExpansion *se) {
-#ifdef HAVE_CGDX9
+#ifdef HAVE_CG
   CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this);
-  if (this -> _cg_context) return result;
-  delete result;
+  return result;
 #endif
   return NULL;
 }
@@ -2395,7 +2385,6 @@ reset() {
 
   _vertex_shader_maximum_constants = d3d_caps.MaxVertexShaderConst;
 
-#ifdef HAVE_CGDX9
   switch (_pixel_shader_version_major)
   {
     case 0:
@@ -2419,11 +2408,49 @@ reset() {
       _shader_model = SM_40;
       break;
   }
-#else
-  _shader_model = SM_00;
-#endif
+
   _auto_detect_shader_model = _shader_model;
 
+#ifdef HAVE_CG
+  cgD3D9SetDevice (_d3d_device);
+
+  if (cgD3D9IsProfileSupported(CG_PROFILE_PS_2_0) &&
+      cgD3D9IsProfileSupported(CG_PROFILE_VS_2_0)) {
+    _supports_basic_shaders = true;
+    _shader_caps._active_vprofile = (int)cgD3D9GetLatestVertexProfile();
+    _shader_caps._active_fprofile = (int)cgD3D9GetLatestPixelProfile();
+    _shader_caps._ultimate_vprofile = (int)CG_PROFILE_VS_3_0;
+    _shader_caps._ultimate_fprofile = (int)CG_PROFILE_PS_3_0;
+  }
+  
+  if (dxgsg9_cat.is_debug()) {
+    
+    CGprofile vertex_profile;
+    CGprofile pixel_profile;
+    
+    vertex_profile = cgD3D9GetLatestVertexProfile( );
+    pixel_profile = cgD3D9GetLatestPixelProfile( );
+    
+    const char *vertex_profile_str =
+      cgGetProfileString(vertex_profile);
+    const char *pixel_profile_str =
+      cgGetProfileString(pixel_profile);
+    
+    if (vertex_profile_str == NULL) {
+      vertex_profile_str = "(null)";
+    }
+    if (pixel_profile_str == NULL) {
+      pixel_profile_str = "(null)";
+    }
+    
+    dxgsg9_cat.debug()
+      << "\nCg vertex profile = " << vertex_profile_str << "  id = " << vertex_profile
+      << "\nCg pixel profile = " << pixel_profile_str << "  id = " << pixel_profile
+      << "\nshader model = " << _shader_model
+      << "\n";
+  }
+#endif
+
   _supports_stream_offset = (d3d_caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET) != 0;
   _screen->_supports_dynamic_textures = ((d3d_caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0);
   _screen->_supports_automatic_mipmap_generation = ((d3d_caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0);
@@ -2475,52 +2502,6 @@ reset() {
 
   this -> reset_render_states ( );
 
-  // duplicates OpenGL version (ARB_vertex_program extension and
-  // ARB_fragment_program extension)
-  if (_vertex_shader_version_major >= 1 &&
-      _pixel_shader_version_major >= 2) {
-    _supports_basic_shaders = true;
-  }
-
-#ifdef HAVE_CGDX9
-  if (_cg_context == 0) {
-    _cg_context = cgCreateContext ( );
-    cgD3D9SetDevice (_d3d_device);
-  }
-  else {
-    cgD3D9SetDevice (_d3d_device);
-  }
-
-  if (_cg_context) {
-    if (dxgsg9_cat.is_debug()) {
-
-      CGprofile vertex_profile;
-      CGprofile pixel_profile;
-
-      vertex_profile = cgD3D9GetLatestVertexProfile( );
-      pixel_profile = cgD3D9GetLatestPixelProfile( );
-
-      const char *vertex_profile_str =
-        cgGetProfileString(vertex_profile);
-      const char *pixel_profile_str =
-        cgGetProfileString(pixel_profile);
-
-      if (vertex_profile_str == NULL) {
-        vertex_profile_str = "(null)";
-      }
-      if (pixel_profile_str == NULL) {
-        pixel_profile_str = "(null)";
-      }
-
-      dxgsg9_cat.debug()
-        << "\nCg vertex profile = " << vertex_profile_str << "  id = " << vertex_profile
-        << "\nCg pixel profile = " << pixel_profile_str << "  id = " << pixel_profile
-        << "\nshader model = " << _shader_model
-        << "\n";
-    }
-  }
-#endif
-
   _max_vertices_per_array = d3d_caps.MaxVertexIndex;
   _max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount;
 
@@ -2945,7 +2926,7 @@ do_issue_shader() {
   ShaderExpansion *expansion = _target_rs->get_shader_expansion();
   if (expansion == 0) {
     if (_target._shader->get_shader() != 0) {
-      expansion = _target._shader->get_shader()->macroexpand(_target_rs);
+      expansion = _target._shader->get_shader()->macroexpand(_target_rs, _shader_caps);
       // I am casting away the const-ness of this pointer, because
       // the 'shader-expansion' field is just a cache.
       ((RenderState *)((const RenderState*)_target_rs))->

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

@@ -250,11 +250,7 @@ protected:
 
 public:
   DXScreenData *_screen;
-
-#ifdef HAVE_CGDX9
-  CGcontext _cg_context;
-#endif
-
+  
 protected:
   LPDIRECT3DDEVICE9 _d3d_device;  // same as _screen->_d3d_device, cached for spd
   IDirect3DSwapChain9 *_swap_chain;

+ 6 - 1
panda/src/dxgsg9/dxShaderContext9.I

@@ -27,6 +27,11 @@
 ////////////////////////////////////////////////////////////////////
 INLINE bool CLP(ShaderContext)::
 valid (GSG *gsg) {
-  return _state;
+#ifdef HAVE_CG
+  if (_cg_context) {
+    return true;
+  }
+#endif
+  return false;
 }
 

+ 195 - 539
panda/src/dxgsg9/dxShaderContext9.cxx

@@ -25,54 +25,14 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef HAVE_CG
+#include "Cg/cgD3D9.h"
+#endif
 
 #define DEBUG_SHADER 0
 
 TypeHandle CLP(ShaderContext)::_type_handle;
 
-static char *vertex_shader_function_name = "vshader";
-static char *pixel_shader_function_name = "fshader";
-
-#ifdef HAVE_CGDX9
-////////////////////////////////////////////////////////////////////
-//     Function: cg_type_to_panda_type
-//       Access: Public, Static
-//  Description: convert a cg shader-arg type to a panda shader-arg type.
-////////////////////////////////////////////////////////////////////
-static ShaderContext::ShaderArgType
-cg_type_to_panda_type(CGtype n) {
-  switch (n) {
-  case CG_FLOAT1:      return ShaderContext::SAT_float1;
-  case CG_FLOAT2:      return ShaderContext::SAT_float2;
-  case CG_FLOAT3:      return ShaderContext::SAT_float3;
-  case CG_FLOAT4:      return ShaderContext::SAT_float4;
-  case CG_FLOAT4x4:    return ShaderContext::SAT_float4x4;
-  case CG_SAMPLER1D:   return ShaderContext::SAT_sampler1d;
-  case CG_SAMPLER2D:   return ShaderContext::SAT_sampler2d;
-  case CG_SAMPLER3D:   return ShaderContext::SAT_sampler3d;
-  case CG_SAMPLERCUBE: return ShaderContext::SAT_samplercube;
-  default:           return ShaderContext::SAT_unknown;
-  }
-}
-#endif  // HAVE_CGDX9
-
-#ifdef HAVE_CGDX9
-////////////////////////////////////////////////////////////////////
-//     Function: cg_dir_to_panda_dir
-//       Access: Public, Static
-//  Description: convert a cg shader-arg type to a panda shader-arg type.
-////////////////////////////////////////////////////////////////////
-static ShaderContext::ShaderArgDir
-cg_dir_to_panda_dir(CGenum n) {
-  switch (n) {
-  case CG_IN:    return ShaderContext::SAD_in;
-  case CG_OUT:   return ShaderContext::SAD_out;
-  case CG_INOUT: return ShaderContext::SAD_inout;
-  default:       return ShaderContext::SAD_unknown;
-  }
-}
-#endif  // HAVE_CGDX9
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DXShaderContext9::Constructor
 //       Access: Public
@@ -80,80 +40,70 @@ cg_dir_to_panda_dir(CGenum n) {
 ////////////////////////////////////////////////////////////////////
 CLP(ShaderContext)::
 CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
-  string header;
-  s->parse_init();
-  s->parse_line(header, true, true);
-
-  _state = false;
-
-#ifdef HAVE_CGDX9
-
-  DBG_SH2  dxgsg9_cat.debug ( ) << "SHADER: Create ShaderContext \n"; DBG_E
-
-  _cg_shader = false;
-
-  _cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
-  _cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
-  _cg_program[SHADER_type_vert] = (CGprogram)0;
-  _cg_program[SHADER_type_frag] = (CGprogram)0;
 
   _vertex_size = 0;
   _vertex_element_array = 0;
-
-  _total_dx_parameters = 0;
-  _dx_parameter_array = 0;
-
-  _transpose_matrix = false;
-
   _name = s->get_name ( );
 
-  if (header == "//Cg") {
-
-    // CGcontext is created once during Reset ( )
-    if (gsg -> _cg_context == 0) {
-      release_resources();
-      dxgsg9_cat.error() << "Cg not supported by this video card.\n";
+#ifdef HAVE_CG
+  if (s->get_header() == "//Cg") {
+    
+    // Ask the shader expansion to compile itself for us and 
+    // to give us the resulting Cg program objects.
+
+    if (!s->cg_compile_for(gsg->_shader_caps,
+                           _cg_context,
+                           _cg_vprogram,
+                           _cg_fprogram, 
+                           _cg_parameter_map)) {
       return;
     }
+        
+    // Load the program.
+
+    BOOL paramater_shadowing;
+    DWORD assembly_flags;
+    
+    paramater_shadowing = FALSE;
+    assembly_flags = 0;
+    
+#if DEBUG_SHADER
+    assembly_flags |= D3DXSHADER_DEBUG;
+#endif
 
-    // Parse any directives in the source.
-    // IGNORE SPECIFIC PROFILES IN DX FOR NOW
-    if (false) {
-      string directive;
-      while (!s->parse_eof()) {
-        s->parse_line(directive, true, true);
-        vector_string pieces;
-        tokenize(directive, pieces, " \t");
-        if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
-          suggest_cg_profile(pieces[2], pieces[3]);
-        }
+    HRESULT hr;
+    bool success = true;
+    hr = cgD3D9LoadProgram(_cg_vprogram, paramater_shadowing, assembly_flags);
+    if (FAILED (hr)) {
+      dxgsg9_cat.error()
+        << "vertex shader cgD3D9LoadProgram failed "
+        << D3DERRORSTRING(hr);
+      
+      CGerror error = cgGetError();
+      if (error != CG_NO_ERROR) {
+        dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
       }
+      success = false;
     }
+    
+    hr = cgD3D9LoadProgram(_cg_fprogram, paramater_shadowing, assembly_flags);
+    if (FAILED (hr)) {
+      dxgsg9_cat.error()
+        << "pixel shader cgD3D9LoadProgram failed "
+        << D3DERRORSTRING(hr);
+      
+      CGerror error = cgGetError();
+      if (error != CG_NO_ERROR) {
+        dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
+      }
+      success = false;
+    }    
 
-    // Select a profile if no preferred profile specified in the source.
-    if (_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN) {
-      _cg_profile[SHADER_type_vert] = cgD3D9GetLatestVertexProfile( );
-    }
-    if (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN) {
-      _cg_profile[SHADER_type_frag] = cgD3D9GetLatestPixelProfile( );
-    }
-
-    // If we still haven't chosen a profile, give up.
-    if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
-        (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
+    if (!success) {
       release_resources();
-      dxgsg9_cat.error() << "Cg not supported by this video card.\n";
-      return;
     }
-
-    // Compile the program.
-    _cg_shader = true;
-    try_cg_compile(s, gsg);
-    return;
   }
 #endif
-
-  dxgsg9_cat.error() << s->get_name() << ": unrecognized shader language " << header << "\n";
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -171,340 +121,53 @@ CLP(ShaderContext)::
   }
 }
 
-#ifdef HAVE_CGDX9
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::report_cg_compile_errors
-//       Access: Public, Static
-//  Description: Used only after a Cg compile command, to print
-//               out any error messages that may have occurred
-//               during the Cg shader compilation.  The 'file'
-//               is the name of the file containing the Cg code.
-////////////////////////////////////////////////////////////////////
-void CLP(ShaderContext)::
-report_cg_compile_errors(const string &file, CGcontext ctx)
-{
-  CGerror err = cgGetError();
-  if (err != CG_NO_ERROR) {
-    if (err == CG_COMPILER_ERROR) {
-      string listing = cgGetLastListing(ctx);
-      vector_string errlines;
-      tokenize(listing, errlines, "\n");
-      for (int i=0; i<(int)errlines.size(); i++) {
-        string line = trim(errlines[i]);
-        if (line != "") {
-          dxgsg9_cat.error() << file << " " << errlines[i] << "\n";
-        }
-      }
-    } else {
-      dxgsg9_cat.error() << file << ": " << cgGetErrorString(err) << "\n";
-    }
-  }
-}
-#endif  // HAVE_CGDX9
-
-////////////////////////////////////////////////////////////////////
-//     Function: DXShaderContext9::suggest_cg_profile
-//       Access: Private
-//  Description: xyz
-////////////////////////////////////////////////////////////////////
-#ifdef HAVE_CGDX9
-void CLP(ShaderContext)::
-suggest_cg_profile(const string &vpro, const string &fpro)
-{
-  // If a good profile has already been suggested, ignore suggestion.
-  if ((_cg_profile[SHADER_type_vert] != CG_PROFILE_UNKNOWN)||
-      (_cg_profile[SHADER_type_frag] != CG_PROFILE_UNKNOWN)) {
-    return;
-  }
-
-  // Parse the suggestion. If not parseable, print error and ignore.
-  _cg_profile[SHADER_type_vert] = parse_cg_profile(vpro, true);
-  _cg_profile[SHADER_type_frag] = parse_cg_profile(fpro, false);
-  if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
-      (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
-    dxgsg9_cat.error() << "Cg: unrecognized profile name: " << vpro << " " << fpro << "\n";
-    _cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
-    _cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
-    return;
-  }
-
-// NO EQUIVALENT FUNCTIONALITY FROM GL TO DX
-/*
-  // If the suggestion is parseable, but not supported, ignore silently.
-  if ((!cgGLIsProfileSupported(_cg_profile[SHADER_type_vert]))||
-      (!cgGLIsProfileSupported(_cg_profile[SHADER_type_frag]))) {
-    _cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
-    _cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
-    return;
-  }
-*/
-
-}
-#endif
-
-////////////////////////////////////////////////////////////////////
-//     Function: DXShaderContext9::parse_cg_profile
-//       Access: Private
-//  Description: xyz
-////////////////////////////////////////////////////////////////////
-#ifdef HAVE_CGDX9
-CGprofile CLP(ShaderContext)::
-parse_cg_profile(const string &id, bool vertex)
-{
-  int i = 0;
-  CGprofile vprofiles[] = { CG_PROFILE_ARBVP1, CG_PROFILE_VP20, CG_PROFILE_VP30, CG_PROFILE_VP40, CG_PROFILE_UNKNOWN };
-  CGprofile fprofiles[] = { CG_PROFILE_ARBFP1, CG_PROFILE_FP20, CG_PROFILE_FP30, CG_PROFILE_FP40, CG_PROFILE_UNKNOWN };
-
-  // near equivalent DX profiles
-#if (CG_VERSION_NUM >= 1502)
-  CGprofile dx_vprofiles[] = { CG_PROFILE_VS_2_0, CG_PROFILE_VS_1_1, CG_PROFILE_VS_2_X, CG_PROFILE_VS_3_0, CG_PROFILE_UNKNOWN };
-  CGprofile dx_fprofiles[] = { CG_PROFILE_PS_2_0, CG_PROFILE_PS_1_1, CG_PROFILE_PS_2_X, CG_PROFILE_PS_3_0, CG_PROFILE_UNKNOWN };
-#else
-  CGprofile dx_vprofiles[] = { CG_PROFILE_VS_2_0, CG_PROFILE_VS_1_1, CG_PROFILE_VS_2_X, CG_PROFILE_VS_2_X, CG_PROFILE_UNKNOWN };
-  CGprofile dx_fprofiles[] = { CG_PROFILE_PS_2_0, CG_PROFILE_PS_1_1, CG_PROFILE_PS_2_X, CG_PROFILE_PS_2_X, CG_PROFILE_UNKNOWN };
-#endif
-
-  if (vertex) {
-    while (vprofiles[i] != CG_PROFILE_UNKNOWN) {
-      if (id == cgGetProfileString(vprofiles[i])) {
-        return dx_vprofiles[i];
-      }
-      i++;
-    }
-  } else {
-    while (fprofiles[i] != CG_PROFILE_UNKNOWN) {
-      if (id == cgGetProfileString(fprofiles[i])) {
-        return dx_fprofiles[i];
-      }
-      i++;
-    }
-  }
-  return CG_PROFILE_UNKNOWN;
-}
-#endif  // HAVE_CGDX9
-
-int save_file (int size, void *data, char *file_path)
-{
-  int state;
-  int file_handle;
-
-  state = false;
-  file_handle = _open (file_path, _O_CREAT | _O_RDWR | _O_TRUNC, _S_IREAD | _S_IWRITE);
-  if (file_handle != -1) {
-    if (_write (file_handle, data, size) == size) {
-      state = true;
-    }
-    _close (file_handle);
-  }
-
-  return state;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DXShaderContext9::try_cg_compile
-//       Access: Private
-//  Description: xyz
-////////////////////////////////////////////////////////////////////
-#ifdef HAVE_CGDX9
-bool CLP(ShaderContext)::
-try_cg_compile(ShaderExpansion *s, GSG *gsg)
-{
-  cgGetError();
-  _cg_program[0] =
-    cgCreateProgram(gsg -> _cg_context, CG_SOURCE, s->_text.c_str(),
-                    _cg_profile[0], vertex_shader_function_name, (const char**)NULL);
-  report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
-
-  cgGetError();
-  _cg_program[1] =
-    cgCreateProgram(gsg -> _cg_context, CG_SOURCE, s->_text.c_str(),
-                    _cg_profile[1], pixel_shader_function_name, (const char**)NULL);
-  report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
-
-  if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
-    release_resources();
-    return false;
-  }
-
-  if (dxgsg9_cat.is_debug()) {
-    // DEBUG: output the generated program
-    const char *vertex_program;
-    const char *pixel_program;
-
-    vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
-    pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
-
-    dxgsg9_cat.debug() << vertex_program << "\n";
-    dxgsg9_cat.debug() << pixel_program << "\n";
-
-    // save the generated program to a file
-    int size;
-    char file_path [512];
-
-    char drive[_MAX_DRIVE];
-    char dir[_MAX_DIR];
-    char fname[_MAX_FNAME];
-    char ext[_MAX_EXT];
-
-    _splitpath (_name.c_str ( ), drive, dir, fname, ext);
-
-    size = strlen (vertex_program);
-    sprintf (file_path, "%s.vasm", fname);
-    save_file (size, (void *) vertex_program, file_path);
-
-    size = strlen (pixel_program);
-    sprintf (file_path, "%s.pasm", fname);
-    save_file (size, (void *) pixel_program, file_path);
-  }
-
-  // The following code is present to work around a bug in the Cg compiler.
-  // It does not generate correct code for shadow map lookups when using arbfp1.
-  // This is a particularly onerous limitation, given that arbfp1 is the only
-  // Cg target that works on radeons.  I suspect this is an intentional
-  // omission on nvidia's part.  The following code fetches the output listing,
-  // detects the error, repairs the code, and resumbits the repaired code to Cg.
-  if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
-    bool shadowunit[32];
-    bool anyshadow = false;
-    memset(shadowunit, 0, sizeof(shadowunit));
-    vector_string lines;
-    tokenize(cgGetProgramString(_cg_program[1], CG_COMPILED_PROGRAM), lines, "\n");
-    // figure out which texture units contain shadow maps.
-    for (int lineno=0; lineno<(int)lines.size(); lineno++) {
-      if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
-        continue;
-      }
-      vector_string fields;
-      tokenize(lines[lineno], fields, ":");
-      if (fields.size()!=5) {
-        continue;
-      }
-      vector_string words;
-      tokenize(trim(fields[2]), words, " ");
-      if (words.size()!=2) {
-        continue;
-      }
-      int unit = atoi(words[1].c_str());
-      if ((unit < 0)||(unit >= 32)) {
-        continue;
-      }
-      anyshadow = true;
-      shadowunit[unit] = true;
-    }
-    // modify all TEX statements that use the relevant texture units.
-    if (anyshadow) {
-      for (int lineno=0; lineno<(int)lines.size(); lineno++) {
-        if (lines[lineno].compare(0,4,"TEX ")) {
-          continue;
-        }
-        vector_string fields;
-        tokenize(lines[lineno], fields, ",");
-        if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
-          continue;
-        }
-        vector_string texunitf;
-        tokenize(trim(fields[2]), texunitf, "[]");
-        if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
-          continue;
-        }
-        int unit = atoi(texunitf[1].c_str());
-        if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
-          continue;
-        }
-        lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
-      }
-      string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
-      for (int lineno=1; lineno<(int)lines.size(); lineno++) {
-        result += (lines[lineno] + "\n");
-      }
-      cgDestroyProgram(_cg_program[1]);
-      _cg_program[1] =
-        cgCreateProgram(gsg -> _cg_context, CG_OBJECT, result.c_str(),
-                        _cg_profile[1], "fshader", (const char**)NULL);
-      report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
-      if (_cg_program[SHADER_type_frag]==0) {
-        release_resources();
-        return false;
-      }
-    }
-  }
-
-  bool success = true;
-  CGparameter parameter;
-  for (int progindex=0; progindex<2; progindex++) {
-    int nvtx = _var_spec.size();
-    for (parameter = cgGetFirstLeafParameter(_cg_program[progindex],CG_PROGRAM);
-         parameter != 0;
-         parameter = cgGetNextLeafParameter(parameter)) {
-      CGenum vbl = cgGetParameterVariability(parameter);
-      if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) {
-        success &= compile_parameter(parameter,
-                                     cgGetParameterName(parameter),
-                                     cg_type_to_panda_type(cgGetParameterType(parameter)),
-                                     cg_dir_to_panda_dir(cgGetParameterDirection(parameter)),
-                                     (vbl == CG_VARYING),
-                                     dxgsg9_cat.get_safe_ptr());
-      }
-    }
-    if ((progindex == SHADER_type_frag) && (nvtx != _var_spec.size())) {
-      dxgsg9_cat.error() << "Cannot use vtx parameters in an fshader\n";
-      success = false;
-    }
-  }
-  if (!success) {
-    release_resources();
-    return false;
-  }
-
-  BOOL paramater_shadowing;
-  DWORD assembly_flags;
-
-  paramater_shadowing = FALSE;
-  assembly_flags = 0;
-
-  #if DEBUG_SHADER
-  assembly_flags |= D3DXSHADER_DEBUG;
-  #endif
-
-  HRESULT hr;
-
-  hr = cgD3D9LoadProgram(_cg_program[SHADER_type_vert], paramater_shadowing, assembly_flags);
-  if (FAILED (hr)) {
-    dxgsg9_cat.error()
-      << "vertex shader cgD3D9LoadProgram failed "
-      << D3DERRORSTRING(hr);
-
-    CGerror error = cgGetError();
-    if (error != CG_NO_ERROR) {
-      dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-    }
-
-    release_resources();
-    return false;
-  }
-
-  hr = cgD3D9LoadProgram(_cg_program[SHADER_type_frag], paramater_shadowing, assembly_flags);
-  if (FAILED (hr)) {
-    dxgsg9_cat.error()
-      << "pixel shader cgD3D9LoadProgram failed "
-      << D3DERRORSTRING(hr);
-
-    CGerror error = cgGetError();
-    if (error != CG_NO_ERROR) {
-      dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-    }
-
-    release_resources();
-    return false;
-  }
-
-  DBG_SH2  dxgsg9_cat.debug ( ) << "SHADER: end try_cg_compile \n"; DBG_E
-
-  _state = true;
-
-  return true;
-}
-#endif
+// int save_file (int size, void *data, char *file_path)
+// {
+//   int state;
+//   int file_handle;
+// 
+//   state = false;
+//   file_handle = _open (file_path, _O_CREAT | _O_RDWR | _O_TRUNC, _S_IREAD | _S_IWRITE);
+//   if (file_handle != -1) {
+//     if (_write (file_handle, data, size) == size) {
+//       state = true;
+//     }
+//     _close (file_handle);
+//   }
+// 
+//   return state;
+// }
+// 
+//   if (dxgsg9_cat.is_debug()) {
+//     // DEBUG: output the generated program
+//     const char *vertex_program;
+//     const char *pixel_program;
+// 
+//     vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
+//     pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
+// 
+//     dxgsg9_cat.debug() << vertex_program << "\n";
+//     dxgsg9_cat.debug() << pixel_program << "\n";
+// 
+//     // save the generated program to a file
+//     int size;
+//     char file_path [512];
+// 
+//     char drive[_MAX_DRIVE];
+//     char dir[_MAX_DIR];
+//     char fname[_MAX_FNAME];
+//     char ext[_MAX_EXT];
+// 
+//     _splitpath (_name.c_str ( ), drive, dir, fname, ext);
+// 
+//     size = strlen (vertex_program);
+//     sprintf (file_path, "%s.vasm", fname);
+//     save_file (size, (void *) vertex_program, file_path);
+// 
+//     size = strlen (pixel_program);
+//     sprintf (file_path, "%s.pasm", fname);
+//     save_file (size, (void *) pixel_program, file_path);
+//   }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DXShaderContext9::release_resources
@@ -514,12 +177,13 @@ try_cg_compile(ShaderExpansion *s, GSG *gsg)
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 release_resources() {
-#ifdef HAVE_CGDX9
-  {
-    _cg_profile[SHADER_type_vert] = (CGprofile)0;
-    _cg_profile[SHADER_type_frag] = (CGprofile)0;
-    _cg_program[SHADER_type_vert] = (CGprogram)0;
-    _cg_program[SHADER_type_frag] = (CGprogram)0;
+#ifdef HAVE_CG
+  if (_cg_context) {
+    cgDestroyContext(_cg_context);
+    _cg_context = 0;
+    _cg_vprogram = 0;
+    _cg_fprogram = 0;
+    _cg_parameter_map.clear();
   }
 #endif
 }
@@ -537,45 +201,42 @@ bind(GSG *gsg) {
   bool bind_state;
 
   bind_state = false;
-#ifdef HAVE_CGDX9
-  if (_state) {
-    if (gsg -> _cg_context != 0) {
-      DBG_SH5  dxgsg9_cat.debug ( ) << "SHADER: bind \n";  DBG_E
-
-      // clear the last cached FVF to make sure the next SetFVF call goes through
-      gsg -> _last_fvf = 0;
-
-      // Pass in k-parameters and transform-parameters
-      issue_parameters(gsg, true);
-
-      HRESULT hr;
-
-      if (_cg_shader) {
-        // Bind the shaders.
-        bind_state = true;
-        hr = cgD3D9BindProgram(_cg_program[SHADER_type_vert]);
-        if (FAILED (hr)) {
-          dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
-
-          CGerror error = cgGetError();
-          if (error != CG_NO_ERROR) {
-            dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-          }
-
-          bind_state = false;
-        }
-        hr = cgD3D9BindProgram(_cg_program[SHADER_type_frag]);
-        if (FAILED (hr)) {
-          dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed " << D3DERRORSTRING(hr);
-
-          CGerror error = cgGetError();
-          if (error != CG_NO_ERROR) {
-            dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-          }
-
-          bind_state = false;
-        }
+#ifdef HAVE_CG
+  if (_cg_context) {
+    DBG_SH5  dxgsg9_cat.debug ( ) << "SHADER: bind \n";  DBG_E
+                                                           
+    // clear the last cached FVF to make sure the next SetFVF call goes through
+                                                           
+    gsg -> _last_fvf = 0;
+
+    // Pass in k-parameters and transform-parameters
+    issue_parameters(gsg, true);
+    
+    HRESULT hr;
+    
+    // Bind the shaders.
+    bind_state = true;
+    hr = cgD3D9BindProgram(_cg_vprogram);
+    if (FAILED (hr)) {
+      dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
+      
+      CGerror error = cgGetError();
+      if (error != CG_NO_ERROR) {
+        dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
+      }
+      
+      bind_state = false;
+    }
+    hr = cgD3D9BindProgram(_cg_fprogram);
+    if (FAILED (hr)) {
+      dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed " << D3DERRORSTRING(hr);
+      
+      CGerror error = cgGetError();
+      if (error != CG_NO_ERROR) {
+        dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
       }
+      
+      bind_state = false;
     }
   }
 #endif
@@ -591,8 +252,8 @@ bind(GSG *gsg) {
 void CLP(ShaderContext)::
 unbind(GSG *gsg) {
 
-#ifdef HAVE_CGDX9
-  if (_state) {
+#ifdef HAVE_CG
+  if (_cg_context) {
 
     DBG_SH5  dxgsg9_cat.debug ( ) << "SHADER: unbind \n"; DBG_E
 
@@ -638,12 +299,12 @@ InternalName *global_internal_name_1 = 0;
 void CLP(ShaderContext)::
 issue_parameters(GSG *gsg, bool altered)
 {
-#ifdef HAVE_CGDX9
-  if (gsg -> _cg_context != 0) {
-    for (int i=0; i<(int)_mat_spec.size(); i++) {
-      if (altered || _mat_spec[i]._trans_dependent) {
-        CGparameter p = (CGparameter)(_mat_spec[i]._parameter);
-        const LMatrix4f *val = gsg->fetch_specified_value(_mat_spec[i], altered);
+#ifdef HAVE_CG
+  if (_cg_context) {
+    for (int i=0; i<(int)_expansion->_mat_spec.size(); i++) {
+      if (altered || _expansion->_mat_spec[i]._trans_dependent) {
+        CGparameter p = _cg_parameter_map[_expansion->_mat_spec[i]._id._seqno];
+        const LMatrix4f *val = gsg->fetch_specified_value(_expansion->_mat_spec[i], altered);
         if (val) {
           HRESULT hr;
           float v [4];
@@ -658,13 +319,13 @@ issue_parameters(GSG *gsg, bool altered)
           #if DEBUG_SHADER
           // DEBUG
           global_data = (float *) data;
-          global_shader_mat_spec = &_mat_spec[i];
+          global_shader_mat_spec = &_expansion->_mat_spec[i];
           global_internal_name_0 = global_shader_mat_spec -> _arg [0];
           global_internal_name_1 = global_shader_mat_spec -> _arg [1];
           #endif
 
-          switch (_mat_spec[i]._piece) {
-          case SMP_whole:
+          switch (_expansion->_mat_spec[i]._piece) {
+          case ShaderExpansion::SMP_whole:
             // TRANSPOSE REQUIRED
             temp_matrix.transpose_from (*val);
             data = temp_matrix.get_data();
@@ -672,7 +333,7 @@ issue_parameters(GSG *gsg, bool altered)
             hr = cgD3D9SetUniform (p, data);
 
             DBG_SH2
-              dxgsg9_cat.debug ( ) << "SMP_whole MATRIX \n" <<
+              dxgsg9_cat.debug ( ) << "ShaderExpansion::SMP_whole MATRIX \n" <<
                 data[ 0] << " " << data[ 1] << " " << data[ 2] << " " << data[ 3] << "\n" <<
                 data[ 4] << " " << data[ 5] << " " << data[ 6] << " " << data[ 7] << "\n" <<
                 data[ 8] << " " << data[ 9] << " " << data[10] << " " << data[11] << "\n" <<
@@ -681,44 +342,44 @@ issue_parameters(GSG *gsg, bool altered)
 
             break;
 
-          case SMP_transpose:
+          case ShaderExpansion::SMP_transpose:
             // NO TRANSPOSE REQUIRED
             hr = cgD3D9SetUniform (p, data);
             break;
 
-          case SMP_row0:
+          case ShaderExpansion::SMP_row0:
             hr = cgD3D9SetUniform (p, data + 0);
             break;
-          case SMP_row1:
+          case ShaderExpansion::SMP_row1:
             hr = cgD3D9SetUniform (p, data + 4);
             break;
-          case SMP_row2:
+          case ShaderExpansion::SMP_row2:
             hr = cgD3D9SetUniform (p, data + 8);
             break;
-          case SMP_row3:
+          case ShaderExpansion::SMP_row3:
             hr = cgD3D9SetUniform (p, data + 12);
             break;
 
-          case SMP_col0:
+          case ShaderExpansion::SMP_col0:
             v[0] = data[0]; v[1] = data[4]; v[2] = data[8]; v[3] = data[12];
             hr = cgD3D9SetUniform (p, v);
             break;
-          case SMP_col1:
+          case ShaderExpansion::SMP_col1:
             v[0] = data[1]; v[1] = data[5]; v[2] = data[9]; v[3] = data[13];
             hr = cgD3D9SetUniform (p, v);
             break;
-          case SMP_col2:
+          case ShaderExpansion::SMP_col2:
             v[0] = data[2]; v[1] = data[6]; v[2] = data[10]; v[3] = data[14];
             hr = cgD3D9SetUniform (p, v);
             break;
-          case SMP_col3:
+          case ShaderExpansion::SMP_col3:
             v[0] = data[3]; v[1] = data[7]; v[2] = data[11]; v[3] = data[15];
             hr = cgD3D9SetUniform (p, v);
             break;
 
           default:
             dxgsg9_cat.error()
-              << "issue_parameters ( ) SMP parameter type not implemented " << _mat_spec[i]._piece << "\n";
+              << "issue_parameters ( ) SMP parameter type not implemented " << _expansion->_mat_spec[i]._piece << "\n";
             break;
           }
 
@@ -726,14 +387,14 @@ issue_parameters(GSG *gsg, bool altered)
 
             string name = "unnamed";
 
-            if (_mat_spec[i]._arg [0]) {
-              name = _mat_spec[i]._arg [0] -> get_basename ( );
+            if (_expansion->_mat_spec[i]._arg [0]) {
+              name = _expansion->_mat_spec[i]._arg [0] -> get_basename ( );
             }
 
             dxgsg9_cat.error()
               << "NAME  " << name << "\n"
               << "MAT TYPE  "
-              << _mat_spec[i]._piece
+              << _expansion->_mat_spec[i]._piece
               << " cgD3D9SetUniform failed "
               << D3DERRORSTRING(hr);
 
@@ -757,14 +418,9 @@ issue_parameters(GSG *gsg, bool altered)
 void CLP(ShaderContext)::
 disable_shader_vertex_arrays(GSG *gsg)
 {
-#ifdef HAVE_CGDX9
-  if (gsg -> _cg_context) {
-    for (int i=0; i<(int)_var_spec.size(); i++) {
-      CGparameter p = (CGparameter)(_var_spec[i]._parameter);
-
-      // DO NOTHING, CURRENTLY USING ONLY ONE STREAM SOURCE
-
-    }
+#ifdef HAVE_CG
+  if (_cg_context) {
+    // DO NOTHING, CURRENTLY USING ONLY ONE STREAM SOURCE
   }
 #endif
 }
@@ -790,8 +446,8 @@ void CLP(ShaderContext)::
 update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
 {
   if (prev) prev->disable_shader_vertex_arrays(gsg);
-#ifdef HAVE_CGDX9
-  if (gsg -> _cg_context) {
+#ifdef HAVE_CG
+  if (_cg_context) {
 
   #ifdef SUPPORT_IMMEDIATE_MODE
 /*
@@ -806,7 +462,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
         const GeomVertexArrayDataPipelineReader *array_reader;
         Geom::NumericType numeric_type;
         int start, stride, num_values;
-        int nvarying = _var_spec.size();
+        int nvarying = _expansion->_var_spec.size();
 
         int stream_index;
         VertexElementArray *vertex_element_array;
@@ -822,9 +478,9 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
         #endif
 
         for (int i=0; i<nvarying; i++) {
-          CGparameter p = (CGparameter)(_var_spec[i]._parameter);
-          InternalName *name = _var_spec[i]._name;
-          int texslot = _var_spec[i]._append_uv;
+          CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
+          InternalName *name = _expansion->_var_spec[i]._name;
+          int texslot = _expansion->_var_spec[i]._append_uv;
           if (texslot >= 0) {
             const Geom::ActiveTextureStages &active_stages =
               gsg->_state._texture->get_on_stages();
@@ -982,8 +638,8 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
 
           state = vertex_element_array -> add_end_vertex_element ( );
           if (state) {
-            if (_cg_shader) {
-              if (cgD3D9ValidateVertexDeclaration (_cg_program [SHADER_type_vert],
+            if (_cg_context) {
+              if (cgD3D9ValidateVertexDeclaration (_cg_vprogram,
                     vertex_element_array -> vertex_element_array) == CG_TRUE) {
                 dxgsg9_cat.debug() << "|||||cgD3D9ValidateVertexDeclaration succeeded\n";
               }
@@ -1013,7 +669,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
       }
     }
   }
-#endif // HAVE_CGDX9
+#endif // HAVE_CG
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1024,10 +680,10 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
 void CLP(ShaderContext)::
 disable_shader_texture_bindings(GSG *gsg)
 {
-#ifdef HAVE_CGDX9
-  if (gsg -> _cg_context) {
-    for (int i=0; i<(int)_tex_spec.size(); i++) {
-      CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
+#ifdef HAVE_CG
+  if (_cg_context) {
+    for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
+      CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
       int texunit = cgGetParameterResourceIndex(p);
 
       HRESULT hr;
@@ -1061,40 +717,40 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg)
 {
   if (prev) prev->disable_shader_texture_bindings(gsg);
 
-#ifdef HAVE_CGDX9
-  if (gsg -> _cg_context) {
-    for (int i=0; i<(int)_tex_spec.size(); i++) {
-      CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
+#ifdef HAVE_CG
+  if (_cg_context) {
+    for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
+      CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
       Texture *tex = 0;
-      InternalName *id = _tex_spec[i]._name;
+      InternalName *id = _expansion->_tex_spec[i]._name;
       if (id != 0) {
         const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
         tex = input->get_texture();
       } else {
-        if (_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
+        if (_expansion->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
           continue;
         }
-        TextureStage *stage = gsg->_target._texture->get_on_stage(_tex_spec[i]._stage);
+        TextureStage *stage = gsg->_target._texture->get_on_stage(_expansion->_tex_spec[i]._stage);
         tex = gsg->_target._texture->get_on_texture(stage);
       }
-      if (_tex_spec[i]._suffix != 0) {
+      if (_expansion->_tex_spec[i]._suffix != 0) {
         // The suffix feature is inefficient. It is a temporary hack.
         if (tex == 0) {
           continue;
         }
-        tex = tex->load_related(_tex_spec[i]._suffix);
+        tex = tex->load_related(_expansion->_tex_spec[i]._suffix);
       }
-      if ((tex == 0) || (tex->get_texture_type() != _tex_spec[i]._desired_type)) {
+      if ((tex == 0) || (tex->get_texture_type() != _expansion->_tex_spec[i]._desired_type)) {
         continue;
       }
       TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);
-//      TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(), gsg);
+      //      TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(), gsg);
       if (tc == (TextureContext*)NULL) {
         continue;
       }
-
+      
       int texunit = cgGetParameterResourceIndex(p);
-
+      
       gsg->apply_texture(texunit, tc);
     }
   }

+ 36 - 87
panda/src/dxgsg9/dxShaderContext9.h

@@ -21,11 +21,6 @@
 
 #include "dtool_config.h"
 #include "pandabase.h"
-#ifdef HAVE_CGDX9
-#include "Cg/cg.h"
-#include "Cg/cgGL.h"
-#include "Cg/cgD3D9.h"
-#endif
 #include "string_utils.h"
 #include "internalName.h"
 #include "shaderExpansion.h"
@@ -39,47 +34,49 @@
 class VertexElementArray;
 class CLP(GraphicsStateGuardian);
 
-typedef struct
-{
-  int vertex_shader;
-  int total_constant_descriptions;
-  D3DXCONSTANT_DESC *constant_description_array;
-}
-DX_PARAMETER;
-
-typedef struct
-{
-  int state;
-  union
-  {
-    DIRECT_3D_VERTEX_SHADER direct_3d_vertex_shader;
-    DIRECT_3D_PIXEL_SHADER direct_3d_pixel_shader;
-  };
-  LPD3DXCONSTANTTABLE constant_table;
-  D3DXCONSTANTTABLE_DESC constant_table_description;
-
-  int total_semantics;
-  D3DXSEMANTIC *semantic_array;
-}
-DIRECT_3D_SHADER;
+// Caution: adding HLSL support is going to be tricky, as the parsing needs
+// to be done in the cull thread, which cannot use the DX API.  - Josh
+//
+//
+// typedef struct
+// {
+//   int vertex_shader;
+//   int total_constant_descriptions;
+//   D3DXCONSTANT_DESC *constant_description_array;
+// }
+// DX_PARAMETER;
+// 
+// typedef struct
+// {
+//   int state;
+//   union
+//   {
+//     DIRECT_3D_VERTEX_SHADER direct_3d_vertex_shader;
+//     DIRECT_3D_PIXEL_SHADER direct_3d_pixel_shader;
+//   };
+//   LPD3DXCONSTANTTABLE constant_table;
+//   D3DXCONSTANTTABLE_DESC constant_table_description;
+// 
+//   int total_semantics;
+//   D3DXSEMANTIC *semantic_array;
+// }
+// DIRECT_3D_SHADER;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DXShaderContext9
 // Description : xyz
 ////////////////////////////////////////////////////////////////////
 
-typedef CLP(GraphicsStateGuardian) GSG;
-
 class EXPCL_PANDADX CLP(ShaderContext): public ShaderContext {
 public:
-
+  typedef CLP(GraphicsStateGuardian) GSG;
+  
   CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg);
   ~CLP(ShaderContext)();
 
   INLINE bool valid(GSG *gsg);
   bool bind(GSG *gsg);
   void unbind(GSG *gsg);
-
   void issue_parameters(GSG *gsg, bool altered);
   void issue_transform(GSG *gsg);
   void disable_shader_vertex_arrays(GSG *gsg);
@@ -87,69 +84,21 @@ public:
   void disable_shader_texture_bindings(GSG *gsg);
   void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
 
-  int _vertex_size;
   class VertexElementArray *_vertex_element_array;
 
   // FOR DEBUGGING
+  int _vertex_size;
   string _name;
-
-  bool _state;
-  bool _cg_shader;
-  bool _transpose_matrix;
-
+  
 private:
 
-#ifdef HAVE_CGDX9
-  struct ShaderAutoBind {
-    CGparameter parameter;
-    int value;
-    DX_PARAMETER *dx_parameter;
-  };
-  struct ShaderArgBind {
-    CGparameter parameter;
-    PT(InternalName) name;
-    DX_PARAMETER *dx_parameter;
-  };
-  struct ShaderTexBind {
-    CGparameter parameter;
-    PT(InternalName) name;
-    int stage;
-    int desiredtype;
-    PT(InternalName) suffix;
-    DX_PARAMETER *dx_parameter;
-  };
-  struct ShaderTransBind {
-    CGparameter parameter;
-    PT(InternalName) src_name;
-    PT(InternalName) rel_name;
-    int trans_piece;
-    DX_PARAMETER *dx_parameter;
-  };
-  struct ShaderVarying {
-    CGparameter parameter;
-    PT(InternalName) name;
-    int append_uv;
-    DX_PARAMETER *dx_parameter;
-  };
-
-//  CGcontext _cg_context;
-  CGprofile _cg_profile[2];
-  CGprogram _cg_program[2];
-
-  void report_cg_compile_errors(const string &file, CGcontext ctx);
-
-  bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
-  void suggest_cg_profile(const string &vpro, const string &fpro);
-  CGprofile parse_cg_profile(const string &id, bool vertex);
+#ifdef HAVE_CG
+  CGcontext _cg_context;
+  CGprogram _cg_vprogram;
+  CGprogram _cg_fprogram;
+  pvector <CGparameter> _cg_parameter_map;
 #endif
 
-public:
-
-  DIRECT_3D_SHADER _direct_3d_vertex_shader;
-  DIRECT_3D_SHADER _direct_3d_pixel_shader;
-  int _total_dx_parameters;
-  DX_PARAMETER *_dx_parameter_array;
-
 private:
 
   void release_resources(void);

+ 11 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -50,6 +50,10 @@
 #include "indirectLess.h"
 #include "pStatTimer.h"
 
+#ifdef HAVE_CG
+#include "Cg/cgGL.h"
+#endif
+
 #include <algorithm>
 
 #define DEBUG_BUFFERS false
@@ -669,10 +673,14 @@ reset() {
     }
   }
 
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) &&
       cgGLIsProfileSupported(CG_PROFILE_ARBVP1)) {
     _supports_basic_shaders = true;
+    _shader_caps._active_vprofile = (int)cgGLGetLatestProfile(CG_GL_VERTEX);
+    _shader_caps._active_fprofile = (int)cgGLGetLatestProfile(CG_GL_FRAGMENT);
+    _shader_caps._ultimate_vprofile = (int)CG_PROFILE_VP40;
+    _shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40;
   }
 #endif
 
@@ -1076,7 +1084,7 @@ reset() {
   void gl_set_stencil_functions (StencilRenderStates *stencil_render_states);
   gl_set_stencil_functions (_stencil_render_states);
 
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
 
   typedef struct
   {
@@ -3357,7 +3365,7 @@ do_issue_shader() {
   ShaderExpansion *expansion = _target_rs->get_shader_expansion();
   if (expansion == 0) {
     if (_target._shader->get_shader() != 0) {
-      expansion = _target._shader->get_shader()->macroexpand(_target_rs);
+      expansion = _target._shader->get_shader()->macroexpand(_target_rs, _shader_caps);
       // I am casting away the const-ness of this pointer, because
       // the 'shader-expansion' field is just a cache.
       ((RenderState *)((const RenderState*)_target_rs))->

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

@@ -27,8 +27,8 @@
 ////////////////////////////////////////////////////////////////////
 INLINE bool CLP(ShaderContext)::
 valid() {
-#ifdef HAVE_CGGL
-  if (_state && _cg_context) return true;
+#ifdef HAVE_CG
+  if (_cg_context) return true;
 #endif
   return false;
 }

+ 74 - 388
panda/src/glstuff/glShaderContext_src.cxx

@@ -16,49 +16,14 @@
 //
 ////////////////////////////////////////////////////////////////////
 
+#ifdef HAVE_CG
+#include "Cg/cgGL.h"
+#endif
+
 #define DEBUG_GL_SHADER 0
 
 TypeHandle CLP(ShaderContext)::_type_handle;
 
-#ifdef HAVE_CGGL
-////////////////////////////////////////////////////////////////////
-//     Function: cg_type_to_panda_type
-//       Access: Public, Static
-//  Description: convert a cg shader-arg type to a panda shader-arg type.
-////////////////////////////////////////////////////////////////////
-static ShaderContext::ShaderArgType
-cg_type_to_panda_type(CGtype n) {
-  switch (n) {
-  case CG_FLOAT1:      return ShaderContext::SAT_float1;
-  case CG_FLOAT2:      return ShaderContext::SAT_float2;
-  case CG_FLOAT3:      return ShaderContext::SAT_float3;
-  case CG_FLOAT4:      return ShaderContext::SAT_float4;
-  case CG_FLOAT4x4:    return ShaderContext::SAT_float4x4;
-  case CG_SAMPLER1D:   return ShaderContext::SAT_sampler1d;
-  case CG_SAMPLER2D:   return ShaderContext::SAT_sampler2d;
-  case CG_SAMPLER3D:   return ShaderContext::SAT_sampler3d;
-  case CG_SAMPLERCUBE: return ShaderContext::SAT_samplercube;
-  default:           return ShaderContext::SAT_unknown;
-  }
-}
-#endif  // HAVE_CGGL
-
-#ifdef HAVE_CGGL
-////////////////////////////////////////////////////////////////////
-//     Function: cg_dir_to_panda_dir
-//       Access: Public, Static
-//  Description: convert a cg shader-arg type to a panda shader-arg type.
-////////////////////////////////////////////////////////////////////
-static ShaderContext::ShaderArgDir
-cg_dir_to_panda_dir(CGenum n) {
-  switch (n) {
-  case CG_IN:    return ShaderContext::SAD_in;
-  case CG_OUT:   return ShaderContext::SAD_out;
-  case CG_INOUT: return ShaderContext::SAD_inout;
-  default:       return ShaderContext::SAD_unknown;
-  }
-}
-#endif  // HAVE_CGGL
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GLShaderContext::Constructor
@@ -67,310 +32,33 @@ cg_dir_to_panda_dir(CGenum n) {
 ////////////////////////////////////////////////////////////////////
 CLP(ShaderContext)::
 CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
-  string header;
-  s->parse_init();
-  s->parse_line(header, true, true);
-
-  _state = false;
-
-#ifdef HAVE_CGGL
-  _cg_context = (CGcontext)0;
-  _cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
-  _cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
-  _cg_program[SHADER_type_vert] = (CGprogram)0;
-  _cg_program[SHADER_type_frag] = (CGprogram)0;
-  _cg_program[2]                = (CGprogram)0;
-
-  if (header == "//Cg") {
-    // Create the Cg context.
-    _cg_context = cgCreateContext();
-    if (_cg_context == 0) {
-      release_resources();
-      GLCAT.error() << "Cg not supported by this video card.\n";
+#ifdef HAVE_CG
+  if (s->get_header() == "//Cg") {
+    
+    // Ask the shader expansion to compile itself for us and 
+    // to give us the resulting Cg program objects.
+
+    if (!s->cg_compile_for(gsg->_shader_caps,
+                           _cg_context,
+                           _cg_vprogram,
+                           _cg_fprogram, 
+                           _cg_parameter_map)) {
       return;
     }
-
-    // Parse any directives in the source.
-    string directive;
-    while (!s->parse_eof()) {
-      s->parse_line(directive, true, true);
-      vector_string pieces;
-      tokenize(directive, pieces, " \t");
-      if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
-        suggest_cg_profile(pieces[2], pieces[3]);
-      }
-    }
-
-    // Select a profile if no preferred profile specified in the source.
-    if (_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN) {
-      _cg_profile[SHADER_type_vert] = cgGLGetLatestProfile(CG_GL_VERTEX);
-    }
-    if (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN) {
-      _cg_profile[SHADER_type_frag] = cgGLGetLatestProfile(CG_GL_FRAGMENT);
-    }
-
-    // If we still haven't chosen a profile, give up.
-    if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
-        (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
+        
+    // Load the program.
+    
+    cgGLLoadProgram(_cg_vprogram);
+    CGerror verror = cgGetError();
+    cgGLLoadProgram(_cg_fprogram);
+    CGerror ferror = cgGetError();
+    if ((verror != CG_NO_ERROR)||(ferror != CG_NO_ERROR)) {
+      GLCAT.error() << "Could not load Cg shader:" << s->get_name() << "\n";
       release_resources();
-      GLCAT.error() << "Cg not supported by this video card.\n";
-      return;
     }
-
-    // Compile the program.
-    try_cg_compile(s, gsg);
-    return;
-  }
-#endif
-
-  GLCAT.error() << s->get_name() << ": unrecognized shader language " << header << "\n";
-}
-
-#ifdef HAVE_CGGL
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::report_cg_compile_errors
-//       Access: Public, Static
-//  Description: Used only after a Cg compile command, to print
-//               out any error messages that may have occurred
-//               during the Cg shader compilation.  The 'file'
-//               is the name of the file containing the Cg code.
-////////////////////////////////////////////////////////////////////
-void CLP(ShaderContext)::
-report_cg_compile_errors(const string &file, CGcontext ctx)
-{
-  CGerror err = cgGetError();
-  if (err != CG_NO_ERROR) {
-    if (err == CG_COMPILER_ERROR) {
-      string listing = cgGetLastListing(ctx);
-      vector_string errlines;
-      tokenize(listing, errlines, "\n");
-      for (int i=0; i<(int)errlines.size(); i++) {
-        string line = trim(errlines[i]);
-        if (line != "") {
-          GLCAT.error() << file << " " << errlines[i] << "\n";
-        }
-      }
-    } else {
-      GLCAT.error() << file << ": " << cgGetErrorString(err) << "\n";
-    }
-  }
-}
-#endif  // HAVE_CGGL
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLShaderContext::suggest_cg_profile
-//       Access: Private
-//  Description: xyz
-////////////////////////////////////////////////////////////////////
-#ifdef HAVE_CGGL
-void CLP(ShaderContext)::
-suggest_cg_profile(const string &vpro, const string &fpro)
-{
-  // If a good profile has already been suggested, ignore suggestion.
-  if ((_cg_profile[SHADER_type_vert] != CG_PROFILE_UNKNOWN)||
-      (_cg_profile[SHADER_type_frag] != CG_PROFILE_UNKNOWN)) {
-    return;
-  }
-
-  // Parse the suggestion. If not parseable, print error and ignore.
-  _cg_profile[SHADER_type_vert] = parse_cg_profile(vpro, true);
-  _cg_profile[SHADER_type_frag] = parse_cg_profile(fpro, false);
-  if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
-      (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
-    GLCAT.error() << "Cg: unrecognized profile name: " << vpro << " " << fpro << "\n";
-    _cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
-    _cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
-    return;
-  }
-
-  // If the suggestion is parseable, but not supported, ignore silently.
-  if ((!cgGLIsProfileSupported(_cg_profile[SHADER_type_vert]))||
-      (!cgGLIsProfileSupported(_cg_profile[SHADER_type_frag]))) {
-    _cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
-    _cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
-    return;
   }
-}
 #endif
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLShaderContext::parse_cg_profile
-//       Access: Private
-//  Description: xyz
-////////////////////////////////////////////////////////////////////
-#ifdef HAVE_CGGL
-CGprofile CLP(ShaderContext)::
-parse_cg_profile(const string &id, bool vertex)
-{
-  int nvprofiles = 4;
-  int nfprofiles = 4;
-  CGprofile vprofiles[] = { CG_PROFILE_ARBVP1, CG_PROFILE_VP20, CG_PROFILE_VP30, CG_PROFILE_VP40 };
-  CGprofile fprofiles[] = { CG_PROFILE_ARBFP1, CG_PROFILE_FP20, CG_PROFILE_FP30, CG_PROFILE_FP40 };
-  if (vertex) {
-    for (int i=0; i<nvprofiles; i++) {
-      if (id == cgGetProfileString(vprofiles[i])) {
-        return vprofiles[i];
-      }
-    }
-  } else {
-    for (int i=0; i<nfprofiles; i++) {
-      if (id == cgGetProfileString(fprofiles[i])) {
-        return fprofiles[i];
-      }
-    }
-  }
-  return CG_PROFILE_UNKNOWN;
 }
-#endif  // HAVE_CGGL
-
-////////////////////////////////////////////////////////////////////
-//     Function: GLShaderContext::try_cg_compile
-//       Access: Private
-//  Description: xyz
-////////////////////////////////////////////////////////////////////
-#ifdef HAVE_CGGL
-bool CLP(ShaderContext)::
-try_cg_compile(ShaderExpansion *s, GSG *gsg)
-{
-  cgGetError();
-  _cg_program[0] =
-    cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
-                    _cg_profile[0], "vshader", (const char**)NULL);
-  report_cg_compile_errors(s->get_name(), _cg_context);
-
-  cgGetError();
-  _cg_program[1] =
-    cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
-                    _cg_profile[1], "fshader", (const char**)NULL);
-  report_cg_compile_errors(s->get_name(), _cg_context);
-
-  if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
-    release_resources();
-    return false;
-  }
-
-  bool success = true;
-  CGparameter parameter;
-  for (int progindex=0; progindex<2; progindex++) {
-    int nvtx = _var_spec.size();
-    for (parameter = cgGetFirstLeafParameter(_cg_program[progindex],CG_PROGRAM);
-         parameter != 0;
-         parameter = cgGetNextLeafParameter(parameter)) {
-      CGenum vbl = cgGetParameterVariability(parameter);
-      if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) {
-        success &= compile_parameter(parameter,
-                                     cgGetParameterName(parameter),
-                                     cg_type_to_panda_type(cgGetParameterType(parameter)),
-                                     cg_dir_to_panda_dir(cgGetParameterDirection(parameter)),
-                                     (vbl == CG_VARYING),
-                                     GLCAT.get_safe_ptr());
-      }
-    }
-    if ((progindex == SHADER_type_frag) && (nvtx != _var_spec.size())) {
-      GLCAT.error() << "Cannot use vtx parameters in an fshader\n";
-      success = false;
-    }
-  }
-  if (!success) {
-    release_resources();
-    return false;
-  }
-
-  // DEBUG: output the generated program
-  if (GLCAT.is_debug()) {
-    const char *vertex_program;
-    const char *pixel_program;
-
-    vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
-    pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
-
-    GLCAT.debug() << vertex_program << "\n";
-    GLCAT.debug() << pixel_program << "\n";
-  }
-
-  // The following code is present to work around a bug in the Cg compiler.
-  // It does not generate correct code for shadow map lookups when using arbfp1.
-  // This is a particularly onerous limitation, given that arbfp1 is the only
-  // Cg target that works on radeons.  I suspect this is an intentional
-  // omission on nvidia's part.  The following code fetches the output listing,
-  // detects the error, repairs the code, and resumbits the repaired code to Cg.
-  if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
-    bool shadowunit[32];
-    bool anyshadow = false;
-    memset(shadowunit, 0, sizeof(shadowunit));
-    vector_string lines;
-    tokenize(cgGetProgramString(_cg_program[SHADER_type_frag],
-                                CG_COMPILED_PROGRAM), lines, "\n");
-    // figure out which texture units contain shadow maps.
-    for (int lineno=0; lineno<(int)lines.size(); lineno++) {
-      if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
-        continue;
-      }
-      vector_string fields;
-      tokenize(lines[lineno], fields, ":");
-      if (fields.size()!=5) {
-        continue;
-      }
-      vector_string words;
-      tokenize(trim(fields[2]), words, " ");
-      if (words.size()!=2) {
-        continue;
-      }
-      int unit = atoi(words[1].c_str());
-      if ((unit < 0)||(unit >= 32)) {
-        continue;
-      }
-      anyshadow = true;
-      shadowunit[unit] = true;
-    }
-    // modify all TEX statements that use the relevant texture units.
-    if (anyshadow) {
-      for (int lineno=0; lineno<(int)lines.size(); lineno++) {
-        if (lines[lineno].compare(0,4,"TEX ")) {
-          continue;
-        }
-        vector_string fields;
-        tokenize(lines[lineno], fields, ",");
-        if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
-          continue;
-        }
-        vector_string texunitf;
-        tokenize(trim(fields[2]), texunitf, "[]");
-        if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
-          continue;
-        }
-        int unit = atoi(texunitf[1].c_str());
-        if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
-          continue;
-        }
-        lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
-      }
-      string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
-      for (int lineno=1; lineno<(int)lines.size(); lineno++) {
-        result += (lines[lineno] + "\n");
-      }
-      _cg_program[2] = _cg_program[SHADER_type_frag];
-      _cg_program[SHADER_type_frag] =
-        cgCreateProgram(_cg_context, CG_OBJECT, result.c_str(),
-                        _cg_profile[SHADER_type_frag], "fshader", (const char**)NULL);
-      report_cg_compile_errors(s->get_name(), _cg_context);
-      if (_cg_program[SHADER_type_frag]==0) {
-        release_resources();
-        return false;
-      }
-    }
-  }
-
-  cgGLLoadProgram(_cg_program[SHADER_type_vert]);
-  report_cg_compile_errors(s->get_name(), _cg_context);
-  cgGLLoadProgram(_cg_program[SHADER_type_frag]);
-  report_cg_compile_errors(s->get_name(), _cg_context);
-
-  _state = true;
-
-  return true;
-}
-#endif
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GLShaderContext::Destructor
@@ -390,15 +78,13 @@ CLP(ShaderContext)::
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 release_resources() {
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context) {
     cgDestroyContext(_cg_context);
-    _cg_context = (CGcontext)0;
-    _cg_profile[SHADER_type_vert] = (CGprofile)0;
-    _cg_profile[SHADER_type_frag] = (CGprofile)0;
-    _cg_program[SHADER_type_vert] = (CGprogram)0;
-    _cg_program[SHADER_type_frag] = (CGprogram)0;
-    _cg_program[2]                = (CGprogram)0;
+    _cg_context = 0;
+    _cg_vprogram = 0;
+    _cg_fprogram = 0;
+    _cg_parameter_map.clear();
   }
 #endif
 }
@@ -412,17 +98,17 @@ release_resources() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 bind(GSG *gsg) {
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context != 0) {
 
     // Pass in k-parameters and transform-parameters
     issue_parameters(gsg, true);
 
     // Bind the shaders.
-    cgGLEnableProfile(_cg_profile[SHADER_type_vert]);
-    cgGLBindProgram(_cg_program[SHADER_type_vert]);
-    cgGLEnableProfile(_cg_profile[SHADER_type_frag]);
-    cgGLBindProgram(_cg_program[SHADER_type_frag]);
+    cgGLEnableProfile(cgGetProgramProfile(_cg_vprogram));
+    cgGLBindProgram(_cg_vprogram);
+    cgGLEnableProfile(cgGetProgramProfile(_cg_fprogram));
+    cgGLBindProgram(_cg_fprogram);
   }
 #endif
 }
@@ -434,10 +120,10 @@ bind(GSG *gsg) {
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 unbind() {
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context != 0) {
-    cgGLDisableProfile(_cg_profile[SHADER_type_vert]);
-    cgGLDisableProfile(_cg_profile[SHADER_type_frag]);
+    cgGLDisableProfile(cgGetProgramProfile(_cg_vprogram));
+    cgGLDisableProfile(cgGetProgramProfile(_cg_fprogram));
   }
 #endif
 }
@@ -459,28 +145,28 @@ unbind() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 issue_parameters(GSG *gsg, bool altered) {
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context == 0) {
     return;
   }
 
-  for (int i=0; i<(int)_mat_spec.size(); i++) {
-    if (altered || _mat_spec[i]._trans_dependent) {
-      CGparameter p = (CGparameter)(_mat_spec[i]._parameter);
-      const LMatrix4f *val = gsg->fetch_specified_value(_mat_spec[i], altered);
+  for (int i=0; i<(int)_expansion->_mat_spec.size(); i++) {
+    if (altered || _expansion->_mat_spec[i]._trans_dependent) {
+      CGparameter p = _cg_parameter_map[_expansion->_mat_spec[i]._id._seqno];
+      const LMatrix4f *val = gsg->fetch_specified_value(_expansion->_mat_spec[i], altered);
       if (val) {
         const float *data = val->get_data();
-        switch (_mat_spec[i]._piece) {
-        case SMP_whole: cgGLSetMatrixParameterfc(p, data); break;
-        case SMP_transpose: cgGLSetMatrixParameterfr(p, data); break;
-        case SMP_row0: cgGLSetParameter4fv(p, data+ 0); break;
-        case SMP_row1: cgGLSetParameter4fv(p, data+ 4); break;
-        case SMP_row2: cgGLSetParameter4fv(p, data+ 8); break;
-        case SMP_row3: cgGLSetParameter4fv(p, data+12); break;
-        case SMP_col0: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); break;
-        case SMP_col1: cgGLSetParameter4f(p, data[1], data[5], data[ 9], data[13]); break;
-        case SMP_col2: cgGLSetParameter4f(p, data[2], data[6], data[10], data[14]); break;
-        case SMP_col3: cgGLSetParameter4f(p, data[3], data[7], data[11], data[15]); break;
+        switch (_expansion->_mat_spec[i]._piece) {
+        case ShaderExpansion::SMP_whole: cgGLSetMatrixParameterfc(p, data); break;
+        case ShaderExpansion::SMP_transpose: cgGLSetMatrixParameterfr(p, data); break;
+        case ShaderExpansion::SMP_row0: cgGLSetParameter4fv(p, data+ 0); break;
+        case ShaderExpansion::SMP_row1: cgGLSetParameter4fv(p, data+ 4); break;
+        case ShaderExpansion::SMP_row2: cgGLSetParameter4fv(p, data+ 8); break;
+        case ShaderExpansion::SMP_row3: cgGLSetParameter4fv(p, data+12); break;
+        case ShaderExpansion::SMP_col0: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); break;
+        case ShaderExpansion::SMP_col1: cgGLSetParameter4f(p, data[1], data[5], data[ 9], data[13]); break;
+        case ShaderExpansion::SMP_col2: cgGLSetParameter4f(p, data[2], data[6], data[10], data[14]); break;
+        case ShaderExpansion::SMP_col3: cgGLSetParameter4f(p, data[3], data[7], data[11], data[15]); break;
         }
       }
     }
@@ -495,13 +181,13 @@ issue_parameters(GSG *gsg, bool altered) {
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 disable_shader_vertex_arrays(GSG *gsg) {
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context == 0) {
     return;
   }
 
-  for (int i=0; i<(int)_var_spec.size(); i++) {
-    CGparameter p = (CGparameter)(_var_spec[i]._parameter);
+  for (int i=0; i<(int)_expansion->_var_spec.size(); i++) {
+    CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
     cgGLDisableClientState(p);
   }
 #endif
@@ -521,7 +207,7 @@ disable_shader_vertex_arrays(GSG *gsg) {
 void CLP(ShaderContext)::
 update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
   if (prev) prev->disable_shader_vertex_arrays(gsg);
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context == 0) {
     return;
   }
@@ -535,11 +221,11 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
     const GeomVertexArrayDataPipelineReader *array_reader;
     Geom::NumericType numeric_type;
     int start, stride, num_values;
-    int nvarying = _var_spec.size();
+    int nvarying = _expansion->_var_spec.size();
     for (int i=0; i<nvarying; i++) {
-      CGparameter p = (CGparameter)(_var_spec[i]._parameter);
-      InternalName *name = _var_spec[i]._name;
-      int texslot = _var_spec[i]._append_uv;
+      CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
+      InternalName *name = _expansion->_var_spec[i]._name;
+      int texslot = _expansion->_var_spec[i]._append_uv;
       if (texslot >= 0) {
         const Geom::ActiveTextureStages &active_stages =
           gsg->_state._texture->get_on_stages();
@@ -566,7 +252,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
       }
     }
   }
-#endif // HAVE_CGGL
+#endif // HAVE_CG
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -576,13 +262,13 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 disable_shader_texture_bindings(GSG *gsg) {
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context == 0) {
     return;
   }
 
-  for (int i=0; i<(int)_tex_spec.size(); i++) {
-    CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
+  for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
+    CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
     int texunit = cgGetParameterResourceIndex(p);
     gsg->_glActiveTexture(GL_TEXTURE0 + texunit);
     GLP(Disable)(GL_TEXTURE_1D);
@@ -613,33 +299,33 @@ disable_shader_texture_bindings(GSG *gsg) {
 void CLP(ShaderContext)::
 update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) {
   if (prev) prev->disable_shader_texture_bindings(gsg);
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   if (_cg_context == 0) {
     return;
   }
 
-  for (int i=0; i<(int)_tex_spec.size(); i++) {
-    CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
+  for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
+    CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
     Texture *tex = 0;
-    InternalName *id = _tex_spec[i]._name;
+    InternalName *id = _expansion->_tex_spec[i]._name;
     if (id != 0) {
       const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
       tex = input->get_texture();
     } else {
-      if (_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
+      if (_expansion->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
         continue;
       }
-      TextureStage *stage = gsg->_target._texture->get_on_stage(_tex_spec[i]._stage);
+      TextureStage *stage = gsg->_target._texture->get_on_stage(_expansion->_tex_spec[i]._stage);
       tex = gsg->_target._texture->get_on_texture(stage);
     }
-    if (_tex_spec[i]._suffix != 0) {
+    if (_expansion->_tex_spec[i]._suffix != 0) {
       // The suffix feature is inefficient. It is a temporary hack.
       if (tex == 0) {
         continue;
       }
-      tex = tex->load_related(_tex_spec[i]._suffix);
+      tex = tex->load_related(_expansion->_tex_spec[i]._suffix);
     }
-    if ((tex == 0) || (tex->get_texture_type() != _tex_spec[i]._desired_type)) {
+    if ((tex == 0) || (tex->get_texture_type() != _expansion->_tex_spec[i]._desired_type)) {
       continue;
     }
     TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);

+ 6 - 14
panda/src/glstuff/glShaderContext_src.h

@@ -17,9 +17,6 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "pandabase.h"
-#ifdef HAVE_CGGL
-#include "Cg/cgGL.h"
-#endif
 #include "string_utils.h"
 #include "internalName.h"
 #include "shaderExpansion.h"
@@ -49,23 +46,18 @@ public:
   void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
   void disable_shader_texture_bindings(GSG *gsg);
   void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
-  bool _state;
 
 private:
 
-#ifdef HAVE_CGGL
+#ifdef HAVE_CG
   CGcontext _cg_context;
-  CGprofile _cg_profile[2];
-  CGprogram _cg_program[3];
-
-  void report_cg_compile_errors(const string &file, CGcontext ctx);
-  bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
-  void suggest_cg_profile(const string &vpro, const string &fpro);
-  CGprofile parse_cg_profile(const string &id, bool vertex);
+  CGprogram _cg_vprogram;
+  CGprogram _cg_fprogram;
+  pvector <CGparameter> _cg_parameter_map;
 #endif
-  
-  void release_resources(void);
 
+  void release_resources(void);
+  
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

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

@@ -1,7 +1,7 @@
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m prc:c
 //#define OSX_SYS_LIBS mx
-#define USE_PACKAGES zlib
+#define USE_PACKAGES zlib cg
 
 #begin lib_target
   #define TARGET gobj

+ 5 - 5
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -88,7 +88,7 @@ PreparedGraphicsObjects::
        sci != _prepared_shaders.end();
        ++sci) {
     ShaderContext *sc = (*sci);
-    sc->_shader_expansion->clear_prepared(this);
+    sc->_expansion->clear_prepared(this);
   }
 
   _prepared_shaders.clear();
@@ -460,12 +460,12 @@ void PreparedGraphicsObjects::
 release_shader(ShaderContext *sc) {
   ReMutexHolder holder(_lock);
 
-  sc->_shader_expansion->clear_prepared(this);
+  sc->_expansion->clear_prepared(this);
 
   // We have to set the Shader pointer to NULL at this point, since
   // the Shader itself might destruct at any time after it has been
   // released.
-  sc->_shader_expansion = (ShaderExpansion *)NULL;
+  sc->_expansion = (ShaderExpansion *)NULL;
 
   bool removed = (_prepared_shaders.erase(sc) != 0);
   nassertv(removed);
@@ -492,8 +492,8 @@ release_all_shaders() {
        sci != _prepared_shaders.end();
        ++sci) {
     ShaderContext *sc = (*sci);
-    sc->_shader_expansion->clear_prepared(this);
-    sc->_shader_expansion = (ShaderExpansion *)NULL;
+    sc->_expansion->clear_prepared(this);
+    sc->_expansion = (ShaderExpansion *)NULL;
 
     _released_shaders.insert(sc);
   }

+ 1 - 1
panda/src/gobj/shaderContext.I

@@ -23,7 +23,7 @@
 ////////////////////////////////////////////////////////////////////
 INLINE ShaderContext::
 ShaderContext(ShaderExpansion *se) :
-  _shader_expansion(se)
+  _expansion(se)
 {
 }
 

+ 0 - 675
panda/src/gobj/shaderContext.cxx

@@ -22,678 +22,3 @@
 
 TypeHandle ShaderContext::_type_handle;
 
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::cp_report_error
-//       Access: Public
-//  Description: Generate an error message including a description
-//               of the specified parameter.
-////////////////////////////////////////////////////////////////////
-void ShaderContext::
-cp_report_error(ShaderArgInfo &p, const string &msg)
-{
-  string vstr;
-  if (p._varying) vstr = "varying ";
-  else            vstr = "uniform ";
-
-  string dstr = "unknown ";
-  if (p._direction == SAD_in)    dstr = "in ";
-  if (p._direction == SAD_out)   dstr = "out ";
-  if (p._direction == SAD_inout) dstr = "inout ";
-
-  string tstr = "invalid ";
-  switch (p._type) {
-  case SAT_float1: tstr = "float1 "; break;
-  case SAT_float2: tstr = "float2 "; break;
-  case SAT_float3: tstr = "float3 "; break;
-  case SAT_float4: tstr = "float4 "; break;
-  case SAT_float4x4: tstr = "float4x4 "; break;
-  case SAT_sampler1d: tstr = "sampler1d "; break;
-  case SAT_sampler2d: tstr = "sampler2d "; break;
-  case SAT_sampler3d: tstr = "sampler3d "; break;
-  case SAT_samplercube: tstr = "samplercube "; break;
-  case SAT_unknown: tstr = "unknown "; break;
-  }
-
-  string fn = _shader_expansion->get_name();
-  p._cat->error() << fn << ": " << msg << " (" <<
-    vstr << dstr << tstr << p._name << ")\n";
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::cp_errchk_parameter_words
-//       Access: Public, Static
-//  Description: Make sure the provided parameter contains
-//               the specified number of words.  If not, print
-//               error message and return false.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-cp_errchk_parameter_words(ShaderArgInfo &p, int len)
-{
-  vector_string words;
-  tokenize(p._name, words, "_");
-  if ((int)words.size() != len) {
-    cp_report_error(p, "parameter name has wrong number of words");
-    return false;
-  }
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::cp_errchk_parameter_in
-//       Access: Public, Static
-//  Description: Make sure the provided parameter has the
-//               'in' direction.  If not, print
-//               error message and return false.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-cp_errchk_parameter_in(ShaderArgInfo &p)
-{
-  if (p._direction != SAD_in) {
-    cp_report_error(p, "parameter should be declared 'in'");
-    return false;
-  }
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::cp_errchk_parameter_varying
-//       Access: Public, Static
-//  Description: Make sure the provided parameter has the
-//               correct variance.  If not, print
-//               error message and return false.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-cp_errchk_parameter_varying(ShaderArgInfo &p)
-{
-  if (!p._varying) {
-    cp_report_error(p, "parameter should be declared 'varying'");
-    return false;
-  }
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::cp_errchk_parameter_uniform
-//       Access: Public, Static
-//  Description: Make sure the provided parameter has the
-//               correct variance.  If not, print
-//               error message and return false.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-cp_errchk_parameter_uniform(ShaderArgInfo &p)
-{
-  if (p._varying) {
-    cp_report_error(p, "parameter should be declared 'uniform'");
-    return false;
-  }
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::cp_errchk_parameter_float
-//       Access: Public, Static
-//  Description: Make sure the provided parameter has
-//               a floating point type.  If not, print
-//               error message and return false.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-cp_errchk_parameter_float(ShaderArgInfo &p, int lo, int hi)
-{
-  int nfloat;
-  switch (p._type) {
-  case SAT_float1: nfloat = 1; break;
-  case SAT_float2: nfloat = 2; break;
-  case SAT_float3: nfloat = 3; break;
-  case SAT_float4: nfloat = 4; break;
-  case SAT_float4x4: nfloat = 16; break;
-  default: nfloat = 0; break;
-  }
-  if ((nfloat < lo)||(nfloat > hi)) {
-    string msg = "wrong type for parameter: should be float";
-    cp_report_error(p, msg);
-    return false;
-  }
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::cp_errchk_parameter_sampler
-//       Access: Public, Static
-//  Description: Make sure the provided parameter has
-//               a texture type.  If not, print
-//               error message and return false.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-cp_errchk_parameter_sampler(ShaderArgInfo &p)
-{
-  if ((p._type!=SAT_sampler1d)&&
-      (p._type!=SAT_sampler2d)&&
-      (p._type!=SAT_sampler3d)&&
-      (p._type!=SAT_samplercube)) {
-    cp_report_error(p, "parameter should have a 'sampler' type");
-    return false;
-  }
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderContext::cp_parse_trans_clause
-//       Access: Public
-//  Description: Parses a single clause of a "trans" parameter.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-cp_parse_trans_clause(ShaderArgInfo &p, ShaderMatSpec &spec, 
-                      int part, const vector_string &pieces,
-                      int &next, ShaderMatInput ofop, ShaderMatInput op) {
-  if (pieces[next+1]=="of") {
-    if (pieces[next+2]=="") {
-      cp_report_error(p, "'of' should be followed by a name");
-      return false;
-    }
-    spec._part[part] = ofop;
-    spec._arg[part] = InternalName::make(pieces[next+2]);
-    next += 3;
-    return true;
-  } else {
-    spec._part[part] = op;
-    spec._arg[part] = NULL;
-    next += 1;
-    return true;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderContext::cp_optimize_mat_spec
-//       Access: Public
-//  Description: Analyzes a ShaderMatSpec and decides what it should
-//               use its cache for.  It can cache the results of any
-//               one opcode, or, it can cache the entire result.  This
-//               routine needs to be smart enough to know which
-//               data items can be correctly cached, and which cannot.
-////////////////////////////////////////////////////////////////////
-void ShaderContext::
-cp_optimize_mat_spec(ShaderMatSpec &spec) {
-
-  // If we're composing with identity, simplify.
-  if (spec._func == SMF_compose) {
-    if (spec._part[1] == SMO_identity) {
-      spec._func = SMF_first;
-    }
-  }
-  if (spec._func == SMF_compose) {
-    if (spec._part[0] == SMO_identity) {
-      spec._func = SMF_first;
-      spec._part[0] = spec._part[1];
-      spec._arg[0] = spec._arg[1];
-    }
-  }
-
-  // See if either half can be cached.
-  bool can_cache_part0 = true;
-  bool can_cache_part1 = true;
-  if ((spec._part[0] == SMO_model_to_view)||
-      (spec._part[0] == SMO_view_to_model)) {
-    can_cache_part0 = false;
-  }
-  if ((spec._part[1] == SMO_model_to_view)||
-      (spec._part[1] == SMO_view_to_model)) {
-    can_cache_part1 = false;
-  }
-  
-  // See if we can use a compose-with-cache variant.
-  if (spec._func == SMF_compose) {
-    if (can_cache_part0) {
-      spec._func = SMF_compose_cache_first;
-    } else if (can_cache_part1) {
-      spec._func = SMF_compose_cache_second;
-    }
-  }
-  
-  // Determine transform-dependence.
-  if (can_cache_part0 && can_cache_part1) {
-    spec._trans_dependent = false;
-  } else {
-    spec._trans_dependent = true;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderContext::compile_parameter
-//       Access: Public
-//  Description: Analyzes a parameter and decides how to
-//               bind the parameter to some part of panda's
-//               internal state.  Updates one of the bind
-//               arrays to cause the binding to occur.
-//
-//               If there is an error, this routine will append
-//               an error message onto the error messages.
-////////////////////////////////////////////////////////////////////
-bool ShaderContext::
-compile_parameter(void *reference,
-                  const string   &arg_name,
-                  ShaderArgType   arg_type,
-                  ShaderArgDir    arg_direction,
-                  bool            arg_varying,
-                  NotifyCategory *arg_cat)
-{
-  ShaderArgInfo p;
-  p._name       = arg_name;
-  p._type       = arg_type;
-  p._direction  = arg_direction;
-  p._varying    = arg_varying;
-  p._cat        = arg_cat;
-
-  if (p._name.size() == 0) return true;
-  if (p._name[0] == '$') return true;
-  vector_string pieces;
-  tokenize(p._name, pieces, "_");
-
-  if (pieces.size() < 2) {
-    cp_report_error(p, "invalid parameter name");
-    return false;
-  }
-
-  // Implement vtx parameters - the varying kind.
-  
-  if (pieces[0] == "vtx") {
-    if ((!cp_errchk_parameter_in(p)) ||
-        (!cp_errchk_parameter_varying(p)) ||
-        (!cp_errchk_parameter_float(p, 1, 4))) {
-      return false;
-    }
-    ShaderVarSpec bind;
-    bind._parameter = reference;
-    if (pieces.size() == 2) {
-      if (pieces[1]=="position") {
-        bind._name = InternalName::get_vertex();
-        bind._append_uv = -1;
-        _var_spec.push_back(bind);
-        return true;
-      }
-      if (pieces[1].substr(0,8)=="texcoord") {
-        bind._name = InternalName::get_texcoord();
-        bind._append_uv = atoi(pieces[1].c_str()+8);
-        _var_spec.push_back(bind);
-        return true;
-      }
-      if (pieces[1].substr(0,7)=="tangent") {
-        bind._name = InternalName::get_tangent();
-        bind._append_uv = atoi(pieces[1].c_str()+7);
-        _var_spec.push_back(bind);
-        return true;
-      }
-      if (pieces[1].substr(0,8)=="binormal") {
-        bind._name = InternalName::get_binormal();
-        bind._append_uv = atoi(pieces[1].c_str()+8);
-        _var_spec.push_back(bind);
-        return true;
-      }
-    }
-    bind._name = InternalName::get_root();
-    bind._append_uv = -1;
-    for (int i=1; i<(int)(pieces.size()-0); i++)
-      bind._name = bind._name->append(pieces[i]);
-    _var_spec.push_back(bind);
-    return true;
-  }
-
-  // Implement some macros. Macros work by altering the
-  // contents of the 'pieces' array, and then falling through.
-
-  if (pieces[0] == "mstrans") {
-    pieces[0] = "trans";
-    pieces.push_back("to");
-    pieces.push_back("model");
-  }
-  if (pieces[0] == "wstrans") {
-    pieces[0] = "trans";
-    pieces.push_back("to");
-    pieces.push_back("world");
-  }
-  if (pieces[0] == "vstrans") {
-    pieces[0] = "trans";
-    pieces.push_back("to");
-    pieces.push_back("view");
-  }
-  if (pieces[0] == "cstrans") {
-    pieces[0] = "trans";
-    pieces.push_back("to");
-    pieces.push_back("clip");
-  }
-  if (pieces[0] == "mspos") {
-    pieces[0] = "row3";
-    pieces.push_back("to");
-    pieces.push_back("model");
-  }
-  if (pieces[0] == "wspos") {
-    pieces[0] = "row3";
-    pieces.push_back("to");
-    pieces.push_back("world");
-  }
-  if (pieces[0] == "vspos") {
-    pieces[0] = "row3";
-    pieces.push_back("to");
-    pieces.push_back("view");
-  }
-  if (pieces[0] == "cspos") {
-    pieces[0] = "row3";
-    pieces.push_back("to");
-    pieces.push_back("clip");
-  }
-
-  // Implement the modelview macros.
-
-  if ((pieces[0] == "mat")||(pieces[0] == "inv")||
-      (pieces[0] == "tps")||(pieces[0] == "itp")) {
-    if (!cp_errchk_parameter_words(p, 2)) {
-      return false;
-    }
-    string trans = pieces[0];
-    string matrix = pieces[1];
-    pieces.clear();
-    if (matrix == "modelview") {
-      tokenize("trans_model_to_apiview", pieces, "_");
-    } else if (matrix == "projection") {
-      tokenize("trans_apiview_to_apiclip", pieces, "_");
-    } else if (matrix == "modelproj") {
-      tokenize("trans_model_to_apiclip", pieces, "_");
-    } else {
-      cp_report_error(p,"unrecognized matrix name");
-      return false;
-    }
-    if (trans=="mat") {
-      pieces[0] = "trans";
-    } else if (trans=="inv") {
-      string t = pieces[1];
-      pieces[1] = pieces[3];
-      pieces[3] = t;
-    } else if (trans=="tps") {
-      pieces[0] = "tpose";
-    } else if (trans=="itp") {
-      string t = pieces[1];
-      pieces[1] = pieces[3];
-      pieces[3] = t;
-      pieces[0] = "tpose";
-    }
-  }
-
-  // Implement the transform-matrix generator.
-
-  if ((pieces[0]=="trans")||
-      (pieces[0]=="tpose")||
-      (pieces[0]=="row0")||
-      (pieces[0]=="row1")||
-      (pieces[0]=="row2")||
-      (pieces[0]=="row3")||
-      (pieces[0]=="col0")||
-      (pieces[0]=="col1")||
-      (pieces[0]=="col2")||
-      (pieces[0]=="col3")) {
-    
-    if ((!cp_errchk_parameter_in(p)) ||
-        (!cp_errchk_parameter_uniform(p)))
-      return false;
-    
-    ShaderMatSpec bind;
-    bind._parameter = reference;
-    bind._func = SMF_compose;
-
-    int next = 1;
-    pieces.push_back("");
-
-    // Decide whether this is a matrix or vector.
-    if      (pieces[0]=="trans")   bind._piece = SMP_whole;
-    else if (pieces[0]=="tpose")   bind._piece = SMP_transpose;
-    else if (pieces[0]=="row0")    bind._piece = SMP_row0;
-    else if (pieces[0]=="row1")    bind._piece = SMP_row1;
-    else if (pieces[0]=="row2")    bind._piece = SMP_row2;
-    else if (pieces[0]=="row3")    bind._piece = SMP_row3;
-    else if (pieces[0]=="col0")    bind._piece = SMP_col0;
-    else if (pieces[0]=="col1")    bind._piece = SMP_col1;
-    else if (pieces[0]=="col2")    bind._piece = SMP_col2;
-    else if (pieces[0]=="col3")    bind._piece = SMP_col3;
-    if ((bind._piece == SMP_whole)||(bind._piece == SMP_transpose)) {
-      if (!cp_errchk_parameter_float(p, 16, 16)) return false;
-    } else {
-      if (!cp_errchk_parameter_float(p, 4, 4)) return false;
-    }
-    
-    // Parse the first half of the clause.
-    bool ok = true;
-    if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
-      cp_report_error(p, "argument missing");
-      return false;
-    } else if (pieces[next] == "world") {
-      bind._part[0] = SMO_world_to_view;
-      bind._arg[0] = NULL;
-      next += 1;
-    } else if (pieces[next] == "model") {
-      ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_model_to_view);
-    } else if (pieces[next] == "clip") {
-      ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_clip_x_to_view, SMO_clip_to_view);
-    } else if (pieces[next] == "view") {
-      ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_identity);
-    } else if (pieces[next] == "apiview") {
-      ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiview_x_to_view, SMO_apiview_to_view);
-    } else if (pieces[next] == "apiclip") {
-      ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiclip_x_to_view, SMO_apiclip_to_view);
-    } else {
-      bind._part[0] = SMO_view_x_to_view;
-      bind._arg[0] = InternalName::make(pieces[next]);
-      next += 1;
-    }
-
-    // Check for errors in the first clause.
-    if (!ok) {
-      return false;
-    }
-
-    // Check for syntactic well-formed-ness.
-    if (pieces[next] != "to") {
-      cp_report_error(p, "keyword 'to' expected");
-      return false;
-    } else {
-      next += 1;
-    }
-    
-    // Parse the second half of the clause.
-    if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
-      cp_report_error(p, "argument missing");
-      return false;
-    } else if (pieces[next] == "world") {
-      bind._part[1] = SMO_view_to_world;
-      bind._arg[1] = NULL;
-      next += 1;
-    } else if (pieces[next] == "model") {
-      ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_view_to_model);
-    } else if (pieces[next] == "clip") {
-      ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_clip_x, SMO_view_to_clip);
-    } else if (pieces[next] == "view") {
-      ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_identity);
-    } else if (pieces[next] == "apiview") {
-      ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiview_x, SMO_view_to_apiview);
-    } else if (pieces[next] == "apiclip") {
-      ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiclip_x, SMO_view_to_apiclip);
-    } else {
-      bind._part[1] = SMO_view_to_view_x;
-      bind._arg[1] = InternalName::make(pieces[next]);
-      next += 1;
-    }
-    
-    // Check for errors in the second clause.
-    if (!ok) {
-      return false;
-    }
-
-    // Check for syntactic well-formed-ness.
-    if (pieces[next] != "") {
-      cp_report_error(p, "end of line expected");
-      return false;
-    }
-    
-    cp_optimize_mat_spec(bind);
-    _mat_spec.push_back(bind);
-    return true;
-  }
-
-  // Keywords to access unusual parameters.
-  
-  if (pieces[0] == "sys") {
-    if ((!cp_errchk_parameter_words(p,2)) ||
-        (!cp_errchk_parameter_in(p)) ||
-        (!cp_errchk_parameter_uniform(p))) {
-      return false;
-    }
-    ShaderMatSpec bind;
-    bind._parameter = reference;
-    bind._piece = SMP_row3;
-    bind._func = SMF_first;
-    bind._part[1] = SMO_identity;
-    bind._arg[1] = NULL;
-    if (pieces[1] == "pixelsize") {
-      if (!cp_errchk_parameter_float(p, 2, 2)) {
-        return false;
-      }
-      bind._part[0] = SMO_pixel_size;
-      bind._arg[0] = NULL;
-    } else if (pieces[1] == "windowsize") {
-      if (!cp_errchk_parameter_float(p, 2, 2)) {
-        return false;
-      }
-      bind._part[0] = SMO_window_size;
-      bind._arg[0] = NULL;
-    } else if (pieces[1] == "cardcenter") {
-      if (!cp_errchk_parameter_float(p, 2, 2)) {
-        return false;
-      }
-      bind._part[0] = SMO_card_center;
-      bind._arg[0] = NULL;
-    } else {
-      cp_report_error(p,"unknown system parameter");
-      return false;
-    }
-    
-    cp_optimize_mat_spec(bind);
-    _mat_spec.push_back(bind);
-    return true;
-  }
-  
-  // Keywords to access textures.
-  
-  if (pieces[0] == "tex") {
-    if ((!cp_errchk_parameter_in(p)) ||
-        (!cp_errchk_parameter_uniform(p)) ||
-        (!cp_errchk_parameter_sampler(p)))
-      return false;
-    if ((pieces.size() != 2)&&(pieces.size() != 3)) {
-      cp_report_error(p, "Invalid parameter name");
-      return false;
-    }
-    ShaderTexSpec bind;
-    bind._parameter = reference;
-    bind._name = 0;
-    bind._stage = atoi(pieces[1].c_str());
-    switch (p._type) {
-    case SAT_sampler1d:   bind._desired_type = Texture::TT_1d_texture; break;
-    case SAT_sampler2d:   bind._desired_type = Texture::TT_2d_texture; break;
-    case SAT_sampler3d:   bind._desired_type = Texture::TT_3d_texture; break;
-    case SAT_samplercube: bind._desired_type = Texture::TT_cube_map; break;
-    default:
-      cp_report_error(p, "Invalid type for a tex-parameter");
-      return false;
-    }
-    if (pieces.size()==3) {
-      bind._suffix = InternalName::make(((string)"-") + pieces[2]);
-    }
-    _tex_spec.push_back(bind);
-    return true;
-  }
-
-  // Keywords to access constants.
-
-  if (pieces[0] == "k") {
-    if ((!cp_errchk_parameter_words(p,2)) ||
-        (!cp_errchk_parameter_in(p)) ||
-        (!cp_errchk_parameter_uniform(p)))
-      return false;
-    switch (p._type) {
-    case SAT_float4: {
-      ShaderMatSpec bind;
-      bind._parameter = reference;
-      bind._piece = SMP_row3;
-      bind._func = SMF_first;
-      bind._part[0] = SMO_vec_constant_x;
-      bind._arg[0] = InternalName::make(pieces[1]);
-      bind._part[1] = SMO_identity;
-      bind._arg[1] = NULL;
-      cp_optimize_mat_spec(bind);
-      _mat_spec.push_back(bind);
-      break;
-    }
-    case SAT_float4x4: {
-      ShaderMatSpec bind;
-      bind._parameter = reference;
-      bind._piece = SMP_whole;
-      bind._func = SMF_first;
-      bind._part[0] = SMO_vec_constant_x;
-      bind._arg[0] = InternalName::make(pieces[1]);
-      bind._part[1] = SMO_identity;
-      bind._arg[1] = NULL;
-      cp_optimize_mat_spec(bind);
-      _mat_spec.push_back(bind);
-      break;
-    }
-    case SAT_sampler1d: {
-      ShaderTexSpec bind;
-      bind._parameter = reference;
-      bind._name = InternalName::make(pieces[1]);
-      bind._desired_type=Texture::TT_1d_texture;
-      _tex_spec.push_back(bind);
-      break;
-    }
-    case SAT_sampler2d: {
-      ShaderTexSpec bind;
-      bind._parameter = reference;
-      bind._name = InternalName::make(pieces[1]);
-      bind._desired_type=Texture::TT_2d_texture;
-      _tex_spec.push_back(bind);
-      break;
-    }
-    case SAT_sampler3d: {
-      ShaderTexSpec bind;
-      bind._parameter = reference;
-      bind._name = InternalName::make(pieces[1]);
-      bind._desired_type=Texture::TT_3d_texture;
-      _tex_spec.push_back(bind);
-      break;
-    }
-    case SAT_samplercube: {
-      ShaderTexSpec bind;
-      bind._parameter = reference;
-      bind._name = InternalName::make(pieces[1]);
-      bind._desired_type = Texture::TT_cube_map;
-      _tex_spec.push_back(bind);
-      break;
-    }
-    default:
-      cp_report_error(p, "Invalid type for a k-parameter");
-      return false;
-    }
-    return true;
-  }
-
-  if (pieces[0] == "l") {
-    // IMPLEMENT THE ERROR CHECKING
-    return true; // Cg handles this automatically.
-  }
-
-  if (pieces[0] == "o") {
-    // IMPLEMENT THE ERROR CHECKING
-    return true; // Cg handles this automatically.
-  }
-
-  cp_report_error(p, "unrecognized parameter name");
-  return false;
-}
-
-

+ 1 - 150
panda/src/gobj/shaderContext.h

@@ -40,156 +40,7 @@ class EXPCL_PANDA ShaderContext: public SavedContext {
 public:
   INLINE ShaderContext(ShaderExpansion *se);
   
-  ShaderExpansion *_shader_expansion;
-
-public:
-  enum {
-    SHADER_type_vert=0,
-    SHADER_type_frag=1,
-    SHADER_type_both=2,
-  };
-
-  enum ShaderMatInput {
-    SMO_identity,
-
-    SMO_window_size,
-    SMO_pixel_size,
-    SMO_card_center,
-    
-    SMO_mat_constant_x,
-    SMO_vec_constant_x,
-    
-    SMO_world_to_view,
-    SMO_view_to_world,
-
-    SMO_model_to_view,
-    SMO_view_to_model,
-
-    SMO_apiview_to_view,
-    SMO_view_to_apiview,
-
-    SMO_clip_to_view,
-    SMO_view_to_clip,
-
-    SMO_apiclip_to_view,
-    SMO_view_to_apiclip,
-    
-    SMO_view_x_to_view,
-    SMO_view_to_view_x,
-
-    SMO_apiview_x_to_view,
-    SMO_view_to_apiview_x,
-
-    SMO_clip_x_to_view,
-    SMO_view_to_clip_x,
-
-    SMO_apiclip_x_to_view,
-    SMO_view_to_apiclip_x,
-  };
-
-  enum ShaderArgType {
-    SAT_float1,
-    SAT_float2,
-    SAT_float3,
-    SAT_float4,
-    SAT_float4x4,
-    SAT_sampler1d,
-    SAT_sampler2d,
-    SAT_sampler3d,
-    SAT_samplercube,
-    SAT_unknown,
-  };
-
-  enum ShaderArgDir {
-    SAD_in,
-    SAD_out,
-    SAD_inout,
-    SAD_unknown,
-  };
-
-  enum ShaderMatPiece {
-    SMP_whole,
-    SMP_transpose,
-    SMP_row0,
-    SMP_row1,
-    SMP_row2,
-    SMP_row3,
-    SMP_col0,
-    SMP_col1,
-    SMP_col2,
-    SMP_col3,
-  };
-
-  enum ShaderMatFunc {
-    SMF_compose,
-    SMF_compose_cache_first,
-    SMF_compose_cache_second,
-    SMF_first,
-  };
-
-  struct ShaderMatSpec {
-    ShaderMatFunc    _func;
-    ShaderMatInput   _part[2];
-    PT(InternalName) _arg[2];
-    LMatrix4f        _cache;
-    ShaderMatPiece   _piece;
-    bool             _trans_dependent;
-    void            *_parameter;
-  };
-
-  struct ShaderTexSpec {
-    PT(InternalName)  _name;
-    int               _stage;
-    int               _desired_type;
-    PT(InternalName)  _suffix;
-    void             *_parameter;
-  };
-
-  struct ShaderVarSpec {
-    PT(InternalName) _name;
-    int              _append_uv;
-    void            *_parameter;
-  };
-
-  struct ShaderArgInfo {
-    string          _name;
-    ShaderArgType   _type;
-    ShaderArgDir    _direction;
-    bool            _varying;
-    NotifyCategory *_cat;
-  };
-
-protected:
-  pvector <ShaderMatSpec> _mat_spec;
-  pvector <ShaderTexSpec> _tex_spec;
-  pvector <ShaderVarSpec> _var_spec;
-  
-private:
-  // These functions are only called from compile_parameter.
-
-  void cp_report_error(ShaderArgInfo &arg, const string &msg);
-  bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len);
-  bool cp_errchk_parameter_in(ShaderArgInfo &arg);
-  bool cp_errchk_parameter_varying(ShaderArgInfo &arg);
-  bool cp_errchk_parameter_uniform(ShaderArgInfo &arg);
-  bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi);
-  bool cp_errchk_parameter_sampler(ShaderArgInfo &arg);
-  bool cp_parse_trans_clause(ShaderArgInfo &arg,
-                             ShaderMatSpec &spec,
-                             int part,
-                             const vector_string &pieces,
-                             int &next,
-                             ShaderMatInput ofop,
-                             ShaderMatInput op);
-  void cp_optimize_mat_spec(ShaderMatSpec &spec);
-
-protected:
-  bool compile_parameter(void *reference,
-                         const string   &arg_name,
-                         ShaderArgType   arg_type,
-                         ShaderArgDir    arg_direction,
-                         bool            arg_varying,
-                         NotifyCategory *arg_cat);
+  ShaderExpansion *_expansion;
 
 public:
   static TypeHandle get_class_type() {

+ 66 - 0
panda/src/gobj/shaderExpansion.I

@@ -36,3 +36,69 @@ get_text() const {
   return _text;
 }
 
+////////////////////////////////////////////////////////////////////
+//  Function: ShaderExpansion::get_header
+//  Access: Public
+//  Description: Return the ShaderExpansion's header line.
+////////////////////////////////////////////////////////////////////
+INLINE const string &ShaderExpansion::
+get_header() const {
+  return _header;
+}
+
+////////////////////////////////////////////////////////////////////
+//  Function: ShaderExpansion::get_error_flag
+//  Access: Public
+//  Description: Returns true if the shader contains a compile-time
+//               error.  This doesn't tell you whether or not the
+//               shader is supported on the current video card.
+////////////////////////////////////////////////////////////////////
+INLINE bool ShaderExpansion::
+get_error_flag() const {
+  return _error_flag;
+}
+
+////////////////////////////////////////////////////////////////////
+//  Function: ShaderExpansion::ShaderCapabilities Constructor
+//  Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderExpansion::ShaderCaps::
+ShaderCaps() {
+  clear();
+}
+
+
+////////////////////////////////////////////////////////////////////
+//  Function: ShaderExpansion::ShaderCapabilities::clear()
+//  Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ShaderExpansion::ShaderCaps::
+clear() {
+#ifdef HAVE_CG
+  _active_vprofile = 0;
+  _active_fprofile = 0;
+  _ultimate_vprofile = 0;
+  _ultimate_fprofile = 0;
+#endif
+}
+
+
+////////////////////////////////////////////////////////////////////
+//  Function: ShaderExpansion::ShaderCapabilities::operator ==
+//  Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool ShaderExpansion::ShaderCaps::
+operator == (const ShaderCaps &other) const {
+#ifdef HAVE_CG
+  if ((_active_vprofile != other._active_vprofile) ||
+      (_active_fprofile != other._active_fprofile) ||
+      (_ultimate_vprofile != other._ultimate_vprofile) ||
+      (_ultimate_fprofile != other._ultimate_fprofile)) {
+     return false;
+  }
+#endif
+  return true;
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 1131 - 1
panda/src/gobj/shaderExpansion.cxx


+ 213 - 11
panda/src/gobj/shaderExpansion.h

@@ -25,29 +25,169 @@
 #include "graphicsStateGuardianBase.h"
 #include "internalName.h"
 
+#ifdef HAVE_CG
+// I don't want to include the Cg header file into panda as a 
+// whole.  Instead, I'll just excerpt some opaque declarations.
+typedef struct _CGcontext *CGcontext;
+typedef struct _CGprogram *CGprogram;
+typedef struct _CGparameter *CGparameter;
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //       Class : ShaderExpansion
 //      Summary: A shader can contain context-sensitive macros.
 //               A ShaderExpansion is the output you get when you
 //               run the macro preprocessor on a shader.
 //               The ShaderExpansion contains the shader's 
-//               macroexpanded text, and a map of ShaderContext
+//               macroexpanded text, an analysis of the shader's
+//               parameters, and a map of ShaderContext
 //               objects.
 ////////////////////////////////////////////////////////////////////
 
 class EXPCL_PANDA ShaderExpansion: public TypedReferenceCount {
 
 PUBLISHED:
-  static PT(ShaderExpansion) make(const string &name, const string &body);
   
   INLINE const string &get_name() const;
   INLINE const string &get_text() const;
-  
+  INLINE const string &get_header() const;
+  INLINE bool get_error_flag() const;
+
   void prepare(PreparedGraphicsObjects *prepared_objects);
   bool release(PreparedGraphicsObjects *prepared_objects);
   int release_all();
   
-PUBLISHED:
+public:
+
+  enum ShaderMatInput {
+    SMO_identity,
+
+    SMO_window_size,
+    SMO_pixel_size,
+    SMO_card_center,
+    
+    SMO_mat_constant_x,
+    SMO_vec_constant_x,
+    
+    SMO_world_to_view,
+    SMO_view_to_world,
+
+    SMO_model_to_view,
+    SMO_view_to_model,
+
+    SMO_apiview_to_view,
+    SMO_view_to_apiview,
+
+    SMO_clip_to_view,
+    SMO_view_to_clip,
+
+    SMO_apiclip_to_view,
+    SMO_view_to_apiclip,
+    
+    SMO_view_x_to_view,
+    SMO_view_to_view_x,
+
+    SMO_apiview_x_to_view,
+    SMO_view_to_apiview_x,
+
+    SMO_clip_x_to_view,
+    SMO_view_to_clip_x,
+
+    SMO_apiclip_x_to_view,
+    SMO_view_to_apiclip_x,
+  };
+
+  enum ShaderArgType {
+    SAT_float1,
+    SAT_float2,
+    SAT_float3,
+    SAT_float4,
+    SAT_float4x4,
+    SAT_sampler1d,
+    SAT_sampler2d,
+    SAT_sampler3d,
+    SAT_samplercube,
+    SAT_unknown,
+  };
+
+  enum ShaderArgDir {
+    SAD_in,
+    SAD_out,
+    SAD_inout,
+    SAD_unknown,
+  };
+
+  enum ShaderMatPiece {
+    SMP_whole,
+    SMP_transpose,
+    SMP_row0,
+    SMP_row1,
+    SMP_row2,
+    SMP_row3,
+    SMP_col0,
+    SMP_col1,
+    SMP_col2,
+    SMP_col3,
+  };
+
+  enum ShaderMatFunc {
+    SMF_compose,
+    SMF_compose_cache_first,
+    SMF_compose_cache_second,
+    SMF_first,
+  };
+
+  struct ShaderArgId {
+    string _name;
+    bool   _fshader;
+    int    _seqno;
+  };
+  
+  struct ShaderMatSpec {
+    ShaderArgId       _id;
+    ShaderMatFunc     _func;
+    ShaderMatInput    _part[2];
+    PT(InternalName)  _arg[2];
+    LMatrix4f         _cache;
+    ShaderMatPiece    _piece;
+    bool              _trans_dependent;
+  };
+
+  struct ShaderTexSpec {
+    ShaderArgId       _id;
+    PT(InternalName)  _name;
+    int               _stage;
+    int               _desired_type;
+    PT(InternalName)  _suffix;
+  };
+
+  struct ShaderVarSpec {
+    ShaderArgId       _id;
+    PT(InternalName)  _name;
+    int               _append_uv;
+  };
+
+  struct ShaderArgInfo {
+    ShaderArgId       _id;
+    ShaderArgType     _type;
+    ShaderArgDir      _direction;
+    bool              _varying;
+    NotifyCategory   *_cat;
+  };
+
+  struct ShaderCaps {
+#ifdef HAVE_CG
+    int _active_vprofile;
+    int _active_fprofile;
+    int _ultimate_vprofile;
+    int _ultimate_fprofile;
+#endif;
+    INLINE void clear();
+    INLINE bool operator == (const ShaderCaps &other) const;
+    INLINE ShaderCaps();
+  };
+
+ private:
   // These routines help split the shader into sections,
   // for those shader implementations that need to do so.
   void parse_init();
@@ -57,11 +197,65 @@ PUBLISHED:
   int  parse_lineno();
   bool parse_eof();
   
-public:
-  ~ShaderExpansion();
+  void cp_report_error(ShaderArgInfo &arg, const string &msg);
+  bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len);
+  bool cp_errchk_parameter_in(ShaderArgInfo &arg);
+  bool cp_errchk_parameter_varying(ShaderArgInfo &arg);
+  bool cp_errchk_parameter_uniform(ShaderArgInfo &arg);
+  bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi);
+  bool cp_errchk_parameter_sampler(ShaderArgInfo &arg);
+  bool cp_parse_trans_clause(ShaderArgInfo &arg,
+                             ShaderMatSpec &spec,
+                             int part,
+                             const vector_string &pieces,
+                             int &next,
+                             ShaderMatInput ofop,
+                             ShaderMatInput op);
+  void cp_optimize_mat_spec(ShaderMatSpec &spec);
+  
+  bool compile_parameter(const ShaderArgId    &arg_id,
+                         ShaderArgType         arg_type,
+                         ShaderArgDir          arg_direction,
+                         bool                  arg_varying,
+                         NotifyCategory       *arg_cat);
+
+  void clear_parameters();
+
+#ifdef HAVE_CG
+ private:
+  ShaderArgType cg_parameter_type(CGparameter p);
+  ShaderArgDir  cg_parameter_dir(CGparameter p);
+  CGprogram     cg_compile_entry_point(char *entry, int active, int ultimate);
+  bool          cg_analyze_entry_point(CGprogram prog, bool fshader);
+  bool          cg_analyze_shader(const ShaderCaps &caps);
+  bool          cg_compile_shader(const ShaderCaps &caps);
+  void          cg_release_resources();
+  
+  ShaderCaps _cg_last_caps;
+  CGcontext  _cg_context;
+  CGprogram  _cg_vprogram;
+  CGprogram  _cg_fprogram;
+  
+ public:
 
+  bool          cg_compile_for(const ShaderCaps &caps,
+                               CGcontext &ctx,
+                               CGprogram &vprogram,
+                               CGprogram &fprogram,
+                               pvector<CGparameter> &map);
+  
+#endif
+
+ public:
+  pvector <ShaderMatSpec> _mat_spec;
+  pvector <ShaderTexSpec> _tex_spec;
+  pvector <ShaderVarSpec> _var_spec;
+  
+ protected:
   string         _name;
   string         _text;
+  string         _header;
+  bool           _error_flag;
   int            _parse;
   
   typedef pair < string, string > ExpansionKey;
@@ -73,15 +267,23 @@ public:
 
   typedef pmap <PreparedGraphicsObjects *, ShaderContext *> Contexts;
   Contexts _contexts;
-  
+
+ public:  
   ShaderContext *prepare_now(PreparedGraphicsObjects *prepared_objects, 
                              GraphicsStateGuardianBase *gsg);
   
-private:  
-  ShaderExpansion();
+ private:  
+  ShaderExpansion(const string &name, const string &text,
+                  const ShaderCaps &caps);
   void clear_prepared(PreparedGraphicsObjects *prepared_objects);
 
-public:
+ public:
+  static PT(ShaderExpansion) make(const string &name, const string &body,
+                                  const ShaderCaps &caps);
+  
+  ~ShaderExpansion();
+  
+ public:
   static TypeHandle get_class_type() {
     return _type_handle;
   }
@@ -95,7 +297,7 @@ public:
   }
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
 
-private:
+ private:
   static TypeHandle _type_handle;
 };
 

+ 0 - 3
panda/src/mesadisplay/mesagsg.h

@@ -44,9 +44,6 @@
 #define EXPCL_GL EXPCL_PANDAMESA
 #define EXPTP_GL EXPTP_PANDAMESA
 
-#undef HAVE_CGGL // Mesa does not support Nvidia Cg... make sure it tries to compile
-                 // without it
-
 // Don't include Mesa's provided glext.h file; we'll provide our own
 // that's more current.
 #define __glext_h_

+ 6 - 2
panda/src/pgraph/shader.cxx

@@ -140,15 +140,19 @@ make(const string &body, int preprocessor) {
 //
 //               Currently, macroexpand is just a stub that returns an
 //               expansion which is exactly equal to the input string.
+//
+//               The "caps" parameter should describe the capabilities
+//               of the gsg on which this is intended to run.
 ////////////////////////////////////////////////////////////////////
 PT(ShaderExpansion) Shader::
-macroexpand(const RenderState *context) const {
+macroexpand(const RenderState *context,
+            const ShaderExpansion::ShaderCaps &caps) const {
   if (_fixed_expansion) {
     return _fixed_expansion;
   }
   // I am casting away the 'const' so as to be able
   // to write to this field.  This field is just a cache.
-  ((Shader*)this)->_fixed_expansion = ShaderExpansion::make(_name,_body);
+  ((Shader*)this)->_fixed_expansion = ShaderExpansion::make(_name,_body,caps);
   return _fixed_expansion;
 }
 

+ 2 - 1
panda/src/pgraph/shader.h

@@ -45,7 +45,8 @@ PUBLISHED:
   INLINE bool            get_loaded() const;
   INLINE bool            get_load_error() const;
 
-  PT(ShaderExpansion) macroexpand(const RenderState *context) const;
+  PT(ShaderExpansion) macroexpand(const RenderState *context,
+                                  const ShaderExpansion::ShaderCaps &caps) const;
 
 public:
   Shader();

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.