69 #include <Cg/cgD3D9.h>
76 #define tostring(x) #x
77 #define SDK_VERSION(major,minor) tostring(major) << "." << tostring(minor)
78 #define DIRECTX_SDK_VERSION SDK_VERSION (_DXSDK_PRODUCT_MAJOR, _DXSDK_PRODUCT_MINOR) << "." << SDK_VERSION (_DXSDK_BUILD_MAJOR, _DXSDK_BUILD_MINOR)
84 TypeHandle DXGraphicsStateGuardian9::_type_handle;
86 D3DMATRIX DXGraphicsStateGuardian9::_d3d_ident_mat;
88 unsigned char *DXGraphicsStateGuardian9::_temp_buffer =
nullptr;
89 unsigned char *DXGraphicsStateGuardian9::_safe_buffer_start =
nullptr;
92 LPDIRECT3DDEVICE9 DXGraphicsStateGuardian9::_cg_device =
nullptr;
95 #define __D3DLIGHT_RANGE_MAX ((PN_stdfloat)sqrt(FLT_MAX)) //for some reason this is missing in dx9 hdrs
97 #define MY_D3DRGBA(r, g, b, a) ((D3DCOLOR) D3DCOLOR_COLORVALUE(r, g, b, a))
102 DXGraphicsStateGuardian9::
106 if (dxgsg9_cat.is_debug()) {
108 <<
"DXGraphicsStateGuardian9 " <<
this <<
" constructing\n";
116 _d3d_device =
nullptr;
118 _dx_is_ready =
false;
119 _vertex_blending_enabled =
false;
120 _overlay_windows_supported =
false;
121 _tex_stats_retrieval_impossible =
false;
122 _supports_render_texture =
false;
124 _active_ibuffer =
nullptr;
128 ZeroMemory(&_d3d_ident_mat,
sizeof(D3DMATRIX));
129 _d3d_ident_mat._11 = _d3d_ident_mat._22 = _d3d_ident_mat._33 = _d3d_ident_mat._44 = 1.0f;
131 _cur_read_pixel_buffer = RenderBuffer::T_front;
135 _copy_texture_inverted =
true;
137 _gsg_managed_textures = dx_management | dx_texture_management;
138 _gsg_managed_vertex_buffers = dx_management;
139 _gsg_managed_index_buffers = dx_management;
142 _num_bound_streams = 0;
143 _white_vbuffer =
nullptr;
145 _vertex_shader_version_major = 0;
146 _vertex_shader_version_minor = 0;
147 _pixel_shader_version_major = 0;
148 _pixel_shader_version_minor = 0;
150 _vertex_shader_profile = 0;
151 _pixel_shader_profile = 0;
153 _vertex_shader_maximum_constants = 0;
155 _supports_stream_offset =
false;
162 atexit (atexit_function);
168 DXGraphicsStateGuardian9::
169 ~DXGraphicsStateGuardian9() {
170 if (dxgsg9_cat.is_debug()) {
172 <<
"DXGraphicsStateGuardian9 " <<
this <<
" destructing\n";
175 if (IS_VALID_PTR(_d3d_device)) {
176 _d3d_device->SetTexture(0,
nullptr);
179 free_nondx_resources();
197 << *dtc->
get_texture() <<
" is stored in an unsupported compressed format.\n";
251 if (aniso_degree >= 1) {
255 int supports_anisotropic_mag_filter;
256 D3DTEXTUREFILTERTYPE new_mag_filter;
258 supports_anisotropic_mag_filter = (_screen -> _d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) != 0;
259 if (aniso_degree <= 1 || supports_anisotropic_mag_filter == 0) {
260 new_mag_filter = ((ft != SamplerState::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT);
262 new_mag_filter = D3DTEXF_ANISOTROPIC;
269 <<
"ERROR: set_sampler_state (D3DSAMP_MAGFILTER, "
270 << new_mag_filter <<
") failed for sampler: " << sampler << endl;
281 new_mip_filter = D3DTEXF_NONE;
286 new_mip_filter = D3DTEXF_NONE;
289 if (aniso_degree >= 2) {
290 new_min_filter = D3DTEXF_ANISOTROPIC;
324 <<
"Unable to re-create texture " << *tex << endl;
328 dtc->
enqueue_lru(&_prepared_objects->_graphics_memory_lru);
342 << *tex <<
" is stored in an unsupported compressed format.\n";
350 if (_effective_incomplete_render && !force) {
354 !_loader.is_null()) {
357 async_reload_texture(dtc);
361 return dtc->create_simple_texture(*_screen);
393 for (
int view = 0; view < num_views; ++view) {
395 nassertr(tc !=
nullptr,
false);
414 case Shader::SL_GLSL:
416 <<
"Tried to load GLSL shader, but GLSL shaders not supported by Direct3D 9.\n";
421 if (_supports_basic_shaders) {
425 <<
"Tried to load Cg shader, but basic shaders not supported.\n";
430 <<
"Tried to load Cg shader, but Cg support not compiled in.\n";
436 <<
"Tried to load shader with unsupported shader language!\n";
468 if (_screen->_managed_vertex_buffers) {
469 pool = D3DPOOL_MANAGED;
470 usage = D3DUSAGE_WRITEONLY;
472 pool = D3DPOOL_DEFAULT;
473 usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
476 int num_bytes = data->get_data_size_bytes();
484 hr = _screen->_d3d_device->CreateVertexBuffer(num_bytes, usage, dvbc->_fvf, pool, &dvbc->_vbuffer,
nullptr);
491 if (dxgsg9_cat.is_debug() && DXdebug_buffers9) {
493 <<
"creating vertex buffer " << dvbc->_vbuffer <<
": "
494 << data->get_num_rows() <<
" vertices "
495 << *data->get_array_format() <<
"\n";
503 <<
"CreateVertexBuffer failed" << D3DERRORSTRING(hr);
505 dvbc->_vbuffer =
nullptr;
522 int num_bytes = reader->get_data_size_bytes();
524 if (dxgsg9_cat.is_debug() && DXdebug_buffers9) {
526 <<
"copying " << num_bytes
527 <<
" bytes into vertex buffer " << dvbc->_vbuffer <<
"\n";
531 if ( num_bytes != 0 ) {
533 if (client_pointer ==
nullptr) {
540 if (dvbc->_vbuffer !=
nullptr) {
541 dvbc->_vbuffer->Release();
542 dvbc->_vbuffer =
nullptr;
547 if (_screen->_managed_vertex_buffers) {
548 pool = D3DPOOL_MANAGED;
549 usage = D3DUSAGE_WRITEONLY;
551 pool = D3DPOOL_DEFAULT;
552 usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
560 hr = _screen->_d3d_device->CreateVertexBuffer(num_bytes, usage, dvbc->_fvf, pool, &dvbc->_vbuffer,
nullptr);
565 dvbc->_vbuffer =
nullptr;
567 <<
"CreateVertexBuffer failed" << D3DERRORSTRING(hr);
572 PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread());
576 if (_screen->_managed_vertex_buffers) {
577 hr = dvbc->_vbuffer->Lock(0, num_bytes, (
void **) &local_pointer, 0);
579 hr = dvbc->_vbuffer->Lock(0, num_bytes, (
void **) &local_pointer, D3DLOCK_DISCARD);
583 <<
"VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
587 memcpy(local_pointer, client_pointer, num_bytes);
589 dvbc->_vbuffer->Unlock();
591 _data_transferred_pcollector.add_level(num_bytes);
596 dvbc->
enqueue_lru(&_prepared_objects->_graphics_memory_lru);
612 if (dxgsg9_cat.is_debug() && DXdebug_buffers9) {
614 <<
"deleting vertex buffer " << dvbc->_vbuffer <<
"\n";
618 if (dvbc->_vbuffer !=
nullptr) {
619 dvbc->_vbuffer->Release();
620 dvbc->_vbuffer =
nullptr;
646 nassertr(vbc !=
nullptr,
false);
679 if (dibc->_ibuffer ==
nullptr) {
683 if (dibc->_ibuffer !=
nullptr) {
689 _d3d_device->SetIndices(dibc->_ibuffer);
690 _active_ibuffer = dibc;
694 _d3d_device->SetIndices(
nullptr);
695 _active_ibuffer =
nullptr;
710 _active_ibuffer =
nullptr;
713 if (_active_ibuffer != dibc) {
714 _d3d_device->SetIndices(dibc->_ibuffer);
715 _active_ibuffer = dibc;
719 dibc->
enqueue_lru(&_prepared_objects->_graphics_memory_lru);
748 nassertv(_supports_occlusion_query);
749 nassertv(_current_occlusion_query ==
nullptr);
751 IDirect3DQuery9 *query;
752 HRESULT hr = _d3d_device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
755 <<
"Occlusion query failed.\n";
761 if (dxgsg9_cat.is_debug()) {
763 <<
"beginning occlusion query " << query <<
"\n";
766 query->Issue(D3DISSUE_BEGIN);
767 _current_occlusion_query = queryobj;
777 end_occlusion_query() {
778 if (_current_occlusion_query ==
nullptr) {
786 if (dxgsg9_cat.is_debug()) {
788 <<
"ending occlusion query " << query <<
"\n";
791 _current_occlusion_query =
nullptr;
792 query->Issue(D3DISSUE_END);
804 return GeomMunger::register_munger(munger, current_thread);
813 DWORD main_flags = 0;
830 main_flags |= D3DCLEAR_TARGET;
834 _screen->_presentation_params.EnableAutoDepthStencil) {
835 aux_flags |= D3DCLEAR_ZBUFFER;
840 if (_screen->_presentation_params.EnableAutoDepthStencil &&
841 IS_STENCIL_FORMAT(_screen->_presentation_params.AutoDepthStencilFormat)) {
842 aux_flags |= D3DCLEAR_STENCIL;
846 if ((main_flags | aux_flags) != 0) {
847 HRESULT hr = _d3d_device->Clear(0,
nullptr, main_flags | aux_flags, color_clear_value,
848 depth_clear_value, stencil_clear_value);
849 if (FAILED(hr) && main_flags == D3DCLEAR_TARGET && aux_flags != 0) {
852 hr = _d3d_device->Clear(0,
nullptr, D3DCLEAR_TARGET, color_clear_value,
853 depth_clear_value, stencil_clear_value);
858 aux_flags |= D3DCLEAR_ZBUFFER;
859 HRESULT hr2 = _d3d_device->Clear(0,
nullptr, D3DCLEAR_ZBUFFER, color_clear_value,
860 depth_clear_value, stencil_clear_value);
863 <<
"Unable to clear depth buffer; removing.\n";
869 aux_flags |= D3DCLEAR_STENCIL;
870 HRESULT hr2 = _d3d_device->Clear(0,
nullptr, D3DCLEAR_STENCIL, color_clear_value,
871 stencil_clear_value, stencil_clear_value);
874 <<
"Unable to clear stencil buffer; removing.\n";
877 _supports_stencil =
false;
885 <<
"clear_buffer failed: Clear returned " << D3DERRORSTRING(hr);
895 nassertv(dr !=
nullptr);
902 D3DVIEWPORT9 vp = { (DWORD)l, (DWORD)u, (DWORD)w, (DWORD)h, 0.0f, 1.0f };
903 _current_viewport = vp;
904 HRESULT hr = _d3d_device->SetViewport(&_current_viewport);
907 <<
"_screen->_swap_chain = " << _screen->_swap_chain <<
" _swap_chain = " << _swap_chain <<
"\n";
909 <<
"SetViewport(" << l <<
", " << u <<
", " << w <<
", " << h
910 <<
") failed" << D3DERRORSTRING(hr);
913 _d3d_device->GetViewport(&vp_old);
915 <<
"GetViewport(" << vp_old.X <<
", " << vp_old.Y <<
", " << vp_old.Width <<
", "
916 << vp_old.Height <<
") returned: Trying to set that vp---->\n";
917 hr = _d3d_device->SetViewport(&vp_old);
921 dxgsg9_cat.error() <<
"Failed again\n";
922 throw_event(
"panda3d-render-error");
927 if (_screen->_can_direct_disable_color_writes) {
941 calc_projection_mat(
const Lens *lens) {
942 if (lens ==
nullptr) {
953 static const LMatrix4 rescale_mat
960 LMatrix4::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
964 if (_scene_setup->get_inverted()) {
967 result *= LMatrix4::scale_mat(1.0f, -1.0f, 1.0f);
970 return TransformState::make_mat(result);
983 LMatrix4f mat = LCAST(
float, _projection_mat->get_mat());
985 _d3d_device->SetTransform(D3DTS_PROJECTION,
986 (D3DMATRIX*)mat.get_data());
987 return SUCCEEDED(hr);
1003 if (_d3d_device ==
nullptr) {
1005 <<
this <<
"::begin_frame(): no device.\n";
1009 HRESULT hr = _d3d_device->BeginScene();
1012 if (hr == D3DERR_DEVICELOST) {
1013 if (dxgsg9_cat.is_debug()) {
1015 <<
"BeginScene returns D3DERR_DEVICELOST" << endl;
1018 check_cooperative_level();
1022 <<
"BeginScene failed, unhandled error hr == "
1023 << D3DERRORSTRING(hr) << endl;
1024 throw_event(
"panda3d-render-error");
1029 if (_current_properties->get_srgb_color()) {
1089 if (_vertex_array_shader_context != 0) {
1091 _vertex_array_shader =
nullptr;
1092 _vertex_array_shader_context =
nullptr;
1094 if (_texture_binding_shader_context != 0) {
1096 _texture_binding_shader =
nullptr;
1097 _texture_binding_shader_context =
nullptr;
1099 if (_current_shader_context != 0) {
1100 _current_shader_context->
unbind(
this);
1101 _current_shader =
nullptr;
1102 _current_shader_context =
nullptr;
1136 HRESULT hr = _d3d_device->EndScene();
1139 if (hr == D3DERR_DEVICELOST) {
1140 if (dxgsg9_cat.is_debug()) {
1142 <<
"EndScene returns DeviceLost\n";
1144 check_cooperative_level();
1148 <<
"EndScene failed, unhandled error hr == " << D3DERRORSTRING(hr);
1149 throw_event(
"panda3d-render-error");
1154 #if defined(DO_PSTATS)
1155 if (_texmgrmem_total_pcollector.is_active()) {
1156 #define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval
1157 static DWORD last_tick_count = 0;
1158 DWORD cur_tick_count = GetTickCount();
1160 if (cur_tick_count - last_tick_count > TICKS_PER_GETTEXINFO) {
1161 last_tick_count = cur_tick_count;
1162 report_texmgr_stats();
1185 nassertr(_data_reader !=
nullptr,
false);
1220 const TransformTable *table = data_reader->get_transform_table();
1221 if (table !=
nullptr) {
1224 table->
get_transform(i)->mult_matrix(mat, _internal_transform->get_mat());
1225 const D3DMATRIX *d3d_mat = (
const D3DMATRIX *)mat.get_data();
1226 _d3d_device->SetTransform(D3DTS_WORLDMATRIX(i), d3d_mat);
1231 _transform_stale =
true;
1233 _vertex_blending_enabled =
true;
1237 if (_vertex_blending_enabled) {
1240 _vertex_blending_enabled =
false;
1243 if (_transform_stale && !_data_reader->is_vertex_transformed()) {
1244 const D3DMATRIX *d3d_mat = (
const D3DMATRIX *)_internal_transform->get_mat().get_data();
1245 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
1246 _transform_stale =
false;
1250 if (_data_reader->is_vertex_transformed()) {
1258 _d3d_device->SetTransform(D3DTS_WORLD, &_d3d_ident_mat);
1259 static const LMatrix4f rescale_mat
1264 _transform_stale =
true;
1266 _d3d_device->SetTransform(D3DTS_PROJECTION, (
const D3DMATRIX *)rescale_mat.get_data());
1269 if (_current_shader_context == 0 ) {
1271 if (_vertex_array_shader_context != 0) {
1274 if (!update_standard_vertex_arrays(force)) {
1279 if (_vertex_array_shader_context == 0) {
1280 disable_standard_vertex_arrays();
1285 if (!_current_shader_context->
1286 update_shader_vertex_arrays(_vertex_array_shader_context,
this, force)) {
1292 _vertex_array_shader = _current_shader;
1293 _vertex_array_shader_context = _current_shader_context;
1304 bool DXGraphicsStateGuardian9::
1305 update_standard_vertex_arrays(
bool force) {
1310 int number_of_arrays = _data_reader->get_num_arrays();
1311 for (
int array_index = 0; array_index < number_of_arrays; ++array_index ) {
1313 if ( array_reader ==
nullptr ) {
1314 dxgsg9_cat.error() <<
"Unable to get reader for array " << array_index <<
"\n";
1321 dxgsg9_cat.error() <<
"Unable to setup vertex buffer for array " << array_index <<
"\n";
1327 hr = _d3d_device->SetStreamSource( array_index, dvbc->_vbuffer, 0, array_format->
get_stride() );
1329 dxgsg9_cat.error() <<
"SetStreamSource failed" << D3DERRORSTRING(hr);
1337 hr = _d3d_device->SetFVF( fvf );
1339 dxgsg9_cat.error() <<
"SetFVF failed" << D3DERRORSTRING(hr);
1352 void DXGraphicsStateGuardian9::
1353 disable_standard_vertex_arrays() {
1354 for (
int array_index = 0; array_index < _num_bound_streams; ++array_index )
1356 _d3d_device->SetStreamSource( array_index,
nullptr, 0, 0 );
1358 _num_bound_streams = 0;
1368 _vertices_tri_pcollector.add_level(reader->get_num_vertices());
1369 _primitive_batches_tri_pcollector.add_level(1);
1371 if (reader->is_indexed()) {
1372 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
1373 int max_vertex = reader->get_max_vertex();
1377 nassertr(ibc !=
nullptr,
false);
1382 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
1384 min_vertex, max_vertex - min_vertex + 1,
1385 0, reader->get_num_primitives() );
1389 const unsigned char *index_pointer = reader->get_read_pointer(force);
1390 if (index_pointer ==
nullptr) {
1394 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1395 if (vertex_pointer ==
nullptr) {
1399 draw_indexed_primitive_up( D3DPT_TRIANGLELIST,
1400 min_vertex, max_vertex,
1401 reader->get_num_primitives(),
1402 index_pointer, index_type, vertex_pointer,
1403 _data_reader->get_format()->get_array(0)->get_stride() );
1407 _d3d_device->DrawPrimitive( D3DPT_TRIANGLELIST,
1408 reader->get_first_vertex(),
1409 reader->get_num_primitives() );
1413 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1414 if (vertex_pointer ==
nullptr) {
1418 draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(),
1419 reader->get_first_vertex(),
1420 reader->get_num_vertices(), vertex_pointer,
1421 _data_reader->get_format()->get_array(0)->get_stride());
1435 if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
1438 _vertices_tristrip_pcollector.add_level(reader->get_num_vertices());
1439 _primitive_batches_tristrip_pcollector.add_level(1);
1441 if (reader->is_indexed()) {
1442 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
1443 int max_vertex = reader->get_max_vertex();
1447 nassertr(ibc !=
nullptr,
false);
1452 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP,
1454 min_vertex, max_vertex - min_vertex + 1,
1455 0, reader->get_num_vertices() - 2 );
1459 const unsigned char *index_pointer = reader->get_read_pointer(force);
1460 if (index_pointer ==
nullptr) {
1464 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1465 if (vertex_pointer ==
nullptr) {
1469 draw_indexed_primitive_up
1470 (D3DPT_TRIANGLESTRIP,
1471 min_vertex, max_vertex,
1472 reader->get_num_vertices() - 2,
1473 index_pointer, index_type, vertex_pointer,
1474 _data_reader->get_format()->get_array(0)->get_stride());
1478 _d3d_device->DrawPrimitive( D3DPT_TRIANGLESTRIP,
1479 reader->get_first_vertex(),
1480 reader->get_num_vertices() - 2 );
1484 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1485 if (vertex_pointer ==
nullptr) {
1488 draw_primitive_up(D3DPT_TRIANGLESTRIP,
1489 reader->get_num_vertices() - 2,
1490 reader->get_first_vertex(),
1491 reader->get_num_vertices(), vertex_pointer,
1492 _data_reader->get_format()->get_array(0)->get_stride());
1499 CPTA_int ends = reader->get_ends();
1500 _primitive_batches_tristrip_pcollector.add_level(ends.size());
1502 if (reader->is_indexed()) {
1503 CPTA_int ends = reader->get_ends();
1504 int index_stride = reader->get_index_stride();
1505 _primitive_batches_tristrip_pcollector.add_level(ends.size());
1509 nassertr(reader->get_mins()->get_num_rows() == (
int)ends.size() &&
1510 reader->get_maxs()->get_num_rows() == (
int)ends.size(),
false);
1514 nassertr(ibc !=
nullptr,
false);
1519 unsigned int start = 0;
1520 for (
size_t i = 0; i < ends.size(); i++) {
1521 _vertices_tristrip_pcollector.add_level(ends[i] - start);
1524 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP,
1527 start, ends[i] - start - 2 );
1528 start = ends[i] + 2;
1533 int stride = _data_reader->get_format()->get_array(0)->get_stride();
1534 const unsigned char *index_pointer = reader->get_read_pointer(force);
1535 if (index_pointer ==
nullptr) {
1539 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1540 if (vertex_pointer ==
nullptr) {
1544 unsigned int start = 0;
1545 for (
size_t i = 0; i < ends.size(); i++) {
1546 _vertices_tristrip_pcollector.add_level(ends[i] - start);
1549 draw_indexed_primitive_up
1550 (D3DPT_TRIANGLESTRIP,
1552 ends[i] - start - 2,
1553 index_pointer + start * index_stride, index_type,
1554 vertex_pointer, stride);
1556 start = ends[i] + 2;
1560 unsigned int first_vertex = reader->get_first_vertex();
1563 unsigned int start = 0;
1564 for (
size_t i = 0; i < ends.size(); i++) {
1565 _vertices_tristrip_pcollector.add_level(ends[i] - start);
1566 _d3d_device->DrawPrimitive( D3DPT_TRIANGLESTRIP,
1567 first_vertex + start,
1568 ends[i] - start - 2 );
1569 start = ends[i] + 2;
1574 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1575 if (vertex_pointer ==
nullptr) {
1578 int stride = _data_reader->get_format()->get_array(0)->get_stride();
1580 unsigned int start = 0;
1581 for (
size_t i = 0; i < ends.size(); i++) {
1582 _vertices_tristrip_pcollector.add_level(ends[i] - start);
1583 draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2,
1584 first_vertex + start,
1586 vertex_pointer, stride);
1588 start = ends[i] + 2;
1603 CPTA_int ends = reader->get_ends();
1604 _primitive_batches_trifan_pcollector.add_level(ends.size());
1606 if (reader->is_indexed()) {
1607 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
1608 int max_vertex = reader->get_max_vertex();
1612 int index_stride = reader->get_index_stride();
1616 nassertr(reader->get_mins()->get_num_rows() == (
int)ends.size() &&
1617 reader->get_maxs()->get_num_rows() == (
int)ends.size(),
false);
1621 nassertr(ibc !=
nullptr,
false);
1626 unsigned int start = 0;
1627 for (
size_t i = 0; i < ends.size(); i++) {
1628 _vertices_trifan_pcollector.add_level(ends[i] - start);
1631 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLEFAN,
1634 start, ends[i] - start - 2 );
1640 int stride = _data_reader->get_format()->get_array(0)->get_stride();
1641 const unsigned char *index_pointer = reader->get_read_pointer(force);
1642 if (index_pointer ==
nullptr) {
1646 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1647 if (vertex_pointer ==
nullptr) {
1651 unsigned int start = 0;
1652 for (
size_t i = 0; i < ends.size(); i++) {
1653 _vertices_trifan_pcollector.add_level(ends[i] - start);
1656 draw_indexed_primitive_up
1659 ends[i] - start - 2,
1660 index_pointer + start * index_stride, index_type,
1661 vertex_pointer, stride);
1667 unsigned int first_vertex = reader->get_first_vertex();
1670 unsigned int start = 0;
1671 for (
size_t i = 0; i < ends.size(); i++) {
1672 _vertices_trifan_pcollector.add_level(ends[i] - start);
1673 _d3d_device->DrawPrimitive( D3DPT_TRIANGLEFAN,
1674 first_vertex + start,
1675 ends[i] - start - 2 );
1681 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1682 if (vertex_pointer ==
nullptr) {
1685 int stride = _data_reader->get_format()->get_array(0)->get_stride();
1687 unsigned int start = 0;
1688 for (
size_t i = 0; i < ends.size(); i++) {
1689 _vertices_trifan_pcollector.add_level(ends[i] - start);
1690 draw_primitive_up(D3DPT_TRIANGLEFAN,
1691 ends[i] - start - 2,
1694 vertex_pointer, stride);
1709 _vertices_other_pcollector.add_level(reader->get_num_vertices());
1710 _primitive_batches_other_pcollector.add_level(1);
1712 if (reader->is_indexed()) {
1713 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
1714 int max_vertex = reader->get_max_vertex();
1718 nassertr(ibc !=
nullptr,
false);
1723 _d3d_device->DrawIndexedPrimitive( D3DPT_LINELIST,
1725 min_vertex, max_vertex - min_vertex + 1,
1726 0, reader->get_num_primitives() );
1730 const unsigned char *index_pointer = reader->get_read_pointer(force);
1731 if (index_pointer ==
nullptr) {
1735 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1736 if (vertex_pointer ==
nullptr) {
1740 draw_indexed_primitive_up
1742 min_vertex, max_vertex,
1743 reader->get_num_primitives(),
1744 index_pointer, index_type, vertex_pointer,
1745 _data_reader->get_format()->get_array(0)->get_stride());
1749 _d3d_device->DrawPrimitive( D3DPT_LINELIST,
1750 reader->get_first_vertex(),
1751 reader->get_num_primitives() );
1755 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1756 if (vertex_pointer ==
nullptr) {
1759 draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(),
1760 reader->get_first_vertex(),
1761 reader->get_num_vertices(), vertex_pointer,
1762 _data_reader->get_format()->get_array(0)->get_stride());
1783 _vertices_other_pcollector.add_level(reader->get_num_vertices());
1784 _primitive_batches_other_pcollector.add_level(1);
1788 nassertr(!reader->is_indexed(),
false);
1791 _d3d_device->DrawPrimitive( D3DPT_POINTLIST,
1792 reader->get_first_vertex(),
1793 reader->get_num_primitives() );
1797 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
1798 if (vertex_pointer ==
nullptr) {
1801 draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(),
1802 reader->get_first_vertex(),
1803 reader->get_num_vertices(), vertex_pointer,
1804 _data_reader->get_format()->get_array(0)->get_stride());
1817 if (_vertex_blending_enabled) {
1820 _vertex_blending_enabled =
false;
1823 if (_data_reader->is_vertex_transformed()) {
1825 LMatrix4f mat = LCAST(
float, _projection_mat->get_mat());
1826 _d3d_device->SetTransform(D3DTS_PROJECTION,
1827 (D3DMATRIX*)mat.get_data());
1842 set_read_buffer(rb);
1856 if (tc ==
nullptr) {
1863 <<
"Unable to re-create texture " << *dtc->
get_texture() << endl;
1874 IDirect3DSurface9 *tex_level_0;
1877 dxgsg9_cat.error() <<
"GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
1882 D3DSURFACE_DESC texdesc;
1883 hr = tex_level_0->GetDesc(&texdesc);
1885 dxgsg9_cat.error() <<
"GetDesc failed in copy_texture" << D3DERRORSTRING(hr);
1886 SAFE_RELEASE(tex_level_0);
1893 SAFE_RELEASE(tex_level_0);
1897 <<
"Unable to re-create texture " << *dtc->
get_texture() << endl;
1902 dxgsg9_cat.error() <<
"GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
1905 hr = tex_level_0->GetDesc(&texdesc);
1907 dxgsg9_cat.error() <<
"GetDesc 2 failed in copy_texture" << D3DERRORSTRING(hr);
1908 SAFE_RELEASE(tex_level_0);
1917 <<
"Unable to copy to texture, texture is wrong size: " << *dtc->
get_texture() << endl;
1918 SAFE_RELEASE(tex_level_0);
1923 DWORD render_target_index;
1924 IDirect3DSurface9 *render_target;
1927 render_target_index = 0;
1929 hr = _d3d_device->GetRenderTarget(render_target_index, &render_target);
1932 <<
"GetRenderTarget failed in framebuffer_copy_to_texture"
1933 << D3DERRORSTRING(hr);
1934 SAFE_RELEASE(tex_level_0);
1941 src_rect.right = xo+w;
1943 src_rect.bottom = yo+h;
1949 D3DTEXTUREFILTERTYPE filter;
1951 filter = D3DTEXF_POINT;
1954 hr = _d3d_device->StretchRect(render_target, &src_rect,
1955 tex_level_0, &src_rect,
1959 <<
"StretchRect failed in framebuffer_copy_to_texture"
1960 << D3DERRORSTRING(hr);
1964 SAFE_RELEASE(render_target);
1965 SAFE_RELEASE(tex_level_0);
1969 dtc->
enqueue_lru(&_prepared_objects->_graphics_memory_lru);
2003 set_read_buffer(rb);
2006 nassertr(tex !=
nullptr && dr !=
nullptr,
false);
2015 case Texture::F_depth_stencil:
2020 format = Texture::F_rgb;
2021 component_type = Texture::T_unsigned_byte;
2024 Texture::TextureType texture_type;
2026 texture_type = Texture::TT_cube_map;
2028 texture_type = Texture::TT_2d_texture;
2037 component_type, format);
2042 rect.right = xo + w;
2043 rect.bottom = yo + h;
2044 bool copy_inverted =
false;
2046 IDirect3DSurface9 *temp_surface =
nullptr;
2052 if (_cur_read_pixel_buffer & RenderBuffer::T_back) {
2053 DWORD render_target_index;
2054 IDirect3DSurface9 *backbuffer =
nullptr;
2058 render_target_index = 0;
2059 hr = _d3d_device->GetRenderTarget(render_target_index, &backbuffer);
2062 dxgsg9_cat.error() <<
"GetRenderTarget failed" << D3DERRORSTRING(hr);
2069 D3DSURFACE_DESC surface_description;
2071 backbuffer -> GetDesc (&surface_description);
2073 pool = D3DPOOL_SYSTEMMEM;
2074 hr = _d3d_device->CreateOffscreenPlainSurface(
2075 surface_description.Width,
2076 surface_description.Height,
2077 surface_description.Format,
2083 <<
"CreateImageSurface failed in copy_pixel_buffer()"
2084 << D3DERRORSTRING(hr);
2085 backbuffer->Release();
2090 hr = _d3d_device -> GetRenderTargetData (backbuffer, temp_surface);
2092 dxgsg9_cat.error() <<
"GetRenderTargetData failed" << D3DERRORSTRING(hr);
2093 temp_surface->Release();
2094 backbuffer->Release();
2098 copy_inverted =
true;
2100 RELEASE(backbuffer, dxgsg9,
"backbuffer", RELEASE_ONCE);
2102 }
else if (_cur_read_pixel_buffer & RenderBuffer::T_front) {
2104 if (_screen->_presentation_params.Windowed) {
2111 minfo.cbSize =
sizeof(MONITORINFO);
2112 GetMonitorInfo(_screen->_monitor, &minfo);
2114 w = RECT_XSIZE(minfo.rcMonitor);
2115 h = RECT_YSIZE(minfo.rcMonitor);
2118 ClientToScreen(_screen->_window, (POINT*)&rect.left);
2119 ClientToScreen(_screen->_window, (POINT*)&rect.right);
2124 hr = _d3d_device->CreateOffscreenPlainSurface(w, h, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &temp_surface,
nullptr);
2127 <<
"CreateImageSurface failed in copy_pixel_buffer()"
2128 << D3DERRORSTRING(hr);
2135 hr = _d3d_device->GetFrontBufferData(swap_chain,temp_surface);
2137 if (hr == D3DERR_DEVICELOST) {
2139 <<
"copy_pixel_buffer failed: device lost\n";
2140 temp_surface->Release();
2144 copy_inverted =
true;
2148 <<
"copy_pixel_buffer: unhandled current_read_pixel_buffer type\n";
2149 temp_surface->Release();
2154 copy_inverted = !copy_inverted;
2157 copy_inverted, tex, view, z);
2159 RELEASE(temp_surface, dxgsg9,
"temp_surface", RELEASE_ONCE);
2165 void DXGraphicsStateGuardian9::reset_render_states (
void)
2168 int maximum_texture_stages;
2170 maximum_texture_stages = D3D_MAXTEXTURESTAGES;
2173 memset (_render_state_array, -1,
sizeof (_render_state_array));
2174 memset (_texture_stage_states_array, -1,
sizeof (_texture_stage_states_array));
2178 _render_state_array [D3DRS_FOGCOLOR] = 0;
2179 _render_state_array [D3DRS_AMBIENT] = 0;
2183 memset (_texture_render_states_array, 0,
sizeof (_texture_render_states_array));
2187 for (index = 0; index < MAXIMUM_TEXTURES; index++) {
2188 TextureRenderStates *texture_render_states;
2190 texture_render_states = &_texture_render_states_array [index];
2191 texture_render_states -> state_array [D3DSAMP_MAGFILTER] = D3DTEXF_POINT;
2192 texture_render_states -> state_array [D3DSAMP_MINFILTER] = D3DTEXF_POINT;
2193 texture_render_states -> state_array [D3DSAMP_MAXANISOTROPY] = 1;
2195 _num_active_texture_stages = 0;
2214 _inv_state_mask.clear_bit(ShaderAttrib::get_class_slot());
2215 _inv_state_mask.clear_bit(AlphaTestAttrib::get_class_slot());
2216 _inv_state_mask.clear_bit(ClipPlaneAttrib::get_class_slot());
2217 _inv_state_mask.clear_bit(ColorAttrib::get_class_slot());
2218 _inv_state_mask.clear_bit(ColorScaleAttrib::get_class_slot());
2219 _inv_state_mask.clear_bit(CullFaceAttrib::get_class_slot());
2220 _inv_state_mask.clear_bit(DepthOffsetAttrib::get_class_slot());
2221 _inv_state_mask.clear_bit(DepthTestAttrib::get_class_slot());
2222 _inv_state_mask.clear_bit(DepthWriteAttrib::get_class_slot());
2223 _inv_state_mask.clear_bit(RenderModeAttrib::get_class_slot());
2224 _inv_state_mask.clear_bit(RescaleNormalAttrib::get_class_slot());
2225 _inv_state_mask.clear_bit(ShadeModelAttrib::get_class_slot());
2226 _inv_state_mask.clear_bit(TransparencyAttrib::get_class_slot());
2227 _inv_state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
2228 _inv_state_mask.clear_bit(ColorBlendAttrib::get_class_slot());
2229 _inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
2230 _inv_state_mask.clear_bit(TexGenAttrib::get_class_slot());
2231 _inv_state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
2232 _inv_state_mask.clear_bit(MaterialAttrib::get_class_slot());
2233 _inv_state_mask.clear_bit(LightAttrib::get_class_slot());
2234 _inv_state_mask.clear_bit(StencilAttrib::get_class_slot());
2235 _inv_state_mask.clear_bit(FogAttrib::get_class_slot());
2236 _inv_state_mask.clear_bit(ScissorAttrib::get_class_slot());
2241 _supported_geom_rendering =
2242 Geom::GR_point | Geom::GR_point_uniform_size |
2243 Geom::GR_point_perspective | Geom::GR_point_sprite |
2244 Geom::GR_indexed_other |
2245 Geom::GR_triangle_strip | Geom::GR_triangle_fan |
2246 Geom::GR_flat_first_vertex |
2247 Geom::GR_render_mode_wireframe | Geom::GR_render_mode_point;
2258 nassertv(_screen->_d3d9 !=
nullptr);
2260 if (_d3d_device ==
nullptr) {
2265 _d3d_device->GetDeviceCaps(&d3d_caps);
2267 _vertex_shader_version_major = D3DSHADER_VERSION_MAJOR (d3d_caps.VertexShaderVersion);
2268 _vertex_shader_version_minor = D3DSHADER_VERSION_MINOR (d3d_caps.VertexShaderVersion);
2269 _pixel_shader_version_major = D3DSHADER_VERSION_MAJOR (d3d_caps.PixelShaderVersion);
2270 _pixel_shader_version_minor = D3DSHADER_VERSION_MINOR (d3d_caps.PixelShaderVersion);
2272 _supports_hlsl = (_pixel_shader_version_major != 0);
2274 _vertex_shader_profile = (
char *) D3DXGetVertexShaderProfile (_d3d_device);
2275 _pixel_shader_profile = (
char *) D3DXGetPixelShaderProfile (_d3d_device);
2277 _vertex_shader_maximum_constants = d3d_caps.MaxVertexShaderConst;
2279 switch (_pixel_shader_version_major)
2282 _shader_model = SM_00;
2285 _shader_model = SM_11;
2289 _shader_model = SM_20;
2290 if (d3d_caps.PS20Caps.NumInstructionSlots >= 512) {
2291 _shader_model = SM_2X;
2295 _shader_model = SM_30;
2298 _shader_model = SM_40;
2302 _shader_model = SM_50;
2306 _auto_detect_shader_model = _shader_model;
2311 _cg_context = cgCreateContext();
2313 if (cgD3D9IsProfileSupported(CG_PROFILE_PS_2_0) &&
2314 cgD3D9IsProfileSupported(CG_PROFILE_VS_2_0)) {
2315 _supports_basic_shaders =
true;
2316 _shader_caps._active_vprofile = (int)cgD3D9GetLatestVertexProfile();
2317 _shader_caps._active_fprofile = (int)cgD3D9GetLatestPixelProfile();
2318 _shader_caps._ultimate_vprofile = (int)CG_PROFILE_VS_3_0;
2319 _shader_caps._ultimate_fprofile = (int)CG_PROFILE_PS_3_0;
2328 if (dxgsg9_cat.is_debug()) {
2329 CGprofile vertex_profile;
2330 CGprofile pixel_profile;
2332 vertex_profile = cgD3D9GetLatestVertexProfile();
2333 pixel_profile = cgD3D9GetLatestPixelProfile();
2335 const char *vertex_profile_str =
2336 cgGetProfileString(vertex_profile);
2337 const char *pixel_profile_str =
2338 cgGetProfileString(pixel_profile);
2340 if (vertex_profile_str ==
nullptr) {
2341 vertex_profile_str =
"(null)";
2343 if (pixel_profile_str ==
nullptr) {
2344 pixel_profile_str =
"(null)";
2348 <<
"\nCg latest vertex profile = " << vertex_profile_str <<
" id = " << vertex_profile
2349 <<
"\nCg latest pixel profile = " << pixel_profile_str <<
" id = " << pixel_profile
2350 <<
"\nshader model = " << _shader_model
2355 _supports_stream_offset = (d3d_caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET) != 0;
2356 _screen->_supports_dynamic_textures = ((d3d_caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0);
2357 _screen->_supports_automatic_mipmap_generation = ((d3d_caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0);
2359 if (support_stencil) {
2360 int min_stencil = D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR;
2361 if ((d3d_caps.StencilCaps & min_stencil) == min_stencil) {
2362 if (dxgsg9_cat.is_debug()) {
2364 <<
"Checking for stencil; mode = "
2365 << D3DFormatStr(_screen->_presentation_params.AutoDepthStencilFormat)
2368 switch (_screen->_presentation_params.AutoDepthStencilFormat) {
2372 case D3DFMT_D24X4S4:
2373 _supports_stencil =
true;
2374 if (dxgsg9_cat.is_debug()) {
2376 <<
"Stencils supported.\n";
2381 if (dxgsg9_cat.is_debug()) {
2383 <<
"Stencils NOT supported.\n";
2389 _supports_stencil_wrap = (d3d_caps.StencilCaps & D3DSTENCILCAPS_INCR) && (d3d_caps.StencilCaps & D3DSTENCILCAPS_DECR);
2390 _supports_two_sided_stencil = ((d3d_caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0);
2392 _max_color_targets = d3d_caps.NumSimultaneousRTs;
2394 _supports_depth_bias = ((d3d_caps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)) == (D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS));
2396 _supports_gamma_calibration = ((d3d_caps.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA) != 0);
2399 hr = _d3d_device->CreateQuery(D3DQUERYTYPE_OCCLUSION,
nullptr);
2400 _supports_occlusion_query = !FAILED(hr);
2402 if (dxgsg9_cat.is_error()) {
2404 <<
"\nHwTransformAndLight = " << ((d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
2405 <<
"\nMaxTextureWidth = " << d3d_caps.MaxTextureWidth
2406 <<
"\nMaxTextureHeight = " << d3d_caps.MaxTextureHeight
2407 <<
"\nMaxVolumeExtent = " << d3d_caps.MaxVolumeExtent
2408 <<
"\nMaxTextureAspectRatio = " << d3d_caps.MaxTextureAspectRatio
2409 <<
"\nTexCoordCount = " << (d3d_caps.FVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK)
2410 <<
"\nMaxTextureBlendStages = " << d3d_caps.MaxTextureBlendStages
2411 <<
"\nMaxSimultaneousTextures = " << d3d_caps.MaxSimultaneousTextures
2412 <<
"\nMaxActiveLights = " << d3d_caps.MaxActiveLights
2413 <<
"\nMaxUserClipPlanes = " << d3d_caps.MaxUserClipPlanes
2414 <<
"\nMaxVertexBlendMatrices = " << d3d_caps.MaxVertexBlendMatrices
2415 <<
"\nMaxVertexBlendMatrixIndex = " << d3d_caps.MaxVertexBlendMatrixIndex
2416 <<
"\nMaxPointSize = " << d3d_caps.MaxPointSize
2417 <<
"\nMaxPrimitiveCount = " << d3d_caps.MaxPrimitiveCount
2418 <<
"\nMaxVertexIndex = " << d3d_caps.MaxVertexIndex
2419 <<
"\nMaxStreams = " << d3d_caps.MaxStreams
2420 <<
"\nMaxStreamStride = " << d3d_caps.MaxStreamStride
2421 <<
"\nD3DTEXOPCAPS_MULTIPLYADD = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) != 0)
2422 <<
"\nD3DTEXOPCAPS_LERP = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0)
2423 <<
"\nD3DPMISCCAPS_TSSARGTEMP = " << ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0)
2424 <<
"\nD3DPRASTERCAPS_DEPTHBIAS = " << ((d3d_caps.RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) != 0)
2425 <<
"\nD3DPRASTERCAPS_SLOPESCALEDEPTHBIAS = " << ((d3d_caps.RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) != 0)
2426 <<
"\nVertexShaderVersion = " << _vertex_shader_version_major <<
"." << _vertex_shader_version_minor
2427 <<
"\nPixelShaderVersion = " << _pixel_shader_version_major <<
"." << _pixel_shader_version_minor
2428 <<
"\nMaxVertexShaderConst = " << _vertex_shader_maximum_constants
2429 <<
"\nsupports_stream_offset = " << _supports_stream_offset
2430 <<
"\nsupports_dynamic_textures = " << _screen->_supports_dynamic_textures
2431 <<
"\nsupports_automatic_mipmap_generation = " << _screen->_supports_automatic_mipmap_generation
2432 <<
"\nsupports_stencil_wrap = " << _supports_stencil_wrap
2433 <<
"\nsupports_two_sided_stencil = " << _supports_two_sided_stencil
2434 <<
"\nsupports_occlusion_query = " << _supports_occlusion_query
2435 <<
"\nsupports_gamma_calibration = " << _supports_gamma_calibration
2436 <<
"\nMaxAnisotropy = " << d3d_caps.MaxAnisotropy
2437 <<
"\nNumSimultaneousRTs = " << d3d_caps.NumSimultaneousRTs
2438 <<
"\nD3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING = " << ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) != 0)
2439 <<
"\nDirectX SDK version " DIRECTX_SDK_VERSION
2444 _screen->_supports_automatic_mipmap_generation =
false;
2446 reset_render_states();
2448 _max_vertices_per_array = d3d_caps.MaxVertexIndex;
2449 _max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount;
2451 _max_texture_stages = d3d_caps.MaxSimultaneousTextures;
2453 _max_texture_dimension = min(d3d_caps.MaxTextureWidth, d3d_caps.MaxTextureHeight);
2455 _supports_tex_non_pow2 = !(d3d_caps.TextureCaps & D3DPTEXTURECAPS_POW2);
2457 _supports_texture_combine = ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0);
2458 _supports_texture_saved_result = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0);
2459 _supports_texture_constant_color = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_PERSTAGECONSTANT) != 0);
2460 _supports_texture_dot3 =
true;
2462 if (_supports_texture_constant_color) {
2463 _constant_color_operand = D3DTA_CONSTANT;
2465 _constant_color_operand = D3DTA_TFACTOR;
2468 _screen->_managed_textures = _gsg_managed_textures;
2469 _screen->_managed_vertex_buffers = _gsg_managed_vertex_buffers;
2470 _screen->_managed_index_buffers = _gsg_managed_index_buffers;
2472 UINT available_texture_memory;
2474 available_texture_memory = _d3d_device->GetAvailableTextureMem ( );
2475 if (dxgsg9_cat.is_debug()) {
2476 dxgsg9_cat.debug() <<
"*** GetAvailableTextureMem = " << available_texture_memory <<
"\n";
2478 _available_texture_memory = available_texture_memory;
2481 D3DDEVICE_CREATION_PARAMETERS creation_parameters;
2483 _supports_render_texture =
false;
2484 _screen->_render_to_texture_d3d_format = D3DFMT_UNKNOWN;
2485 _screen->_framebuffer_d3d_format = D3DFMT_UNKNOWN;
2487 #define TOTAL_RENDER_TO_TEXTURE_FORMATS 3
2489 D3DFORMAT render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS] =
2496 render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS - 1] = _screen->_display_mode.Format;
2498 hr = _d3d_device->GetCreationParameters (&creation_parameters);
2499 if (SUCCEEDED (hr)) {
2500 _screen->_framebuffer_d3d_format = _screen->_display_mode.Format;
2503 for (index = 0; index < TOTAL_RENDER_TO_TEXTURE_FORMATS; index++) {
2504 hr = _screen->_d3d9->CheckDeviceFormat (
2505 creation_parameters.AdapterOrdinal,
2506 creation_parameters.DeviceType,
2507 _screen->_display_mode.Format,
2508 D3DUSAGE_RENDERTARGET,
2510 render_to_texture_formats [index]);
2511 if (SUCCEEDED (hr)) {
2512 _screen->_render_to_texture_d3d_format = render_to_texture_formats [index];
2513 _supports_render_texture =
true;
2515 if (_supports_render_texture) {
2520 if (dxgsg9_cat.is_debug()) {
2521 dxgsg9_cat.debug() <<
"Render to Texture Support = " << _supports_render_texture <<
"\n";
2527 _supports_3d_texture = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) != 0);
2528 if (_supports_3d_texture) {
2529 _max_3d_texture_dimension = d3d_caps.MaxVolumeExtent;
2531 _supports_cube_map = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) != 0);
2532 if (_supports_cube_map) {
2533 _max_cube_map_dimension = _max_texture_dimension;
2536 _max_lights = (int)d3d_caps.MaxActiveLights;
2537 _max_clip_planes = (
int)d3d_caps.MaxUserClipPlanes;
2538 _max_vertex_transforms = d3d_caps.MaxVertexBlendMatrices;
2539 _max_vertex_transform_indices = d3d_caps.MaxVertexBlendMatrixIndex;
2543 _clip_plane_bits = 0;
2561 _has_scene_graph_color =
false;
2563 _last_testcooplevel_result = D3D_OK;
2565 if (dxgsg9_cat.is_debug()) {
2566 dxgsg9_cat.debug() <<
"Supported texture formats:\n";
2569 for(
int i = 0; i < MAX_POSSIBLE_TEXFMTS; i++) {
2571 D3DFORMAT_FLAG fmtflag = D3DFORMAT_FLAG(1 << i);
2572 hr = _screen->_d3d9->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format,
2573 0x0, D3DRTYPE_TEXTURE, g_D3DFORMATmap[fmtflag]);
2574 if (SUCCEEDED(hr)) {
2575 if (dxgsg9_cat.is_debug()) {
2576 dxgsg9_cat.debug() <<
" " << D3DFormatStr(g_D3DFORMATmap[fmtflag]) <<
"\n";
2578 _screen->_supported_tex_formats_mask |= fmtflag;
2582 _supports_depth_stencil = ((_screen->_supported_tex_formats_mask & D24S8_FLAG) != 0);
2583 _supports_depth_texture = _supports_depth_stencil ||
2584 (_screen->_supported_tex_formats_mask & D16_FLAG) != 0 ||
2585 (_screen->_supported_tex_formats_mask & D32_FLAG) != 0 ||
2586 (_screen->_supported_tex_formats_mask & D24X8_FLAG) != 0;
2592 _supports_shadow_filter = _supports_depth_texture;
2595 #define CHECK_COMPRESSED_FMT(mode, fmt) \
2596 if (_screen->_supported_tex_formats_mask & fmt##_FLAG) {\
2597 if (dxgsg9_cat.is_debug()) {\
2598 dxgsg9_cat.debug() << "Compressed texture format " << #fmt << " supported\n";\
2600 _supports_compressed_texture = true;\
2601 _compressed_texture_formats.set_bit(Texture::mode);\
2604 if (_screen->_intel_compressed_texture_bug) {
2606 <<
"Buggy Intel driver detected; disabling compressed textures.\n";
2607 _screen->_supported_tex_formats_mask &=
2608 ~(DXT1_FLAG | DXT2_FLAG | DXT3_FLAG | DXT4_FLAG | DXT5_FLAG);
2612 CHECK_COMPRESSED_FMT(CM_dxt1, DXT1);
2613 CHECK_COMPRESSED_FMT(CM_dxt2, DXT2);
2614 CHECK_COMPRESSED_FMT(CM_dxt3, DXT3);
2615 CHECK_COMPRESSED_FMT(CM_dxt4, DXT4);
2616 CHECK_COMPRESSED_FMT(CM_dxt5, DXT5);
2617 CHECK_COMPRESSED_FMT(CM_rgtc, ATI1);
2618 CHECK_COMPRESSED_FMT(CM_rgtc, ATI2);
2621 #undef CHECK_COMPRESSED_FMT
2623 _screen->_supports_rgba16f_texture_format =
false;
2624 hr = _screen->_d3d9->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format, 0x0, D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F);
2626 _screen->_supports_rgba16f_texture_format =
true;
2628 _screen->_supports_rgba32_texture_format =
false;
2629 hr = _screen->_d3d9->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format, 0x0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F);
2631 _screen->_supports_rgba32_texture_format =
true;
2635 if (_screen->_d3dcaps.MaxTextureWidth == 0)
2636 _screen->_d3dcaps.MaxTextureWidth = 256;
2638 if (_screen->_d3dcaps.MaxTextureHeight == 0)
2639 _screen->_d3dcaps.MaxTextureHeight = 256;
2641 if (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) {
2645 _do_fog_type = PerPixelFog;
2649 nassertv((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0);
2654 if (dx_no_vertex_fog) {
2655 _do_fog_type = None;
2657 _do_fog_type = PerVertexFog;
2660 if (dx_use_rangebased_fog && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)) {
2666 _screen->_can_direct_disable_color_writes = ((_screen->_d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0);
2672 bool dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(_screen->_presentation_params.BackBufferFormat)
2673 && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER));
2680 if (_supports_two_sided_stencil) {
2688 _current_fill_mode = RenderModeAttrib::M_filled;
2695 _cull_face_mode = CullFaceAttrib::M_cull_none;
2708 _current_shader =
nullptr;
2709 _current_shader_context =
nullptr;
2710 _vertex_array_shader =
nullptr;
2711 _vertex_array_shader_context =
nullptr;
2712 _texture_binding_shader =
nullptr;
2713 _texture_binding_shader_context =
nullptr;
2715 PRINT_REFCNT(dxgsg9, _d3d_device);
2725 void DXGraphicsStateGuardian9::
2726 apply_fog(
Fog *fog) {
2727 if (_do_fog_type == None)
2730 Fog::Mode panda_fogmode = fog->get_mode();
2731 D3DFOGMODE d3dfogmode = get_fog_mode_type(panda_fogmode);
2735 const LColor &fog_colr = fog->
get_color();
2737 MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f));
2743 switch (panda_fogmode) {
2746 PN_stdfloat onset, opaque;
2750 *((LPDWORD) (&onset)));
2752 *((LPDWORD) (&opaque)));
2755 case Fog::M_exponential:
2756 case Fog::M_exponential_squared:
2761 *((LPDWORD) (&fog_density)));
2774 void DXGraphicsStateGuardian9::
2775 do_issue_transform() {
2777 DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1));
2779 if (_current_shader_context) {
2785 LMatrix4f mat = LCAST(
float, transform->
get_mat());
2786 const D3DMATRIX *d3d_mat = (
const D3DMATRIX *)mat.get_data();
2787 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
2791 LMatrix4f mat = LCAST(
float, transform->
get_mat());
2792 const D3DMATRIX *d3d_mat = (
const D3DMATRIX *)mat.get_data();
2793 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
2808 _transform_stale =
false;
2814 void DXGraphicsStateGuardian9::
2815 do_issue_alpha_test() {
2816 if (_target_shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
2820 AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->
get_mode();
2821 if (mode == AlphaTestAttrib::M_none) {
2835 void DXGraphicsStateGuardian9::
2840 if (_target_shader) {
2841 shader = (
Shader *)(_target_shader->get_shader());
2847 if (context == 0 || (context && context -> valid (
this) ==
false)) {
2848 if (_current_shader_context != 0) {
2849 _current_shader_context->
unbind(
this);
2850 _current_shader = 0;
2851 _current_shader_context = 0;
2852 disable_standard_texture_bindings();
2857 if (context != _current_shader_context) {
2860 if (_current_shader_context != 0) {
2861 _current_shader_context->
unbind(
this);
2862 _current_shader_context = 0;
2863 _current_shader = 0;
2864 disable_standard_texture_bindings();
2867 context->
bind(
this);
2868 _current_shader = shader;
2869 _current_shader_context = context;
2880 void DXGraphicsStateGuardian9::
2881 do_issue_render_mode() {
2883 _target_rs->get_attrib_def(target_render_mode);
2884 RenderModeAttrib::Mode mode = target_render_mode->
get_mode();
2887 case RenderModeAttrib::M_unchanged:
2888 case RenderModeAttrib::M_filled:
2889 case RenderModeAttrib::M_filled_flat:
2893 case RenderModeAttrib::M_wireframe:
2897 case RenderModeAttrib::M_point:
2903 <<
"Unknown render mode " << (int)mode << endl;
2907 PN_stdfloat point_size = target_render_mode->
get_thickness();
2913 LVector3 height(0.0f, point_size, 1.0f);
2914 height = height * _projection_mat->get_mat();
2915 PN_stdfloat s = height[1] / point_size;
2917 PN_stdfloat zero = 0.0f;
2918 PN_stdfloat one_over_s2 = 1.0f / (s * s);
2927 _current_fill_mode = mode;
2933 void DXGraphicsStateGuardian9::
2934 do_issue_rescale_normal() {
2935 RescaleNormalAttrib::Mode mode = RescaleNormalAttrib::M_none;
2938 if (_target_rs->get_attrib(target_rescale_normal)) {
2939 mode = target_rescale_normal->
get_mode();
2943 case RescaleNormalAttrib::M_none:
2947 case RescaleNormalAttrib::M_rescale:
2948 case RescaleNormalAttrib::M_normalize:
2954 <<
"Unknown rescale_normal mode " << (int)mode << endl;
2961 void DXGraphicsStateGuardian9::
2962 do_issue_depth_test() {
2964 DepthTestAttrib::PandaCompareFunc mode = target_depth_test->
get_mode();
2965 if (mode == DepthTestAttrib::M_none) {
2976 void DXGraphicsStateGuardian9::
2977 do_issue_depth_write() {
2979 DepthWriteAttrib::Mode mode = target_depth_write->
get_mode();
2980 if (mode == DepthWriteAttrib::M_on) {
2990 void DXGraphicsStateGuardian9::
2991 do_issue_cull_face() {
2995 switch (_cull_face_mode) {
2996 case CullFaceAttrib::M_cull_none:
3002 case CullFaceAttrib::M_cull_clockwise:
3008 case CullFaceAttrib::M_cull_counter_clockwise:
3016 <<
"invalid cull face mode " << (int)_cull_face_mode << endl;
3024 void DXGraphicsStateGuardian9::
3026 const FogAttrib *target_fog = DCAST(
FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
3027 if (!target_fog->
is_off()) {
3030 nassertv(fog !=
nullptr);
3040 void DXGraphicsStateGuardian9::
3041 do_issue_depth_offset() {
3043 int offset = target_depth_offset->
get_offset();
3045 if (_supports_depth_bias && !dx_broken_depth_bias) {
3052 static const PN_stdfloat bias_scale = dx_depth_bias_scale;
3053 D3DVIEWPORT9 vp = _current_viewport;
3054 vp.MinZ -= bias_scale * offset;
3055 vp.MaxZ -= bias_scale * offset;
3056 _d3d_device->SetViewport(&vp);
3063 void DXGraphicsStateGuardian9::
3064 do_issue_shade_model() {
3066 switch (target_shade_model->
get_mode()) {
3067 case ShadeModelAttrib::M_smooth:
3071 case ShadeModelAttrib::M_flat:
3093 if (gsg_cat.is_spam()) {
3094 gsg_cat.spam() <<
"Setting GSG state to " << (
void *)target <<
":\n";
3095 target->write(gsg_cat.spam(
false), 2);
3098 _state_pcollector.add_level(1);
3099 PStatTimer timer1(_draw_set_state_pcollector);
3101 if (transform != _internal_transform) {
3103 _state_pcollector.add_level(1);
3104 _internal_transform = transform;
3105 do_issue_transform();
3108 if (target == _state_rs && (_state_mask | _inv_state_mask).is_all_on()) {
3111 _target_rs = target;
3113 determine_target_shader();
3115 int alpha_test_slot = AlphaTestAttrib::get_class_slot();
3116 if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
3117 !_state_mask.get_bit(alpha_test_slot)) {
3119 do_issue_alpha_test();
3120 _state_mask.set_bit(alpha_test_slot);
3123 int clip_plane_slot = ClipPlaneAttrib::get_class_slot();
3124 if (_target_rs->get_attrib(clip_plane_slot) != _state_rs->get_attrib(clip_plane_slot) ||
3125 !_state_mask.get_bit(clip_plane_slot)) {
3127 do_issue_clip_plane();
3128 _state_mask.set_bit(clip_plane_slot);
3131 int color_slot = ColorAttrib::get_class_slot();
3132 int color_scale_slot = ColorScaleAttrib::get_class_slot();
3133 if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
3134 _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
3135 !_state_mask.get_bit(color_slot) ||
3136 !_state_mask.get_bit(color_scale_slot)) {
3139 do_issue_color_scale();
3140 _state_mask.set_bit(color_slot);
3141 _state_mask.set_bit(color_scale_slot);
3142 if (_current_shader_context) {
3148 int cull_face_slot = CullFaceAttrib::get_class_slot();
3149 if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
3150 !_state_mask.get_bit(cull_face_slot)) {
3152 do_issue_cull_face();
3153 _state_mask.set_bit(cull_face_slot);
3156 int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
3157 if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
3158 !_state_mask.get_bit(depth_offset_slot)) {
3160 do_issue_depth_offset();
3161 _state_mask.set_bit(depth_offset_slot);
3164 int depth_test_slot = DepthTestAttrib::get_class_slot();
3165 if (_target_rs->get_attrib(depth_test_slot) != _state_rs->get_attrib(depth_test_slot) ||
3166 !_state_mask.get_bit(depth_test_slot)) {
3168 do_issue_depth_test();
3169 _state_mask.set_bit(depth_test_slot);
3172 int depth_write_slot = DepthWriteAttrib::get_class_slot();
3173 if (_target_rs->get_attrib(depth_write_slot) != _state_rs->get_attrib(depth_write_slot) ||
3174 !_state_mask.get_bit(depth_write_slot)) {
3176 do_issue_depth_write();
3177 _state_mask.set_bit(depth_write_slot);
3180 int render_mode_slot = RenderModeAttrib::get_class_slot();
3181 if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
3182 !_state_mask.get_bit(render_mode_slot)) {
3184 do_issue_render_mode();
3185 _state_mask.set_bit(render_mode_slot);
3188 int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
3189 if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
3190 !_state_mask.get_bit(rescale_normal_slot)) {
3192 do_issue_rescale_normal();
3193 _state_mask.set_bit(rescale_normal_slot);
3196 int shade_model_slot = ShadeModelAttrib::get_class_slot();
3197 if (_target_rs->get_attrib(shade_model_slot) != _state_rs->get_attrib(shade_model_slot) ||
3198 !_state_mask.get_bit(shade_model_slot)) {
3200 do_issue_shade_model();
3201 _state_mask.set_bit(shade_model_slot);
3204 int transparency_slot = TransparencyAttrib::get_class_slot();
3205 int color_write_slot = ColorWriteAttrib::get_class_slot();
3206 int color_blend_slot = ColorBlendAttrib::get_class_slot();
3207 if (_target_rs->get_attrib(transparency_slot) != _state_rs->get_attrib(transparency_slot) ||
3208 _target_rs->get_attrib(color_write_slot) != _state_rs->get_attrib(color_write_slot) ||
3209 _target_rs->get_attrib(color_blend_slot) != _state_rs->get_attrib(color_blend_slot) ||
3210 !_state_mask.get_bit(transparency_slot) ||
3211 !_state_mask.get_bit(color_write_slot) ||
3212 !_state_mask.get_bit(color_blend_slot) ||
3213 (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
3214 _state_shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
3216 do_issue_blending();
3217 _state_mask.set_bit(transparency_slot);
3218 _state_mask.set_bit(color_write_slot);
3219 _state_mask.set_bit(color_blend_slot);
3222 if (_target_shader != _state_shader) {
3225 _state_shader = _target_shader;
3226 _state_mask.clear_bit(TextureAttrib::get_class_slot());
3229 int texture_slot = TextureAttrib::get_class_slot();
3230 int tex_matrix_slot = TexMatrixAttrib::get_class_slot();
3231 int tex_gen_slot = TexGenAttrib::get_class_slot();
3232 if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
3233 _target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) ||
3234 _target_rs->get_attrib(tex_gen_slot) != _state_rs->get_attrib(tex_gen_slot) ||
3235 !_state_mask.get_bit(texture_slot) ||
3236 !_state_mask.get_bit(tex_matrix_slot) ||
3237 !_state_mask.get_bit(tex_gen_slot)) {
3239 determine_target_texture();
3242 _state_texture = _target_texture;
3243 _state_mask.set_bit(texture_slot);
3244 _state_mask.set_bit(tex_matrix_slot);
3245 _state_mask.set_bit(tex_gen_slot);
3248 int material_slot = MaterialAttrib::get_class_slot();
3249 if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
3250 !_state_mask.get_bit(material_slot)) {
3252 do_issue_material();
3253 _state_mask.set_bit(material_slot);
3254 if (_current_shader_context) {
3259 int light_slot = LightAttrib::get_class_slot();
3260 if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
3261 !_state_mask.get_bit(light_slot)) {
3264 _state_mask.set_bit(light_slot);
3267 int stencil_slot = StencilAttrib::get_class_slot();
3268 if (_target_rs->get_attrib(stencil_slot) != _state_rs->get_attrib(stencil_slot) ||
3269 !_state_mask.get_bit(stencil_slot)) {
3272 _state_mask.set_bit(stencil_slot);
3275 int fog_slot = FogAttrib::get_class_slot();
3276 if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) ||
3277 !_state_mask.get_bit(fog_slot)) {
3280 _state_mask.set_bit(fog_slot);
3281 if (_current_shader_context) {
3286 int scissor_slot = ScissorAttrib::get_class_slot();
3287 if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
3288 !_state_mask.get_bit(scissor_slot)) {
3291 _state_mask.set_bit(scissor_slot);
3294 _state_rs = _target_rs;
3308 const LMatrix4 &light_mat = transform->
get_mat();
3309 LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
3310 LPoint3f pos = LCAST(
float, light_obj->
get_point() * rel_mat);
3312 D3DCOLORVALUE black;
3313 black.r = black.g = black.b = black.a = 0.0f;
3315 alight.Type = D3DLIGHT_POINT;
3316 alight.Diffuse = get_light_color(light_obj);
3317 alight.Ambient = black ;
3319 alight.Specular = *(D3DCOLORVALUE *)(color.get_data());
3323 alight.Position = *(D3DVECTOR *)pos.get_data();
3325 alight.Range = __D3DLIGHT_RANGE_MAX;
3326 alight.Falloff = 1.0f;
3329 alight.Attenuation0 = att[0];
3330 alight.Attenuation1 = att[1];
3331 alight.Attenuation2 = att[2];
3333 HRESULT hr = _d3d_device->SetLight(light_id, &alight);
3335 wdxdisplay9_cat.warning()
3336 <<
"Could not set light properties for " << light
3337 <<
" to id " << light_id <<
": " << D3DERRORSTRING(hr) <<
"\n";
3348 static PStatCollector _draw_set_state_light_bind_directional_pcollector(
"Draw:Set State:Light:Bind:Directional");
3351 std::pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT9()));
3352 D3DLIGHT9 &fdata = (*lookup.first).second;
3353 if (lookup.second) {
3358 const LMatrix4 &light_mat = transform->
get_mat();
3359 LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
3360 LVector3f dir = LCAST(
float, light_obj->
get_direction() * rel_mat);
3362 D3DCOLORVALUE black;
3363 black.r = black.g = black.b = black.a = 0.0f;
3365 ZeroMemory(&fdata,
sizeof(D3DLIGHT9));
3367 fdata.Type = D3DLIGHT_DIRECTIONAL;
3368 fdata.Ambient = black ;
3370 fdata.Specular = *(D3DCOLORVALUE *)(color.get_data());
3372 fdata.Direction = *(D3DVECTOR *)dir.get_data();
3374 fdata.Range = __D3DLIGHT_RANGE_MAX;
3375 fdata.Falloff = 1.0f;
3377 fdata.Attenuation0 = 1.0f;
3378 fdata.Attenuation1 = 0.0f;
3379 fdata.Attenuation2 = 0.0f;
3385 fdata.Diffuse = get_light_color(light_obj);
3387 HRESULT hr = _d3d_device->SetLight(light_id, &fdata);
3389 wdxdisplay9_cat.warning()
3390 <<
"Could not set light properties for " << light
3391 <<
" to id " << light_id <<
": " << D3DERRORSTRING(hr) <<
"\n";
3403 nassertv(lens !=
nullptr);
3409 const LMatrix4 &light_mat = transform->
get_mat();
3410 LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
3414 D3DCOLORVALUE black;
3415 black.r = black.g = black.b = black.a = 0.0f;
3418 ZeroMemory(&alight,
sizeof(D3DLIGHT9));
3420 alight.Type = D3DLIGHT_SPOT;
3421 alight.Ambient = black ;
3422 alight.Diffuse = get_light_color(light_obj);
3424 alight.Specular = *(D3DCOLORVALUE *)(color.get_data());
3426 alight.Position = *(D3DVECTOR *)pos.get_data();
3428 alight.Direction = *(D3DVECTOR *)dir.get_data();
3430 alight.Range = __D3DLIGHT_RANGE_MAX;
3434 PN_stdfloat fov = lens->
get_hfov();
3435 alight.Falloff = light_obj->
get_exponent() * (fov * fov * fov) / 1620000.0f;
3437 alight.Theta = 0.0f;
3438 alight.Phi = deg_2_rad(fov);
3441 alight.Attenuation0 = att[0];
3442 alight.Attenuation1 = att[1];
3443 alight.Attenuation2 = att[2];
3445 HRESULT hr = _d3d_device->SetLight(light_id, &alight);
3447 wdxdisplay9_cat.warning()
3448 <<
"Could not set light properties for " << light
3449 <<
" to id " << light_id <<
": " << D3DERRORSTRING(hr) <<
"\n";
3458 switch (numeric_type) {
3460 case Geom::NT_uint8:
3461 case Geom::NT_uint16:
3462 return D3DFMT_INDEX16;
3464 case Geom::NT_uint32:
3465 return D3DFMT_INDEX32;
3469 <<
"Invalid index NumericType value (" << (int)numeric_type <<
")\n";
3470 return D3DFMT_INDEX16;
3476 void DXGraphicsStateGuardian9::
3477 do_issue_material() {
3481 if (target_material->
is_off()) {
3487 D3DMATERIAL9 cur_material;
3488 LColorf color = LCAST(
float, material->
get_diffuse());
3489 cur_material.Diffuse = *(D3DCOLORVALUE *)(color.get_data());
3491 cur_material.Ambient = *(D3DCOLORVALUE *)(color.get_data());
3493 cur_material.Specular = *(D3DCOLORVALUE *)(color.get_data());
3495 cur_material.Emissive = *(D3DCOLORVALUE *)(color.get_data());
3503 if (_has_material_force_color) {
3504 color = LCAST(
float, _material_force_color);
3505 cur_material.Diffuse = *(D3DCOLORVALUE *)color.get_data();
3516 if (_has_material_force_color) {
3517 color = LCAST(
float, _material_force_color);
3518 cur_material.Ambient = *(D3DCOLORVALUE *)color.get_data();
3537 _d3d_device->SetMaterial(&cur_material);
3543 void DXGraphicsStateGuardian9::
3544 do_issue_texture() {
3545 DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
3547 if (_texture_binding_shader_context==0) {
3548 if (_current_shader_context==0) {
3549 update_standard_texture_bindings();
3551 disable_standard_texture_bindings();
3555 if (_current_shader_context==0) {
3557 update_standard_texture_bindings();
3559 _current_shader_context->
3560 update_shader_texture_bindings(_texture_binding_shader_context,
this);
3563 _texture_binding_shader = _current_shader;
3564 _texture_binding_shader_context = _current_shader_context;
3570 void DXGraphicsStateGuardian9::
3571 disable_standard_texture_bindings() {
3573 for (
int i = 0; i < _num_active_texture_stages; i++) {
3576 hr = _d3d_device -> SetTexture (i,
nullptr);
3581 <<
", NULL) failed "
3582 << D3DERRORSTRING(hr);
3587 _num_active_texture_stages = 0;
3593 void DXGraphicsStateGuardian9::
3594 update_standard_texture_bindings() {
3595 DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
3597 int num_stages = _target_texture->get_num_on_ff_stages();
3598 int num_old_stages = _max_texture_stages;
3599 if (_state_texture !=
nullptr) {
3600 num_old_stages = _state_texture->get_num_on_ff_stages();
3603 nassertv(num_stages <= _max_texture_stages &&
3604 _num_active_texture_stages <= _max_texture_stages);
3606 _texture_involves_color_scale =
false;
3613 for (si = 0; si < num_stages; si++) {
3614 TextureStage *stage = _target_texture->get_on_ff_stage(si);
3615 int texcoord_index = _target_texture->get_ff_tc_index(si);
3617 Texture *texture = _target_texture->get_on_texture(stage);
3618 nassertv(texture !=
nullptr);
3619 const SamplerState &sampler = _target_texture->get_on_sampler(stage);
3626 set_texture_blend_mode(si, stage);
3628 int texcoord_dimensions = 2;
3632 if (target_tex_matrix->has_stage(stage)) {
3633 tex_mat = target_tex_matrix->get_transform(stage);
3637 TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage);
3638 bool any_point_sprite =
false;
3641 case TexGenAttrib::M_off:
3642 case TexGenAttrib::M_unused2:
3646 case TexGenAttrib::M_eye_sphere_map:
3649 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
3654 TransformState::make_mat(LMatrix4(0.33, 0.0f, 0.0f, 0.0f,
3655 0.0f, 0.33, 0.0f, 0.0f,
3656 0.0f, 0.0f, 1.0f, 0.0f,
3657 0.5f, 0.5f, 0.0f, 1.0f));
3658 tex_mat = tex_mat->compose(sphere_map);
3659 texcoord_dimensions = 3;
3663 case TexGenAttrib::M_world_cube_map:
3670 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
3671 texcoord_dimensions = 3;
3672 CPT(
TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
3673 tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3::zero()));
3677 case TexGenAttrib::M_eye_cube_map:
3679 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
3680 tex_mat = tex_mat->compose(_inv_cs_transform);
3681 texcoord_dimensions = 3;
3684 case TexGenAttrib::M_world_normal:
3690 texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
3691 texcoord_dimensions = 3;
3692 CPT(
TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
3693 tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3::zero()));
3697 case TexGenAttrib::M_eye_normal:
3699 texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
3700 texcoord_dimensions = 3;
3701 tex_mat = tex_mat->compose(_inv_cs_transform);
3704 case TexGenAttrib::M_world_position:
3709 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
3710 texcoord_dimensions = 3;
3711 CPT(
TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
3712 tex_mat = tex_mat->compose(camera_transform);
3716 case TexGenAttrib::M_eye_position:
3718 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
3719 texcoord_dimensions = 3;
3720 tex_mat = tex_mat->compose(_inv_cs_transform);
3723 case TexGenAttrib::M_point_sprite:
3725 any_point_sprite =
true;
3728 case TexGenAttrib::M_constant:
3741 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
3742 texcoord_dimensions = 3;
3744 const LTexCoord3 &v = _target_tex_gen->get_constant_value(stage);
3746 TransformState::make_pos_hpr_scale(v, LVecBase3::zero(),
3748 tex_mat = tex_mat->compose(squash);
3755 if (!tex_mat->is_identity()) {
3756 if ( texcoord_dimensions <= 2) {
3758 LMatrix4 m = tex_mat->get_mat();
3760 mf.set(m(0, 0), m(0, 1), m(0, 3), 0.0f,
3761 m(1, 0), m(1, 1), m(1, 3), 0.0f,
3762 m(3, 0), m(3, 1), m(3, 3), 0.0f,
3763 0.0f, 0.0f, 0.0f, 1.0f);
3764 _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)mf.get_data());
3768 LMatrix4f mf = LCAST(
float, tex_mat->get_mat());
3769 _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)mf.get_data());
3770 DWORD transform_flags = texcoord_dimensions;
3771 if (mf.get_col(3) != LVecBase4f(0.0f, 0.0f, 0.0f, 1.0f)) {
3774 transform_flags = D3DTTFF_COUNT4 | D3DTTFF_PROJECTED;
3786 _d3d_device->SetTransform(get_tex_mat_sym(si), &_d3d_ident_mat);
3791 for (si = num_stages; si < _num_active_texture_stages; si++) {
3793 _d3d_device->SetTexture(si,
nullptr);
3797 _num_active_texture_stages = num_stages;
3805 void DXGraphicsStateGuardian9::
3806 do_issue_blending() {
3811 unsigned int color_channels =
3812 target_color_write->
get_channels() & _color_write_mask;
3813 if (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
3814 color_channels &= ~(ColorWriteAttrib::C_alpha);
3816 if (color_channels == ColorWriteAttrib::C_off) {
3817 if (_screen->_can_direct_disable_color_writes) {
3827 if (_screen->_can_direct_disable_color_writes) {
3833 _target_rs->get_attrib_def(color_blend);
3834 ColorBlendAttrib::Mode color_blend_mode = color_blend->
get_mode();
3837 _target_rs->get_attrib_def(target_transparency);
3838 TransparencyAttrib::Mode transparency_mode = target_transparency->
get_mode();
3841 if (color_blend_mode != ColorBlendAttrib::M_none) {
3854 switch (transparency_mode) {
3855 case TransparencyAttrib::M_none:
3856 case TransparencyAttrib::M_binary:
3859 case TransparencyAttrib::M_alpha:
3860 case TransparencyAttrib::M_multisample:
3861 case TransparencyAttrib::M_multisample_mask:
3862 case TransparencyAttrib::M_dual:
3864 if (old_alpha_blend) {
3877 case TransparencyAttrib::M_premultiplied_alpha:
3887 <<
"invalid transparency mode " << (int)transparency_mode << endl;
3900 void DXGraphicsStateGuardian9::
3901 reissue_transforms() {
3903 do_issue_transform();
3911 void DXGraphicsStateGuardian9::
3912 enable_lighting(
bool enable) {
3921 void DXGraphicsStateGuardian9::
3922 set_ambient_light(
const LColor &color) {
3924 c.set(c[0] * _light_color_scale[0],
3925 c[1] * _light_color_scale[1],
3926 c[2] * _light_color_scale[2],
3927 c[3] * _light_color_scale[3]);
3937 void DXGraphicsStateGuardian9::
3938 enable_light(
int light_id,
bool enable) {
3939 HRESULT hr = _d3d_device->LightEnable(light_id, enable);
3942 wdxdisplay9_cat.warning()
3943 <<
"Could not enable light " << light_id <<
": "
3944 << D3DERRORSTRING(hr) <<
"\n";
3953 void DXGraphicsStateGuardian9::
3954 enable_clip_plane(
int plane_id,
bool enable) {
3956 _clip_plane_bits |= ((DWORD)1 << plane_id);
3958 _clip_plane_bits &= ~((DWORD)1 << plane_id);
3968 void DXGraphicsStateGuardian9::
3969 bind_clip_plane(
const NodePath &plane,
int plane_id) {
3974 const LMatrix4 &plane_mat = transform->
get_mat();
3975 LMatrix4 rel_mat = plane_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
3977 DCAST_INTO_V(plane_node, plane.
node());
3978 LPlanef world_plane = LCAST(
float, plane_node->
get_plane() * rel_mat);
3980 HRESULT hr = _d3d_device->SetClipPlane(plane_id, world_plane.get_data());
3982 wdxdisplay9_cat.warning()
3983 <<
"Could not set clip plane for " << plane
3984 <<
" to id " << plane_id <<
": " << D3DERRORSTRING(hr) <<
"\n";
3993 void DXGraphicsStateGuardian9::
3995 GraphicsStateGuardian::close_gsg();
3997 if (_prepared_objects.is_null()) {
4001 if (dxgsg9_cat.is_debug()) {
4003 <<
"Closing GSG, prepared_objects count = "
4004 << _prepared_objects->get_ref_count() <<
"\n";
4009 if (_prepared_objects->get_ref_count() == 1) {
4014 _prepared_objects->begin_frame(
this, current_thread);
4015 _prepared_objects->end_frame(current_thread);
4022 void DXGraphicsStateGuardian9::
4023 free_nondx_resources() {
4026 cgDestroyContext(_cg_context);
4036 void DXGraphicsStateGuardian9::
4039 _state_rs = RenderState::make_empty();
4040 _state_mask.clear();
4044 _dx_is_ready =
false;
4046 if (_d3d_device !=
nullptr) {
4047 for(
int i = 0; i < D3D_MAXTEXTURESTAGES; i++) {
4049 _d3d_device->SetTexture(i,
nullptr);
4055 if (_d3d_device !=
nullptr) {
4056 RELEASE(_d3d_device, dxgsg9,
"d3dDevice", RELEASE_DOWN_TO_ZERO);
4059 free_nondx_resources();
4069 void DXGraphicsStateGuardian9::
4071 dxgsg9_cat.fatal() <<
"DX set_draw_buffer unimplemented!!!";
4078 void DXGraphicsStateGuardian9::
4080 if (rb._buffer_type & RenderBuffer::T_front) {
4081 _cur_read_pixel_buffer = RenderBuffer::T_front;
4082 }
else if (rb._buffer_type & RenderBuffer::T_back) {
4083 _cur_read_pixel_buffer = RenderBuffer::T_back;
4084 }
else if (rb._buffer_type & RenderBuffer::T_aux_rgba_ALL) {
4085 _cur_read_pixel_buffer = RenderBuffer::T_back;
4087 dxgsg9_cat.error() <<
"Invalid or unimplemented Argument to set_read_buffer!\n";
4097 const D3DCOLORVALUE &DXGraphicsStateGuardian9::
4098 get_light_color(
Light *light)
const {
4101 cf.set(c[0] * _light_color_scale[0],
4102 c[1] * _light_color_scale[1],
4103 c[2] * _light_color_scale[2],
4104 c[3] * _light_color_scale[3]);
4105 return *(D3DCOLORVALUE *)cf.get_data();
4111 D3DBLENDOP DXGraphicsStateGuardian9::
4112 get_blend_mode(ColorBlendAttrib::Mode mode) {
4114 case ColorBlendAttrib::M_add:
4115 return D3DBLENDOP_ADD;
4117 case ColorBlendAttrib::M_subtract:
4118 return D3DBLENDOP_SUBTRACT;
4120 case ColorBlendAttrib::M_inv_subtract:
4121 return D3DBLENDOP_REVSUBTRACT;
4123 case ColorBlendAttrib::M_min:
4124 return D3DBLENDOP_MIN;
4126 case ColorBlendAttrib::M_max:
4127 return D3DBLENDOP_MAX;
4131 <<
"Unknown color blend mode " << (int)mode << endl;
4132 return D3DBLENDOP_ADD;
4138 D3DBLEND DXGraphicsStateGuardian9::
4139 get_blend_func(ColorBlendAttrib::Operand operand) {
4141 case ColorBlendAttrib::O_zero:
4142 return D3DBLEND_ZERO;
4144 case ColorBlendAttrib::O_one:
4145 return D3DBLEND_ONE;
4147 case ColorBlendAttrib::O_incoming_color:
4148 return D3DBLEND_SRCCOLOR;
4150 case ColorBlendAttrib::O_one_minus_incoming_color:
4151 return D3DBLEND_INVSRCCOLOR;
4153 case ColorBlendAttrib::O_fbuffer_color:
4154 return D3DBLEND_DESTCOLOR;
4156 case ColorBlendAttrib::O_one_minus_fbuffer_color:
4157 return D3DBLEND_INVDESTCOLOR;
4159 case ColorBlendAttrib::O_incoming_alpha:
4160 return D3DBLEND_SRCALPHA;
4162 case ColorBlendAttrib::O_one_minus_incoming_alpha:
4163 return D3DBLEND_INVSRCALPHA;
4165 case ColorBlendAttrib::O_fbuffer_alpha:
4166 return D3DBLEND_DESTALPHA;
4168 case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
4169 return D3DBLEND_INVDESTALPHA;
4171 case ColorBlendAttrib::O_constant_color:
4173 return D3DBLEND_SRCCOLOR;
4175 case ColorBlendAttrib::O_one_minus_constant_color:
4177 return D3DBLEND_INVSRCCOLOR;
4179 case ColorBlendAttrib::O_constant_alpha:
4181 return D3DBLEND_SRCALPHA;
4183 case ColorBlendAttrib::O_one_minus_constant_alpha:
4185 return D3DBLEND_INVSRCALPHA;
4187 case ColorBlendAttrib::O_incoming_color_saturate:
4188 return D3DBLEND_SRCALPHASAT;
4190 case ColorBlendAttrib::O_incoming1_color:
4191 return (D3DBLEND)16;
4193 case ColorBlendAttrib::O_one_minus_incoming1_color:
4194 return (D3DBLEND)17;
4196 case ColorBlendAttrib::O_incoming1_alpha:
4198 return (D3DBLEND)18;
4200 case ColorBlendAttrib::O_one_minus_incoming1_alpha:
4202 return (D3DBLEND)19;
4206 <<
"Unknown color blend operand " << (int)operand << endl;
4207 return D3DBLEND_ZERO;
4213 void DXGraphicsStateGuardian9::
4214 report_texmgr_stats() {
4220 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
4221 DWORD dwTexTotal, dwTexFree, dwVidTotal, dwVidFree;
4223 if (_total_texmem_pcollector.is_active()) {
4226 ZeroMemory(&ddsCaps,
sizeof(ddsCaps));
4228 ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
4229 if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwVidTotal, &dwVidFree))) {
4230 dxgsg9_cat.fatal() <<
"report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << D3DERRORSTRING(hr);
4231 throw_event(
"panda3d-render-error");
4235 ddsCaps.dwCaps = DDSCAPS_TEXTURE;
4236 if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwTexTotal, &dwTexFree))) {
4237 dxgsg9_cat.fatal() <<
"report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << D3DERRORSTRING(hr);
4238 throw_event(
"panda3d-render-error");
4242 #endif // TEXMGRSTATS_USES_GETAVAILVIDMEM
4244 D3DDEVINFO_RESOURCEMANAGER all_resource_stats;
4245 ZeroMemory(&all_resource_stats,
sizeof(D3DDEVINFO_RESOURCEMANAGER));
4272 if (_texmgrmem_total_pcollector.is_active()) {
4274 _texmgrmem_total_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].TotalBytes);
4275 _texmgrmem_resident_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].WorkingSetBytes);
4277 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
4278 if (_total_texmem_pcollector.is_active()) {
4279 _total_texmem_pcollector.set_level(dwTexTotal);
4280 _used_texmem_pcollector.set_level(dwTexTotal - dwTexFree);
4282 #endif // TEXMGRSTATS_USES_GETAVAILVIDMEM
4289 void DXGraphicsStateGuardian9::
4291 nassertv(new_context !=
nullptr);
4292 _screen = new_context;
4293 _d3d_device = _screen->_d3d_device;
4294 _swap_chain = _screen->_swap_chain;
4296 _screen->_dxgsg9 =
this;
4303 void DXGraphicsStateGuardian9::
4304 set_render_target() {
4305 if (_d3d_device ==
nullptr) {
4309 LPDIRECT3DSURFACE9 back =
nullptr, stencil =
nullptr;
4317 _d3d_device->GetBackBuffer(swap_chain, 0, D3DBACKBUFFER_TYPE_MONO, &back);
4319 _swap_chain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back);
4324 _d3d_device->GetDepthStencilSurface(&stencil);
4327 DWORD render_target_index;
4328 render_target_index = 0;
4329 _d3d_device->SetRenderTarget(render_target_index, back);
4342 void DXGraphicsStateGuardian9::
4343 set_texture_blend_mode(
int i,
const TextureStage *stage) {
4345 case TextureStage::M_modulate:
4346 case TextureStage::M_modulate_glow:
4347 case TextureStage::M_modulate_gloss:
4357 case TextureStage::M_decal:
4367 case TextureStage::M_replace:
4375 case TextureStage::M_add:
4385 case TextureStage::M_blend:
4386 case TextureStage::M_blend_color_scale:
4399 case TextureStage::M_combine:
4410 (i, D3DTSS_COLORARG0,
4417 (i, D3DTSS_COLORARG2,
4424 (i, D3DTSS_COLORARG1,
4441 (i, D3DTSS_ALPHAARG0,
4448 (i, D3DTSS_ALPHAARG2,
4455 (i, D3DTSS_ALPHAARG1,
4467 <<
"Unknown texture mode " << (int)stage->
get_mode() << endl;
4480 D3DCOLOR constant_color;
4483 color.set(color[0] * _current_color_scale[0],
4484 color[1] * _current_color_scale[1],
4485 color[2] * _current_color_scale[2],
4486 color[3] * _current_color_scale[3]);
4487 _texture_involves_color_scale =
true;
4492 if (_supports_texture_constant_color) {
4506 void DXGraphicsStateGuardian9::
4512 free_nondx_resources();
4513 PRINT_REFCNT(dxgsg9, _d3d_device);
4517 RELEASE(_d3d_device, dxgsg9,
"d3dDevice", RELEASE_DOWN_TO_ZERO);
4518 _screen->_d3d_device =
nullptr;
4530 HRESULT DXGraphicsStateGuardian9::
4531 reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
4535 nassertr(IS_VALID_PTR(presentation_params), E_FAIL);
4536 nassertr(IS_VALID_PTR(_screen->_d3d9), E_FAIL);
4537 nassertr(IS_VALID_PTR(_d3d_device), E_FAIL);
4541 _screen->_d3d9->GetAdapterDisplayMode(_screen->_card_id, &_screen->_display_mode);
4542 presentation_params->BackBufferFormat = _screen->_display_mode.Format;
4549 if (
true || !(_screen->_swap_chain)
4550 || (_presentation_reset.BackBufferWidth < presentation_params->BackBufferWidth)
4551 || (_presentation_reset.BackBufferHeight < presentation_params->BackBufferHeight)) {
4552 if (wdxdisplay9_cat.is_debug()) {
4553 wdxdisplay9_cat.debug()
4554 <<
"swap_chain = " << _screen->_swap_chain <<
" _presentation_reset = "
4555 << _presentation_reset.BackBufferWidth <<
"x" << _presentation_reset.BackBufferHeight
4556 <<
" presentation_params = "
4557 << presentation_params->BackBufferWidth <<
"x" << presentation_params->BackBufferHeight <<
"\n";
4562 if (_screen->_swap_chain) {
4563 _presentation_reset.BackBufferWidth = max(_presentation_reset.BackBufferWidth, presentation_params->BackBufferWidth);
4564 _presentation_reset.BackBufferHeight = max(_presentation_reset.BackBufferHeight, presentation_params->BackBufferHeight);
4567 _presentation_reset.BackBufferWidth = presentation_params->BackBufferWidth;
4568 _presentation_reset.BackBufferHeight = presentation_params->BackBufferHeight;
4580 if (_white_vbuffer !=
nullptr) {
4581 _white_vbuffer->Release();
4582 _white_vbuffer =
nullptr;
4587 _prepared_objects->begin_frame(
this, current_thread);
4592 std::list <wdxGraphicsBuffer9 **>::iterator graphics_buffer_iterator;
4594 for (graphics_buffer_iterator = _graphics_buffer_list.begin( ); graphics_buffer_iterator != _graphics_buffer_list.end( ); graphics_buffer_iterator++)
4596 graphics_buffer = **graphics_buffer_iterator;
4597 if (graphics_buffer -> _color_backing_store)
4599 graphics_buffer -> _color_backing_store -> Release ( );
4600 graphics_buffer -> _color_backing_store = 0;
4602 if (graphics_buffer -> _depth_backing_store)
4604 graphics_buffer -> _depth_backing_store -> Release ( );
4605 graphics_buffer -> _depth_backing_store = 0;
4611 hr = _d3d_device->Reset(&_presentation_reset);
4612 if (FAILED(hr) && hr != D3DERR_DEVICELOST) {
4621 if (presentation_params != &_screen->_presentation_params) {
4622 memcpy(&_screen->_presentation_params, presentation_params,
sizeof(D3DPRESENT_PARAMETERS));
4629 if (_screen && _screen->_swap_chain) {
4630 _screen->_swap_chain->Release();
4631 wdxdisplay9_cat.debug()
4632 <<
"swap chain " << _screen->_swap_chain <<
" is released\n";
4633 _screen->_swap_chain =
nullptr;
4634 hr = _d3d_device->CreateAdditionalSwapChain(presentation_params, &_screen->_swap_chain);
4636 if (SUCCEEDED(hr)) {
4637 if (presentation_params != &_screen->_presentation_params) {
4638 memcpy(&_screen->_presentation_params, presentation_params,
sizeof(D3DPRESENT_PARAMETERS));
4650 bool DXGraphicsStateGuardian9::
4651 check_cooperative_level() {
4652 bool bDoReactivateWindow =
false;
4653 if (_d3d_device ==
nullptr) {
4657 HRESULT hr = _d3d_device->TestCooperativeLevel();
4659 if (SUCCEEDED(hr)) {
4660 nassertr(SUCCEEDED(_last_testcooplevel_result),
false);
4665 case D3DERR_DEVICENOTRESET:
4666 _dx_is_ready =
false;
4671 hr = reset_d3d_device(&_screen->_presentation_params);
4676 <<
"check_cooperative_level Reset() failed, hr = " << D3DERRORSTRING(hr);
4679 hr = _d3d_device->TestCooperativeLevel();
4683 <<
"TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr);
4687 _dx_is_ready = TRUE;
4690 case D3DERR_DEVICELOST:
4694 if (SUCCEEDED(_last_testcooplevel_result)) {
4696 _dx_is_ready =
false;
4697 if (dxgsg9_cat.is_debug()) {
4698 dxgsg9_cat.debug() <<
"D3D Device was Lost, waiting...\n";
4704 _last_testcooplevel_result = hr;
4705 return SUCCEEDED(hr);
4711 void DXGraphicsStateGuardian9::
4713 if (_d3d_device ==
nullptr) {
4723 hr = _swap_chain->Present(
nullptr,
nullptr, (HWND)
nullptr,
nullptr, flags);
4725 hr = _d3d_device->Present(
nullptr,
nullptr, (HWND)
nullptr,
nullptr);
4729 if (hr == D3DERR_DEVICELOST) {
4730 check_cooperative_level();
4733 <<
"show_frame() - Present() failed" << D3DERRORSTRING(hr);
4734 throw_event(
"panda3d-render-error");
4742 bool DXGraphicsStateGuardian9::
4750 hr = new_context->_d3d_device->CreateAdditionalSwapChain(&new_context->_presentation_params, &new_context->_swap_chain);
4752 wdxdisplay9_cat.debug() <<
"Swapchain creation failed :"<<D3DERRORSTRING(hr)<<
"\n";
4761 bool DXGraphicsStateGuardian9::
4764 if (new_context->_swap_chain) {
4765 hr = new_context->_swap_chain->Release();
4767 wdxdisplay9_cat.debug() <<
"Swapchain release failed:" << D3DERRORSTRING(hr) <<
"\n";
4777 void DXGraphicsStateGuardian9::
4779 memcpy(&_presentation_reset, &_screen->_presentation_params,
sizeof(D3DPRESENT_PARAMETERS));
4785 D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian9::
4786 get_d3d_min_type(SamplerState::FilterType filter_type) {
4787 switch (filter_type) {
4788 case SamplerState::FT_nearest:
4789 return D3DTEXF_POINT;
4791 case SamplerState::FT_linear:
4792 return D3DTEXF_LINEAR;
4794 case SamplerState::FT_nearest_mipmap_nearest:
4795 return D3DTEXF_POINT;
4797 case SamplerState::FT_linear_mipmap_nearest:
4798 return D3DTEXF_LINEAR;
4800 case SamplerState::FT_nearest_mipmap_linear:
4801 return D3DTEXF_POINT;
4803 case SamplerState::FT_linear_mipmap_linear:
4804 return D3DTEXF_LINEAR;
4806 case SamplerState::FT_shadow:
4807 case SamplerState::FT_default:
4808 return D3DTEXF_LINEAR;
4812 <<
"Invalid FilterType value (" << (int)filter_type <<
")\n";
4813 return D3DTEXF_POINT;
4819 D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian9::
4820 get_d3d_mip_type(SamplerState::FilterType filter_type) {
4821 switch (filter_type) {
4822 case SamplerState::FT_nearest:
4823 return D3DTEXF_NONE;
4825 case SamplerState::FT_linear:
4826 return D3DTEXF_NONE;
4828 case SamplerState::FT_nearest_mipmap_nearest:
4829 return D3DTEXF_POINT;
4831 case SamplerState::FT_linear_mipmap_nearest:
4832 return D3DTEXF_POINT;
4834 case SamplerState::FT_nearest_mipmap_linear:
4835 return D3DTEXF_LINEAR;
4837 case SamplerState::FT_linear_mipmap_linear:
4838 return D3DTEXF_LINEAR;
4840 case SamplerState::FT_shadow:
4841 case SamplerState::FT_default:
4842 return D3DTEXF_NONE;
4846 <<
"Invalid FilterType value (" << (int)filter_type <<
")\n";
4847 return D3DTEXF_NONE;
4854 D3DTEXTUREOP DXGraphicsStateGuardian9::
4855 get_texture_operation(TextureStage::CombineMode mode,
int scale) {
4857 case TextureStage::CM_undefined:
4858 case TextureStage::CM_replace:
4859 return D3DTOP_SELECTARG1;
4861 case TextureStage::CM_modulate:
4863 return D3DTOP_MODULATE;
4864 }
else if (scale < 4) {
4865 return D3DTOP_MODULATE2X;
4867 return D3DTOP_MODULATE4X;
4870 case TextureStage::CM_add:
4873 case TextureStage::CM_add_signed:
4875 return D3DTOP_ADDSIGNED;
4877 return D3DTOP_ADDSIGNED2X;
4880 case TextureStage::CM_interpolate:
4883 case TextureStage::CM_subtract:
4884 return D3DTOP_SUBTRACT;
4886 case TextureStage::CM_dot3_rgb:
4887 case TextureStage::CM_dot3_rgba:
4888 return D3DTOP_DOTPRODUCT3;
4892 <<
"Invalid TextureStage::CombineMode value (" << (int)mode <<
")\n";
4893 return D3DTOP_DISABLE;
4901 DWORD DXGraphicsStateGuardian9::
4902 get_texture_argument(TextureStage::CombineSource source,
4903 TextureStage::CombineOperand operand)
const {
4905 case TextureStage::CS_undefined:
4906 case TextureStage::CS_texture:
4907 return D3DTA_TEXTURE | get_texture_argument_modifier(operand);
4909 case TextureStage::CS_constant:
4910 case TextureStage::CS_constant_color_scale:
4911 return _constant_color_operand | get_texture_argument_modifier(operand);
4913 case TextureStage::CS_primary_color:
4914 return D3DTA_DIFFUSE | get_texture_argument_modifier(operand);
4916 case TextureStage::CS_previous:
4917 return D3DTA_CURRENT | get_texture_argument_modifier(operand);
4919 case TextureStage::CS_last_saved_result:
4920 return D3DTA_TEMP | get_texture_argument_modifier(operand);
4923 <<
"Invalid TextureStage::CombineSource value (" << (int)source <<
")\n";
4924 return D3DTA_CURRENT;
4931 DWORD DXGraphicsStateGuardian9::
4932 get_texture_argument_modifier(TextureStage::CombineOperand operand) {
4934 case TextureStage::CO_src_color:
4937 case TextureStage::CO_one_minus_src_color:
4938 return D3DTA_COMPLEMENT;
4940 case TextureStage::CO_src_alpha:
4941 return D3DTA_ALPHAREPLICATE;
4943 case TextureStage::CO_one_minus_src_alpha:
4944 return D3DTA_ALPHAREPLICATE | D3DTA_COMPLEMENT;
4946 case TextureStage::CO_undefined:
4950 <<
"Invalid TextureStage::CombineOperand value (" << (int)operand <<
")\n";
4959 void DXGraphicsStateGuardian9::
4960 draw_primitive_up(D3DPRIMITIVETYPE primitive_type,
4961 unsigned int primitive_count,
4962 unsigned int first_vertex,
4963 unsigned int num_vertices,
4964 const unsigned char *buffer,
size_t stride) {
4971 const unsigned char *buffer_start = buffer + stride * first_vertex;
4972 const unsigned char *buffer_end = buffer_start + stride * num_vertices;
4974 if (buffer_end - buffer_start > 0x10000) {
4977 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
4978 buffer_start, stride);
4980 }
else if ((((uintptr_t)buffer_end ^ (uintptr_t)buffer_start) & ~0xffff) == 0) {
4982 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
4983 buffer_start, stride);
4988 unsigned char *safe_buffer_start = get_safe_buffer_start();
4989 memcpy(safe_buffer_start, buffer_start, buffer_end - buffer_start);
4990 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
4991 safe_buffer_start, stride);
5003 void DXGraphicsStateGuardian9::
5004 draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type,
5005 unsigned int min_index,
unsigned int max_index,
5006 unsigned int num_primitives,
5007 const unsigned char *index_data,
5008 D3DFORMAT index_type,
5009 const unsigned char *buffer,
size_t stride) {
5012 const unsigned char *buffer_start = buffer + stride * min_index;
5013 const unsigned char *buffer_end = buffer + stride * (max_index + 1);
5015 if (buffer_end - buffer_start > 0x10000) {
5018 _d3d_device->DrawIndexedPrimitiveUP
5019 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
5020 index_data, index_type, buffer, stride);
5022 }
else if ((((uintptr_t)buffer_end ^ (uintptr_t)buffer_start) & ~0xffff) == 0) {
5024 _d3d_device->DrawIndexedPrimitiveUP
5025 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
5026 index_data, index_type, buffer, stride);
5031 unsigned char *safe_buffer_start = get_safe_buffer_start();
5032 memcpy(safe_buffer_start, buffer_start, buffer_end - buffer_start);
5033 _d3d_device->DrawIndexedPrimitiveUP
5034 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
5035 index_data, index_type, safe_buffer_start - stride * min_index, stride);
5058 case D3DERR_OUTOFVIDEOMEMORY:
5062 size_t current_size = _prepared_objects->_graphics_memory_lru.get_total_size();
5063 size_t target_size = max(current_size - allocation_size * attempts, (
size_t) 0);
5064 _prepared_objects->_graphics_memory_lru.evict_to(target_size);
5066 <<
"Evicted " << current_size - _prepared_objects->_graphics_memory_lru.get_total_size() <<
" bytes of texture memory to make room for more.\n";
5067 if (_prepared_objects->_graphics_memory_lru.get_total_size() < current_size) {
5082 static int dx_stencil_comparison_function_array[] = {
5089 D3DCMP_GREATEREQUAL,
5093 static int dx_stencil_operation_array[] = {
5096 D3DSTENCILOP_REPLACE,
5099 D3DSTENCILOP_INVERT,
5101 D3DSTENCILOP_INCRSAT,
5102 D3DSTENCILOP_DECRSAT,
5108 void DXGraphicsStateGuardian9::
5109 do_issue_stencil() {
5110 if (!_supports_stencil) {
5116 if (stencil !=
nullptr) {
5119 dxgsg9_cat.debug() <<
"STENCIL STATE CHANGE\n";
5120 dxgsg9_cat.debug() <<
"\n"
5121 <<
"SRS_front_comparison_function " << stencil->
get_render_state(StencilAttrib::SRS_front_comparison_function) <<
"\n"
5122 <<
"SRS_front_stencil_fail_operation " << stencil->
get_render_state(StencilAttrib::SRS_front_stencil_fail_operation) <<
"\n"
5123 <<
"SRS_front_stencil_pass_z_fail_operation " << stencil->
get_render_state(StencilAttrib::SRS_front_stencil_pass_z_fail_operation) <<
"\n"
5124 <<
"SRS_front_stencil_pass_z_pass_operation " << stencil->
get_render_state(StencilAttrib::SRS_front_stencil_pass_z_pass_operation) <<
"\n"
5125 <<
"SRS_reference " << stencil->
get_render_state(StencilAttrib::SRS_reference) <<
"\n"
5126 <<
"SRS_read_mask " << stencil->
get_render_state(StencilAttrib::SRS_read_mask) <<
"\n"
5127 <<
"SRS_write_mask " << stencil->
get_render_state(StencilAttrib::SRS_write_mask) <<
"\n"
5128 <<
"SRS_back_comparison_function " << stencil->
get_render_state(StencilAttrib::SRS_back_comparison_function) <<
"\n"
5129 <<
"SRS_back_stencil_fail_operation " << stencil->
get_render_state(StencilAttrib::SRS_back_stencil_fail_operation) <<
"\n"
5130 <<
"SRS_back_stencil_pass_z_fail_operation " << stencil->
get_render_state(StencilAttrib::SRS_back_stencil_pass_z_fail_operation) <<
"\n"
5131 <<
"SRS_back_stencil_pass_z_pass_operation " << stencil->
get_render_state(StencilAttrib::SRS_back_stencil_pass_z_pass_operation) <<
"\n";
5136 unsigned int front_compare;
5137 front_compare = stencil->
get_render_state(StencilAttrib::SRS_front_comparison_function);
5139 if (front_compare != RenderAttrib::M_none) {
5141 set_render_state(D3DRS_STENCILFUNC, dx_stencil_comparison_function_array[front_compare]);
5143 stencil->
get_render_state(StencilAttrib::SRS_front_stencil_fail_operation)]);
5145 stencil->
get_render_state(StencilAttrib::SRS_front_stencil_pass_z_fail_operation)]);
5147 stencil->
get_render_state(StencilAttrib::SRS_front_stencil_pass_z_pass_operation)]);
5153 if (_supports_two_sided_stencil) {
5154 unsigned int back_compare;
5155 back_compare = stencil->
get_render_state(StencilAttrib::SRS_back_comparison_function);
5157 if (back_compare != RenderAttrib::M_none) {
5159 set_render_state(D3DRS_CCW_STENCILFUNC, dx_stencil_comparison_function_array[back_compare]);
5161 stencil->
get_render_state(StencilAttrib::SRS_back_stencil_fail_operation)]);
5163 stencil->
get_render_state(StencilAttrib::SRS_back_stencil_pass_z_fail_operation)]);
5165 stencil->
get_render_state(StencilAttrib::SRS_back_stencil_pass_z_pass_operation)]);
5179 _d3d_device->Clear(0,
nullptr, D3DCLEAR_STENCIL, 0, 0.0f, stencil->
get_render_state(StencilAttrib::SRS_clear_value));
5185 dxgsg9_cat.debug() <<
"STENCIL STATE CHANGE TO OFF\n";
5189 if (_supports_two_sided_stencil) {
5198 void DXGraphicsStateGuardian9::
5199 do_issue_scissor() {
5201 const LVecBase4 &frame = target_scissor->
get_frame();
5204 r.left = _current_viewport.X + _current_viewport.Width * frame[0];
5205 r.top = _current_viewport.Y + _current_viewport.Height * (1.0f - frame[3]);
5206 r.right = _current_viewport.X + _current_viewport.Width * frame[1];
5207 r.bottom = _current_viewport.Y + _current_viewport.Height * (1.0f - frame[2]);
5208 _d3d_device->SetScissorRect(&r);
5218 DWORD multisampletype, DWORD multisamplequality) {
5221 int r=0, g=0, b=0, a=0;
5223 case D3DFMT_R8G8B8: r=8; g=8; b=8; a=0;
break;
5224 case D3DFMT_A8R8G8B8: r=8; g=8; b=8; a=8;
break;
5225 case D3DFMT_X8R8G8B8: r=8; g=8; b=8; a=0;
break;
5226 case D3DFMT_R5G6B5: r=5; g=6; b=5; a=0;
break;
5227 case D3DFMT_X1R5G5B5: r=5; g=5; b=5; a=0;
break;
5228 case D3DFMT_A1R5G5B5: r=5; g=5; b=5; a=1;
break;
5229 case D3DFMT_A4R4G4B4: r=4; g=4; b=4; a=4;
break;
5230 case D3DFMT_R3G3B2: r=3; g=3; b=2; a=0;
break;
5231 case D3DFMT_A8R3G3B2: r=3; g=3; b=2; a=8;
break;
5232 case D3DFMT_X4R4G4B4: r=4; g=4; b=4; a=0;
break;
5233 case D3DFMT_A2B10G10R10: r=10;g=10;b=10;a=2;
break;
5234 case D3DFMT_A8P8: index=8; a=8;
break;
5235 case D3DFMT_P8: index=8; a=0;
break;
5239 props.set_rgb_color(0);
5240 props.set_indexed_color(1);
5242 }
else if (r + g + b > 0) {
5243 props.set_rgb_color(1);
5244 props.set_indexed_color(0);
5247 props.set_alpha_bits(a);
5252 case D3DFMT_D32: depth=32; stencil=0;
break;
5253 case D3DFMT_D15S1: depth=15; stencil=1;
break;
5254 case D3DFMT_D24S8: depth=24; stencil=8;
break;
5255 case D3DFMT_D16: depth=16; stencil=0;
break;
5256 case D3DFMT_D24X8: depth=24; stencil=0;
break;
5257 case D3DFMT_D24X4S4: depth=24; stencil=4;
break;
5260 props.set_depth_bits(depth);
5261 props.set_stencil_bits(stencil);
5262 if (multisampletype == D3DMULTISAMPLE_NONMASKABLE) {
5263 props.set_multisamples(2);
5265 props.set_multisamples(multisampletype);
5271 #define GAMMA_1 (255.0 * 256.0)
5273 static bool _gamma_table_initialized =
false;
5274 static bool _gamma_changed =
false;
5275 static unsigned short _original_gamma_table [256 * 3];
5277 void _create_gamma_table_dx9 (PN_stdfloat gamma,
unsigned short *original_red_table,
unsigned short *original_green_table,
unsigned short *original_blue_table,
unsigned short *red_table,
unsigned short *green_table,
unsigned short *blue_table) {
5279 double gamma_correction;
5285 gamma_correction = 1.0 / (double) gamma;
5287 for (i = 0; i < 256; i++) {
5292 if (original_red_table) {
5293 r = (double) original_red_table [i] / GAMMA_1;
5294 g = (double) original_green_table [i] / GAMMA_1;
5295 b = (double) original_blue_table [i] / GAMMA_1;
5298 r = ((double) i / 255.0);
5303 r = pow (r, gamma_correction);
5304 g = pow (g, gamma_correction);
5305 b = pow (b, gamma_correction);
5322 green_table [i] = g;
5335 if (_gamma_table_initialized ==
false) {
5336 HDC hdc = GetDC(
nullptr);
5339 if (GetDeviceGammaRamp (hdc, (LPVOID) _original_gamma_table)) {
5340 _gamma_table_initialized =
true;
5344 ReleaseDC (
nullptr, hdc);
5357 HDC hdc = GetDC(
nullptr);
5361 unsigned short ramp [256 * 3];
5363 if (restore && _gamma_table_initialized) {
5364 _create_gamma_table_dx9 (gamma, &_original_gamma_table [0], &_original_gamma_table [256], &_original_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
5367 _create_gamma_table_dx9 (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
5370 if (SetDeviceGammaRamp (hdc, ramp)) {
5372 _gamma_changed = !restore;
5375 ReleaseDC (
nullptr, hdc);
5410 if (_gamma_changed) {
5424 CGprofile profile = cgGetProfile(name.c_str());
5426 if (profile == CG_PROFILE_UNKNOWN) {
5427 dxgsg9_cat.error() << name <<
", unknown Cg-profile\n";
5430 return cgD3D9IsProfileSupported(cgGetProfile(name.c_str())) != 0;
5441 if (_cg_device != cg_device) {
5442 cgD3D9SetDevice(cg_device);
5443 _cg_device = cg_device;
5453 if (_white_vbuffer !=
nullptr) {
5454 return _white_vbuffer;
5457 LPDIRECT3DVERTEXBUFFER9 vbuffer;
5459 hr = _screen->_d3d_device->CreateVertexBuffer(
sizeof(D3DCOLOR), D3DUSAGE_WRITEONLY, D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, &vbuffer,
nullptr);
5463 <<
"CreateVertexBuffer failed" << D3DERRORSTRING(hr);
5467 D3DCOLOR *local_pointer;
5468 hr = vbuffer->Lock(0,
sizeof(D3DCOLOR), (
void **) &local_pointer, D3DLOCK_DISCARD);
5471 <<
"VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
5475 *local_pointer = D3DCOLOR_ARGB(255, 255, 255, 255);
5478 _white_vbuffer = vbuffer;
5482 typedef std::string KEY;
5484 typedef struct _KEY_ELEMENT
5488 int secondary_count;
5490 struct _KEY_ELEMENT *next;
5494 typedef struct _KEY_LIST
5496 int total_key_elements;
5497 KEY_ELEMENT *key_element;
5501 KEY_ELEMENT *new_key_element (KEY key, KEY_LIST *key_list)
5503 KEY_ELEMENT *key_element;
5505 key_element =
new KEY_ELEMENT;
5506 key_element -> key = key;
5507 key_element -> count = 1;
5508 key_element -> secondary_count = 0;
5509 key_element -> next = 0;
5511 key_list -> total_key_elements++;
5516 KEY_ELEMENT *first_key_element (KEY_LIST *key_list)
5518 return key_list -> key_element;
5521 KEY_ELEMENT *next_key_element (KEY_ELEMENT *key_element)
5523 return key_element -> next;
5526 void delete_key_list (KEY_LIST *key_list)
5530 KEY_ELEMENT *key_element;
5531 KEY_ELEMENT *key_element_next;
5533 key_element = first_key_element (key_list);
5536 key_element_next = next_key_element (key_element);
5538 key_element = key_element_next;
5545 KEY_LIST *new_key_list (
void)
5549 key_list =
new KEY_LIST;
5550 memset (key_list, 0,
sizeof (KEY_LIST));
5555 KEY_ELEMENT *add_to_key_list (KEY key, KEY_LIST *key_list)
5557 KEY_ELEMENT *key_element;
5558 KEY_ELEMENT *last_key_element;
5559 KEY_ELEMENT *current_key_element;
5562 last_key_element = 0;
5563 current_key_element = key_list -> key_element;
5564 if (current_key_element == 0)
5566 key_element = new_key_element (key, key_list);
5567 key_list -> key_element = key_element;
5571 while (current_key_element)
5573 if (key < current_key_element -> key)
5575 key_element = new_key_element (key, key_list);
5576 key_element -> next = current_key_element;
5578 if (last_key_element == 0)
5580 key_list -> key_element = key_element;
5584 last_key_element -> next = key_element;
5590 if (key > current_key_element -> key)
5592 if (current_key_element -> next == 0)
5594 key_element = new_key_element (key, key_list);
5595 current_key_element -> next = key_element;
5605 current_key_element -> count++;
5610 last_key_element = current_key_element;
5611 current_key_element = current_key_element -> next;