00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "dxVertexBufferContext9.h"
00016 #include "geomVertexArrayData.h"
00017 #include "geomVertexArrayFormat.h"
00018 #include "graphicsStateGuardian.h"
00019 #include "pStatTimer.h"
00020 #include "internalName.h"
00021 #include "config_dxgsg9.h"
00022
00023 #define DEBUG_VERTEX_BUFFER false
00024
00025 TypeHandle DXVertexBufferContext9::_type_handle;
00026
00027
00028
00029
00030
00031
00032 DXVertexBufferContext9::
00033 DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data, DXScreenData &scrn) :
00034 VertexBufferContext(pgo, data),
00035 _vbuffer(NULL)
00036 {
00037
00038 const GeomVertexArrayFormat *array_format = data->get_array_format();
00039
00040
00041
00042 int index;
00043 int n = 0;
00044 int num_columns = array_format->get_num_columns();
00045
00046 _vertex_element_type_array = 0;
00047
00048 VERTEX_ELEMENT_TYPE *vertex_element_type_array;
00049
00050
00051 {
00052 int total_elements;
00053 unsigned char vertex_element_type_counter_array [VS_TOTAL_TYPES];
00054 VERTEX_ELEMENT_TYPE *vertex_element_type;
00055
00056 total_elements = num_columns + 2;
00057 vertex_element_type_array = new VERTEX_ELEMENT_TYPE [total_elements];
00058 memset (vertex_element_type_array, 0, total_elements * sizeof (VERTEX_ELEMENT_TYPE));
00059 memset (vertex_element_type_counter_array, 0, sizeof (vertex_element_type_counter_array));
00060
00061
00062 vertex_element_type = vertex_element_type_array;
00063 for (index = 0; index < num_columns; index++)
00064 {
00065 int num_values;
00066 const InternalName *name;
00067
00068 name = array_format -> get_column (index) -> get_name ( );
00069 num_values = array_format -> get_column(index) -> get_num_values ( );
00070
00071 if (false) {
00072
00073 } else if (name -> get_top ( ) == InternalName::get_vertex ( )) {
00074
00075 switch (num_values)
00076 {
00077 case 3:
00078 vertex_element_type -> vs_input_type = VS_POSITION_XYZ;
00079 break;
00080 case 4:
00081 vertex_element_type -> vs_input_type = VS_POSITION_XYZW;
00082 break;
00083 default:
00084 dxgsg9_cat.warning ( ) << "VERTEX ERROR: invalid number of position coordinate elements " << num_values << "\n";
00085 break;
00086 }
00087
00088 } else if (name -> get_top ( ) == InternalName::get_texcoord ( )) {
00089
00090 switch (num_values)
00091 {
00092 case 1:
00093 vertex_element_type -> vs_input_type = VS_TEXTURE_U;
00094 break;
00095 case 2:
00096 vertex_element_type -> vs_input_type = VS_TEXTURE_UV;
00097 break;
00098 case 3:
00099 vertex_element_type -> vs_input_type = VS_TEXTURE_UVW;
00100 break;
00101 default:
00102 dxgsg9_cat.warning ( ) << "VERTEX ERROR: invalid number of vertex texture coordinate elements " << num_values << "\n";
00103 break;
00104 }
00105
00106 } else if (name -> get_top ( ) == InternalName::get_normal ( )) {
00107
00108 vertex_element_type -> vs_input_type = VS_NORMAL;
00109
00110 } else if (name -> get_top ( ) == InternalName::get_binormal ( )) {
00111
00112 vertex_element_type -> vs_input_type = VS_BINORMAL;
00113
00114 } else if (name -> get_top ( ) == InternalName::get_tangent ( )) {
00115
00116 vertex_element_type -> vs_input_type = VS_TANGENT;
00117
00118 } else if (name -> get_top ( ) == InternalName::get_color ( )) {
00119
00120 vertex_element_type -> vs_input_type = VS_DIFFUSE;
00121
00122 } else {
00123
00124 dxgsg9_cat.error ( )
00125 << "VERTEX ERROR: unsupported vertex element " << name -> get_name ( )
00126 << "\n";
00127
00128 vertex_element_type -> vs_input_type = VS_ERROR;
00129 }
00130
00131 vertex_element_type -> index = vertex_element_type_counter_array [vertex_element_type -> vs_input_type];
00132 vertex_element_type_counter_array [vertex_element_type -> vs_input_type]++;
00133
00134
00135 vertex_element_type -> stream = 0;
00136 vertex_element_type -> offset = array_format -> get_column(index) -> get_start ( );
00137
00138 vertex_element_type++;
00139 }
00140 }
00141
00142 _vertex_element_type_array = vertex_element_type_array;
00143
00144 _fvf = 0;
00145 _managed = -1;
00146
00147 _direct_3d_vertex_declaration = 0;
00148 _shader_context = 0;
00149
00150 if (n < num_columns &&
00151 array_format->get_column(n)->get_name() == InternalName::get_vertex()) {
00152 ++n;
00153
00154 int num_blend_values = 0;
00155
00156 if (n < num_columns &&
00157 array_format->get_column(n)->get_name() == InternalName::get_transform_weight()) {
00158
00159 num_blend_values = array_format->get_column(n)->get_num_values();
00160 ++n;
00161 }
00162
00163 if (n < num_columns &&
00164 array_format->get_column(n)->get_name() == InternalName::get_transform_index()) {
00165
00166 _fvf |= D3DFVF_LASTBETA_UBYTE4;
00167 ++num_blend_values;
00168 ++n;
00169 }
00170
00171 switch (num_blend_values) {
00172 case 0:
00173 _fvf |= D3DFVF_XYZ;
00174 break;
00175
00176 case 1:
00177 _fvf |= D3DFVF_XYZB1;
00178 break;
00179
00180 case 2:
00181 _fvf |= D3DFVF_XYZB2;
00182 break;
00183
00184 case 3:
00185 _fvf |= D3DFVF_XYZB3;
00186 break;
00187
00188 case 4:
00189 _fvf |= D3DFVF_XYZB4;
00190 break;
00191
00192 case 5:
00193 _fvf |= D3DFVF_XYZB5;
00194 break;
00195 }
00196 }
00197
00198 if (n < num_columns &&
00199 array_format->get_column(n)->get_name() == InternalName::get_normal()) {
00200 _fvf |= D3DFVF_NORMAL;
00201 ++n;
00202 }
00203 if (n < num_columns &&
00204 array_format->get_column(n)->get_name() == InternalName::get_color()) {
00205 _fvf |= D3DFVF_DIFFUSE;
00206 ++n;
00207 }
00208
00209
00210
00211 int texcoord_index = 0;
00212 while (n < num_columns &&
00213 array_format->get_column(n)->get_contents() == Geom::C_texcoord) {
00214 const GeomVertexColumn *column = array_format->get_column(n);
00215 switch (column->get_num_values()) {
00216 case 1:
00217 _fvf |= D3DFVF_TEXCOORDSIZE1(texcoord_index);
00218 ++n;
00219 break;
00220 case 2:
00221 _fvf |= D3DFVF_TEXCOORDSIZE2(texcoord_index);
00222 ++n;
00223 break;
00224 case 3:
00225 _fvf |= D3DFVF_TEXCOORDSIZE3(texcoord_index);
00226 ++n;
00227 break;
00228 case 4:
00229 _fvf |= D3DFVF_TEXCOORDSIZE4(texcoord_index);
00230 ++n;
00231 break;
00232 }
00233 ++texcoord_index;
00234 }
00235
00236 switch (texcoord_index) {
00237 case 0:
00238 break;
00239 case 1:
00240 _fvf |= D3DFVF_TEX1;
00241 break;
00242 case 2:
00243 _fvf |= D3DFVF_TEX2;
00244 break;
00245 case 3:
00246 _fvf |= D3DFVF_TEX3;
00247 break;
00248 case 4:
00249 _fvf |= D3DFVF_TEX4;
00250 break;
00251 case 5:
00252 _fvf |= D3DFVF_TEX5;
00253 break;
00254 case 6:
00255 _fvf |= D3DFVF_TEX6;
00256 break;
00257 case 7:
00258 _fvf |= D3DFVF_TEX7;
00259 break;
00260 case 8:
00261 _fvf |= D3DFVF_TEX8;
00262 break;
00263 }
00264 }
00265
00266
00267
00268
00269
00270
00271 DXVertexBufferContext9::
00272 ~DXVertexBufferContext9() {
00273
00274 if (_vertex_element_type_array) {
00275 delete _vertex_element_type_array;
00276 _vertex_element_type_array = 0;
00277 }
00278 if (_direct_3d_vertex_declaration) {
00279 _direct_3d_vertex_declaration -> Release ( );
00280 _direct_3d_vertex_declaration = 0;
00281 }
00282
00283 free_vbuffer ( );
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 void DXVertexBufferContext9::
00302 evict_lru() {
00303 dequeue_lru();
00304 free_vbuffer();
00305 update_data_size_bytes(0);
00306 mark_unloaded();
00307 }
00308
00309
00310
00311
00312
00313
00314 void DXVertexBufferContext9::
00315 free_vbuffer(void) {
00316
00317 if (_vbuffer != NULL) {
00318 if (DEBUG_VERTEX_BUFFER && dxgsg9_cat.is_debug()) {
00319 dxgsg9_cat.debug()
00320 << "deleting vertex buffer " << _vbuffer << "\n";
00321 }
00322
00323 if (DEBUG_VERTEX_BUFFER) {
00324 RELEASE(_vbuffer, dxgsg9, "vertex buffer", RELEASE_ONCE);
00325 }
00326 else {
00327 _vbuffer -> Release ( );
00328 }
00329
00330 _vbuffer = NULL;
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339 void DXVertexBufferContext9::
00340 allocate_vbuffer(DXScreenData &scrn,
00341 const GeomVertexArrayDataHandle *reader) {
00342
00343 int data_size;
00344 HRESULT hr;
00345 DWORD usage;
00346 D3DPOOL pool;
00347
00348 data_size = reader->get_data_size_bytes();
00349
00350 _managed = scrn._managed_vertex_buffers;
00351 if (_managed) {
00352 pool = D3DPOOL_MANAGED;
00353 usage = D3DUSAGE_WRITEONLY;
00354 }
00355 else {
00356 pool = D3DPOOL_DEFAULT;
00357 usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
00358 }
00359
00360 int attempts;
00361
00362 attempts = 0;
00363 do
00364 {
00365 hr = scrn._d3d_device->CreateVertexBuffer
00366 (data_size, usage, _fvf, pool, &_vbuffer, NULL);
00367 attempts++;
00368 }
00369 while (scrn._dxgsg9 -> check_dx_allocation (hr, data_size, attempts));
00370
00371 if (FAILED(hr)) {
00372 dxgsg9_cat.warning()
00373 << "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
00374
00375 printf ("data_size %d \n", data_size);
00376
00377 _vbuffer = NULL;
00378 } else {
00379 if (DEBUG_VERTEX_BUFFER && dxgsg9_cat.is_debug()) {
00380 dxgsg9_cat.debug()
00381 << "created vertex buffer " << _vbuffer << ": "
00382 << reader->get_num_rows() << " vertices "
00383 << *reader->get_array_format() << "\n";
00384 }
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393
00394 void DXVertexBufferContext9::
00395 create_vbuffer(DXScreenData &scrn,
00396 const GeomVertexArrayDataHandle *reader,
00397 string name) {
00398 nassertv(reader->get_object() == get_data());
00399 Thread *current_thread = reader->get_current_thread();
00400
00401 free_vbuffer ( );
00402
00403 PStatTimer timer(GraphicsStateGuardian::_create_vertex_buffer_pcollector,
00404 current_thread);
00405
00406 int data_size;
00407
00408 data_size = reader->get_data_size_bytes();
00409
00410 this -> allocate_vbuffer(scrn, reader);
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 bool DXVertexBufferContext9::
00420 upload_data(const GeomVertexArrayDataHandle *reader, bool force) {
00421 nassertr(reader->get_object() == get_data(), false);
00422 nassertr(_vbuffer != NULL, false);
00423 Thread *current_thread = reader->get_current_thread();
00424
00425 const unsigned char *data_pointer = reader->get_read_pointer(force);
00426 if (data_pointer == NULL) {
00427 return false;
00428 }
00429 int data_size = reader->get_data_size_bytes();
00430
00431 if (dxgsg9_cat.is_spam()) {
00432 dxgsg9_cat.spam()
00433 << "copying " << data_size
00434 << " bytes into vertex buffer " << _vbuffer << "\n";
00435 }
00436 PStatTimer timer(GraphicsStateGuardian::_load_vertex_buffer_pcollector,
00437 current_thread);
00438
00439 HRESULT hr;
00440 BYTE *local_pointer;
00441
00442 if (_managed) {
00443 hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, 0);
00444 }
00445 else {
00446 hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
00447 }
00448 if (FAILED(hr)) {
00449 dxgsg9_cat.error()
00450 << "VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
00451 return false;
00452 }
00453
00454 GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
00455 memcpy(local_pointer, data_pointer, data_size);
00456
00457 _vbuffer->Unlock();
00458 return true;
00459 }