From 8b6d25c53ea5b4f4448d2043051101d5ca86c459 Mon Sep 17 00:00:00 2001 From: cxgeorge <> Date: Mon, 20 Aug 2001 02:30:25 +0000 Subject: [PATCH] partial vtx buffer chkin, plus some pipeline tweaks --- panda/src/dxgsg/dxGeomNodeContext.I | 9 +- panda/src/dxgsg/dxGeomNodeContext.cxx | 12 + panda/src/dxgsg/dxGeomNodeContext.h | 27 +- panda/src/dxgsg/dxGraphicsStateGuardian.cxx | 584 +++++++++++++------- panda/src/dxgsg/dxGraphicsStateGuardian.h | 2 + 5 files changed, 412 insertions(+), 222 deletions(-) diff --git a/panda/src/dxgsg/dxGeomNodeContext.I b/panda/src/dxgsg/dxGeomNodeContext.I index 1b12a84bae..8d30be3c3b 100644 --- a/panda/src/dxgsg/dxGeomNodeContext.I +++ b/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; } diff --git a/panda/src/dxgsg/dxGeomNodeContext.cxx b/panda/src/dxgsg/dxGeomNodeContext.cxx index e499c1affa..fee6d21cb3 100644 --- a/panda/src/dxgsg/dxGeomNodeContext.cxx +++ b/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; +} + diff --git a/panda/src/dxgsg/dxGeomNodeContext.h b/panda/src/dxgsg/dxGeomNodeContext.h index 6b55830364..085380d27d 100644 --- a/panda/src/dxgsg/dxGeomNodeContext.h +++ b/panda/src/dxgsg/dxGeomNodeContext.h @@ -32,6 +32,9 @@ #include #include "pvector.h" +#define D3D_OVERLOADS // get D3DVECTOR '+' operator, etc from d3dtypes.h +#include + //////////////////////////////////////////////////////////////////// // 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 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() { diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx index 7573b85344..526f0c0d56 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx +++ b/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;iGeomget_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;iimake_dirty(); - } - - return NULL; - -#if 0 - // 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; - - for (i = 0; (i < num_geoms) && all_dynamic; i++) { - dDrawable *geom = node->get_geom(i); - all_dynamic = geom->is_dynamic(); + me->make_dirty(); } - if (all_dynamic) { + } // if(link_tristrips) + + // for now, only using vertexbufs for static Geom, so + // Make sure we have at least some static Geoms in the GeomNode; + 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); 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(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_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;iiget_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); } - - } else { - // We do have a saved context; use it. - add_to_geom_node_record(gnc); - DXGeomNodeContext *ggnc = DCAST(DXGeomNodeContext, gnc); - DXCallList(ggnc->_index); - -#ifdef DO_PSTATS - DO_PSTATS_STUFF(PStatTimer timer(_draw_primitive_pcollector)); - _vertices_display_list_pcollector.add_level(ggnc->_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); - } + return; } + + // We do have a saved context; use it. + add_to_geom_node_record(gnc); + DXGeomNodeContext *dx_gnc = DCAST(DXGeomNodeContext, gnc); + + #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(dx_gnc->_num_verts); #endif + + + // Also draw all the dynamic Geoms. + for (i = 0; i < num_geoms; i++) { + dx_gnc->_other_geoms[i]->draw(this); + } + } //////////////////////////////////////////////////////////////////// @@ -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 } diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.h b/panda/src/dxgsg/dxGraphicsStateGuardian.h index b99f5c68a9..2f2b15889d 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.h +++ b/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;