Browse Source

partial vtx buffer chkin, plus some pipeline tweaks

cxgeorge 24 years ago
parent
commit
8b6d25c53e

+ 4 - 5
panda/src/dxgsg/dxGeomNodeContext.I

@@ -19,14 +19,13 @@
 
 ////////////////////////////////////////////////////////////////////
 //     Function: dxGeomNodeContext::Constructor
-//       Access: Public
+//       Access: Public                                 
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE DXGeomNodeContext::
-DXGeomNodeContext(GeomNode *node) :
-  GeomNodeContext(node)
+DXGeomNodeContext(GeomNode *node) : GeomNodeContext(node)
 {
-#ifdef DO_PSTATS
   _num_verts = 0;
-#endif
+  _pVB = NULL;
+  _pXformed_VB = NULL;
 }

+ 12 - 0
panda/src/dxgsg/dxGeomNodeContext.cxx

@@ -19,3 +19,15 @@
 #include "dxGeomNodeContext.h"
 
 TypeHandle DXGeomNodeContext::_type_handle;
+
+DXGeomNodeContext::~DXGeomNodeContext()
+{
+   if(_pXformed_VB!=NULL)
+       _pXformed_VB->Release();
+   _pXformed_VB=NULL;
+
+   if(_pVB!=NULL)
+       _pVB->Release();
+   _pVB=NULL;
+}
+

+ 15 - 12
panda/src/dxgsg/dxGeomNodeContext.h

@@ -32,6 +32,9 @@
 #include <geomNode.h>
 #include "pvector.h"
 
+#define D3D_OVERLOADS   //  get D3DVECTOR '+' operator, etc from d3dtypes.h
+#include <d3d.h>
+
 ////////////////////////////////////////////////////////////////////
 //       Class : DXGeomNodeContext
 // Description :
@@ -39,22 +42,22 @@
 class EXPCL_PANDADX DXGeomNodeContext : public GeomNodeContext {
 public:
   INLINE DXGeomNodeContext(GeomNode *node);
+  ~DXGeomNodeContext();
 
-#if 0
-  // The DX display list index that draws the contents of this
-  // GeomNode.
-  DXuint _index;
-#endif
   // A list of the dynamic Geoms within the GeomNode; these aren't
-  // part of the above display list.
+  // part of the above display list and must be drawn separately
   typedef pvector<PT(dDrawable) > Geoms;
-  Geoms _dynamic_geoms;
+  Geoms _other_geoms;
 
-#ifdef DO_PSTATS
-  // The number of vertices represented by the display list.  This is
-  // strictly for the benefit of PStats reporting.
-  int _num_verts;
-#endif
+  // VB's are already reference-counted by D3D, no need to make separate panda object to do that
+  // but we will want a way to know if VB has already been xformed by ProcessVerts this frame
+  // if multiple geomnodes share VBs
+
+  LPDIRECT3DVERTEXBUFFER7 _pVB;
+  LPDIRECT3DVERTEXBUFFER7 _pXformed_VB;
+
+  int _start_index;   // starting offset of this geom's verts within the VB
+  int _num_verts;     // number of verts used by this geomcontext within the VB
 
 public:
   static TypeHandle get_class_type() {

+ 372 - 198
panda/src/dxgsg/dxGraphicsStateGuardian.cxx

@@ -85,9 +85,12 @@
 // For sparkle particles, we can have 4 vertices per sparkle, and a
 // particle pool size of 1024 particles
 
+// for sprites, 1000 prims, 6 verts/prim, 24 bytes/vert
 const int VERT_BUFFER_SIZE = (32*6*1024L);
 
-// for sprites, 1000 prims, 6 verts/prim, 24 bytes/vert
+// if defined, pandadx only handles 1 panda display region
+// note multiple region code doesnt work now (see prepare_display_region,set_clipper)
+#define NO_MULTIPLE_DISPLAY_REGIONS
 
 TypeHandle DXGraphicsStateGuardian::_type_handle;
 
@@ -104,8 +107,6 @@ TypeHandle DXGraphicsStateGuardian::_type_handle;
 
 static D3DMATRIX matIdentity;
 
-#define Colorf_to_D3DCOLOR(out_color) (D3DRGBA((out_color)[0], (out_color)[1], (out_color)[2], (out_color)[3]))
-
 #ifdef COUNT_DRAWPRIMS
 
 static DWORD cDPcount=0;
@@ -136,6 +137,67 @@ static void CountDPs(DWORD nVerts,DWORD nTris) {
 static bool bTexStatsRetrievalImpossible=false;
 #endif
 
+//#define Colorf_to_D3DCOLOR(out_color) (D3DRGBA((out_color)[0], (out_color)[1], (out_color)[2], (out_color)[3]))
+
+INLINE DWORD
+//Colorf_to_D3DCOLOR(float *alpha,float *red,float *grn,float *blue) {
+Colorf_to_D3DCOLOR(Colorf &cColorf) {
+// MS VC defines _M_IX86 for x86.  gcc should define _X86_
+//#if defined(_M_IX86) || defined(_X86_)
+#if 1
+    DWORD d3dcolor,tempcolorval=255;
+//    DWORD *Colorf_addr=(DWORD*)&cColorf;
+    // note the default FPU rounding mode will give 255*0.5f=0x80, not 0x7F as VC would force it to by resetting rounding mode
+    // dont think this makes much difference
+
+    __asm {
+;        push eax
+        push ebx   ; want to save this in case this fn is inlined
+        push ecx
+;        mov ecx, Colorf_addr  ; must be a better way to do this w/o using ecx
+        mov ecx, cColorf
+        fild tempcolorval
+        fld [ecx]
+        fmul ST(0),ST(1)
+        fistp tempcolorval  ; no way to store directly to int register
+        mov eax, tempcolorval
+        shl eax, 16
+
+        fld DWORD PTR [ecx+4]  ;grn
+        fmul ST(0),ST(1)
+        fistp tempcolorval   
+        mov ebx,tempcolorval
+        shl ebx, 8
+        or eax,ebx
+
+        fld DWORD PTR [ecx+8]  ;blue
+        fmul ST(0),ST(1)
+        fistp tempcolorval
+        or eax,tempcolorval
+
+        fld DWORD PTR [ecx+12] ;alpha
+        fmul ST(0),ST(1)
+        fistp tempcolorval
+        ; simulate pop 255.0 off FP stack w/o store, mark top as empty and increment stk ptr
+        ffree ST(0)
+        fincstp
+        mov ebx,tempcolorval
+        shl ebx, 24
+        or eax,ebx
+        mov d3dcolor,eax
+        pop ecx
+        pop ebx
+;        pop eax
+    }
+
+//   dxgsg_cat.debug() << (void*)d3dcolor << endl;
+
+   return d3dcolor;
+#else //!_X86_
+   return D3DRGBA(cColorf[0], cColorf[1], cColorf[2], cColorf[3]);
+#endif //!_X86_
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian::Constructor
 //       Access: Public
@@ -312,6 +374,9 @@ init_dx(  LPDIRECTDRAW7     context,
 
     _last_testcooplevel_result = S_OK;
 
+    // only 1 channel on dx currently
+    _panda_gfx_channel = _win->get_channel(0);
+
     HRESULT hr;
 
     if(dx_show_fps_meter) {
@@ -617,8 +682,6 @@ enable_light(int light, bool val) {
     return TRUE;
 }
 
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian::prepare_display_region
 //       Access: Public, Virtual
@@ -630,10 +693,10 @@ prepare_display_region() {
     if (_current_display_region == (DisplayRegion*)0L) {
         dxgsg_cat.error()
         << "Invalid NULL display region in prepare_display_region()\n";
-
     } else if (_current_display_region != _actual_display_region) {
         _actual_display_region = _current_display_region;
-/*
+
+#ifndef NO_MULTIPLE_DISPLAY_REGIONS
     int l, b, w, h;
     _actual_display_region->get_region_pixels(l, b, w, h);
     GLint x = GLint(l);
@@ -641,8 +704,8 @@ prepare_display_region() {
     GLsizei width = GLsizei(w);
     GLsizei height = GLsizei(h);
 #ifdef WBD_GL_MODE
-    call_glScissor( x, y, width, height );
-    call_glViewport( x, y, width, height );
+//    call_glScissor( x, y, width, height );
+//    call_glViewport( x, y, width, height );
 #else
     if ( _scissor_x != x || _scissor_y != y ||
             _scissor_width != width || _scissor_height != height )
@@ -654,11 +717,11 @@ prepare_display_region() {
         set_clipper(cliprect);
         }
 #endif   //WBD_GL_MODE
-*/
+#endif
     }
 }
 
-#if 0
+#ifndef NO_MULTIPLE_DISPLAY_REGIONS
 ////////////////////////////////////////////////////////////////////
 //     Function: set_clipper
 //       Access:
@@ -761,20 +824,30 @@ render_frame() {
 
     if (_clear_buffer_type != 0) {
       // First, clear the entire window.
-      PT(DisplayRegion) win_dr =
-        _win->make_scratch_display_region(_win->get_width(), _win->get_height());
-      clear(get_render_buffer(_clear_buffer_type), win_dr);
+      #ifndef NO_MULTIPLE_DISPLAY_REGIONS
+        PT(DisplayRegion) win_dr = _win->make_scratch_display_region(_win->get_width(), _win->get_height());
+        clear(get_render_buffer(_clear_buffer_type), win_dr);
+      #else
+        clear(get_render_buffer(_clear_buffer_type));     
+      #endif
     }
 
-    // Now render each of our layers in order.
+#if 0
     int max_channel_index = _win->get_max_channel_index();
     for (int c = 0; c < max_channel_index; c++) {
         if (_win->is_channel_defined(c)) {
-            GraphicsChannel *chan = _win->get_channel(c);
-            if (chan->is_active()) {
-                int num_layers = chan->get_num_layers();
+#endif
+
+    // only 1 channel on dx currently
+    assert(_win->get_max_channel_index()==1);
+    assert(_win->is_channel_defined(0));
+
+            if(_panda_gfx_channel->is_active()) {
+                // Now render each of our layers in order.
+
+                int num_layers = _panda_gfx_channel->get_num_layers();
                 for (int l = 0; l < num_layers; l++) {
-                    GraphicsLayer *layer = chan->get_layer(l);
+                    GraphicsLayer *layer = _panda_gfx_channel->get_layer(l);
                     if (layer->is_active()) {
                         int num_drs = layer->get_num_drs();
                         for (int d = 0; d < num_drs; d++) {
@@ -793,8 +866,10 @@ render_frame() {
                     }       //      if (layer->is_active())
                 }
             }       //      if (chan->is_active())
+#if 0
         }
     }   //  for (int c = 0; c < max_channel_index; c++)
+#endif
 
     // Now we're done with the frame processing.  Clean up.
 
@@ -1125,10 +1200,11 @@ render_subgraph(RenderTraverser *traverser,
     }
 #endif
 
+    HRESULT hr;
+
     // We load the projection matrix directly.
-    HRESULT res =
-    _d3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,
-                             (LPD3DMATRIX) _current_projection_mat.get_data());
+    hr = _d3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,
+                                 (LPD3DMATRIX) _current_projection_mat.get_data());
 
     // We infer the modelview matrix by doing a wrt on the projection
     // node.
@@ -1159,9 +1235,8 @@ render_subgraph(RenderTraverser *traverser,
     // We must now restore the projection matrix from before.  We could
     // do a push/pop matrix if we were using D3DX
     if (_projection_mat_stack_count > 0)
-        _d3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,
-                                 (LPD3DMATRIX) _current_projection_mat.get_data());
-
+        hr =_d3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,
+                                    (LPD3DMATRIX) _current_projection_mat.get_data());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1355,46 +1430,34 @@ wants_colors() const {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
 draw_prim_inner_loop(int nVerts, const Geom *geom, DWORD perFlags) {
+    perFlags &= ~PER_COORD;  // should always be set anyway
 
     for(;nVerts > 0;nVerts--) {
 
         GET_NEXT_VERTEX();   // coord info will always be perVertex
 
-        switch (perFlags) {
-            case 0x3:
-                GET_NEXT_NORMAL();
-            case 0x1:
-                break;
-            case 0x5:
-            case 0x4:
-                GET_NEXT_COLOR();
-                break;
-            case 0x7:
-            case 0x6:
-                GET_NEXT_COLOR();
-            case 0x2:
-                GET_NEXT_NORMAL();
-                break;
-            case 0x9:
-            case 0x8:
-                GET_NEXT_TEXCOORD();
-                break;
-            case 0xB:
-            case 0xA:
-                GET_NEXT_NORMAL();
-                GET_NEXT_TEXCOORD();
-                break;
-            case 0xD:
-            case 0xC:
-                GET_NEXT_COLOR();
-                GET_NEXT_TEXCOORD();
-                break;
-            case 0xF:
-            case 0xE:
-                GET_NEXT_NORMAL();
-                GET_NEXT_COLOR();
-                GET_NEXT_TEXCOORD();
-                break;
+        if(perFlags==0xC) {
+            // break out the common case first
+            GET_NEXT_TEXCOORD();
+            GET_NEXT_COLOR();
+        } else {
+            switch (perFlags) {
+                case 0x4:
+                    GET_NEXT_COLOR();
+                    break;
+                case 0x6:
+                    GET_NEXT_COLOR();
+                case 0x2:
+                    GET_NEXT_NORMAL();
+                    break;
+                case 0xE:
+                    GET_NEXT_COLOR();
+                case 0xA:
+                    GET_NEXT_NORMAL();
+                case 0x8:
+                    GET_NEXT_TEXCOORD();
+                    break;
+            }
         }
 
         add_to_FVFBuf((void *)&p_vertex, sizeof(D3DVECTOR));
@@ -1570,13 +1633,14 @@ draw_line(GeomLine* geom, GeomContext *gc) {
 #ifdef _DEBUG
     static BOOL bPrintedMsg=FALSE;
 
+    // note: need to implement approximation of non-1.0 width lines with quads
+
     if (!bPrintedMsg && (geom->get_width()!=1.0f)) {
         bPrintedMsg=TRUE;
         dxgsg_cat.warning() << "DX does not support drawing lines with a non-1.0f pixel width, setting width to 1.0f!\n";
     }
 #endif
 
-
     int nPrims = geom->get_num_prims();
 
     if (nPrims==0) {
@@ -2628,31 +2692,31 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
 #endif
             _pCurFvfBufPtr = _pFvfBufBasePtr;            // _pCurFvfBufPtr changes,  _pFvfBufBasePtr doesn't
 
-                        if(perComp==0x0) {
-                                draw_prim_inner_loop(nVerts, geom, perVertex);
-                        } else {
-                                if(trilisttype==D3DPT_TRIANGLEFAN) {
-                                   // in flat shade mode, D3D fans color using the 2nd vertex. 
-                                   // (note: differs from OGL, which always uses last vtx for strips&fans
-                                   // perComp attribs should not be fetched for first & last verts, they will
-                                   // be associated with middle n-2 verts
-        
-                                        draw_prim_inner_loop(1, geom, perVertex);
-        
-                                        draw_prim_inner_loop(nVerts-2, geom, perVertex | perComp);
-        
-                                        draw_prim_inner_loop(1, geom, perVertex);
-                                } else {
-                                   // in flat shade mode, D3D strips color using the 1st vertex. 
-                                   // (note: differs from OGL, which always uses last vtx for strips&fans
-        
-                                        // Store all but last 2 verts
-                                        draw_prim_inner_loop(nVerts-2, geom, perVertex | perComp);
-        
-                                        // perComp attribs should not be fetched for last 2 verts
-                                        draw_prim_inner_loop(2, geom, perVertex);
-                                }
-                        }
+            if(perComp==0x0) {
+                    draw_prim_inner_loop(nVerts, geom, perVertex);
+            } else {
+                    if(trilisttype==D3DPT_TRIANGLESTRIP) {
+                       // in flat shade mode, D3D strips color using the 1st vertex. 
+                       // (note: differs from OGL, which always uses last vtx for strips&fans
+
+                            // Store all but last 2 verts
+                            draw_prim_inner_loop(nVerts-2, geom, perVertex | perComp);
+
+                            // perComp attribs should not be fetched for last 2 verts
+                            draw_prim_inner_loop(2, geom, perVertex);
+                    } else {
+                       // in flat shade mode, D3D fans color using the 2nd vertex. 
+                       // (note: differs from OGL, which always uses last vtx for strips&fans
+                       // perComp attribs should not be fetched for first & last verts, they will
+                       // be associated with middle n-2 verts
+
+                            draw_prim_inner_loop(1, geom, perVertex);
+
+                            draw_prim_inner_loop(nVerts-2, geom, perVertex | perComp);
+
+                            draw_prim_inner_loop(1, geom, perVertex);
+                    }
+            }
 
             HRESULT hr = _d3dDevice->DrawPrimitive(trilisttype,  p_flags, _pFvfBufBasePtr, nVerts, NULL);
             TestDrawPrimFailure(DrawPrim,hr,_pDD,nVerts,nVerts-2);
@@ -6027,9 +6091,8 @@ HRESULT SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, D3DVECTOR& vAt,
 GeomNodeContext *DXGraphicsStateGuardian::
 prepare_geom_node(GeomNode *node) {
 
-  if(!link_tristrips)
-    return NULL;
-    
+
+ if(link_tristrips) {
   for(int iGeom=0;iGeom<node->get_num_geoms();iGeom++) {
     dDrawable *drawable1 = node->get_geom(iGeom);
     
@@ -6272,105 +6335,188 @@ prepare_geom_node(GeomNode *node) {
            me->set_##ATTRNAME##s(old_##ATTRNAME##s, ATTRNAME##binding, new_##ATTRNAME##_indices);     \
         }                                                                                             \
     }
-/*    
-int ii;
-for( ii=0;ii<old_coords.size();ii++) 
-    dxgsg_cat.debug() << "old coord[" << ii <<"] " << old_coords[ii] << endl;
-dxgsg_cat.debug() << "=================\n";
-for(ii=0;ii<new_coords.size();ii++) 
-    dxgsg_cat.debug() << "new coord[" << ii <<"] " << new_coords[ii] << endl;
-dxgsg_cat.debug() << "=================\n";
-
-for( ii=0;ii<old_normals.size();ii++) 
-    dxgsg_cat.debug() << "old norm[" << ii <<"] " << old_normals[ii] << endl;
-dxgsg_cat.debug() << "=================\n";
-for(ii=0;ii<new_normals.size();ii++) 
-    dxgsg_cat.debug() << "new norm[" << ii <<"] " << new_normals[ii] << endl;
-
-if(old_color_indices!=NULL) {
-
-for( ii=0;ii<old_color_indices.size();ii++) 
-    dxgsg_cat.debug() << "old colorindex[" << ii <<"] " << old_color_indices[ii] << endl;
-dxgsg_cat.debug() << "=================\n";
-for( ii=0;ii<new_color_indices.size();ii++) 
-    dxgsg_cat.debug() << "new colorindex[" << ii <<"] " << new_color_indices[ii] << endl;
-}
-*/
-
-  SET_NEW_ATTRIBS(color);
-  SET_NEW_ATTRIBS(normal);
-  SET_NEW_ATTRIBS(texcoord);
+    /*    
+    int ii;
+    for( ii=0;ii<old_coords.size();ii++) 
+        dxgsg_cat.debug() << "old coord[" << ii <<"] " << old_coords[ii] << endl;
+    dxgsg_cat.debug() << "=================\n";
+    for(ii=0;ii<new_coords.size();ii++) 
+        dxgsg_cat.debug() << "new coord[" << ii <<"] " << new_coords[ii] << endl;
+    dxgsg_cat.debug() << "=================\n";
+    
+    for( ii=0;ii<old_normals.size();ii++) 
+        dxgsg_cat.debug() << "old norm[" << ii <<"] " << old_normals[ii] << endl;
+    dxgsg_cat.debug() << "=================\n";
+    for(ii=0;ii<new_normals.size();ii++) 
+        dxgsg_cat.debug() << "new norm[" << ii <<"] " << new_normals[ii] << endl;
+    
+    if(old_color_indices!=NULL) {
+    
+    for( ii=0;ii<old_color_indices.size();ii++) 
+        dxgsg_cat.debug() << "old colorindex[" << ii <<"] " << old_color_indices[ii] << endl;
+    dxgsg_cat.debug() << "=================\n";
+    for( ii=0;ii<new_color_indices.size();ii++) 
+        dxgsg_cat.debug() << "new colorindex[" << ii <<"] " << new_color_indices[ii] << endl;
+    }
+    */
 
-  me->make_dirty();
- }
+    SET_NEW_ATTRIBS(color);
+    SET_NEW_ATTRIBS(normal);
+    SET_NEW_ATTRIBS(texcoord);
 
- return NULL;
+    me->make_dirty();
+  }
+ } // if(link_tristrips)
 
-#if 0
+  // for now, only using vertexbufs for static Geom, so
   // Make sure we have at least some static Geoms in the GeomNode;
-  // otherwise there's no point in building a display list.
-  int num_geoms = node->get_num_geoms();
-  bool all_dynamic = true;
-  int i;
+  int cNumVerts=0,i,num_geoms = node->get_num_geoms();
+
+  // need to always put in space for color because we might have some scene-graph color we need to add?
+  // will that even work?  I think we'd have to overwrite all the VB colors dynamically, and then restore
+  // them from somewhere if the global color goes away
+
+  DWORD fvfFlags=D3DFVF_XYZ;// | D3DFVF_DIFFUSE;
 
-  for (i = 0; (i < num_geoms) && all_dynamic; i++) {
-    dDrawable *geom = node->get_geom(i);
-    all_dynamic = geom->is_dynamic();
+  for (i = 0; (i < num_geoms); i++) {
+    dDrawable *drawable1 = node->get_geom(i);
+    if(!drawable1->is_of_type(Geom::get_class_type()))
+      continue;
+    
+    Geom *geom=DCAST(Geom, drawable1);
+    assert(geom!=NULL);
+
+    if(!geom->is_dynamic()) {
+        cNumVerts+=geom->get_num_vertices();
+        if(geom->get_binding(G_COLOR) != G_OFF)
+            fvfFlags |= D3DFVF_DIFFUSE;
+        if(geom->get_binding(G_NORMAL) != G_OFF)
+            fvfFlags |= D3DFVF_NORMAL;
+        if(geom->get_binding(G_TEXCOORD) != G_OFF) 
+            fvfFlags |= (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
+    }
   }
-  if (all_dynamic) {
+
+  if(cNumVerts==0) {
     // Never mind.
     return (GeomNodeContext *)NULL;
   }
 
   // Ok, we've got something; use it.
-  DXGeomNodeContext *ggnc = new DXGeomNodeContext(node);
+  DXGeomNodeContext *dx_gnc = new DXGeomNodeContext(node);
 
-#if 0
-  ggnc->_index = DXGenLists(1);
-  if (ggnc->_index == 0) {
-    DXgsg_cat.error() << "Ran out of display list indices.\n";
-    delete ggnc;
-    return (GeomNodeContext *)NULL;
+  assert(dx_gnc!=NULL);
+
+  // right now there is a 1-1 correspondence b/w vertbufs and geomnodecontexts.
+  // later multiple geomnodecontexts will use the same vertbuf
+
+  HRESULT hr;
+  LPDIRECT3D7 pD3D;
+
+  assert(_d3dDevice!=NULL);
+  hr=_d3dDevice->GetDirect3D(&pD3D);
+  assert(!FAILED(hr));
+  LPDIRECT3DVERTEXBUFFER7 pD3DVertexBuffer;
+  DX_DECLARE_CLEAN(D3DVERTEXBUFFERDESC, VBdesc);
+
+  VBdesc.dwCaps = D3DVBCAPS_WRITEONLY;
+  VBdesc.dwCaps |= _bIsTNLDevice ? 0x0 : D3DVBCAPS_SYSTEMMEMORY;
+  VBdesc.dwFVF=fvfFlags;
+  VBdesc.dwNumVertices=cNumVerts;
+
+  hr=pD3D->CreateVertexBuffer(&VBdesc,&pD3DVertexBuffer,0x0);
+  if(FAILED(hr)) {
+    dxgsg_cat.error() << "error creating vertex buffer: " << ConvD3DErrorToString(hr) << endl;
+    delete dx_gnc;
+    exit(1);
   }
-#endif
 
-  // We need to temporarily force normals and UV's on, so the display
-  // list will have them built in.
-  bool old_normals_enabled = _normals_enabled;
-  bool old_texturing_enabled = _texturing_enabled;
-  bool old_vertex_colors_enabled = _vertex_colors_enabled;
-  _normals_enabled = true;
-  _texturing_enabled = true;
-  _vertex_colors_enabled = true;
+  dx_gnc->_pVB = pD3DVertexBuffer;
 
-#ifdef DO_PSTATS
-  // Count up the number of vertices we're about to render, by
-  // checking the PStats vertex counters now, and at the end.  This is
-  // kind of hacky, but this is debug code.
-  float num_verts_before = 
-    _vertices_tristrip_pcollector.get_level() +
-    _vertices_trifan_pcollector.get_level() +
-    _vertices_tri_pcollector.get_level() +
-    _vertices_other_pcollector.get_level();
-#endif
+  if(!_bIsTNLDevice) {
+      // create VB for ProcessVerts to xform to
 
-  // Now define the display list.
-  DXNewList(ggnc->_index, DX_COMPILE);
-  for (i = 0; i < num_geoms; i++) {
-    dDrawable *geom = node->get_geom(i);
-    if (geom->is_dynamic()) {
-      // Wait, this is a dynamic Geom.  We can't safely put it in the
-      // display list, because it may change from one frame to the
-      // next; instead, we'll keep it out.
-      ggnc->_dynamic_geoms.push_back(geom);
+      fvfFlags&=~D3DFVF_XYZ;    // switch to xformed vert type
+      fvfFlags&=~D3DFVF_NORMAL; // xformed verts are also lighted, so no normals allowed
+      fvfFlags|=D3DFVF_XYZRHW; 
+      VBdesc.dwFVF=fvfFlags;
+
+      hr=pD3D->CreateVertexBuffer(&VBdesc,&pD3DVertexBuffer,0x0);
+      if(FAILED(hr)) {
+          dxgsg_cat.error() << "error creating xformed vertex buffer: " << ConvD3DErrorToString(hr) << endl;
+          delete dx_gnc;
+          exit(1);
+      }
+
+      dx_gnc->_pXformed_VB = pD3DVertexBuffer;
+  }
+
+  pD3D->Release();
+
+  dx_gnc->_num_verts=cNumVerts;
+  dx_gnc->_start_index=0;   
+
+  DWORD *pVertData=NULL;
+  DWORD dwVBFlags = DDLOCK_NOOVERWRITE | DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR |
+                    DDLOCK_WAIT | DDLOCK_DISCARDCONTENTS;
+
+  hr=dx_gnc->_pVB->Lock(dwVBFlags,(LPVOID*)&pVertData,NULL);
+  if(FAILED(hr)) {
+        dxgsg_cat.error() << "error locking vertex buffer: " << ConvD3DErrorToString(hr) << endl;
+        delete dx_gnc;
+        exit(1);
+  }
+
+  assert(pVertData!=NULL);
+
+  for (i = 0; (i < num_geoms); i++) {
+    dDrawable *drawable1 = node->get_geom(i);
+    if(!drawable1->is_of_type(Geom::get_class_type()))
+      continue;
+    
+    Geom *geom=DCAST(Geom, drawable1);
+    assert(geom!=NULL);
+
+    if(geom->is_dynamic()) {
+      dx_gnc->_other_geoms.push_back(geom);
     } else {
-      // A static Geom becomes part of the display list.
-      geom->draw(this);
+#if 0
+        PTA_Vertexf coords;
+        PTA_Normalf norms;
+        PTA_Colorf colors;
+        PTA_TexCoordf texcoords;
+        GeomBindType TexCoordBinding,ColorBinding,NormalBinding,CoordBinding;
+        PTA_ushort vindexes,nindexes,tindexes,cindexes;
+
+        geom->get_coords(coords,CoordBinding,vindexes);
+        geom->get_normals(norms,NormalBinding,nindexes);
+        geom->get_colors(colors,ColorBinding,cindexes);
+        geom->get_texcoords(texcoords,TexCoordBinding,tindexes);
+
+        //// copy geometry into pVertData
+       just use lengths array and copy it straight in, we dont need to know type, right
+       no that wont work because of per-prim and per-component info
+           need to call draw fns with special flag to not call drawp
+#endif
+
     }
   }
-  DXEndList();
 
-#ifdef DO_PSTATS
+  hr=dx_gnc->_pVB->Unlock();
+  if(FAILED(hr)) {
+      dxgsg_cat.error() << "error unlocking vertex buffer: " << ConvD3DErrorToString(hr) << endl;
+      delete dx_gnc;
+      exit(1);
+  }
+
+  hr=dx_gnc->_pVB->Optimize(_d3dDevice,0x0);
+  if(FAILED(hr)) {
+      dxgsg_cat.error() << "error optimizing vertex buffer: " << ConvD3DErrorToString(hr) << endl;
+      delete dx_gnc;
+      exit(1);
+  }
+
+#if 0  //DO_PSTATS
   float num_verts_after = 
     _vertices_tristrip_pcollector.get_level() +
     _vertices_trifan_pcollector.get_level() +
@@ -6380,19 +6526,14 @@ for( ii=0;ii<new_color_indices.size();ii++)
   ggnc->_num_verts = (int)(num_verts + 0.5);
 #endif
 
-  _normals_enabled = old_normals_enabled;
-  _texturing_enabled = old_texturing_enabled;
-  _vertex_colors_enabled = old_vertex_colors_enabled;
-
-  bool inserted = mark_prepared_geom_node(ggnc);
+  bool inserted = mark_prepared_geom_node(dx_gnc);
 
   // If this assertion fails, the same GeomNode was prepared twice,
   // which shouldn't be possible, since the GeomNode itself should
   // detect this.
   nassertr(inserted, NULL);
 
-  return ggnc;
-#endif
+  return dx_gnc;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -6403,33 +6544,69 @@ for( ii=0;ii<new_color_indices.size();ii++)
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
 draw_geom_node(GeomNode *node, GeomNodeContext *gnc) {
-#if 0
+
+  int i,num_geoms = node->get_num_geoms();
+
   if (gnc == (GeomNodeContext *)NULL) {
+
     // We don't have a saved context; just draw the GeomNode in
     // immediate mode.
-    int num_geoms = node->get_num_geoms();
-    for (int i = 0; i < num_geoms; i++) {
+    for (i = 0; i < num_geoms; i++) {
       node->get_geom(i)->draw(this);
     }
+    return;
+  }
 
-  } else {
-    // We do have a saved context; use it.
-    add_to_geom_node_record(gnc);
-    DXGeomNodeContext *ggnc = DCAST(DXGeomNodeContext, gnc);
-    DXCallList(ggnc->_index);
+  // We do have a saved context; use it.
+  add_to_geom_node_record(gnc);
+  DXGeomNodeContext *dx_gnc = DCAST(DXGeomNodeContext, gnc);
 
-#ifdef DO_PSTATS
+  #ifdef _DEBUG
+     assert(dx_gnc->_pVB!=NULL);
+     if(_bIsTNLDevice) 
+        assert(dx_gnc->_pXformed_VB!=NULL);
+  #endif
+  
+  if(!_bIsTNLDevice) {
+      HRESULT hr;
+    
+      DWORD PVOp=D3DVOP_CLIP | D3DVOP_TRANSFORM | D3DVOP_EXTENTS;
+    
+      D3DVERTEXBUFFERDESC VBdesc;
+      VBdesc.dwSize=sizeof(VBdesc);
+      hr=dx_gnc->_pVB->GetVertexBufferDesc(&VBdesc);   // would be useful to keep fvf in vertbuf struct to avoid having to do this
+      if(FAILED(hr)) {
+        dxgsg_cat.error() << "error in getvbdesc: " << ConvD3DErrorToString(hr) << endl;
+        exit(1);
+      }
+    
+      if(VBdesc.dwFVF & D3DFVF_NORMAL) {
+          PVOp|=D3DVOP_LIGHT;
+      }
+    
+      hr=dx_gnc->_pXformed_VB->ProcessVertices(PVOp,0,dx_gnc->_num_verts,dx_gnc->_pVB,0,_d3dDevice,0x0);
+      if(FAILED(hr)) {
+        dxgsg_cat.error() << "error in ProcessVertices: " << ConvD3DErrorToString(hr) << endl;
+        exit(1);
+      }
+  }
+
+
+  for (i = 0; i < num_geoms; i++) {
+      node->get_geom(i)->draw(this);
+  }
+
+#if 0 //def DO_PSTATS
     DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector));
-    _vertices_display_list_pcollector.add_level(ggnc->_num_verts);
+    _vertices_display_list_pcollector.add_level(dx_gnc->_num_verts);
 #endif
 
-    // Also draw all the dynamic Geoms.
-    int num_geoms = ggnc->_dynamic_geoms.size();
-    for (int i = 0; i < num_geoms; i++) {
-      ggnc->_dynamic_geoms[i]->draw(this);
-    }
+
+  // Also draw all the dynamic Geoms.
+  for (i = 0; i < num_geoms; i++) {
+      dx_gnc->_other_geoms[i]->draw(this);
   }
-#endif
+
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -6441,19 +6618,16 @@ draw_geom_node(GeomNode *node, GeomNodeContext *gnc) {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
 release_geom_node(GeomNodeContext *gnc) {
-#if 0
   if (gnc != (GeomNodeContext *)NULL) {
-    DXGeomNodeContext *ggnc = DCAST(DXGeomNodeContext, gnc);
-    DXDeleteLists(ggnc->_index, 1);
+    DXGeomNodeContext *dx_gnc = DCAST(DXGeomNodeContext, gnc);
 
-    bool erased = unmark_prepared_geom_node(ggnc);
+    bool erased = unmark_prepared_geom_node(dx_gnc);
 
     // If this assertion fails, a GeomNode was released that hadn't
     // been prepared (or a GeomNode was released twice).
     nassertv(erased);
     
-    ggnc->_node->clear_gsg(this);
-    delete ggnc;
+    dx_gnc->_node->clear_gsg(this);
+    delete dx_gnc;  // should release vertex buffer
   }
-#endif
 }

+ 2 - 0
panda/src/dxgsg/dxGraphicsStateGuardian.h

@@ -355,6 +355,8 @@ protected:
   bool _alpha_test_enabled;
   int _decal_level;
 
+  GraphicsChannel *_panda_gfx_channel;  // cache the 1 channel dx supports
+
   // Cur Texture State
   TextureApplyProperty::Mode _CurTexBlendMode;
   Texture::FilterType _CurTexMagFilter,_CurTexMinFilter;