Răsfoiți Sursa

fix box.egg bug, minor reordering opts

cxgeorge 24 ani în urmă
părinte
comite
c21451e861

+ 222 - 129
panda/src/dxgsg/dxGraphicsStateGuardian.cxx

@@ -361,7 +361,7 @@ DXGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
     ZeroMemory(&scrn,sizeof(DXScreenData));
     _bShowFPSMeter = false;
     _pCurFvfBufPtr = NULL;
-    _pFvfBufBasePtr = new char[VERT_BUFFER_SIZE];  // allocate storage for vertex info.
+    _pFvfBufBasePtr = new BYTE[VERT_BUFFER_SIZE];  // allocate storage for vertex info.
     _index_buf = new WORD[D3DMAXNUMVERTICES];  // allocate storage for vertex index info.
     _fpsmeter_verts=NULL;
     _fpsmeter_font_surf=NULL;
@@ -1949,6 +1949,8 @@ draw_prim_setup(const Geom *geom) {
    PTA_ushort tindexes;
    geom->get_texcoords(texcoords,TexCoordBinding,tindexes);
    if (TexCoordBinding != G_OFF) {
+       assert(TexCoordBinding == G_PER_VERTEX);
+
        // used by faster path
        if(tindexes!=NULL) {
           _pCurTexCoordIndex = _texcoordindex_array = &tindexes[0];
@@ -2039,46 +2041,56 @@ draw_prim_inner_loop(int nVerts, const Geom *geom, ushort perFlags) {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
 draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom) {
-    // assumes coord and texcoord data is per-vertex, color is not per-vert, and no normal data
-    // this should be common situation for animated character data
+    // assumes coord and texcoord data is per-vertex, 
+    // color is not per-vert/component (which would require fetching new vals in the vertex loop),
+    // and no normal data. this should be common situation for animated character data
     // inc'ing local ptrs instead of member ones, seems to optimize better
     // bypass all the slow vertex iterator stuff
 
+    #ifdef _DEBUG
+     {
+      assert(geom->get_binding(G_NORMAL) == G_OFF);
+      GeomBindType ColorBinding = geom->get_binding(G_COLOR);
+      assert((ColorBinding != G_PER_VERTEX) || (ColorBinding != G_PER_COMPONENT));
+      assert(geom->get_binding(G_TEXCOORD) == G_PER_VERTEX);
+     }
+    #endif
+
     Vertexf *pCurCoord = _pCurCoord;
     ushort *pCurCoordIndex = _pCurCoordIndex;
     TexCoordf *pCurTexCoord = _pCurTexCoord;
     ushort *pCurTexCoordIndex = _pCurTexCoordIndex;
 
-    char *LocalFvfBufPtr = _pCurFvfBufPtr;
+    BYTE *pLocalFvfBufPtr = _pCurFvfBufPtr;
     DWORD cur_color = _curD3Dcolor;
     bool bDoIndexedTexCoords = (_texcoordindex_array != NULL);
     bool bDoIndexedCoords = (_coordindex_array != NULL);
 
     for(;nVerts>0;nVerts--) {
         if(bDoIndexedCoords) {
-           memcpy(LocalFvfBufPtr,(void*)&_coord_array[*pCurCoordIndex],sizeof(D3DVECTOR));
+           memcpy(pLocalFvfBufPtr,(void*)&_coord_array[*pCurCoordIndex],sizeof(D3DVECTOR));
            pCurCoordIndex++;           
         } else {
-           memcpy(LocalFvfBufPtr,(void*)pCurCoord,sizeof(D3DVECTOR));
+           memcpy(pLocalFvfBufPtr,(void*)pCurCoord,sizeof(D3DVECTOR));
            pCurCoord++;
         }
 
-        LocalFvfBufPtr+=sizeof(D3DVECTOR);
+        pLocalFvfBufPtr+=sizeof(D3DVECTOR);
 
-        *((DWORD *)LocalFvfBufPtr) = cur_color;
-        LocalFvfBufPtr += sizeof(DWORD);
+        *((DWORD *)pLocalFvfBufPtr) = cur_color;
+        pLocalFvfBufPtr += sizeof(DWORD);
 
         if(bDoIndexedTexCoords) {
-           memcpy(LocalFvfBufPtr,(void*)&_texcoord_array[*pCurTexCoordIndex],sizeof(TexCoordf));
+           memcpy(pLocalFvfBufPtr,(void*)&_texcoord_array[*pCurTexCoordIndex],sizeof(TexCoordf));
            pCurTexCoordIndex++;
         } else {
-           memcpy(LocalFvfBufPtr,(void*)pCurTexCoord,sizeof(TexCoordf));
+           memcpy(pLocalFvfBufPtr,(void*)pCurTexCoord,sizeof(TexCoordf));
            pCurTexCoord++;
         }
-        LocalFvfBufPtr+=sizeof(TexCoordf);
+        pLocalFvfBufPtr+=sizeof(TexCoordf);
     }
 
-    _pCurFvfBufPtr=LocalFvfBufPtr;
+    _pCurFvfBufPtr=pLocalFvfBufPtr;
     _pCurCoord = pCurCoord;
     _pCurCoordIndex = pCurCoordIndex;
     _pCurTexCoord = pCurTexCoord;
@@ -2153,11 +2165,12 @@ draw_point(GeomPoint *geom, GeomContext *gc) {
     // need to add code to handle fully indexed mode (and handle cases with index arrays of different lengths,
     // values (may only be possible to handle certain cases without reverting to old pipeline)
     if (GeomVrtFmt!=FlatVerts) {
-
         _perVertex = 0x0; 
-        _perPrim = 0;
-        if (geom->get_binding(G_NORMAL) == G_PER_VERTEX) _perVertex |= PER_NORMAL;
-        if (geom->get_binding(G_COLOR) == G_PER_VERTEX) _perVertex |= PER_COLOR;
+        _perPrim = 0x0;
+        if (geom->get_binding(G_NORMAL) == G_PER_VERTEX) 
+            _perVertex |= PER_NORMAL;
+        if (geom->get_binding(G_COLOR) == G_PER_VERTEX) 
+            _perVertex |= PER_COLOR;
 
         size_t vertex_size = draw_prim_setup(geom);
 
@@ -2168,6 +2181,8 @@ draw_point(GeomPoint *geom, GeomContext *gc) {
         // iterate through the point
         draw_prim_inner_loop(nPrims, geom, _perVertex | _perPrim);
 
+        nassertv((nPrims*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
+
         if(!_bDrawPrimDoSetupVertexBuffer) {
            HRESULT hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_POINTLIST, _curFVFflags, _pFvfBufBasePtr, nPrims, NULL);   
            TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nPrims,0);
@@ -2248,20 +2263,22 @@ draw_line(GeomLine* geom, GeomContext *gc) {
 
     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";
+        if(dxgsg_cat.is_debug())
+            dxgsg_cat.debug() << "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) {
-        dxgsg_cat.warning() << "draw_line() called with ZERO vertices!!" << endl;
+        if(dxgsg_cat.is_debug())
+           dxgsg_cat.debug() << "draw_line() called with ZERO vertices!!" << endl;
         return;
     }
 
-    assert(geom->get_binding(G_COORD) == G_PER_VERTEX);
     _perVertex = 0x0;
-    _perPrim = _perComp = 0x0;
+    _perPrim = 0x0;
+    _perComp = 0x0;
 
     switch(geom->get_binding(G_NORMAL)) {
         case G_PER_VERTEX:
@@ -2287,13 +2304,13 @@ draw_line(GeomLine* geom, GeomContext *gc) {
 
     size_t vertex_size = draw_prim_setup(geom);
 
-    char *_tmp_fvf = NULL;
+    BYTE *_tmp_fvfOverrunBuf = NULL;
     nassertv(_pCurFvfBufPtr == NULL);    // make sure the storage pointer is clean.
 //  nassertv(nPrims * 2 * vertex_size < VERT_BUFFER_SIZE);
 
     if (nPrims * 2 * vertex_size > VERT_BUFFER_SIZE) {
         // bugbug: need cleaner way to handle tmp buffer size overruns (malloc/realloc?)
-        _pCurFvfBufPtr = _tmp_fvf = new char[nPrims * 2 * vertex_size];
+        _pCurFvfBufPtr = _tmp_fvfOverrunBuf = new BYTE[nPrims * 2 * vertex_size];
     } else  _pCurFvfBufPtr = _pFvfBufBasePtr;            // _pCurFvfBufPtr changes,  _pFvfBufBasePtr doesn't
 
     for (int i = 0; i < nPrims; i++) {
@@ -2307,18 +2324,20 @@ draw_line(GeomLine* geom, GeomContext *gc) {
 
     HRESULT hr;
 
-    DWORD vertCount = nPrims<<1;
+    DWORD nVerts = nPrims<<1;
 
     if(!_bDrawPrimDoSetupVertexBuffer) {
-        if (_tmp_fvf == NULL)
-            hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _pFvfBufBasePtr, vertCount, NULL);
-        else {
-            hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _tmp_fvf, vertCount, NULL);
-            delete [] _tmp_fvf;
+        if (_tmp_fvfOverrunBuf == NULL) {
+            nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
+            hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL);
+        } else {
+            nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_tmp_fvfOverrunBuf));
+            hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _tmp_fvfOverrunBuf, nVerts, NULL);
+            delete [] _tmp_fvfOverrunBuf;
         }
-        TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,vertCount,0);
+        TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,0);
     } else {
-        COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINELIST,vertCount);
+        COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINELIST,nVerts);
     }
 
     _pCurFvfBufPtr = NULL;
@@ -2332,7 +2351,8 @@ draw_linestrip(GeomLinestrip* geom, GeomContext *gc) {
 
     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";
+        if(dxgsg_cat.is_debug())
+            dxgsg_cat.debug() << "DX does not support drawing lines with a non-1.0f pixel width, setting width to 1.0f!\n";
     }
 #endif
 
@@ -2346,6 +2366,7 @@ draw_linestrip(GeomLinestrip* geom, GeomContext *gc) {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
 draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) {
+// Note draw_linestrip_base() may be called from non-line draw_fns to support wireframe mode
 
 #ifdef GSG_VERBOSE
     dxgsg_cat.debug() << "draw_linestrip()" << endl;
@@ -2355,17 +2376,18 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) {
     DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices()));
 
     int nPrims = geom->get_num_prims();
-    const int *plen = geom->get_lengths();
+    const int *pLengthArr = geom->get_lengths();
 
-    if (nPrims==0) {
-        dxgsg_cat.warning() << "draw_linestrip() called with ZERO vertices!!" << endl;
+    if(nPrims==0) {
+        if(dxgsg_cat.is_debug())
+            dxgsg_cat.debug() << "draw_linestrip() called with ZERO vertices!!" << endl;
         return;
     }
 
-    assert(geom->get_binding(G_COORD) == G_PER_VERTEX);
     _perVertex = 0x0;
+    _perPrim = 0x0;
+    _perComp = 0x0;
 
-    _perPrim = _perComp = 0;
     switch(geom->get_binding(G_NORMAL)) {
         case G_PER_VERTEX:
             _perVertex |=  PER_NORMAL;
@@ -2391,18 +2413,26 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) {
     size_t vertex_size = draw_prim_setup(geom);
     ushort perFlags = _perVertex | _perComp;
 
+    bool bPerPrimColor = ((_perPrim & PER_COLOR)!=0);
+    bool bPerPrimNormal = ((_perPrim & PER_NORMAL)!=0);
+
+    DWORD nVerts;
+
+    if(pLengthArr==NULL) // we've been called by draw_quad, which has no lengths array
+      nVerts=4;
+
     for (int i = 0; i < nPrims; i++) {
-        if (_perPrim & PER_COLOR) {
+        if (bPerPrimColor) {
             GET_NEXT_COLOR();
         }
 
-        int nVerts;
+        if (bPerPrimNormal) {
+            p_normal = geom->get_next_normal(ni);   // set primitive normal if there is one.
+        }
 
-        if(plen!=NULL) {
-            nVerts= *(plen++);
+        if(pLengthArr!=NULL) {
+            nVerts= *(pLengthArr++);
             nassertv(nVerts >= 2);
-        } else {
-            nVerts=4;  // we've been called by draw_quad, which has no lengths array
         }
 
         nassertv(_pCurFvfBufPtr == NULL);   // make sure the storage pointer is clean.
@@ -2418,6 +2448,8 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) {
              nVerts++;
         }
 
+        nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
+
         if(!_bDrawPrimDoSetupVertexBuffer) {
             HRESULT hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINESTRIP, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL);
             TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,0);
@@ -2837,6 +2869,8 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) {
         CurVertCount+=4;
     }
 
+    nassertv(((4*nprims)*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
+
     // cant do tristrip/fan since it would require 1 call want to make 1 call for multiple quads which arent connected
     // best we can do is indexed primitive, which sends 2 redundant indices instead of sending 2 redundant full verts
     HRESULT hr = scrn.pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, 4*nprims, _index_buf,QUADVERTLISTLEN*nprims,NULL);
@@ -2869,10 +2903,10 @@ draw_polygon(GeomPolygon *geom, GeomContext *gc) {
    // wireframe polygon will be drawn as linestrip, otherwise draw as multi-tri trifan
    DWORD rstate;
    scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate);
-   if(rstate==D3DFILL_WIREFRAME) {
-       draw_linestrip_base(geom,gc,true);
-   } else {
+   if(rstate!=D3DFILL_WIREFRAME) {
        draw_multitri(geom, D3DPT_TRIANGLEFAN);
+   } else {
+       draw_linestrip_base(geom,gc,true);
    }
 }
 
@@ -2893,10 +2927,10 @@ draw_quad(GeomQuad *geom, GeomContext *gc) {
    // wireframe quad will be drawn as linestrip, otherwise draw as multi-tri trifan
    DWORD rstate;
    scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate);
-   if(rstate==D3DFILL_WIREFRAME) {
-       draw_linestrip_base(geom,gc,true);
-   } else {
+   if(rstate!=D3DFILL_WIREFRAME) {
        draw_multitri(geom, D3DPT_TRIANGLEFAN);
+   } else {
+       draw_linestrip_base(geom,gc,true);
    }
 }
 
@@ -2939,17 +2973,22 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
     geom->get_colors(colors,ColorBinding,cindexes);
     geom->get_texcoords(texcoords,TexCoordBinding,tindexes);
 
+/*
+   for now, always use complex path, since DPstrided path never gave speedup
     GeomVertFormat GeomVrtFmt=FlatVerts;
 
     // first determine if we're indexed or non-indexed
 
+
     if ((vindexes!=NULL)&&(cindexes!=NULL)&&(tindexes!=NULL)&&(nindexes!=NULL)) {
         GeomVrtFmt=IndexedVerts;
         //make sure array sizes are consistent, we can only pass 1 size to DrawIPrm
 //      nassertv(coords.size==norms.size);      nassertv(coords.size==colors.size);     nassertv(coords.size==texcoords.size);  need to assert only if we have this w/same binding
         // indexed mode requires all used norms,colors,texcoords,coords array be the same
         // length, or 0 or 1 (dwStride==0), also requires all elements to use the same index array
-    } else if (!((vindexes==NULL)&&(cindexes==NULL)&&(tindexes==NULL)&&(nindexes==NULL)))
+    }
+     
+    else if (!((vindexes==NULL)&&(cindexes==NULL)&&(tindexes==NULL)&&(nindexes==NULL)))
         GeomVrtFmt=MixedFmtVerts;
 
 #ifdef DONT_USE_DRAWPRIMSTRIDED
@@ -2963,25 +3002,41 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
     // for Indexed Prims and mixed indexed/non-indexed prims, we will use old pipeline for now
     // need to add code to handle fully indexed mode (and handle cases with index arrays of different lengths,
     // values (may only be possible to handle certain cases without reverting to old pipeline)
-    if (GeomVrtFmt!=FlatVerts) {
+    if (GeomVrtFmt!=FlatVerts)
+*/       
+        
+     {
         // this is the old geom setup, it reformats every vtx into an output array passed to d3d
 
         _perVertex = 0x0;
         _perPrim = 0x0;
 
-        if(NormalBinding == G_PER_VERTEX)   
-          _perVertex |= PER_NORMAL;
-         else if(NormalBinding == G_PER_PRIM) 
-                 _perPrim |= PER_NORMAL;
+        bool bUseTexCoordOnlyLoop = ((ColorBinding != G_PER_VERTEX) &&
+                                     (NormalBinding == G_OFF) &&
+                                     (TexCoordBinding != G_OFF));
+
+        bool bPerPrimNormal;
+        bool bPerPrimColor=((_perPrim & PER_COLOR)!=0);
+
+        if(bUseTexCoordOnlyLoop) {
+           _perVertex |= PER_TEXCOORD;  // TexCoords are either G_OFF or G_PER_VERTEX 
+        } else {
+            if(NormalBinding == G_PER_VERTEX)   
+                _perVertex |= PER_NORMAL;
+            else if(NormalBinding == G_PER_PRIM) 
+                    _perPrim |= PER_NORMAL;
+
+            bPerPrimNormal=((_perPrim & PER_NORMAL)!=0);
 
-        if(ColorBinding == G_PER_PRIM)  
+            if(TexCoordBinding == G_PER_VERTEX) 
+               _perVertex |= PER_TEXCOORD;
+        } 
+
+        if(bPerPrimColor)
            _perPrim |= PER_COLOR;
           else if(ColorBinding == G_PER_VERTEX)    
                  _perVertex |= PER_COLOR;
 
-        if (TexCoordBinding == G_PER_VERTEX) 
-           _perVertex |= PER_TEXCOORD;
-
         size_t vertex_size = draw_prim_setup(geom);
 
         nassertv(_pCurFvfBufPtr == NULL);    // make sure the storage pointer is clean.
@@ -2991,21 +3046,24 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
         // iterate through the triangle primitive
 
         for (uint i = 0; i < nPrims; i++) {
-            if (_perPrim & PER_COLOR) {
+            if(bPerPrimColor) {  // remember color might be G_OVERALL too!
                 GET_NEXT_COLOR();
             }
 
-            if (_perPrim & PER_NORMAL)
-                p_normal = geom->get_next_normal(ni);   // set primitive normal if there is one.
-
-
-            if(_perVertex==TexCoordOnly)
+            if(bUseTexCoordOnlyLoop) {
                draw_prim_inner_loop_coordtexonly(3, geom);   
-             else draw_prim_inner_loop(3, geom, _perVertex);
+            } else {
+                if(bPerPrimNormal)
+                    p_normal = geom->get_next_normal(ni);   // set primitive normal if there is one.
+
+                draw_prim_inner_loop(3, geom, _perVertex);
+            }
         }
 
         DWORD nVerts=nPrims*3;
 
+        nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
+
         if(!_bDrawPrimDoSetupVertexBuffer) {
             hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL);
             TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,nPrims);
@@ -3014,7 +3072,10 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
         }
 
         _pCurFvfBufPtr = NULL;
-    } else {
+    } 
+    
+/*  
+    else {
 
         // new geom setup that uses strided DP calls to avoid making an extra pass over the data
 
@@ -3205,8 +3266,10 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
 
         _pCurFvfBufPtr = NULL;
     }
-
+*/
 ///////////////////////////
+
+/*
 #if 0
     // test triangle for me to dbg experiments only
     float vert_buf[15] = {
@@ -3223,6 +3286,7 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
     HRESULT hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,  _curFVFflags, vert_buf, nPrims*3, NULL);
     TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nPrims*3,nPrims);
 #endif
+*/
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3293,7 +3357,7 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
     geom->get_normals(norms,NormalBinding,nindexes);
     geom->get_colors(colors,ColorBinding,cindexes);
     geom->get_texcoords(texcoords,TexCoordBinding,tindexes);
-
+/*
     GeomVertFormat GeomVrtFmt;
 
 #ifdef DONT_USE_DRAWPRIMSTRIDED
@@ -3323,60 +3387,77 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
     // for Indexed Prims and mixed indexed/non-indexed prims, we will use old pipeline
     // cant handle indexed prims because usually have different index arrays for different components,
     // and DrIdxPrmStrd only accepts 1 index array for all components
-    if (GeomVrtFmt!=FlatVerts) {
+    if (GeomVrtFmt!=FlatVerts) 
+*/  
+
+    {
+
+        size_t vertex_size = draw_prim_setup(geom);
 
         // this is the old geom setup, it reformats every vtx into an output array passed to d3d
         _perVertex = 0x0;
-        _perPrim = _perComp = 0;
+        _perPrim = 0x0;
+        _perComp = 0x0;
 
-        switch (NormalBinding) {
-            case G_OFF:
-                break;
-            case G_PER_VERTEX:
-                _perVertex |= PER_NORMAL;
-                break;
-            case G_PER_PRIM:
-                _perPrim |= PER_NORMAL;
-                break;
-            case G_PER_COMPONENT:
-                _perComp |= PER_NORMAL;
-                break;
-        }
+        bool bIsTriList=(trilisttype==D3DPT_TRIANGLESTRIP);
+        bool bPerPrimColor=false;
+        bool bPerPrimNormal;
+        bool bUseTexCoordOnlyLoop = (((ColorBinding == G_OVERALL) || (ColorBinding == G_PER_PRIM)) &&
+                                     (NormalBinding == G_OFF) &&
+                                     (TexCoordBinding != G_OFF));
 
-        switch (ColorBinding) {
-            case G_PER_PRIM:
+        if(bUseTexCoordOnlyLoop) {
+           if(ColorBinding == G_PER_PRIM) {
                 _perPrim |= PER_COLOR;
-                break;
-            case G_PER_COMPONENT:
-                _perComp |= PER_COLOR;
-                break;
-            case G_PER_VERTEX:
-                _perVertex |= PER_COLOR;
-                break;
-        }
+                 bPerPrimColor=true;
+           }
+        } else {
+            switch (NormalBinding) {
+                case G_PER_VERTEX:
+                    _perVertex |= PER_NORMAL;
+                    break;
+                case G_PER_PRIM:
+                    _perPrim |= PER_NORMAL;
+                    break;
+                case G_PER_COMPONENT:
+                    _perComp |= PER_NORMAL;
+                    break;
+            }
 
-        if (TexCoordBinding == G_PER_VERTEX)
-            _perVertex |= PER_TEXCOORD;
+            bPerPrimNormal=((_perPrim & PER_NORMAL)!=0);            
 
-        size_t vertex_size = draw_prim_setup(geom);
+            if (TexCoordBinding == G_PER_VERTEX)
+                _perVertex |= PER_TEXCOORD;
+
+            switch (ColorBinding) {
+                case G_PER_PRIM:
+                    _perPrim |= PER_COLOR;
+                    break;
+                case G_PER_COMPONENT:
+                    _perComp |= PER_COLOR;
+                    break;
+                case G_PER_VERTEX:
+                    _perVertex |= PER_COLOR;
+                    break;
+            }
+        }
 
         // iterate through the triangle primitives
 
-        for (uint i = 0; i < nPrims; i++) {
+        int nVerts;
+        if(pLengthArr==NULL) {
+           // we've been called by draw_quad, which has no lengths array
+           nVerts=4;
+        }
 
-            if (_perPrim & PER_COLOR) {
-                GET_NEXT_COLOR();
-            }
-            if (_perPrim & PER_NORMAL)
-                p_normal = geom->get_next_normal(ni);   // set primitive normal if there is one.
-            
-            int nVerts;
+        for (uint i = 0; i < nPrims; i++) {
 
             if(pLengthArr!=NULL) {
               nVerts = *(pLengthArr++);
-            } else {
-              // we've been called by draw_quad, which has no lengths array
-              nVerts=4;
+            } 
+
+            if(bPerPrimColor) {  // remember color might be G_OVERALL too!
+                GET_NEXT_COLOR();
             }
 
 #ifdef _DEBUG
@@ -3387,33 +3468,41 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
             _pCurFvfBufPtr = _pFvfBufBasePtr;            // _pCurFvfBufPtr changes,  _pFvfBufBasePtr doesn't
 
             if(_perComp==0x0) {
-                 if(_perVertex==TexCoordOnly)
+                 if(bUseTexCoordOnlyLoop) {  
                     draw_prim_inner_loop_coordtexonly(nVerts, geom);   
-                   else 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
+                 } else {
+                     if (bPerPrimNormal)
+                         p_normal = geom->get_next_normal(ni);   // set primitive normal if there is one.
 
-                            // 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(nVerts, geom, _perVertex);
+                 }
+            } else {
+                if(bPerPrimNormal)
+                    p_normal = geom->get_next_normal(ni);   // set primitive normal if there is one.
 
-                            draw_prim_inner_loop(1, geom, _perVertex);
+                if(bIsTriList) {
+                   // in flat shade mode, D3D strips color using the 1st vertex. 
+                   // (note: differs from OGL, which always uses last vtx for strips&fans
 
-                            draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp);
+                    // Store all but last 2 verts
+                    draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp);
 
-                            draw_prim_inner_loop(1, geom, _perVertex);
-                    }
+                    // _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);
+                }
             }
 
+            assert((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr));
+
             if(!_bDrawPrimDoSetupVertexBuffer) {
                 hr = scrn.pD3DDevice->DrawPrimitive(trilisttype,  _curFVFflags, _pFvfBufBasePtr, nVerts, NULL);
                 TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,nVerts-2);
@@ -3423,7 +3512,10 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
 
             _pCurFvfBufPtr = NULL;
         }
-    } else {
+    }
+
+#if 0
+    else {
 
         // new geom setup that uses strided DP calls to avoid making an extra pass over the data
 
@@ -3668,6 +3760,7 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
 
         nassertv(_pCurFvfBufPtr == NULL);
     }
+#endif
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 1
panda/src/dxgsg/dxGraphicsStateGuardian.h

@@ -273,7 +273,7 @@ protected:
   void set_read_buffer(const RenderBuffer &rb);
 
   // for storage of the flexible vertex format
-  char *_pCurFvfBufPtr,*_pFvfBufBasePtr;
+  BYTE *_pCurFvfBufPtr,*_pFvfBufBasePtr;
   INLINE void add_to_FVFBuf(void *data,  size_t bytes) ;
   WORD *_index_buf;  // base of malloced array
 

+ 4 - 4
panda/src/dxgsg/dxTextureContext.cxx

@@ -917,13 +917,13 @@ HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf)
                                 // pixel buffer is in ABGR format(it stores big-endian RGBA)
                                 // need to change byte order from ARGB
 
-                                r = *pSrcByte++;
-                                g = *pSrcByte++;
                                 b = *pSrcByte++;
+                                g = *pSrcByte++;
+                                r = *pSrcByte++;
 
-                                *pDstByte++ = b;
-                                *pDstByte++ = g;
                                 *pDstByte++ = r;
+                                *pDstByte++ = g;
+                                *pDstByte++ = b;
                             }
                           #endif
                         }