Panda3D
|
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