diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx index a47acf01f3..a542d9a43f 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx @@ -99,10 +99,14 @@ const int VERT_BUFFER_SIZE = (32*6*1024L); TypeHandle DXGraphicsStateGuardian::_type_handle; // bit masks used for drawing primitives -#define PER_TEXCOORD 0x8 -#define PER_COLOR 0x4 -#define PER_NORMAL 0x2 -#define PER_COORD 0x1 +// bitmask type: normal=0x1,color=0x2,texcoord=0x4 +typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly, + Normal_TexCoord,Color_TexCoord,Normal_Color_TexCoord +} DrawLoopFlags; + +#define PER_NORMAL NormalOnly +#define PER_COLOR ColorOnly +#define PER_TEXCOORD TexCoordOnly // technically DX7's front-end has no limit on the number of lights, but it's simpler for // this implementation to set a small GL-like limit to make the light array traversals short @@ -1809,6 +1813,16 @@ draw_prim_setup(const Geom *geom) { }} //////// + + // this stuff should eventually replace the iterators below + geom->get_coords(_coords,_vindexes); + if(_vindexes!=NULL) { + _pCurCoordIndex = &_vindexes[0]; + } else { + _pCurCoord = &_coords[0]; + } + + /////////////// vi = geom->make_vertex_iterator(); _curFVFflags = D3DFVF_XYZ; @@ -1846,10 +1860,21 @@ draw_prim_setup(const Geom *geom) { p_normal = geom->get_next_normal(ni); // set overall normal if there is one } - if (geom->get_binding(G_TEXCOORD) != G_OFF) { - ti = geom->make_texcoord_iterator(); - _curFVFflags |= (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); - vertex_size += sizeof(float) * 2; + + GeomBindType TexCoordBinding; + geom->get_texcoords(_texcoords,TexCoordBinding,_texcoord_indexes); + if (TexCoordBinding != G_OFF) { + + // used by faster path + if(_texcoord_indexes!=NULL) { + _pCurTexCoordIndex = &_texcoord_indexes[0]; + } else { + _pCurTexCoord = &_texcoords[0]; + } + + ti = geom->make_texcoord_iterator(); + _curFVFflags |= (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); + vertex_size += sizeof(float) * 2; } // If we have per-vertex colors or normals, we need smooth shading. @@ -1903,36 +1928,34 @@ wants_colors() const { // for component normals and color //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -draw_prim_inner_loop(int nVerts, const Geom *geom, DWORD perFlags) { - +draw_prim_inner_loop(int nVerts, const Geom *geom, ushort perFlags) { Vertexf NextVert; - perFlags &= ~PER_COORD; // should always be set anyway for(;nVerts > 0;nVerts--) { - // coord info will always be _perVertex GET_NEXT_VERTEX(NextVert); // need to optimize these add_to_FVFBuf((void *)&NextVert, sizeof(D3DVECTOR)); - if(perFlags==0xC) { - // break out the common case first + if(perFlags==(ushort)TexCoordOnly) { + // break out the common case (for animated chars) 1st GET_NEXT_TEXCOORD(); - GET_NEXT_COLOR(); } else { - switch (perFlags) { - case 0x4: + switch (DrawLoopFlags(perFlags)) { + case Color_TexCoord: + GET_NEXT_TEXCOORD(); + case ColorOnly: GET_NEXT_COLOR(); break; - case 0x6: + case Normal_Color: GET_NEXT_COLOR(); - case 0x2: + case NormalOnly: GET_NEXT_NORMAL(); break; - case 0xE: + case Normal_Color_TexCoord: GET_NEXT_COLOR(); - case 0xA: + case Normal_TexCoord: GET_NEXT_NORMAL(); - case 0x8: + // case TexCoordOnly: GET_NEXT_TEXCOORD(); break; } @@ -1947,6 +1970,54 @@ draw_prim_inner_loop(int nVerts, const Geom *geom, DWORD perFlags) { } } +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian::draw_prim_inner_loop_coordtexonly +// Access: Private +// Description: FastPath loop used by animated character data +//////////////////////////////////////////////////////////////////// +void DXGraphicsStateGuardian:: +draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom) { + // inc'ing local ptrs avoids 'this' ptr derefs for member fields + Vertexf *pCurVert = _pCurCoord; + ushort *pCurVertIndex = _pCurCoordIndex; + TexCoordf *pCurTexCoord = _pCurTexCoord; + ushort *pCurTexCoordIndex = _pCurTexCoordIndex; + char *LocalFvfBufPtr=_pCurFvfBufPtr; + DWORD cur_color = _curD3Dcolor; + bool bDoIndexedTexCoords = (_texcoord_indexes != NULL); + bool bDoIndexedCoords = (_vindexes != NULL); + + for(;nVerts > 0;nVerts--) { + if(bDoIndexedCoords) { + memcpy(LocalFvfBufPtr,(void*)&_coords[*pCurVertIndex],sizeof(D3DVECTOR)); + pCurVertIndex++; + } else { + memcpy(LocalFvfBufPtr,(void*)pCurVert,sizeof(D3DVECTOR)); + pCurVert++; + } + + LocalFvfBufPtr+=sizeof(D3DVECTOR); + + *((DWORD *)LocalFvfBufPtr) = cur_color; + LocalFvfBufPtr += sizeof(DWORD); + + if(bDoIndexedTexCoords) { + memcpy(LocalFvfBufPtr,(void*)&_texcoords[*pCurTexCoordIndex],sizeof(TexCoordf)); + pCurTexCoordIndex++; + } else { + memcpy(LocalFvfBufPtr,(void*)pCurTexCoord,sizeof(TexCoordf)); + pCurTexCoord++; + } + LocalFvfBufPtr+=sizeof(TexCoordf); + } + + _pCurFvfBufPtr=LocalFvfBufPtr; + _pCurCoord = pCurVert; + _pCurCoordIndex = pCurVertIndex; + _pCurTexCoord = pCurTexCoord; + _pCurTexCoordIndex = pCurTexCoordIndex; +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian::draw_point // Access: Public, Virtual @@ -2016,9 +2087,8 @@ draw_point(GeomPoint *geom, GeomContext *gc) { // values (may only be possible to handle certain cases without reverting to old pipeline) if (GeomVrtFmt!=FlatVerts) { - _perVertex = PER_COORD; + _perVertex = 0x0; _perPrim = 0; - if (geom->get_binding(G_COORD) == G_PER_VERTEX) _perVertex |= PER_COORD; if (geom->get_binding(G_NORMAL) == G_PER_VERTEX) _perVertex |= PER_NORMAL; if (geom->get_binding(G_COLOR) == G_PER_VERTEX) _perVertex |= PER_COLOR; @@ -2123,9 +2193,9 @@ draw_line(GeomLine* geom, GeomContext *gc) { } assert(geom->get_binding(G_COORD) == G_PER_VERTEX); - _perVertex = PER_COORD; + _perVertex = 0x0; + _perPrim = _perComp = 0x0; - _perPrim = _perComp = 0; switch(geom->get_binding(G_NORMAL)) { case G_PER_VERTEX: _perVertex |= PER_NORMAL; @@ -2226,7 +2296,7 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { } assert(geom->get_binding(G_COORD) == G_PER_VERTEX); - _perVertex = PER_COORD; + _perVertex = 0x0; _perPrim = _perComp = 0; switch(geom->get_binding(G_NORMAL)) { @@ -2252,6 +2322,7 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { } size_t vertex_size = draw_prim_setup(geom); + ushort perFlags = _perVertex | _perComp; for (int i = 0; i < nPrims; i++) { if (_perPrim & PER_COLOR) { @@ -2260,19 +2331,17 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { int nVerts; - if(plen==NULL) { - nVerts=4; // we've been called by draw_quad, which has no lengths array - } else { + if(plen!=NULL) { nVerts= *(plen++); 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. nassertv(nVerts * vertex_size < VERT_BUFFER_SIZE); _pCurFvfBufPtr = _pFvfBufBasePtr; // _pCurFvfBufPtr changes, _pFvfBufBasePtr doesn't - DWORD perFlags = _perVertex | _perComp; - draw_prim_inner_loop(nVerts, geom, perFlags); if(bConnectEnds) { @@ -2830,15 +2899,21 @@ draw_tri(GeomTri *geom, GeomContext *gc) { if (GeomVrtFmt!=FlatVerts) { // this is the old geom setup, it reformats every vtx into an output array passed to d3d - _perVertex = PER_COORD; + _perVertex = 0x0; + _perPrim = 0x0; - if (NormalBinding == G_PER_VERTEX) _perVertex |= PER_NORMAL; - if (ColorBinding == G_PER_VERTEX) _perVertex |= PER_COLOR; - if (TexCoordBinding == G_PER_VERTEX) _perVertex |= PER_TEXCOORD; + if(NormalBinding == G_PER_VERTEX) + _perVertex |= PER_NORMAL; + else if(NormalBinding == G_PER_PRIM) + _perPrim |= PER_NORMAL; - _perPrim = 0; - if (NormalBinding == G_PER_PRIM) _perPrim |= PER_NORMAL; - if (ColorBinding == G_PER_PRIM) _perPrim |= PER_COLOR; + if(ColorBinding == G_PER_PRIM) + _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); @@ -2856,7 +2931,10 @@ draw_tri(GeomTri *geom, GeomContext *gc) { if (_perPrim & PER_NORMAL) p_normal = geom->get_next_normal(ni); // set primitive normal if there is one. - draw_prim_inner_loop(3, geom, _perVertex); + + if(_perVertex==TexCoordOnly) + draw_prim_inner_loop_coordtexonly(3, geom); + else draw_prim_inner_loop(3, geom, _perVertex); } DWORD nVerts=nPrims*3; @@ -3181,10 +3259,12 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { if (GeomVrtFmt!=FlatVerts) { // this is the old geom setup, it reformats every vtx into an output array passed to d3d - _perVertex = PER_COORD; + _perVertex = 0x0; _perPrim = _perComp = 0; switch (NormalBinding) { + case G_OFF: + break; case G_PER_VERTEX: _perVertex |= PER_NORMAL; break; @@ -3197,15 +3277,15 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { } switch (ColorBinding) { - case G_PER_VERTEX: - _perVertex |= PER_COLOR; - break; case G_PER_PRIM: _perPrim |= PER_COLOR; break; case G_PER_COMPONENT: _perComp |= PER_COLOR; break; + case G_PER_VERTEX: + _perVertex |= PER_COLOR; + break; } if (TexCoordBinding == G_PER_VERTEX) @@ -3240,7 +3320,9 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { _pCurFvfBufPtr = _pFvfBufBasePtr; // _pCurFvfBufPtr changes, _pFvfBufBasePtr doesn't if(_perComp==0x0) { - draw_prim_inner_loop(nVerts, geom, _perVertex); + if(_perVertex==TexCoordOnly) + 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. @@ -3960,36 +4042,6 @@ apply_texture(TextureContext *tc) { D3DTEXTUREMINFILTER minfilter = PandaToD3DMinType[(DWORD)ft]; D3DTEXTUREMIPFILTER mipfilter = PandaToD3DMipType[(DWORD)ft]; -/* - switch (ft) { - case Texture::FT_nearest: - minfilter = D3DTFN_POINT; - mipfilter = D3DTFP_NONE; - break; - case Texture::FT_linear: - minfilter = D3DTFN_LINEAR; - mipfilter = D3DTFP_NONE; - break; - case Texture::FT_nearest_mipmap_nearest: - minfilter = D3DTFN_POINT; - mipfilter = D3DTFP_POINT; - break; - case Texture::FT_linear_mipmap_nearest: - minfilter = D3DTFN_LINEAR; - mipfilter = D3DTFP_POINT; - break; - case Texture::FT_nearest_mipmap_linear: - minfilter = D3DTFN_POINT; - mipfilter = D3DTFP_LINEAR; - break; - case Texture::FT_linear_mipmap_linear: - minfilter = D3DTFN_LINEAR; - mipfilter = D3DTFP_LINEAR; - break; - default: - dxgsg_cat.error() << "Unknown tex filter type for tex: " << tex->get_name() << " filter: "<<(DWORD)ft<<"\n"; - } -*/ #ifndef NDEBUG extern char *PandaFilterNameStrs[]; diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.h b/panda/src/dxgsg/dxGraphicsStateGuardian.h index 80cd72dd22..ae4ff25351 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.h +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.h @@ -310,23 +310,19 @@ protected: INLINE void enable_dither(bool val); INLINE void enable_stencil_test(bool val); bool enable_light(int light, bool val); - - void draw_prim_inner_loop(int nVerts, const Geom *geom, DWORD perFlags); - size_t draw_prim_setup(const Geom *geom) ; + void report_texmgr_stats(); void draw_multitri(Geom *geom, D3DPRIMITIVETYPE tri_id); - void report_texmgr_stats(); + void draw_prim_inner_loop(int nVerts, const Geom *geom, ushort perFlags); + void draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom); + size_t draw_prim_setup(const Geom *geom) ; // for drawing primitives - // Colorf p_color; bypassed by _curD3Dcolor; - // Vertexf p_vertex; Normalf p_normal; // still used to hold G_OVERALL, G_PER_PRIM values TexCoordf p_texcoord; D3DCOLOR _curD3Dcolor; DWORD _curFVFflags; - short _perPrim; - short _perVertex; - short _perComp; + DWORD _perPrim,_perVertex,_perComp; // these hold DrawLoopFlags bitmask values bool _issued_color_enabled; // WBD ADDED bool _enable_all_color; @@ -352,11 +348,16 @@ protected: PTA_ushort _vindexes; ushort *_pCurCoordIndex; + PTA_TexCoordf _texcoords; + TexCoordf *_pCurTexCoord; + PTA_ushort _texcoord_indexes; + ushort *_pCurTexCoordIndex; +/* not used yet PTA_Normalf _norms; PTA_Colorf _colors; - PTA_TexCoordf _texcoords; - PTA_ushort _cindexes,_nindexes,_tindexes; + PTA_ushort _cindexes,_nindexes; +*/ Colorf _lmodel_ambient; float _material_ambient;