Panda3D

dxVertexBufferContext8.cxx

00001 // Filename: dxVertexBufferContext8.cxx
00002 // Created by:  drose (18Mar05)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "dxVertexBufferContext8.h"
00016 #include "geomVertexArrayData.h"
00017 #include "geomVertexArrayFormat.h"
00018 #include "graphicsStateGuardian.h"
00019 #include "pStatTimer.h"
00020 #include "internalName.h"
00021 #include "config_dxgsg8.h"
00022 #include "dxgsg8base.h"
00023 
00024 TypeHandle DXVertexBufferContext8::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: DXVertexBufferContext8::Constructor
00028 //       Access: Public
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 DXVertexBufferContext8::
00032 DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
00033   VertexBufferContext(pgo, data),
00034   _vbuffer(NULL)
00035 {
00036   // Now fill in the FVF code.
00037   const GeomVertexArrayFormat *array_format = data->get_array_format();
00038 
00039   // We have to start with the vertex data, and work up from there in
00040   // order, since that's the way the FVF is defined.
00041   int n = 0;
00042   int num_columns = array_format->get_num_columns();
00043 
00044   _fvf = 0;
00045 
00046   if (n < num_columns &&
00047       array_format->get_column(n)->get_name() == InternalName::get_vertex()) {
00048     ++n;
00049 
00050     int num_blend_values = 0;
00051 
00052     if (n < num_columns &&
00053         array_format->get_column(n)->get_name() == InternalName::get_transform_weight()) {
00054       // We have hardware vertex animation.
00055       num_blend_values = array_format->get_column(n)->get_num_values();
00056       ++n;
00057     }
00058 
00059     if (n < num_columns &&
00060         array_format->get_column(n)->get_name() == InternalName::get_transform_index()) {
00061       // Furthermore, it's indexed vertex animation.
00062       _fvf |= D3DFVF_LASTBETA_UBYTE4;
00063       ++num_blend_values;
00064       ++n;
00065     }
00066 
00067     switch (num_blend_values) {
00068     case 0:
00069       _fvf |= D3DFVF_XYZ;
00070       break;
00071 
00072     case 1:
00073       _fvf |= D3DFVF_XYZB1;
00074       break;
00075 
00076     case 2:
00077       _fvf |= D3DFVF_XYZB2;
00078       break;
00079 
00080     case 3:
00081       _fvf |= D3DFVF_XYZB3;
00082       break;
00083 
00084     case 4:
00085       _fvf |= D3DFVF_XYZB4;
00086       break;
00087 
00088     case 5:
00089       _fvf |= D3DFVF_XYZB5;
00090       break;
00091     }
00092   }
00093 
00094   if (n < num_columns &&
00095       array_format->get_column(n)->get_name() == InternalName::get_normal()) {
00096     _fvf |= D3DFVF_NORMAL;
00097     ++n;
00098   }
00099   if (n < num_columns &&
00100       array_format->get_column(n)->get_name() == InternalName::get_color()) {
00101     _fvf |= D3DFVF_DIFFUSE;
00102     ++n;
00103   }
00104 
00105   // Now look for all of the texcoord names and enable them in the
00106   // same order they appear in the array.
00107   int texcoord_index = 0;
00108   while (n < num_columns &&
00109          array_format->get_column(n)->get_contents() == Geom::C_texcoord) {
00110     const GeomVertexColumn *column = array_format->get_column(n);
00111     switch (column->get_num_values()) {
00112     case 1:
00113       _fvf |= D3DFVF_TEXCOORDSIZE1(texcoord_index);
00114       ++n;
00115       break;
00116     case 2:
00117       _fvf |= D3DFVF_TEXCOORDSIZE2(texcoord_index);
00118       ++n;
00119       break;
00120     case 3:
00121       _fvf |= D3DFVF_TEXCOORDSIZE3(texcoord_index);
00122       ++n;
00123       break;
00124     case 4:
00125       _fvf |= D3DFVF_TEXCOORDSIZE4(texcoord_index);
00126       ++n;
00127       break;
00128     }
00129     ++texcoord_index;
00130   }
00131 
00132   switch (texcoord_index) {
00133   case 0:
00134     break;
00135   case 1:
00136     _fvf |= D3DFVF_TEX1;
00137     break;
00138   case 2:
00139     _fvf |= D3DFVF_TEX2;
00140     break;
00141   case 3:
00142     _fvf |= D3DFVF_TEX3;
00143     break;
00144   case 4:
00145     _fvf |= D3DFVF_TEX4;
00146     break;
00147   case 5:
00148     _fvf |= D3DFVF_TEX5;
00149     break;
00150   case 6:
00151     _fvf |= D3DFVF_TEX6;
00152     break;
00153   case 7:
00154     _fvf |= D3DFVF_TEX7;
00155     break;
00156   case 8:
00157     _fvf |= D3DFVF_TEX8;
00158     break;
00159   }
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: DXVertexBufferContext8::Destructor
00164 //       Access: Public
00165 //  Description:
00166 ////////////////////////////////////////////////////////////////////
00167 DXVertexBufferContext8::
00168 ~DXVertexBufferContext8() {
00169   if (_vbuffer != NULL) {
00170     if (dxgsg8_cat.is_debug()) {
00171       dxgsg8_cat.debug()
00172         << "deleting vertex buffer " << _vbuffer << "\n";
00173     }
00174 
00175     RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
00176     _vbuffer = NULL;
00177   }
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: DXVertexBufferContext8::evict_lru
00182 //       Access: Public, Virtual
00183 //  Description: Evicts the page from the LRU.  Called internally when
00184 //               the LRU determines that it is full.  May also be
00185 //               called externally when necessary to explicitly evict
00186 //               the page.
00187 //
00188 //               It is legal for this method to either evict the page
00189 //               as requested, do nothing (in which case the eviction
00190 //               will be requested again at the next epoch), or
00191 //               requeue itself on the tail of the queue (in which
00192 //               case the eviction will be requested again much
00193 //               later).
00194 ////////////////////////////////////////////////////////////////////
00195 void DXVertexBufferContext8::
00196 evict_lru() {
00197   dequeue_lru();
00198 
00199   if (_vbuffer != NULL) {
00200     if (dxgsg8_cat.is_debug()) {
00201       dxgsg8_cat.debug()
00202         << "deleting vertex buffer " << _vbuffer << "\n";
00203     }
00204 
00205     RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
00206     _vbuffer = NULL;
00207   }
00208 
00209   update_data_size_bytes(0);
00210   mark_unloaded();
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: DXVertexBufferContext8::create_vbuffer
00215 //       Access: Public
00216 //  Description: Creates a new vertex buffer (but does not upload data
00217 //               to it).
00218 ////////////////////////////////////////////////////////////////////
00219 void DXVertexBufferContext8::
00220 create_vbuffer(DXScreenData &scrn,
00221                const GeomVertexArrayDataHandle *reader) {
00222   nassertv(reader->get_object() == get_data());
00223   Thread *current_thread = reader->get_current_thread();
00224 
00225   if (_vbuffer != NULL) {
00226     if (dxgsg8_cat.is_debug()) {
00227       dxgsg8_cat.debug()
00228         << "deleting vertex buffer " << _vbuffer << "\n";
00229     }
00230 
00231     RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
00232     _vbuffer = NULL;
00233   }
00234 
00235   PStatTimer timer(GraphicsStateGuardian::_create_vertex_buffer_pcollector,
00236                    current_thread);
00237 
00238   HRESULT hr = scrn._d3d_device->CreateVertexBuffer
00239 //    (reader->get_data_size_bytes(), D3DUSAGE_WRITEONLY,
00240 //     _fvf, D3DPOOL_MANAGED, &_vbuffer);
00241      (reader->get_data_size_bytes(), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC,
00242      _fvf, D3DPOOL_DEFAULT, &_vbuffer);
00243   if (FAILED(hr)) {
00244     dxgsg8_cat.warning()
00245       << "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
00246     _vbuffer = NULL;
00247   } else {
00248     if (dxgsg8_cat.is_debug()) {
00249       dxgsg8_cat.debug()
00250         << "created vertex buffer " << _vbuffer << ": "
00251         << reader->get_num_rows() << " vertices "
00252         << *reader->get_array_format() << "\n";
00253     }
00254   }
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: DXVertexBufferContext8::upload_data
00259 //       Access: Public
00260 //  Description: Copies the latest data from the client store to
00261 //               DirectX.
00262 ////////////////////////////////////////////////////////////////////
00263 bool DXVertexBufferContext8::
00264 upload_data(const GeomVertexArrayDataHandle *reader, bool force) {
00265   nassertr(reader->get_object() == get_data(), false);
00266   nassertr(_vbuffer != NULL, false);
00267   Thread *current_thread = reader->get_current_thread();
00268 
00269   const unsigned char *data_pointer = reader->get_read_pointer(force);
00270   if (data_pointer == NULL) {
00271     return false;
00272   }
00273   int data_size = reader->get_data_size_bytes();
00274 
00275   if (dxgsg8_cat.is_spam()) {
00276     dxgsg8_cat.spam()
00277       << "copying " << data_size
00278       << " bytes into vertex buffer " << _vbuffer << "\n";
00279   }
00280 
00281   PStatTimer timer(GraphicsStateGuardian::_load_vertex_buffer_pcollector,
00282                    current_thread);
00283 
00284   BYTE *local_pointer;
00285 //  HRESULT hr = _vbuffer->Lock(0, data_size, &local_pointer, 0);
00286   HRESULT hr = _vbuffer->Lock(0, data_size, &local_pointer, D3DLOCK_DISCARD);
00287   if (FAILED(hr)) {
00288     dxgsg8_cat.error()
00289       << "VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
00290     return false;
00291   }
00292 
00293   GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
00294   memcpy(local_pointer, data_pointer, data_size);
00295 
00296   _vbuffer->Unlock();
00297   return true;
00298 }
00299 
 All Classes Functions Variables Enumerations