00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "dxGraphicsStateGuardian9.h"
00017 #include "config_dxgsg9.h"
00018 #include "displayRegion.h"
00019 #include "renderBuffer.h"
00020 #include "geom.h"
00021 #include "graphicsWindow.h"
00022 #include "graphicsEngine.h"
00023 #include "lens.h"
00024 #include "ambientLight.h"
00025 #include "directionalLight.h"
00026 #include "pointLight.h"
00027 #include "spotlight.h"
00028 #include "textureAttrib.h"
00029 #include "texGenAttrib.h"
00030 #include "shadeModelAttrib.h"
00031 #include "cullFaceAttrib.h"
00032 #include "transparencyAttrib.h"
00033 #include "alphaTestAttrib.h"
00034 #include "depthTestAttrib.h"
00035 #include "depthWriteAttrib.h"
00036 #include "colorWriteAttrib.h"
00037 #include "texMatrixAttrib.h"
00038 #include "materialAttrib.h"
00039 #include "renderModeAttrib.h"
00040 #include "rescaleNormalAttrib.h"
00041 #include "fogAttrib.h"
00042 #include "depthOffsetAttrib.h"
00043 #include "lightAttrib.h"
00044 #include "stencilAttrib.h"
00045 #include "scissorAttrib.h"
00046 #include "clipPlaneAttrib.h"
00047 #include "fog.h"
00048 #include "throw_event.h"
00049 #include "geomVertexFormat.h"
00050 #include "geomVertexData.h"
00051 #include "geomTriangles.h"
00052 #include "geomTristrips.h"
00053 #include "geomTrifans.h"
00054 #include "geomLines.h"
00055 #include "geomLinestrips.h"
00056 #include "geomPoints.h"
00057 #include "geomVertexReader.h"
00058 #include "dxGeomMunger9.h"
00059 #include "config_gobj.h"
00060 #include "dxVertexBufferContext9.h"
00061 #include "dxIndexBufferContext9.h"
00062 #include "dxOcclusionQueryContext9.h"
00063 #include "pStatTimer.h"
00064 #include "pStatCollector.h"
00065 #include "wdxGraphicsBuffer9.h"
00066 #include "config_pgraph.h"
00067 #include "shaderGenerator.h"
00068 #ifdef HAVE_CG
00069 #include "Cg/cgD3D9.h"
00070 #endif
00071
00072 #include <mmsystem.h>
00073
00074 #include <dxsdkver.h>
00075
00076 #define tostring(x) #x
00077 #define SDK_VERSION(major,minor) tostring(major) << "." << tostring(minor)
00078 #define DIRECTX_SDK_VERSION SDK_VERSION (_DXSDK_PRODUCT_MAJOR, _DXSDK_PRODUCT_MINOR) << "." << SDK_VERSION (_DXSDK_BUILD_MAJOR, _DXSDK_BUILD_MINOR)
00079
00080 TypeHandle DXGraphicsStateGuardian9::_type_handle;
00081
00082 D3DMATRIX DXGraphicsStateGuardian9::_d3d_ident_mat;
00083
00084 unsigned char *DXGraphicsStateGuardian9::_temp_buffer = NULL;
00085 unsigned char *DXGraphicsStateGuardian9::_safe_buffer_start = NULL;
00086
00087 LPDIRECT3DDEVICE9 DXGraphicsStateGuardian9::_cg_device = NULL;
00088
00089 #define __D3DLIGHT_RANGE_MAX ((PN_stdfloat)sqrt(FLT_MAX)) //for some reason this is missing in dx9 hdrs
00090
00091 #define MY_D3DRGBA(r, g, b, a) ((D3DCOLOR) D3DCOLOR_COLORVALUE(r, g, b, a))
00092
00093
00094
00095
00096
00097
00098 DXGraphicsStateGuardian9::
00099 DXGraphicsStateGuardian9(GraphicsEngine *engine, GraphicsPipe *pipe) :
00100 GraphicsStateGuardian(CS_yup_left, engine, pipe)
00101 {
00102 if (dxgsg9_cat.is_debug()) {
00103 dxgsg9_cat.debug()
00104 << "DXGraphicsStateGuardian9 " << this << " constructing\n";
00105 }
00106
00107
00108
00109 _is_hardware = true;
00110
00111 _screen = NULL;
00112 _d3d_device = NULL;
00113
00114 _dx_is_ready = false;
00115 _vertex_blending_enabled = false;
00116 _overlay_windows_supported = false;
00117 _tex_stats_retrieval_impossible = false;
00118 _supports_render_texture = false;
00119
00120 _active_ibuffer = NULL;
00121
00122
00123
00124
00125 ZeroMemory(&_d3d_ident_mat, sizeof(D3DMATRIX));
00126 _d3d_ident_mat._11 = _d3d_ident_mat._22 = _d3d_ident_mat._33 = _d3d_ident_mat._44 = 1.0f;
00127
00128 _cur_read_pixel_buffer = RenderBuffer::T_front;
00129
00130
00131
00132 _copy_texture_inverted = true;
00133
00134 _gsg_managed_textures = dx_management | dx_texture_management;
00135 _gsg_managed_vertex_buffers = dx_management;
00136 _gsg_managed_index_buffers = dx_management;
00137
00138 _last_fvf = 0;
00139 _num_bound_streams = 0;
00140
00141 _vertex_shader_version_major = 0;
00142 _vertex_shader_version_minor = 0;
00143 _pixel_shader_version_major = 0;
00144 _pixel_shader_version_minor = 0;
00145
00146 _vertex_shader_profile = 0;
00147 _pixel_shader_profile = 0;
00148
00149 _vertex_shader_maximum_constants = 0;
00150
00151 _supports_stream_offset = false;
00152
00153 get_gamma_table();
00154 atexit (atexit_function);
00155 }
00156
00157
00158
00159
00160
00161
00162 DXGraphicsStateGuardian9::
00163 ~DXGraphicsStateGuardian9() {
00164 if (dxgsg9_cat.is_debug()) {
00165 dxgsg9_cat.debug()
00166 << "DXGraphicsStateGuardian9 " << this << " destructing\n";
00167 }
00168
00169 if (IS_VALID_PTR(_d3d_device)) {
00170 _d3d_device->SetTexture(0, NULL);
00171 }
00172
00173 free_nondx_resources();
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 TextureContext *DXGraphicsStateGuardian9::
00190 prepare_texture(Texture *tex, int view) {
00191 DXTextureContext9 *dtc = new DXTextureContext9(_prepared_objects, tex, view);
00192
00193 if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
00194 dxgsg9_cat.error()
00195 << *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
00196 return NULL;
00197 }
00198
00199 return dtc;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 void DXGraphicsStateGuardian9::
00209 apply_texture(int i, TextureContext *tc) {
00210 if (tc == (TextureContext *)NULL) {
00211
00212
00213 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
00214 return;
00215 }
00216 if (!update_texture(tc, false)) {
00217
00218 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
00219 return;
00220 }
00221
00222 tc->set_active(true);
00223
00224 DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
00225 Texture *tex = tc->get_texture();
00226
00227 Texture::WrapMode wrap_u, wrap_v, wrap_w;
00228
00229 DWORD address_u;
00230 DWORD address_v;
00231 DWORD address_w;
00232
00233 wrap_u = tex->get_wrap_u();
00234 wrap_v = tex->get_wrap_v();
00235 wrap_w = tex->get_wrap_w();
00236
00237 address_u = get_texture_wrap_mode(wrap_u);
00238 address_v = get_texture_wrap_mode(wrap_v);
00239 address_w = get_texture_wrap_mode(wrap_w);
00240
00241 set_sampler_state(i, D3DSAMP_ADDRESSU, address_u);
00242 set_sampler_state(i, D3DSAMP_ADDRESSV, address_v);
00243 set_sampler_state(i, D3DSAMP_ADDRESSW, address_w);
00244
00245 DWORD border_color;
00246 border_color = LColor_to_D3DCOLOR(tex->get_border_color());
00247
00248 set_sampler_state(i, D3DSAMP_BORDERCOLOR, border_color);
00249
00250 uint aniso_degree = tex->get_effective_anisotropic_degree();
00251 Texture::FilterType ft = tex->get_effective_magfilter();
00252
00253 if (aniso_degree >= 1) {
00254 set_sampler_state(i, D3DSAMP_MAXANISOTROPY, aniso_degree);
00255 }
00256
00257 int supports_anisotropic_mag_filter;
00258 D3DTEXTUREFILTERTYPE new_mag_filter;
00259
00260 supports_anisotropic_mag_filter = (_screen -> _d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) != 0;
00261 if (aniso_degree <= 1 || supports_anisotropic_mag_filter == 0) {
00262 new_mag_filter = ((ft != Texture::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT);
00263 } else {
00264 new_mag_filter = D3DTEXF_ANISOTROPIC;
00265 }
00266
00267 HRESULT hr;
00268 hr = set_sampler_state(i, D3DSAMP_MAGFILTER, new_mag_filter);
00269 if (hr != D3D_OK) {
00270 dxgsg9_cat.error()
00271 << "ERROR: set_sampler_state (D3DSAMP_MAGFILTER, "
00272 << new_mag_filter << ") failed for texture:" << tex -> get_name() << endl;
00273 }
00274
00275
00276 D3DTEXTUREFILTERTYPE new_min_filter = get_d3d_min_type(tex->get_effective_minfilter());
00277 D3DTEXTUREFILTERTYPE new_mip_filter = get_d3d_mip_type(tex->get_effective_minfilter());
00278
00279 if (!tex->might_have_ram_image()) {
00280
00281
00282
00283 new_mip_filter = D3DTEXF_NONE;
00284 }
00285
00286
00287 if (!dtc->has_mipmaps()) {
00288 new_mip_filter = D3DTEXF_NONE;
00289 }
00290
00291 if (aniso_degree >= 2) {
00292 new_min_filter = D3DTEXF_ANISOTROPIC;
00293 }
00294
00295 set_sampler_state(i, D3DSAMP_MINFILTER, new_min_filter);
00296 set_sampler_state(i, D3DSAMP_MIPFILTER, new_mip_filter);
00297
00298 _d3d_device->SetTexture(i, dtc->get_d3d_texture());
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 bool DXGraphicsStateGuardian9::
00318 update_texture(TextureContext *tc, bool force) {
00319 DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
00320
00321
00322
00323
00324 if (dtc->was_modified()) {
00325 if (!upload_texture(dtc, force)) {
00326
00327 Texture *tex = tc->get_texture();
00328 dxgsg9_cat.error()
00329 << "Unable to re-create texture " << *tex << endl;
00330 return false;
00331 }
00332 }
00333 dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
00334
00335 return true;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 bool DXGraphicsStateGuardian9::
00345 upload_texture(DXTextureContext9 *dtc, bool force) {
00346 Texture *tex = dtc->get_texture();
00347 if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
00348 dxgsg9_cat.error()
00349 << *tex << " is stored in an unsupported compressed format.\n";
00350 return false;
00351 }
00352
00353 dtc->delete_texture();
00354 dtc->update_data_size_bytes(0);
00355 dtc->mark_unloaded();
00356
00357 if (_effective_incomplete_render && !force) {
00358 bool has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image();
00359 if (!has_image && tex->might_have_ram_image() &&
00360 tex->has_simple_ram_image() &&
00361 !_loader.is_null()) {
00362
00363
00364 async_reload_texture(dtc);
00365 has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image();
00366 if (!has_image) {
00367 if (dtc->was_simple_image_modified()) {
00368 return dtc->create_simple_texture(*_screen);
00369 }
00370 return true;
00371 }
00372 }
00373 }
00374
00375 return dtc->create_texture(*_screen);
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 void DXGraphicsStateGuardian9::
00385 release_texture(TextureContext *tc) {
00386 DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
00387 delete dtc;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 bool DXGraphicsStateGuardian9::
00403 extract_texture_data(Texture *tex) {
00404 bool success = true;
00405
00406 int num_views = tex->get_num_views();
00407 for (int view = 0; view < num_views; ++view) {
00408 TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this);
00409 nassertr(tc != (TextureContext *)NULL, false);
00410 DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
00411
00412 if (!dtc->extract_texture_data(*_screen)) {
00413 success = false;
00414 }
00415 }
00416
00417 return success;
00418 }
00419
00420
00421
00422
00423
00424
00425 ShaderContext *DXGraphicsStateGuardian9::
00426 prepare_shader(Shader *se) {
00427 #ifdef HAVE_CG
00428 CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this);
00429 return result;
00430 #endif
00431 return NULL;
00432 }
00433
00434
00435
00436
00437
00438
00439 void DXGraphicsStateGuardian9::
00440 release_shader(ShaderContext *sc) {
00441 CLP(ShaderContext) *gsc = DCAST(CLP(ShaderContext), sc);
00442 delete gsc;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 VertexBufferContext *CLP(GraphicsStateGuardian)::
00459 prepare_vertex_buffer(GeomVertexArrayData *data) {
00460 CLP(VertexBufferContext) *dvbc = new CLP(VertexBufferContext)(this, _prepared_objects, data);
00461
00462 DWORD usage;
00463 D3DPOOL pool;
00464 if (_screen->_managed_vertex_buffers) {
00465 pool = D3DPOOL_MANAGED;
00466 usage = D3DUSAGE_WRITEONLY;
00467 } else {
00468 pool = D3DPOOL_DEFAULT;
00469 usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
00470 }
00471
00472 int num_bytes = data->get_data_size_bytes();
00473
00474 PStatTimer timer(_create_vertex_buffer_pcollector, Thread::get_current_thread());
00475
00476 HRESULT hr;
00477 int attempts = 0;
00478 do
00479 {
00480 hr = _screen->_d3d_device->CreateVertexBuffer(num_bytes, usage, dvbc->_fvf, pool, &dvbc->_vbuffer, NULL);
00481 attempts++;
00482 }
00483 while (check_dx_allocation(hr, num_bytes, attempts));
00484
00485 if (!FAILED(hr)) {
00486 #if 0
00487 if (dxgsg9_cat.is_debug() && CLP(debug_buffers)) {
00488 dxgsg9_cat.debug()
00489 << "creating vertex buffer " << dvbc->_vbuffer << ": "
00490 << data->get_num_rows() << " vertices "
00491 << *data->get_array_format() << "\n";
00492 }
00493 #endif
00494
00495 return dvbc;
00496 } else {
00497 dxgsg9_cat.error()
00498 << "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
00499
00500 dvbc->_vbuffer = NULL;
00501 }
00502
00503 return NULL;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512 bool CLP(GraphicsStateGuardian)::
00513 apply_vertex_buffer(VertexBufferContext *vbc,
00514 const GeomVertexArrayDataHandle *reader, bool force ) {
00515
00516 CLP(VertexBufferContext) *dvbc = DCAST(CLP(VertexBufferContext), vbc);
00517
00518 if (dvbc->was_modified(reader)) {
00519 int num_bytes = reader->get_data_size_bytes();
00520 #if 0
00521 if (dxgsg9_cat.is_debug() && CLP(debug_buffers)) {
00522 dxgsg9_cat.debug()
00523 << "copying " << num_bytes
00524 << " bytes into vertex buffer " << dvbc->_vbuffer << "\n";
00525 }
00526 #endif
00527
00528 if ( num_bytes != 0 ) {
00529 const unsigned char *client_pointer = reader->get_read_pointer(force);
00530 if (client_pointer == NULL) {
00531 return false;
00532 }
00533
00534 PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread());
00535
00536 #if 0
00537 if (dvbc->changed_size(reader)) {
00538
00539
00540 dvbc->create_vbuffer(*_screen, reader);
00541 }
00542 #endif
00543
00544 HRESULT hr;
00545 BYTE *local_pointer;
00546 if (_screen->_managed_vertex_buffers) {
00547 hr = dvbc->_vbuffer->Lock(0, num_bytes, (void **) &local_pointer, 0);
00548 } else {
00549 hr = dvbc->_vbuffer->Lock(0, num_bytes, (void **) &local_pointer, D3DLOCK_DISCARD);
00550 }
00551 if (FAILED(hr)) {
00552 dxgsg9_cat.error()
00553 << "VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
00554 return false;
00555 }
00556
00557 memcpy(local_pointer, client_pointer, num_bytes);
00558
00559 dvbc->_vbuffer->Unlock();
00560
00561 _data_transferred_pcollector.add_level(num_bytes);
00562 }
00563
00564 dvbc->mark_loaded(reader);
00565 }
00566 dvbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
00567
00568 return true;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 void CLP(GraphicsStateGuardian)::
00580 release_vertex_buffer(VertexBufferContext *vbc) {
00581
00582 CLP(VertexBufferContext) *dvbc = DCAST(CLP(VertexBufferContext), vbc);
00583
00584 #if 0
00585 if (dxgsg9_cat.is_debug() && CLP(debug_buffers)) {
00586 dxgsg9_cat.debug()
00587 << "deleting vertex buffer " << dvbc->_vbuffer << "\n";
00588 }
00589 #endif
00590
00591 dvbc->_vbuffer->Release();
00592 dvbc->_vbuffer = NULL;
00593
00594 delete dvbc;
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 bool CLP(GraphicsStateGuardian)::
00616 setup_array_data(CLP(VertexBufferContext)*& dvbc,
00617 const GeomVertexArrayDataHandle* array_reader,
00618 bool force) {
00619
00620
00621 VertexBufferContext* vbc = ((GeomVertexArrayData *)array_reader->get_object())->prepare_now(get_prepared_objects(), this);
00622 nassertr(vbc != (VertexBufferContext *)NULL, false);
00623 if (!apply_vertex_buffer(vbc, array_reader, force)) {
00624 return false;
00625 }
00626
00627 dvbc = (CLP(VertexBufferContext)*)vbc;
00628 return true;
00629 }
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 IndexBufferContext *DXGraphicsStateGuardian9::
00645 prepare_index_buffer(GeomPrimitive *data) {
00646 DXIndexBufferContext9 *dibc = new DXIndexBufferContext9(_prepared_objects, data);
00647 return dibc;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656 bool DXGraphicsStateGuardian9::
00657 apply_index_buffer(IndexBufferContext *ibc,
00658 const GeomPrimitivePipelineReader *reader, bool force) {
00659 DXIndexBufferContext9 *dibc = DCAST(DXIndexBufferContext9, ibc);
00660
00661 if (dibc->_ibuffer == NULL) {
00662
00663 dibc->create_ibuffer(*_screen, reader);
00664
00665 if (dibc->_ibuffer != NULL) {
00666 if (!dibc->upload_data(reader, force)) {
00667 return false;
00668 }
00669 dibc->mark_loaded(reader);
00670
00671 _d3d_device->SetIndices(dibc->_ibuffer);
00672 _active_ibuffer = dibc;
00673 dibc->set_active(true);
00674
00675 } else {
00676 _d3d_device->SetIndices(NULL);
00677 _active_ibuffer = NULL;
00678 }
00679
00680 } else {
00681 if (dibc->was_modified(reader)) {
00682 if (dibc->changed_size(reader)) {
00683
00684
00685 dibc->create_ibuffer(*_screen, reader);
00686 }
00687
00688 if (!dibc->upload_data(reader, force)) {
00689 return false;
00690 }
00691
00692 dibc->mark_loaded(reader);
00693 _active_ibuffer = NULL;
00694 }
00695
00696 if (_active_ibuffer != dibc) {
00697 _d3d_device->SetIndices(dibc->_ibuffer);
00698 _active_ibuffer = dibc;
00699 dibc->set_active(true);
00700 }
00701 }
00702 dibc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
00703
00704 return true;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 void DXGraphicsStateGuardian9::
00716 release_index_buffer(IndexBufferContext *ibc) {
00717 DXIndexBufferContext9 *dibc = DCAST(DXIndexBufferContext9, ibc);
00718 delete dibc;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 void DXGraphicsStateGuardian9::
00738 begin_occlusion_query() {
00739 nassertv(_supports_occlusion_query);
00740 nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL);
00741
00742 IDirect3DQuery9 *query;
00743 HRESULT hr = _d3d_device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
00744 if (FAILED(hr)) {
00745 dxgsg9_cat.warning()
00746 << "Occlusion query failed.\n";
00747 return;
00748 }
00749
00750 PT(DXOcclusionQueryContext9) queryobj = new DXOcclusionQueryContext9(query);
00751
00752 if (dxgsg9_cat.is_debug()) {
00753 dxgsg9_cat.debug()
00754 << "beginning occlusion query " << query << "\n";
00755 }
00756
00757 query->Issue(D3DISSUE_BEGIN);
00758 _current_occlusion_query = queryobj;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 PT(OcclusionQueryContext) DXGraphicsStateGuardian9::
00771 end_occlusion_query() {
00772 if (_current_occlusion_query == (OcclusionQueryContext *)NULL) {
00773 return NULL;
00774 }
00775
00776 PT(OcclusionQueryContext) result = _current_occlusion_query;
00777
00778 IDirect3DQuery9 *query = DCAST(DXOcclusionQueryContext9, result)->_query;
00779
00780 if (dxgsg9_cat.is_debug()) {
00781 dxgsg9_cat.debug()
00782 << "ending occlusion query " << query << "\n";
00783 }
00784
00785 _current_occlusion_query = NULL;
00786 query->Issue(D3DISSUE_END);
00787
00788 return result;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797 PT(GeomMunger) DXGraphicsStateGuardian9::
00798 make_geom_munger(const RenderState *state, Thread *current_thread) {
00799 PT(DXGeomMunger9) munger = new DXGeomMunger9(this, state);
00800 return GeomMunger::register_munger(munger, current_thread);
00801 }
00802
00803
00804
00805
00806
00807
00808
00809 void DXGraphicsStateGuardian9::
00810 clear(DrawableRegion *clearable) {
00811
00812 DWORD main_flags = 0;
00813 DWORD aux_flags = 0;
00814
00815 if ((!clearable->get_clear_color_active())&&
00816 (!clearable->get_clear_depth_active())&&
00817 (!clearable->get_clear_stencil_active())) {
00818 return;
00819 }
00820
00821 set_state_and_transform(RenderState::make_empty(), _internal_transform);
00822
00823 D3DCOLOR color_clear_value = LColor_to_D3DCOLOR(clearable->get_clear_color());
00824 PN_stdfloat depth_clear_value = clearable->get_clear_depth();
00825 DWORD stencil_clear_value = (DWORD)(clearable->get_clear_stencil());
00826
00827
00828 if (clearable->get_clear_color_active()) {
00829 main_flags |= D3DCLEAR_TARGET;
00830 }
00831
00832 if (clearable->get_clear_depth_active()) {
00833 aux_flags |= D3DCLEAR_ZBUFFER;
00834 nassertv(_screen->_presentation_params.EnableAutoDepthStencil);
00835 }
00836
00837 if (clearable->get_clear_stencil_active()) {
00838
00839 if (_screen->_presentation_params.EnableAutoDepthStencil &&
00840 IS_STENCIL_FORMAT(_screen->_presentation_params.AutoDepthStencilFormat)) {
00841 aux_flags |= D3DCLEAR_STENCIL;
00842 }
00843 }
00844
00845 if ((main_flags | aux_flags) != 0) {
00846 HRESULT hr = _d3d_device->Clear(0, NULL, main_flags | aux_flags, color_clear_value,
00847 depth_clear_value, stencil_clear_value);
00848 if (FAILED(hr) && main_flags == D3DCLEAR_TARGET && aux_flags != 0) {
00849
00850
00851 hr = _d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, color_clear_value,
00852 depth_clear_value, stencil_clear_value);
00853 if (!FAILED(hr)) {
00854
00855
00856 if (clearable->get_clear_depth_active()) {
00857 aux_flags |= D3DCLEAR_ZBUFFER;
00858 HRESULT hr2 = _d3d_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color_clear_value,
00859 depth_clear_value, stencil_clear_value);
00860 if (FAILED(hr2)) {
00861 dxgsg9_cat.error()
00862 << "Unable to clear depth buffer; removing.\n";
00863
00864 ((FrameBufferProperties *)_current_properties)->set_depth_bits(0);
00865 }
00866 }
00867 if (clearable->get_clear_stencil_active()) {
00868 aux_flags |= D3DCLEAR_STENCIL;
00869 HRESULT hr2 = _d3d_device->Clear(0, NULL, D3DCLEAR_STENCIL, color_clear_value,
00870 stencil_clear_value, stencil_clear_value);
00871 if (FAILED(hr2)) {
00872 dxgsg9_cat.error()
00873 << "Unable to clear stencil buffer; removing.\n";
00874
00875 ((FrameBufferProperties *)_current_properties)->set_stencil_bits(0);
00876 _supports_stencil = false;
00877 }
00878 }
00879 }
00880 }
00881
00882 if (FAILED(hr)) {
00883 dxgsg9_cat.error()
00884 << "clear_buffer failed: Clear returned " << D3DERRORSTRING(hr);
00885 }
00886 }
00887 }
00888
00889
00890
00891
00892
00893
00894
00895 void DXGraphicsStateGuardian9::
00896 prepare_display_region(DisplayRegionPipelineReader *dr) {
00897 nassertv(dr != (DisplayRegionPipelineReader *)NULL);
00898 GraphicsStateGuardian::prepare_display_region(dr);
00899
00900 int l, u, w, h;
00901 dr->get_region_pixels_i(l, u, w, h);
00902
00903
00904 D3DVIEWPORT9 vp = { l, u, w, h, 0.0f, 1.0f };
00905 _current_viewport = vp;
00906 HRESULT hr = _d3d_device->SetViewport(&_current_viewport);
00907 if (FAILED(hr)) {
00908 dxgsg9_cat.error()
00909 << "_screen->_swap_chain = " << _screen->_swap_chain << " _swap_chain = " << _swap_chain << "\n";
00910 dxgsg9_cat.error()
00911 << "SetViewport(" << l << ", " << u << ", " << w << ", " << h
00912 << ") failed" << D3DERRORSTRING(hr);
00913
00914 D3DVIEWPORT9 vp_old;
00915 _d3d_device->GetViewport(&vp_old);
00916 dxgsg9_cat.error()
00917 << "GetViewport(" << vp_old.X << ", " << vp_old.Y << ", " << vp_old.Width << ", "
00918 << vp_old.Height << ") returned: Trying to set that vp---->\n";
00919 hr = _d3d_device->SetViewport(&vp_old);
00920 set_render_state(D3DRS_SCISSORTESTENABLE, FALSE);
00921
00922 if (FAILED(hr)) {
00923 dxgsg9_cat.error() << "Failed again\n";
00924 throw_event("panda3d-render-error");
00925 nassertv(false);
00926 }
00927 }
00928
00929 if (_screen->_can_direct_disable_color_writes) {
00930 set_render_state(D3DRS_COLORWRITEENABLE, _color_write_mask);
00931 }
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 CPT(TransformState) DXGraphicsStateGuardian9::
00946 calc_projection_mat(const Lens *lens) {
00947 if (lens == (Lens *)NULL) {
00948 return NULL;
00949 }
00950
00951 if (!lens->is_linear()) {
00952 return NULL;
00953 }
00954
00955
00956
00957
00958 static const LMatrix4 rescale_mat
00959 (1, 0, 0, 0,
00960 0, 1, 0, 0,
00961 0, 0, 0.5, 0,
00962 0, 0, 0.5, 1);
00963
00964 LMatrix4 result =
00965 LMatrix4::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
00966 lens->get_projection_mat(_current_stereo_channel) *
00967 rescale_mat;
00968
00969 if (_scene_setup->get_inverted()) {
00970
00971
00972 result *= LMatrix4::scale_mat(1.0f, -1.0f, 1.0f);
00973 }
00974
00975 return TransformState::make_mat(result);
00976 }
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 bool DXGraphicsStateGuardian9::
00991 prepare_lens() {
00992 LMatrix4f mat = LCAST(float, _projection_mat->get_mat());
00993 HRESULT hr =
00994 _d3d_device->SetTransform(D3DTS_PROJECTION,
00995 (D3DMATRIX*)mat.get_data());
00996 return SUCCEEDED(hr);
00997 }
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012 bool DXGraphicsStateGuardian9::
01013 begin_frame(Thread *current_thread) {
01014
01015 GraphicsStateGuardian::begin_frame(current_thread);
01016
01017 if (_d3d_device == NULL) {
01018 dxgsg9_cat.debug()
01019 << this << "::begin_frame(): no device.\n";
01020 return false;
01021 }
01022
01023 HRESULT hr = _d3d_device->BeginScene();
01024
01025 if (FAILED(hr)) {
01026 if (hr == D3DERR_DEVICELOST) {
01027 if (dxgsg9_cat.is_debug()) {
01028 dxgsg9_cat.debug()
01029 << "BeginScene returns D3DERR_DEVICELOST" << endl;
01030 }
01031
01032 check_cooperative_level();
01033
01034 } else {
01035 dxgsg9_cat.error()
01036 << "BeginScene failed, unhandled error hr == "
01037 << D3DERRORSTRING(hr) << endl;
01038 throw_event("panda3d-render-error");
01039 }
01040 return false;
01041 }
01042
01043 return true;
01044 }
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 bool DXGraphicsStateGuardian9::
01062 begin_scene() {
01063 if (!GraphicsStateGuardian::begin_scene()) {
01064 return false;
01065 }
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 return true;
01090 }
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 void DXGraphicsStateGuardian9::
01102 end_scene() {
01103 GraphicsStateGuardian::end_scene();
01104
01105 if (_vertex_array_shader_context != 0) {
01106 _vertex_array_shader_context->disable_shader_vertex_arrays(this);
01107 _vertex_array_shader = (Shader *)NULL;
01108 _vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
01109 }
01110 if (_texture_binding_shader_context != 0) {
01111 _texture_binding_shader_context->disable_shader_texture_bindings(this);
01112 _texture_binding_shader = (Shader *)NULL;
01113 _texture_binding_shader_context = (CLP(ShaderContext) *)NULL;
01114 }
01115 if (_current_shader_context != 0) {
01116 _current_shader_context->unbind(this);
01117 _current_shader = (Shader *)NULL;
01118 _current_shader_context = (CLP(ShaderContext) *)NULL;
01119 }
01120
01121 _dlights.clear();
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 }
01144
01145
01146
01147
01148
01149
01150
01151
01152 void DXGraphicsStateGuardian9::
01153 end_frame(Thread *current_thread) {
01154
01155 HRESULT hr = _d3d_device->EndScene();
01156
01157 if (FAILED(hr)) {
01158 if (hr == D3DERR_DEVICELOST) {
01159 if (dxgsg9_cat.is_debug()) {
01160 dxgsg9_cat.debug()
01161 << "EndScene returns DeviceLost\n";
01162 }
01163 check_cooperative_level();
01164
01165 } else {
01166 dxgsg9_cat.error()
01167 << "EndScene failed, unhandled error hr == " << D3DERRORSTRING(hr);
01168 throw_event("panda3d-render-error");
01169 }
01170 return;
01171 }
01172
01173 #if defined(DO_PSTATS)
01174 if (_texmgrmem_total_pcollector.is_active()) {
01175 #define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval
01176 static DWORD last_tick_count = 0;
01177 DWORD cur_tick_count = GetTickCount();
01178
01179 if (cur_tick_count - last_tick_count > TICKS_PER_GETTEXINFO) {
01180 last_tick_count = cur_tick_count;
01181 report_texmgr_stats();
01182 }
01183 }
01184 #endif
01185
01186
01187
01188
01189 GraphicsStateGuardian::end_frame(current_thread);
01190 }
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200 bool DXGraphicsStateGuardian9::
01201 begin_draw_primitives(const GeomPipelineReader *geom_reader,
01202 const GeomMunger *munger,
01203 const GeomVertexDataPipelineReader *data_reader,
01204 bool force) {
01205 if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger,
01206 data_reader, force)) {
01207 return false;
01208 }
01209 nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false);
01210
01211 const GeomVertexFormat *format = _data_reader->get_format();
01212
01213 const GeomVertexAnimationSpec &animation =
01214 data_reader->get_format()->get_animation();
01215 if (animation.get_animation_type() == Geom::AT_hardware) {
01216
01217 switch (animation.get_num_transforms()) {
01218 case 1:
01219
01220
01221
01222
01223
01224
01225 set_render_state(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
01226 break;
01227 case 2:
01228 set_render_state(D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS);
01229 break;
01230 case 3:
01231 set_render_state(D3DRS_VERTEXBLEND, D3DVBF_2WEIGHTS);
01232 break;
01233 case 4:
01234 set_render_state(D3DRS_VERTEXBLEND, D3DVBF_3WEIGHTS);
01235 break;
01236 }
01237
01238 if (animation.get_indexed_transforms()) {
01239
01240 set_render_state(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
01241 } else {
01242 set_render_state(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
01243 }
01244
01245 const TransformTable *table = data_reader->get_transform_table();
01246 if (table != (TransformTable *)NULL) {
01247 for (int i = 0; i < table->get_num_transforms(); i++) {
01248 LMatrix4 mat;
01249 table->get_transform(i)->mult_matrix(mat, _internal_transform->get_mat());
01250 const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data();
01251 _d3d_device->SetTransform(D3DTS_WORLDMATRIX(i), d3d_mat);
01252 }
01253
01254
01255
01256 _transform_stale = true;
01257 }
01258 _vertex_blending_enabled = true;
01259
01260 } else {
01261
01262 if (_vertex_blending_enabled) {
01263 set_render_state(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
01264 set_render_state(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
01265 _vertex_blending_enabled = false;
01266 }
01267
01268 if (_transform_stale && !_data_reader->is_vertex_transformed()) {
01269 const D3DMATRIX *d3d_mat = (const D3DMATRIX *)_internal_transform->get_mat().get_data();
01270 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
01271 _transform_stale = false;
01272 }
01273 }
01274
01275 if (_data_reader->is_vertex_transformed()) {
01276
01277
01278
01279
01280
01281
01282
01283
01284 _d3d_device->SetTransform(D3DTS_WORLD, &_d3d_ident_mat);
01285 static const LMatrix4f rescale_mat
01286 (1, 0, 0, 0,
01287 0, 1, 0, 0,
01288 0, 0, 0.5, 0,
01289 0, 0, 0.5, 1);
01290 _transform_stale = true;
01291
01292 _d3d_device->SetTransform(D3DTS_PROJECTION, (const D3DMATRIX *)rescale_mat.get_data());
01293 }
01294
01295 if (_current_shader_context == 0 ) {
01296
01297 if (_vertex_array_shader_context != 0) {
01298 _vertex_array_shader_context->disable_shader_vertex_arrays(this);
01299 }
01300 if (!update_standard_vertex_arrays(force)) {
01301 return false;
01302 }
01303 } else {
01304
01305 if (_vertex_array_shader_context == 0) {
01306 disable_standard_vertex_arrays();
01307 if (!_current_shader_context->update_shader_vertex_arrays(NULL, this, force)) {
01308 return false;
01309 }
01310 } else {
01311 if (!_current_shader_context->
01312 update_shader_vertex_arrays(_vertex_array_shader_context, this, force)) {
01313 return false;
01314 }
01315 }
01316 }
01317
01318 _vertex_array_shader = _current_shader;
01319 _vertex_array_shader_context = _current_shader_context;
01320
01321 return true;
01322 }
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 bool CLP(GraphicsStateGuardian)::
01334 update_standard_vertex_arrays(bool force) {
01335
01336 int fvf = 0;
01337 HRESULT hr;
01338
01339 int number_of_arrays = _data_reader->get_num_arrays();
01340 for ( int array_index = 0; array_index < number_of_arrays; ++array_index ) {
01341 const GeomVertexArrayDataHandle* array_reader = _data_reader->get_array_reader( array_index );
01342 if ( array_reader == NULL ) {
01343 dxgsg9_cat.error() << "Unable to get reader for array " << array_index << "\n";
01344 return false;
01345 }
01346
01347
01348 CLP(VertexBufferContext)* dvbc;
01349 if (!setup_array_data(dvbc, array_reader, force)) {
01350 dxgsg9_cat.error() << "Unable to setup vertex buffer for array " << array_index << "\n";
01351 return false;
01352 }
01353
01354
01355 const GeomVertexArrayFormat* array_format = array_reader->get_array_format();
01356 hr = _d3d_device->SetStreamSource( array_index, dvbc->_vbuffer, 0, array_format->get_stride() );
01357 if (FAILED(hr)) {
01358 dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
01359 return false;
01360 }
01361
01362
01363 fvf |= dvbc->_fvf;
01364 }
01365
01366 hr = _d3d_device->SetFVF( fvf );
01367 if (FAILED(hr)) {
01368 dxgsg9_cat.error() << "SetFVF failed" << D3DERRORSTRING(hr);
01369 return false;
01370 }
01371
01372 return true;
01373 }
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 void CLP(GraphicsStateGuardian)::
01385 disable_standard_vertex_arrays() {
01386 for ( int array_index = 0; array_index < _num_bound_streams; ++array_index )
01387 {
01388 _d3d_device->SetStreamSource( array_index, NULL, 0, 0 );
01389 }
01390 _num_bound_streams = 0;
01391 }
01392
01393
01394
01395
01396
01397
01398 bool DXGraphicsStateGuardian9::
01399 draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
01400
01401
01402 _vertices_tri_pcollector.add_level(reader->get_num_vertices());
01403 _primitive_batches_tri_pcollector.add_level(1);
01404
01405 if (reader->is_indexed()) {
01406 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
01407 int max_vertex = reader->get_max_vertex();
01408
01409
01410 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01411 nassertr(ibc != (IndexBufferContext *)NULL, false);
01412 if (!apply_index_buffer(ibc, reader, force)) {
01413 return false;
01414 }
01415
01416 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
01417 0,
01418 min_vertex, max_vertex - min_vertex + 1,
01419 0, reader->get_num_primitives() );
01420
01421 #if 0
01422
01423 const unsigned char *index_pointer = reader->get_read_pointer(force);
01424 if (index_pointer == NULL) {
01425 return false;
01426 }
01427 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01428 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01429 if (vertex_pointer == NULL) {
01430 return false;
01431 }
01432
01433 draw_indexed_primitive_up( D3DPT_TRIANGLELIST,
01434 min_vertex, max_vertex,
01435 reader->get_num_primitives(),
01436 index_pointer, index_type, vertex_pointer,
01437 _data_reader->get_format()->get_array(0)->get_stride() );
01438 #endif
01439 } else {
01440
01441 _d3d_device->DrawPrimitive( D3DPT_TRIANGLELIST,
01442 reader->get_first_vertex(),
01443 reader->get_num_primitives() );
01444
01445 #if 0
01446
01447 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01448 if (vertex_pointer == NULL) {
01449 return false;
01450 }
01451
01452 draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(),
01453 reader->get_first_vertex(),
01454 reader->get_num_vertices(), vertex_pointer,
01455 _data_reader->get_format()->get_array(0)->get_stride());
01456 #endif
01457 }
01458
01459 return true;
01460 }
01461
01462
01463
01464
01465
01466
01467 bool DXGraphicsStateGuardian9::
01468 draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
01469
01470
01471 if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
01472
01473
01474 _vertices_tristrip_pcollector.add_level(reader->get_num_vertices());
01475 _primitive_batches_tristrip_pcollector.add_level(1);
01476
01477 if (reader->is_indexed()) {
01478 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
01479 int max_vertex = reader->get_max_vertex();
01480
01481
01482 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01483 nassertr(ibc != (IndexBufferContext *)NULL, false);
01484 if (!apply_index_buffer(ibc, reader, force)) {
01485 return false;
01486 }
01487
01488 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP,
01489 0,
01490 min_vertex, max_vertex - min_vertex + 1,
01491 0, reader->get_num_vertices() - 2 );
01492
01493 #if 0
01494
01495 const unsigned char *index_pointer = reader->get_read_pointer(force);
01496 if (index_pointer == NULL) {
01497 return false;
01498 }
01499 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01500 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01501 if (vertex_pointer == NULL) {
01502 return false;
01503 }
01504
01505 draw_indexed_primitive_up
01506 (D3DPT_TRIANGLESTRIP,
01507 min_vertex, max_vertex,
01508 reader->get_num_vertices() - 2,
01509 index_pointer, index_type, vertex_pointer,
01510 _data_reader->get_format()->get_array(0)->get_stride());
01511 #endif
01512 } else {
01513
01514 _d3d_device->DrawPrimitive( D3DPT_TRIANGLESTRIP,
01515 reader->get_first_vertex(),
01516 reader->get_num_vertices() - 2 );
01517
01518 #if 0
01519
01520 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01521 if (vertex_pointer == NULL) {
01522 return false;
01523 }
01524 draw_primitive_up(D3DPT_TRIANGLESTRIP,
01525 reader->get_num_vertices() - 2,
01526 reader->get_first_vertex(),
01527 reader->get_num_vertices(), vertex_pointer,
01528 _data_reader->get_format()->get_array(0)->get_stride());
01529 #endif
01530 }
01531
01532 } else {
01533
01534 CPTA_int ends = reader->get_ends();
01535 _primitive_batches_tristrip_pcollector.add_level(ends.size());
01536
01537 if (reader->is_indexed()) {
01538 CPTA_int ends = reader->get_ends();
01539 int index_stride = reader->get_index_stride();
01540 _primitive_batches_tristrip_pcollector.add_level(ends.size());
01541
01542 GeomVertexReader mins(reader->get_mins(), 0);
01543 GeomVertexReader maxs(reader->get_maxs(), 0);
01544 nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
01545 reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
01546
01547
01548 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01549 nassertr(ibc != (IndexBufferContext *)NULL, false);
01550 if (!apply_index_buffer(ibc, reader, force)) {
01551 return false;
01552 }
01553
01554 unsigned int start = 0;
01555 for (size_t i = 0; i < ends.size(); i++) {
01556 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01557 unsigned int min = mins.get_data1i();
01558 unsigned int max = maxs.get_data1i();
01559 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP,
01560 0,
01561 min, max - min + 1,
01562 start, ends[i] - start - 2 );
01563 start = ends[i] + 2;
01564 }
01565
01566 #if 0
01567
01568 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01569 const unsigned char *index_pointer = reader->get_read_pointer(force);
01570 if (index_pointer == NULL) {
01571 return false;
01572 }
01573 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01574 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01575 if (vertex_pointer == NULL) {
01576 return false;
01577 }
01578
01579 unsigned int start = 0;
01580 for (size_t i = 0; i < ends.size(); i++) {
01581 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01582 unsigned int min = mins.get_data1i();
01583 unsigned int max = maxs.get_data1i();
01584 draw_indexed_primitive_up
01585 (D3DPT_TRIANGLESTRIP,
01586 min, max,
01587 ends[i] - start - 2,
01588 index_pointer + start * index_stride, index_type,
01589 vertex_pointer, stride);
01590
01591 start = ends[i] + 2;
01592 }
01593 #endif
01594 } else {
01595 unsigned int first_vertex = reader->get_first_vertex();
01596
01597
01598 unsigned int start = 0;
01599 for (size_t i = 0; i < ends.size(); i++) {
01600 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01601 _d3d_device->DrawPrimitive( D3DPT_TRIANGLESTRIP,
01602 first_vertex + start,
01603 ends[i] - start - 2 );
01604 start = ends[i] + 2;
01605 }
01606
01607 #if 0
01608
01609 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01610 if (vertex_pointer == NULL) {
01611 return false;
01612 }
01613 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01614
01615 unsigned int start = 0;
01616 for (size_t i = 0; i < ends.size(); i++) {
01617 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01618 draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2,
01619 first_vertex + start,
01620 ends[i] - start,
01621 vertex_pointer, stride);
01622
01623 start = ends[i] + 2;
01624 }
01625 #endif
01626 }
01627 }
01628 return true;
01629 }
01630
01631
01632
01633
01634
01635
01636 bool DXGraphicsStateGuardian9::
01637 draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
01638
01639
01640 CPTA_int ends = reader->get_ends();
01641 _primitive_batches_trifan_pcollector.add_level(ends.size());
01642
01643 if (reader->is_indexed()) {
01644 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
01645 int max_vertex = reader->get_max_vertex();
01646
01647
01648
01649 int index_stride = reader->get_index_stride();
01650
01651 GeomVertexReader mins(reader->get_mins(), 0);
01652 GeomVertexReader maxs(reader->get_maxs(), 0);
01653 nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
01654 reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
01655
01656
01657 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01658 nassertr(ibc != (IndexBufferContext *)NULL, false);
01659 if (!apply_index_buffer(ibc, reader, force)) {
01660 return false;
01661 }
01662
01663 unsigned int start = 0;
01664 for (size_t i = 0; i < ends.size(); i++) {
01665 _vertices_trifan_pcollector.add_level(ends[i] - start);
01666 unsigned int min = mins.get_data1i();
01667 unsigned int max = maxs.get_data1i();
01668 _d3d_device->DrawIndexedPrimitive( D3DPT_TRIANGLEFAN,
01669 0,
01670 min, max - min + 1,
01671 start, ends[i] - start - 2 );
01672 start = ends[i];
01673 }
01674
01675 #if 0
01676
01677 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01678 const unsigned char *index_pointer = reader->get_read_pointer(force);
01679 if (index_pointer == NULL) {
01680 return false;
01681 }
01682 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01683 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01684 if (vertex_pointer == NULL) {
01685 return false;
01686 }
01687
01688 unsigned int start = 0;
01689 for (size_t i = 0; i < ends.size(); i++) {
01690 _vertices_trifan_pcollector.add_level(ends[i] - start);
01691 unsigned int min = mins.get_data1i();
01692 unsigned int max = maxs.get_data1i();
01693 draw_indexed_primitive_up
01694 (D3DPT_TRIANGLEFAN,
01695 min, max,
01696 ends[i] - start - 2,
01697 index_pointer + start * index_stride, index_type,
01698 vertex_pointer, stride);
01699
01700 start = ends[i];
01701 }
01702 #endif
01703 } else {
01704 unsigned int first_vertex = reader->get_first_vertex();
01705
01706
01707 unsigned int start = 0;
01708 for (size_t i = 0; i < ends.size(); i++) {
01709 _vertices_trifan_pcollector.add_level(ends[i] - start);
01710 _d3d_device->DrawPrimitive( D3DPT_TRIANGLEFAN,
01711 first_vertex + start,
01712 ends[i] - start - 2 );
01713 start = ends[i];
01714 }
01715
01716 #if 0
01717
01718 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01719 if (vertex_pointer == NULL) {
01720 return false;
01721 }
01722 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01723
01724 unsigned int start = 0;
01725 for (size_t i = 0; i < ends.size(); i++) {
01726 _vertices_trifan_pcollector.add_level(ends[i] - start);
01727 draw_primitive_up(D3DPT_TRIANGLEFAN,
01728 ends[i] - start - 2,
01729 first_vertex,
01730 ends[i] - start,
01731 vertex_pointer, stride);
01732 start = ends[i];
01733 }
01734 #endif
01735 }
01736 return true;
01737 }
01738
01739
01740
01741
01742
01743
01744 bool DXGraphicsStateGuardian9::
01745 draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
01746
01747
01748 _vertices_other_pcollector.add_level(reader->get_num_vertices());
01749 _primitive_batches_other_pcollector.add_level(1);
01750
01751 if (reader->is_indexed()) {
01752 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
01753 int max_vertex = reader->get_max_vertex();
01754
01755
01756 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01757 nassertr(ibc != (IndexBufferContext *)NULL, false);
01758 if (!apply_index_buffer(ibc, reader, force)) {
01759 return false;
01760 }
01761
01762 _d3d_device->DrawIndexedPrimitive( D3DPT_LINELIST,
01763 0,
01764 min_vertex, max_vertex - min_vertex + 1,
01765 0, reader->get_num_primitives() );
01766
01767 #if 0
01768
01769 const unsigned char *index_pointer = reader->get_read_pointer(force);
01770 if (index_pointer == NULL) {
01771 return false;
01772 }
01773 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01774 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01775 if (vertex_pointer == NULL) {
01776 return false;
01777 }
01778
01779 draw_indexed_primitive_up
01780 (D3DPT_LINELIST,
01781 min_vertex, max_vertex,
01782 reader->get_num_primitives(),
01783 index_pointer, index_type, vertex_pointer,
01784 _data_reader->get_format()->get_array(0)->get_stride());
01785 #endif
01786 } else {
01787
01788 _d3d_device->DrawPrimitive( D3DPT_LINELIST,
01789 reader->get_first_vertex(),
01790 reader->get_num_primitives() );
01791
01792 #if 0
01793
01794 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01795 if (vertex_pointer == NULL) {
01796 return false;
01797 }
01798 draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(),
01799 reader->get_first_vertex(),
01800 reader->get_num_vertices(), vertex_pointer,
01801 _data_reader->get_format()->get_array(0)->get_stride());
01802 #endif
01803 }
01804 return true;
01805 }
01806
01807
01808
01809
01810
01811
01812 bool DXGraphicsStateGuardian9::
01813 draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
01814 return false;
01815 }
01816
01817
01818
01819
01820
01821
01822 bool DXGraphicsStateGuardian9::
01823 draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
01824
01825
01826 _vertices_other_pcollector.add_level(reader->get_num_vertices());
01827 _primitive_batches_other_pcollector.add_level(1);
01828
01829
01830
01831 nassertr(!reader->is_indexed(), false);
01832
01833
01834 _d3d_device->DrawPrimitive( D3DPT_POINTLIST,
01835 reader->get_first_vertex(),
01836 reader->get_num_primitives() );
01837
01838 #if 0
01839
01840 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01841 if (vertex_pointer == NULL) {
01842 return false;
01843 }
01844 draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(),
01845 reader->get_first_vertex(),
01846 reader->get_num_vertices(), vertex_pointer,
01847 _data_reader->get_format()->get_array(0)->get_stride());
01848 #endif
01849
01850 return true;
01851 }
01852
01853
01854
01855
01856
01857
01858
01859
01860 void DXGraphicsStateGuardian9::
01861 end_draw_primitives() {
01862
01863
01864 if (_vertex_blending_enabled) {
01865 set_render_state(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
01866 set_render_state(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
01867 _vertex_blending_enabled = false;
01868 }
01869
01870 if (_data_reader->is_vertex_transformed()) {
01871
01872 LMatrix4f mat = LCAST(float, _projection_mat->get_mat());
01873 _d3d_device->SetTransform(D3DTS_PROJECTION,
01874 (D3DMATRIX*)mat.get_data());
01875 }
01876
01877 GraphicsStateGuardian::end_draw_primitives();
01878 }
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889 bool DXGraphicsStateGuardian9::
01890 framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
01891 const RenderBuffer &rb) {
01892 set_read_buffer(rb);
01893
01894 int orig_x = tex->get_x_size();
01895 int orig_y = tex->get_y_size();
01896
01897 HRESULT hr;
01898 int xo, yo, w, h;
01899 dr->get_region_pixels_i(xo, yo, w, h);
01900 tex->set_size_padded(w, h);
01901
01902
01903 tex->set_render_to_texture(true);
01904
01905 int view = dr->get_tex_view_offset();
01906 TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this);
01907 if (tc == (TextureContext *)NULL) {
01908 return false;
01909 }
01910 DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
01911 if (!dtc->create_texture(*_screen)) {
01912
01913 dxgsg9_cat.error()
01914 << "Unable to re-create texture " << *dtc->get_texture() << endl;
01915 return false;
01916 }
01917
01918 if (tex->get_texture_type() != Texture::TT_2d_texture) {
01919
01920
01921 return do_framebuffer_copy_to_ram(tex, z, dr, rb, true);
01922 }
01923 nassertr(dtc->get_d3d_2d_texture() != NULL, false);
01924
01925 IDirect3DSurface9 *tex_level_0;
01926 hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0);
01927 if (FAILED(hr)) {
01928 dxgsg9_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
01929 return false;
01930 }
01931
01932
01933 D3DSURFACE_DESC texdesc;
01934 hr = tex_level_0->GetDesc(&texdesc);
01935 if (FAILED(hr)) {
01936 dxgsg9_cat.error() << "GetDesc failed in copy_texture" << D3DERRORSTRING(hr);
01937 SAFE_RELEASE(tex_level_0);
01938 return false;
01939 }
01940 if ((texdesc.Width != tex->get_x_size())||(texdesc.Height != tex->get_y_size())) {
01941 if ((orig_x != tex->get_x_size()) || (orig_y != tex->get_y_size())) {
01942
01943 SAFE_RELEASE(tex_level_0);
01944 if (!dtc->create_texture(*_screen)) {
01945
01946 dxgsg9_cat.error()
01947 << "Unable to re-create texture " << *dtc->get_texture() << endl;
01948 return false;
01949 }
01950 hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0);
01951 if (FAILED(hr)) {
01952 dxgsg9_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
01953 return false;
01954 }
01955 hr = tex_level_0->GetDesc(&texdesc);
01956 if (FAILED(hr)) {
01957 dxgsg9_cat.error() << "GetDesc 2 failed in copy_texture" << D3DERRORSTRING(hr);
01958 SAFE_RELEASE(tex_level_0);
01959 return false;
01960 }
01961 }
01962 if ((texdesc.Width != tex->get_x_size())||(texdesc.Height != tex->get_y_size())) {
01963
01964
01965 dxgsg9_cat.error()
01966 << "Unable to copy to texture, texture is wrong size: " << *dtc->get_texture() << endl;
01967 SAFE_RELEASE(tex_level_0);
01968 return false;
01969 }
01970 }
01971
01972 DWORD render_target_index;
01973 IDirect3DSurface9 *render_target;
01974
01975
01976 render_target_index = 0;
01977
01978 hr = _d3d_device->GetRenderTarget(render_target_index, &render_target);
01979 if (FAILED(hr)) {
01980 dxgsg9_cat.error()
01981 << "GetRenderTarget failed in framebuffer_copy_to_texture"
01982 << D3DERRORSTRING(hr);
01983 SAFE_RELEASE(tex_level_0);
01984 return false;
01985 }
01986
01987 RECT src_rect;
01988
01989 src_rect.left = xo;
01990 src_rect.right = xo+w;
01991 src_rect.top = yo;
01992 src_rect.bottom = yo+h;
01993
01994
01995
01996
01997
01998 D3DTEXTUREFILTERTYPE filter;
01999
02000 filter = D3DTEXF_POINT;
02001
02002 bool okflag = true;
02003 hr = _d3d_device->StretchRect(render_target, &src_rect,
02004 tex_level_0, &src_rect,
02005 filter);
02006 if (FAILED(hr)) {
02007 dxgsg9_cat.debug()
02008 << "StretchRect failed in framebuffer_copy_to_texture"
02009 << D3DERRORSTRING(hr);
02010 okflag = false;
02011 }
02012
02013 SAFE_RELEASE(render_target);
02014 SAFE_RELEASE(tex_level_0);
02015
02016 if (okflag) {
02017 dtc->mark_loaded();
02018 dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
02019
02020 } else {
02021
02022
02023 return do_framebuffer_copy_to_ram(tex, z, dr, rb, true);
02024 }
02025
02026 return true;
02027 }
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040 bool DXGraphicsStateGuardian9::
02041 framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
02042 const RenderBuffer &rb) {
02043 return do_framebuffer_copy_to_ram(tex, z, dr, rb, false);
02044 }
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055 bool DXGraphicsStateGuardian9::
02056 do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
02057 const RenderBuffer &rb, bool inverted) {
02058 set_read_buffer(rb);
02059
02060 RECT rect;
02061 nassertr(tex != NULL && dr != NULL, false);
02062
02063 int xo, yo, w, h;
02064 dr->get_region_pixels_i(xo, yo, w, h);
02065
02066 Texture::Format format = tex->get_format();
02067 Texture::ComponentType component_type = tex->get_component_type();
02068
02069 switch (format) {
02070 case Texture::F_depth_stencil:
02071
02072 return false;
02073
02074 default:
02075 format = Texture::F_rgb;
02076 component_type = Texture::T_unsigned_byte;
02077 }
02078
02079 Texture::TextureType texture_type;
02080 if (z >= 0) {
02081 texture_type = Texture::TT_cube_map;
02082 } else {
02083 texture_type = Texture::TT_2d_texture;
02084 }
02085
02086 if (tex->get_x_size() != w || tex->get_y_size() != h ||
02087 tex->get_component_type() != component_type ||
02088 tex->get_format() != format ||
02089 tex->get_texture_type() != texture_type) {
02090
02091 tex->setup_texture(texture_type, w, h, tex->get_z_size(),
02092 component_type, format);
02093 }
02094
02095 rect.top = yo;
02096 rect.left = xo;
02097 rect.right = xo + w;
02098 rect.bottom = yo + h;
02099 bool copy_inverted = false;
02100
02101 IDirect3DSurface9 *temp_surface = NULL;
02102 HRESULT hr;
02103
02104
02105
02106
02107 if (_cur_read_pixel_buffer & RenderBuffer::T_back) {
02108 DWORD render_target_index;
02109 IDirect3DSurface9 *backbuffer = NULL;
02110
02111
02112
02113
02114 render_target_index = 0;
02115 hr = _d3d_device->GetRenderTarget(render_target_index, &backbuffer);
02116
02117 if (FAILED(hr)) {
02118 dxgsg9_cat.error() << "GetRenderTarget failed" << D3DERRORSTRING(hr);
02119 return false;
02120 }
02121
02122
02123
02124
02125 D3DPOOL pool;
02126 D3DSURFACE_DESC surface_description;
02127
02128 backbuffer -> GetDesc (&surface_description);
02129
02130 pool = D3DPOOL_SYSTEMMEM;
02131 hr = _d3d_device->CreateOffscreenPlainSurface(
02132 surface_description.Width,
02133 surface_description.Height,
02134 surface_description.Format,
02135 pool,
02136 &temp_surface,
02137 NULL);
02138 if (FAILED(hr)) {
02139 dxgsg9_cat.error()
02140 << "CreateImageSurface failed in copy_pixel_buffer()"
02141 << D3DERRORSTRING(hr);
02142 backbuffer->Release();
02143 return false;
02144 }
02145
02146
02147 hr = _d3d_device -> GetRenderTargetData (backbuffer, temp_surface);
02148 if (FAILED(hr)) {
02149 dxgsg9_cat.error() << "GetRenderTargetData failed" << D3DERRORSTRING(hr);
02150 temp_surface->Release();
02151 backbuffer->Release();
02152 return false;
02153 }
02154
02155 copy_inverted = true;
02156
02157 RELEASE(backbuffer, dxgsg9, "backbuffer", RELEASE_ONCE);
02158
02159 } else if (_cur_read_pixel_buffer & RenderBuffer::T_front) {
02160
02161 if (_screen->_presentation_params.Windowed) {
02162
02163
02164
02165
02166
02167 MONITORINFO minfo;
02168 minfo.cbSize = sizeof(MONITORINFO);
02169 GetMonitorInfo(_screen->_monitor, &minfo);
02170
02171 w = RECT_XSIZE(minfo.rcMonitor);
02172 h = RECT_YSIZE(minfo.rcMonitor);
02173
02174
02175 ClientToScreen(_screen->_window, (POINT*)&rect.left);
02176 ClientToScreen(_screen->_window, (POINT*)&rect.right);
02177 }
02178
02179
02180
02181
02182 hr = _d3d_device->CreateOffscreenPlainSurface(w, h, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &temp_surface, NULL);
02183 if (FAILED(hr)) {
02184 dxgsg9_cat.error()
02185 << "CreateImageSurface failed in copy_pixel_buffer()"
02186 << D3DERRORSTRING(hr);
02187 return false;
02188 }
02189
02190 UINT swap_chain;
02191
02192 swap_chain = 0;
02193 hr = _d3d_device->GetFrontBufferData(swap_chain,temp_surface);
02194
02195 if (hr == D3DERR_DEVICELOST) {
02196 dxgsg9_cat.error()
02197 << "copy_pixel_buffer failed: device lost\n";
02198 temp_surface->Release();
02199 return false;
02200 }
02201
02202 copy_inverted = true;
02203
02204 } else {
02205 dxgsg9_cat.error()
02206 << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n";
02207 temp_surface->Release();
02208 return false;
02209 }
02210
02211 if (inverted) {
02212 copy_inverted = !copy_inverted;
02213 }
02214 DXTextureContext9::d3d_surface_to_texture(rect, temp_surface,
02215 copy_inverted, tex, z);
02216
02217 RELEASE(temp_surface, dxgsg9, "temp_surface", RELEASE_ONCE);
02218
02219 nassertr(tex->has_ram_image(), false);
02220 return true;
02221 }
02222
02223 void DXGraphicsStateGuardian9::reset_render_states (void)
02224 {
02225 int index;
02226 int maximum_texture_stages;
02227
02228 maximum_texture_stages = D3D_MAXTEXTURESTAGES;
02229
02230
02231 memset (_render_state_array, -1, sizeof (_render_state_array));
02232 memset (_texture_stage_states_array, -1, sizeof (_texture_stage_states_array));
02233
02234
02235 _render_state_array [D3DRS_FOGCOLOR] = 0;
02236 _render_state_array [D3DRS_AMBIENT] = 0;
02237
02238
02239 memset (_texture_render_states_array, 0, sizeof (_texture_render_states_array));
02240
02241
02242 for (index = 0; index < MAXIMUM_TEXTURES; index++) {
02243 TextureRenderStates *texture_render_states;
02244
02245 texture_render_states = &_texture_render_states_array [index];
02246 texture_render_states -> state_array [D3DSAMP_MAGFILTER] = D3DTEXF_POINT;
02247 texture_render_states -> state_array [D3DSAMP_MINFILTER] = D3DTEXF_POINT;
02248 texture_render_states -> state_array [D3DSAMP_MAXANISOTROPY] = 1;
02249 }
02250 _num_active_texture_stages = 0;
02251
02252 set_render_state(D3DRS_NORMALIZENORMALS, false);
02253
02254 _last_fvf = 0;
02255 }
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266 void DXGraphicsStateGuardian9::
02267 reset() {
02268 GraphicsStateGuardian::reset();
02269
02270
02271
02272 _inv_state_mask.clear_bit(ShaderAttrib::get_class_slot());
02273 _inv_state_mask.clear_bit(AlphaTestAttrib::get_class_slot());
02274 _inv_state_mask.clear_bit(ClipPlaneAttrib::get_class_slot());
02275 _inv_state_mask.clear_bit(ColorAttrib::get_class_slot());
02276 _inv_state_mask.clear_bit(ColorScaleAttrib::get_class_slot());
02277 _inv_state_mask.clear_bit(CullFaceAttrib::get_class_slot());
02278 _inv_state_mask.clear_bit(DepthOffsetAttrib::get_class_slot());
02279 _inv_state_mask.clear_bit(DepthTestAttrib::get_class_slot());
02280 _inv_state_mask.clear_bit(DepthWriteAttrib::get_class_slot());
02281 _inv_state_mask.clear_bit(RenderModeAttrib::get_class_slot());
02282 _inv_state_mask.clear_bit(RescaleNormalAttrib::get_class_slot());
02283 _inv_state_mask.clear_bit(ShadeModelAttrib::get_class_slot());
02284 _inv_state_mask.clear_bit(TransparencyAttrib::get_class_slot());
02285 _inv_state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
02286 _inv_state_mask.clear_bit(ColorBlendAttrib::get_class_slot());
02287 _inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
02288 _inv_state_mask.clear_bit(TexGenAttrib::get_class_slot());
02289 _inv_state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
02290 _inv_state_mask.clear_bit(MaterialAttrib::get_class_slot());
02291 _inv_state_mask.clear_bit(LightAttrib::get_class_slot());
02292 _inv_state_mask.clear_bit(StencilAttrib::get_class_slot());
02293 _inv_state_mask.clear_bit(FogAttrib::get_class_slot());
02294 _inv_state_mask.clear_bit(ScissorAttrib::get_class_slot());
02295
02296
02297
02298
02299 _supported_geom_rendering =
02300 Geom::GR_point | Geom::GR_point_uniform_size |
02301 Geom::GR_point_perspective | Geom::GR_point_sprite |
02302 Geom::GR_indexed_other |
02303 Geom::GR_triangle_strip | Geom::GR_triangle_fan |
02304 Geom::GR_flat_first_vertex;
02305
02306 _auto_rescale_normal = false;
02307
02308
02309
02310 HRESULT hr;
02311
02312
02313
02314
02315
02316
02317 nassertv(_screen->_d3d9 != NULL);
02318
02319 if (_d3d_device == NULL) {
02320 return;
02321 }
02322
02323 D3DCAPS9 d3d_caps;
02324 _d3d_device->GetDeviceCaps(&d3d_caps);
02325
02326 _vertex_shader_version_major = D3DSHADER_VERSION_MAJOR (d3d_caps.VertexShaderVersion);
02327 _vertex_shader_version_minor = D3DSHADER_VERSION_MINOR (d3d_caps.VertexShaderVersion);
02328 _pixel_shader_version_major = D3DSHADER_VERSION_MAJOR (d3d_caps.PixelShaderVersion);
02329 _pixel_shader_version_minor = D3DSHADER_VERSION_MINOR (d3d_caps.PixelShaderVersion);
02330
02331 _vertex_shader_profile = (char *) D3DXGetVertexShaderProfile (_d3d_device);
02332 _pixel_shader_profile = (char *) D3DXGetPixelShaderProfile (_d3d_device);
02333
02334 _vertex_shader_maximum_constants = d3d_caps.MaxVertexShaderConst;
02335
02336 switch (_pixel_shader_version_major)
02337 {
02338 case 0:
02339 _shader_model = SM_00;
02340 break;
02341 case 1:
02342 _shader_model = SM_11;
02343 break;
02344 case 2:
02345
02346 _shader_model = SM_20;
02347 if (d3d_caps.PS20Caps.NumInstructionSlots >= 512) {
02348 _shader_model = SM_2X;
02349 }
02350 break;
02351 case 3:
02352 _shader_model = SM_30;
02353 break;
02354 case 4:
02355 default:
02356 _shader_model = SM_40;
02357 break;
02358 }
02359
02360 _auto_detect_shader_model = _shader_model;
02361
02362 #ifdef HAVE_CG
02363 set_cg_device(_d3d_device);
02364
02365 if (cgD3D9IsProfileSupported(CG_PROFILE_PS_2_0) &&
02366 cgD3D9IsProfileSupported(CG_PROFILE_VS_2_0)) {
02367 _supports_basic_shaders = true;
02368 _shader_caps._active_vprofile = (int)cgD3D9GetLatestVertexProfile();
02369 _shader_caps._active_fprofile = (int)cgD3D9GetLatestPixelProfile();
02370 _shader_caps._ultimate_vprofile = (int)CG_PROFILE_VS_3_0;
02371 _shader_caps._ultimate_fprofile = (int)CG_PROFILE_PS_3_0;
02372
02373
02374
02375
02376
02377
02378 }
02379
02380 if (dxgsg9_cat.is_debug()) {
02381
02382 CGprofile vertex_profile;
02383 CGprofile pixel_profile;
02384
02385 vertex_profile = cgD3D9GetLatestVertexProfile( );
02386 pixel_profile = cgD3D9GetLatestPixelProfile( );
02387
02388 const char *vertex_profile_str =
02389 cgGetProfileString(vertex_profile);
02390 const char *pixel_profile_str =
02391 cgGetProfileString(pixel_profile);
02392
02393 if (vertex_profile_str == NULL) {
02394 vertex_profile_str = "(null)";
02395 }
02396 if (pixel_profile_str == NULL) {
02397 pixel_profile_str = "(null)";
02398 }
02399
02400 dxgsg9_cat.debug()
02401 << "\nCg vertex profile = " << vertex_profile_str << " id = " << vertex_profile
02402 << "\nCg pixel profile = " << pixel_profile_str << " id = " << pixel_profile
02403 << "\nshader model = " << _shader_model
02404 << "\n";
02405 }
02406 #endif
02407
02408 _supports_stream_offset = (d3d_caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET) != 0;
02409 _screen->_supports_dynamic_textures = ((d3d_caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0);
02410 _screen->_supports_automatic_mipmap_generation = ((d3d_caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0);
02411
02412 if (support_stencil) {
02413 int min_stencil = D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR;
02414 if ((d3d_caps.StencilCaps & min_stencil) == min_stencil) {
02415 if (dxgsg9_cat.is_debug()) {
02416 dxgsg9_cat.debug()
02417 << "Checking for stencil; mode = "
02418 << D3DFormatStr(_screen->_presentation_params.AutoDepthStencilFormat)
02419 << "\n";
02420 }
02421 switch (_screen->_presentation_params.AutoDepthStencilFormat) {
02422
02423 case D3DFMT_D15S1:
02424 case D3DFMT_D24S8:
02425 case D3DFMT_D24X4S4:
02426 _supports_stencil = true;
02427 if (dxgsg9_cat.is_debug()) {
02428 dxgsg9_cat.debug()
02429 << "Stencils supported.\n";
02430 }
02431 break;
02432
02433 default:
02434 if (dxgsg9_cat.is_debug()) {
02435 dxgsg9_cat.debug()
02436 << "Stencils NOT supported.\n";
02437 }
02438 }
02439 }
02440 }
02441
02442 _supports_stencil_wrap = (d3d_caps.StencilCaps & D3DSTENCILCAPS_INCR) && (d3d_caps.StencilCaps & D3DSTENCILCAPS_DECR);
02443 _supports_two_sided_stencil = ((d3d_caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0);
02444
02445 _maximum_simultaneous_render_targets = d3d_caps.NumSimultaneousRTs;
02446
02447 _supports_depth_bias = ((d3d_caps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)) == (D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS));
02448
02449 _supports_gamma_calibration = ((d3d_caps.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA) != 0);
02450
02451
02452 hr = _d3d_device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
02453 _supports_occlusion_query = !FAILED(hr);
02454
02455 if (dxgsg9_cat.is_error()) {
02456 dxgsg9_cat.debug()
02457 << "\nHwTransformAndLight = " << ((d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
02458 << "\nMaxTextureWidth = " << d3d_caps.MaxTextureWidth
02459 << "\nMaxTextureHeight = " << d3d_caps.MaxTextureHeight
02460 << "\nMaxVolumeExtent = " << d3d_caps.MaxVolumeExtent
02461 << "\nMaxTextureAspectRatio = " << d3d_caps.MaxTextureAspectRatio
02462 << "\nTexCoordCount = " << (d3d_caps.FVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK)
02463 << "\nMaxTextureBlendStages = " << d3d_caps.MaxTextureBlendStages
02464 << "\nMaxSimultaneousTextures = " << d3d_caps.MaxSimultaneousTextures
02465 << "\nMaxActiveLights = " << d3d_caps.MaxActiveLights
02466 << "\nMaxUserClipPlanes = " << d3d_caps.MaxUserClipPlanes
02467 << "\nMaxVertexBlendMatrices = " << d3d_caps.MaxVertexBlendMatrices
02468 << "\nMaxVertexBlendMatrixIndex = " << d3d_caps.MaxVertexBlendMatrixIndex
02469 << "\nMaxPointSize = " << d3d_caps.MaxPointSize
02470 << "\nMaxPrimitiveCount = " << d3d_caps.MaxPrimitiveCount
02471 << "\nMaxVertexIndex = " << d3d_caps.MaxVertexIndex
02472 << "\nMaxStreams = " << d3d_caps.MaxStreams
02473 << "\nMaxStreamStride = " << d3d_caps.MaxStreamStride
02474 << "\nD3DTEXOPCAPS_MULTIPLYADD = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) != 0)
02475 << "\nD3DTEXOPCAPS_LERP = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0)
02476 << "\nD3DPMISCCAPS_TSSARGTEMP = " << ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0)
02477 << "\nD3DPRASTERCAPS_DEPTHBIAS = " << ((d3d_caps.RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) != 0)
02478 << "\nD3DPRASTERCAPS_SLOPESCALEDEPTHBIAS = " << ((d3d_caps.RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) != 0)
02479 << "\nVertexShaderVersion = " << _vertex_shader_version_major << "." << _vertex_shader_version_minor
02480 << "\nPixelShaderVersion = " << _pixel_shader_version_major << "." << _pixel_shader_version_minor
02481 << "\nMaxVertexShaderConst = " << _vertex_shader_maximum_constants
02482 << "\nsupports_stream_offset = " << _supports_stream_offset
02483 << "\nsupports_dynamic_textures = " << _screen->_supports_dynamic_textures
02484 << "\nsupports_automatic_mipmap_generation = " << _screen->_supports_automatic_mipmap_generation
02485 << "\nsupports_stencil_wrap = " << _supports_stencil_wrap
02486 << "\nsupports_two_sided_stencil = " << _supports_two_sided_stencil
02487 << "\nsupports_occlusion_query = " << _supports_occlusion_query
02488 << "\nsupports_gamma_calibration = " << _supports_gamma_calibration
02489 << "\nMaxAnisotropy = " << d3d_caps.MaxAnisotropy
02490 << "\nNumSimultaneousRTs = " << d3d_caps.NumSimultaneousRTs
02491 << "\nD3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING = " << ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) != 0)
02492 << "\nDirectX SDK version " DIRECTX_SDK_VERSION
02493 << "\n";
02494 }
02495
02496
02497 _screen->_supports_automatic_mipmap_generation = false;
02498
02499 this -> reset_render_states ( );
02500
02501 _max_vertices_per_array = d3d_caps.MaxVertexIndex;
02502 _max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount;
02503
02504 _max_texture_stages = d3d_caps.MaxSimultaneousTextures;
02505
02506 _max_texture_dimension = min(d3d_caps.MaxTextureWidth, d3d_caps.MaxTextureHeight);
02507
02508 _supports_tex_non_pow2 = !(d3d_caps.TextureCaps & D3DPTEXTURECAPS_POW2);
02509
02510 _supports_texture_combine = ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0);
02511 _supports_texture_saved_result = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0);
02512 _supports_texture_constant_color = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_PERSTAGECONSTANT) != 0);
02513 _supports_texture_dot3 = true;
02514
02515 if (_supports_texture_constant_color) {
02516 _constant_color_operand = D3DTA_CONSTANT;
02517 } else {
02518 _constant_color_operand = D3DTA_TFACTOR;
02519 }
02520
02521 _screen->_managed_textures = _gsg_managed_textures;
02522 _screen->_managed_vertex_buffers = _gsg_managed_vertex_buffers;
02523 _screen->_managed_index_buffers = _gsg_managed_index_buffers;
02524
02525 UINT available_texture_memory;
02526
02527 available_texture_memory = _d3d_device->GetAvailableTextureMem ( );
02528 if (dxgsg9_cat.is_debug()) {
02529 dxgsg9_cat.debug() << "*** GetAvailableTextureMem = " << available_texture_memory << "\n";
02530 }
02531 _available_texture_memory = available_texture_memory;
02532
02533
02534 D3DDEVICE_CREATION_PARAMETERS creation_parameters;
02535
02536 _supports_render_texture = false;
02537 _screen->_render_to_texture_d3d_format = D3DFMT_UNKNOWN;
02538 _screen->_framebuffer_d3d_format = D3DFMT_UNKNOWN;
02539
02540 #define TOTAL_RENDER_TO_TEXTURE_FORMATS 3
02541
02542 D3DFORMAT render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS] =
02543 {
02544 D3DFMT_A8R8G8B8,
02545 D3DFMT_X8R8G8B8,
02546 D3DFMT_UNKNOWN,
02547 };
02548
02549 render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS - 1] = _screen->_display_mode.Format;
02550
02551 hr = _d3d_device->GetCreationParameters (&creation_parameters);
02552 if (SUCCEEDED (hr)) {
02553 _screen->_framebuffer_d3d_format = _screen->_display_mode.Format;
02554
02555 int index;
02556 for (index = 0; index < TOTAL_RENDER_TO_TEXTURE_FORMATS; index++) {
02557 hr = _screen->_d3d9->CheckDeviceFormat (
02558 creation_parameters.AdapterOrdinal,
02559 creation_parameters.DeviceType,
02560 _screen->_display_mode.Format,
02561 D3DUSAGE_RENDERTARGET,
02562 D3DRTYPE_TEXTURE,
02563 render_to_texture_formats [index]);
02564 if (SUCCEEDED (hr)) {
02565 _screen->_render_to_texture_d3d_format = render_to_texture_formats [index];
02566 _supports_render_texture = true;
02567 }
02568 if (_supports_render_texture) {
02569 break;
02570 }
02571 }
02572 }
02573 if (dxgsg9_cat.is_debug()) {
02574 dxgsg9_cat.debug() << "Render to Texture Support = " << _supports_render_texture << "\n";
02575 }
02576
02577
02578
02579
02580 _supports_3d_texture = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) != 0);
02581 if (_supports_3d_texture) {
02582 _max_3d_texture_dimension = d3d_caps.MaxVolumeExtent;
02583 }
02584 _supports_cube_map = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) != 0);
02585 if (_supports_cube_map) {
02586 _max_cube_map_dimension = _max_texture_dimension;
02587 }
02588
02589 _max_lights = (int)d3d_caps.MaxActiveLights;
02590 _max_clip_planes = (int)d3d_caps.MaxUserClipPlanes;
02591 _max_vertex_transforms = d3d_caps.MaxVertexBlendMatrices;
02592 _max_vertex_transform_indices = d3d_caps.MaxVertexBlendMatrixIndex;
02593
02594 set_render_state(D3DRS_AMBIENT, 0x0);
02595
02596 _clip_plane_bits = 0;
02597 set_render_state(D3DRS_CLIPPLANEENABLE , 0x0);
02598
02599 set_render_state(D3DRS_CLIPPING, true);
02600
02601 set_render_state(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
02602
02603 set_render_state(D3DRS_ZWRITEENABLE, TRUE);
02604
02605
02606
02607
02608 set_render_state(D3DRS_ZENABLE, D3DZB_FALSE);
02609
02610 set_render_state(D3DRS_ALPHABLENDENABLE, FALSE);
02611
02612 set_render_state(D3DRS_FOGENABLE, FALSE);
02613
02614 _has_scene_graph_color = false;
02615
02616 _last_testcooplevel_result = D3D_OK;
02617
02618 for(int i = 0; i < MAX_POSSIBLE_TEXFMTS; i++) {
02619
02620 D3DFORMAT_FLAG fmtflag = D3DFORMAT_FLAG(1 << i);
02621 hr = _screen->_d3d9->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format,
02622 0x0, D3DRTYPE_TEXTURE, g_D3DFORMATmap[fmtflag]);
02623 if (SUCCEEDED(hr)){
02624 _screen->_supported_tex_formats_mask |= fmtflag;
02625 }
02626 }
02627
02628
02629 #define CHECK_FOR_DXTVERSION(num) \
02630 if (_screen->_supported_tex_formats_mask & DXT##num##_FLAG) {\
02631 if (dxgsg9_cat.is_debug()) {\
02632 dxgsg9_cat.debug() << "Compressed texture format DXT" << #num << " supported \n";\
02633 }\
02634 _supports_compressed_texture = true;\
02635 _compressed_texture_formats.set_bit(Texture::CM_dxt##num);\
02636 }
02637
02638 if (_screen->_intel_compressed_texture_bug) {
02639 dxgsg9_cat.info()
02640 << "Buggy Intel driver detected; disabling compressed textures.\n";
02641 _screen->_supported_tex_formats_mask &=
02642 ~(DXT1_FLAG | DXT2_FLAG | DXT3_FLAG | DXT4_FLAG | DXT5_FLAG);
02643
02644 } else {
02645
02646 CHECK_FOR_DXTVERSION(1);
02647 CHECK_FOR_DXTVERSION(2);
02648 CHECK_FOR_DXTVERSION(3);
02649 CHECK_FOR_DXTVERSION(4);
02650 CHECK_FOR_DXTVERSION(5);
02651 }
02652
02653 #undef CHECK_FOR_DXTVERSION
02654
02655 _screen->_supports_rgba16f_texture_format = false;
02656 hr = _screen->_d3d9->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format, 0x0, D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F);
02657 if (SUCCEEDED(hr)){
02658 _screen->_supports_rgba16f_texture_format = true;
02659 }
02660 _screen->_supports_rgba32_texture_format = false;
02661 hr = _screen->_d3d9->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format, 0x0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F);
02662 if (SUCCEEDED(hr)){
02663 _screen->_supports_rgba32_texture_format = true;
02664 }
02665
02666
02667 if (_screen->_d3dcaps.MaxTextureWidth == 0)
02668 _screen->_d3dcaps.MaxTextureWidth = 256;
02669
02670 if (_screen->_d3dcaps.MaxTextureHeight == 0)
02671 _screen->_d3dcaps.MaxTextureHeight = 256;
02672
02673 if (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) {
02674
02675
02676
02677
02678 _do_fog_type = PerPixelFog;
02679 } else {
02680
02681
02682 nassertv((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0);
02683
02684
02685
02686
02687 if (dx_no_vertex_fog) {
02688 _do_fog_type = None;
02689 } else {
02690 _do_fog_type = PerVertexFog;
02691
02692
02693 if (dx_use_rangebased_fog && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)) {
02694 set_render_state(D3DRS_RANGEFOGENABLE, true);
02695 }
02696 }
02697 }
02698
02699 _screen->_can_direct_disable_color_writes = ((_screen->_d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0);
02700
02701
02702 set_render_state(D3DRS_LIGHTING, false);
02703
02704
02705 bool dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(_screen->_presentation_params.BackBufferFormat)
02706 && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER));
02707 set_render_state(D3DRS_DITHERENABLE, dither_enabled);
02708
02709 set_render_state(D3DRS_CLIPPING, true);
02710
02711
02712 set_render_state(D3DRS_STENCILENABLE, FALSE);
02713 if (_supports_two_sided_stencil) {
02714 set_render_state(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
02715 }
02716
02717
02718
02719
02720
02721 _current_fill_mode = RenderModeAttrib::M_filled;
02722 set_render_state(D3DRS_FILLMODE, D3DFILL_SOLID);
02723
02724
02725
02726
02727 set_texture_stage_state(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
02728
02729 _cull_face_mode = CullFaceAttrib::M_cull_none;
02730 set_render_state(D3DRS_CULLMODE, D3DCULL_NONE);
02731
02732 set_render_state(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
02733 set_render_state(D3DRS_ALPHAREF, 255);
02734 set_render_state(D3DRS_ALPHATESTENABLE, FALSE);
02735
02736
02737
02738 set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD);
02739
02740 _current_shader = (Shader *)NULL;
02741 _current_shader_context = (CLP(ShaderContext) *)NULL;
02742 _vertex_array_shader = (Shader *)NULL;
02743 _vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
02744 _texture_binding_shader = (Shader *)NULL;
02745 _texture_binding_shader_context = (CLP(ShaderContext) *)NULL;
02746
02747 PRINT_REFCNT(dxgsg9, _d3d_device);
02748
02749 void dx_set_stencil_functions (StencilRenderStates *stencil_render_states);
02750 dx_set_stencil_functions (_stencil_render_states);
02751
02752
02753
02754 add_gsg(this);
02755 }
02756
02757
02758
02759
02760
02761
02762 void DXGraphicsStateGuardian9::
02763 apply_fog(Fog *fog) {
02764 if (_do_fog_type == None)
02765 return;
02766
02767 Fog::Mode panda_fogmode = fog->get_mode();
02768 D3DFOGMODE d3dfogmode = get_fog_mode_type(panda_fogmode);
02769
02770 set_render_state((D3DRENDERSTATETYPE)_do_fog_type, d3dfogmode);
02771
02772 const LColor &fog_colr = fog->get_color();
02773 set_render_state(D3DRS_FOGCOLOR,
02774 MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f));
02775
02776
02777
02778
02779 switch (panda_fogmode) {
02780 case Fog::M_linear:
02781 {
02782 PN_stdfloat onset, opaque;
02783 fog->get_linear_range(onset, opaque);
02784
02785 set_render_state(D3DRS_FOGSTART,
02786 *((LPDWORD) (&onset)));
02787 set_render_state(D3DRS_FOGEND,
02788 *((LPDWORD) (&opaque)));
02789 }
02790 break;
02791 case Fog::M_exponential:
02792 case Fog::M_exponential_squared:
02793 {
02794
02795 PN_stdfloat fog_density = fog->get_exp_density();
02796 set_render_state(D3DRS_FOGDENSITY,
02797 *((LPDWORD) (&fog_density)));
02798 }
02799 break;
02800 }
02801 }
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812 void DXGraphicsStateGuardian9::
02813 do_issue_transform() {
02814 const TransformState *transform = _internal_transform;
02815 DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1));
02816
02817 if (_current_shader_context) {
02818
02819 _current_shader_context->issue_parameters(this, Shader::SSD_transform);
02820
02821
02822 LMatrix4f mat = LCAST(float, transform->get_mat());
02823 const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data();
02824 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
02825
02826 }
02827 else {
02828 LMatrix4f mat = LCAST(float, transform->get_mat());
02829 const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data();
02830 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843 }
02844
02845 _transform_stale = false;
02846
02847 if (_auto_rescale_normal) {
02848 do_auto_rescale_normal();
02849 }
02850 }
02851
02852
02853
02854
02855
02856
02857 void DXGraphicsStateGuardian9::
02858 do_issue_alpha_test() {
02859 if (_target_shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
02860 set_render_state(D3DRS_ALPHATESTENABLE, FALSE);
02861 } else {
02862 const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
02863 AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode();
02864 if (mode == AlphaTestAttrib::M_none) {
02865 set_render_state(D3DRS_ALPHATESTENABLE, FALSE);
02866 } else {
02867
02868 set_render_state(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode);
02869 set_render_state(D3DRS_ALPHAREF, (UINT) (target_alpha_test->get_reference_alpha()*255.0f));
02870 set_render_state(D3DRS_ALPHATESTENABLE, TRUE);
02871 }
02872 }
02873 }
02874
02875
02876
02877
02878
02879
02880 void DXGraphicsStateGuardian9::
02881 do_issue_shader() {
02882
02883 CLP(ShaderContext) *context = 0;
02884 Shader *shader = 0;
02885 if (_target_shader) {
02886 shader = (Shader *)(_target_shader->get_shader());
02887 }
02888 if (shader) {
02889 context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));
02890 }
02891
02892 if (context == 0 || (context && context -> valid (this) == false)) {
02893 if (_current_shader_context != 0) {
02894 _current_shader_context->unbind(this);
02895 _current_shader = 0;
02896 _current_shader_context = 0;
02897 disable_standard_texture_bindings();
02898 }
02899 return;
02900 }
02901
02902 if (context != _current_shader_context) {
02903
02904
02905 if (_current_shader_context != 0) {
02906 _current_shader_context->unbind(this);
02907 _current_shader_context = 0;
02908 _current_shader = 0;
02909 disable_standard_texture_bindings();
02910 }
02911 if (context != 0) {
02912 context->bind(this);
02913 _current_shader = shader;
02914 _current_shader_context = context;
02915 }
02916 } else {
02917
02918 context->issue_parameters(this, Shader::SSD_shaderinputs);
02919 }
02920 }
02921
02922
02923
02924
02925
02926
02927 void DXGraphicsStateGuardian9::
02928 do_issue_render_mode() {
02929 const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()));
02930 RenderModeAttrib::Mode mode = target_render_mode->get_mode();
02931
02932 switch (mode) {
02933 case RenderModeAttrib::M_unchanged:
02934 case RenderModeAttrib::M_filled:
02935 case RenderModeAttrib::M_filled_flat:
02936 set_render_state(D3DRS_FILLMODE, D3DFILL_SOLID);
02937 break;
02938
02939 case RenderModeAttrib::M_wireframe:
02940 set_render_state(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
02941 break;
02942
02943 case RenderModeAttrib::M_point:
02944 set_render_state(D3DRS_FILLMODE, D3DFILL_POINT);
02945 break;
02946
02947 default:
02948 dxgsg9_cat.error()
02949 << "Unknown render mode " << (int)mode << endl;
02950 }
02951
02952
02953 PN_stdfloat point_size = target_render_mode->get_thickness();
02954 set_render_state(D3DRS_POINTSIZE, *((DWORD*)&point_size));
02955
02956 if (target_render_mode->get_perspective()) {
02957 set_render_state(D3DRS_POINTSCALEENABLE, TRUE);
02958
02959 LVector3 height(0.0f, point_size, 1.0f);
02960 height = height * _projection_mat->get_mat();
02961 PN_stdfloat s = height[1] / point_size;
02962
02963 PN_stdfloat zero = 0.0f;
02964 PN_stdfloat one_over_s2 = 1.0f / (s * s);
02965 set_render_state(D3DRS_POINTSCALE_A, *((DWORD*)&zero));
02966 set_render_state(D3DRS_POINTSCALE_B, *((DWORD*)&zero));
02967 set_render_state(D3DRS_POINTSCALE_C, *((DWORD*)&one_over_s2));
02968
02969 } else {
02970 set_render_state(D3DRS_POINTSCALEENABLE, FALSE);
02971 }
02972
02973 _current_fill_mode = mode;
02974 }
02975
02976
02977
02978
02979
02980
02981 void DXGraphicsStateGuardian9::
02982 do_issue_rescale_normal() {
02983 const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()));
02984 RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
02985
02986 _auto_rescale_normal = false;
02987
02988 switch (mode) {
02989 case RescaleNormalAttrib::M_none:
02990 set_render_state(D3DRS_NORMALIZENORMALS, false);
02991 break;
02992
02993 case RescaleNormalAttrib::M_rescale:
02994 case RescaleNormalAttrib::M_normalize:
02995 set_render_state(D3DRS_NORMALIZENORMALS, true);
02996 break;
02997
02998 case RescaleNormalAttrib::M_auto:
02999 _auto_rescale_normal = true;
03000 do_auto_rescale_normal();
03001 break;
03002
03003 default:
03004 dxgsg9_cat.error()
03005 << "Unknown rescale_normal mode " << (int)mode << endl;
03006 }
03007 }
03008
03009
03010
03011
03012
03013
03014 void DXGraphicsStateGuardian9::
03015 do_issue_depth_test() {
03016 const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
03017 DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode();
03018 if (mode == DepthTestAttrib::M_none) {
03019 set_render_state(D3DRS_ZENABLE, D3DZB_FALSE);
03020 } else {
03021 set_render_state(D3DRS_ZENABLE, D3DZB_TRUE);
03022 set_render_state(D3DRS_ZFUNC, (D3DCMPFUNC) mode);
03023 }
03024 }
03025
03026
03027
03028
03029
03030
03031 void DXGraphicsStateGuardian9::
03032 do_issue_depth_write() {
03033 const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
03034 DepthWriteAttrib::Mode mode = target_depth_write->get_mode();
03035 if (mode == DepthWriteAttrib::M_on) {
03036 set_render_state(D3DRS_ZWRITEENABLE, TRUE);
03037 } else {
03038 set_render_state(D3DRS_ZWRITEENABLE, FALSE);
03039 }
03040 }
03041
03042
03043
03044
03045
03046
03047 void DXGraphicsStateGuardian9::
03048 do_issue_cull_face() {
03049 const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()));
03050 _cull_face_mode = target_cull_face->get_effective_mode();
03051
03052 switch (_cull_face_mode) {
03053 case CullFaceAttrib::M_cull_none:
03054 set_render_state(D3DRS_CULLMODE, D3DCULL_NONE);
03055
03056
03057
03058 break;
03059 case CullFaceAttrib::M_cull_clockwise:
03060 set_render_state(D3DRS_CULLMODE, D3DCULL_CW);
03061
03062
03063
03064 break;
03065 case CullFaceAttrib::M_cull_counter_clockwise:
03066 set_render_state(D3DRS_CULLMODE, D3DCULL_CCW);
03067
03068
03069
03070 break;
03071 default:
03072 dxgsg9_cat.error()
03073 << "invalid cull face mode " << (int)_cull_face_mode << endl;
03074 break;
03075 }
03076 }
03077
03078
03079
03080
03081
03082
03083 void DXGraphicsStateGuardian9::
03084 do_issue_fog() {
03085 const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
03086 if (!target_fog->is_off()) {
03087 set_render_state(D3DRS_FOGENABLE, TRUE);
03088 Fog *fog = target_fog->get_fog();
03089 nassertv(fog != (Fog *)NULL);
03090 apply_fog(fog);
03091 } else {
03092 set_render_state(D3DRS_FOGENABLE, FALSE);
03093 }
03094 }
03095
03096
03097
03098
03099
03100
03101 void DXGraphicsStateGuardian9::
03102 do_issue_depth_offset() {
03103 const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
03104 int offset = target_depth_offset->get_offset();
03105
03106 if (_supports_depth_bias && !dx_broken_depth_bias) {
03107 set_render_state(D3DRS_DEPTHBIAS, offset);
03108 set_render_state(D3DRS_SLOPESCALEDEPTHBIAS, offset);
03109
03110 } else {
03111
03112
03113
03114 static const PN_stdfloat bias_scale = dx_depth_bias_scale;
03115 D3DVIEWPORT9 vp = _current_viewport;
03116 vp.MinZ -= bias_scale * offset;
03117 vp.MaxZ -= bias_scale * offset;
03118 _d3d_device->SetViewport(&vp);
03119 }
03120 }
03121
03122
03123
03124
03125
03126
03127 void DXGraphicsStateGuardian9::
03128 do_issue_shade_model() {
03129 const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()));
03130 switch (target_shade_model->get_mode()) {
03131 case ShadeModelAttrib::M_smooth:
03132 set_render_state(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
03133 break;
03134
03135 case ShadeModelAttrib::M_flat:
03136 set_render_state(D3DRS_SHADEMODE, D3DSHADE_FLAT);
03137 break;
03138 }
03139 }
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158 void DXGraphicsStateGuardian9::
03159 set_state_and_transform(const RenderState *target,
03160 const TransformState *transform) {
03161 #ifndef NDEBUG
03162 if (gsg_cat.is_spam()) {
03163 gsg_cat.spam() << "Setting GSG state to " << (void *)target << ":\n";
03164 target->write(gsg_cat.spam(false), 2);
03165 }
03166 #endif
03167 _state_pcollector.add_level(1);
03168 PStatTimer timer1(_draw_set_state_pcollector);
03169
03170 if (transform != _internal_transform) {
03171
03172 _state_pcollector.add_level(1);
03173 _internal_transform = transform;
03174 do_issue_transform();
03175 }
03176
03177 if (target == _state_rs && (_state_mask | _inv_state_mask).is_all_on()) {
03178 return;
03179 }
03180 _target_rs = target;
03181
03182 _target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()));
03183 if (_target_shader->auto_shader()) {
03184
03185 if (_target_rs->_generated_shader == NULL) {
03186 if (_shader_generator == NULL) {
03187 _shader_generator = new ShaderGenerator(this, _scene_setup->get_display_region()->get_window());
03188 }
03189 const_cast<RenderState*>(_target_rs.p())->_generated_shader = DCAST(ShaderAttrib, _shader_generator->synthesize_shader(_target_rs));
03190 }
03191 _target_shader = DCAST(ShaderAttrib, _target_rs->_generated_shader);
03192 }
03193
03194 int alpha_test_slot = AlphaTestAttrib::get_class_slot();
03195 if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
03196 !_state_mask.get_bit(alpha_test_slot)) {
03197
03198 do_issue_alpha_test();
03199 _state_mask.set_bit(alpha_test_slot);
03200 }
03201
03202 int clip_plane_slot = ClipPlaneAttrib::get_class_slot();
03203 if (_target_rs->get_attrib(clip_plane_slot) != _state_rs->get_attrib(clip_plane_slot) ||
03204 !_state_mask.get_bit(clip_plane_slot)) {
03205
03206 do_issue_clip_plane();
03207 _state_mask.set_bit(clip_plane_slot);
03208 }
03209
03210 int color_slot = ColorAttrib::get_class_slot();
03211 int color_scale_slot = ColorScaleAttrib::get_class_slot();
03212 if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
03213 _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
03214 !_state_mask.get_bit(color_slot) ||
03215 !_state_mask.get_bit(color_scale_slot)) {
03216
03217 do_issue_color();
03218 do_issue_color_scale();
03219 _state_mask.set_bit(color_slot);
03220 _state_mask.set_bit(color_scale_slot);
03221 if (_current_shader_context) {
03222 _current_shader_context->issue_parameters(this, Shader::SSD_color);
03223 _current_shader_context->issue_parameters(this, Shader::SSD_colorscale);
03224 }
03225 }
03226
03227 int cull_face_slot = CullFaceAttrib::get_class_slot();
03228 if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
03229 !_state_mask.get_bit(cull_face_slot)) {
03230
03231 do_issue_cull_face();
03232 _state_mask.set_bit(cull_face_slot);
03233 }
03234
03235 int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
03236 if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
03237 !_state_mask.get_bit(depth_offset_slot)) {
03238
03239 do_issue_depth_offset();
03240 _state_mask.set_bit(depth_offset_slot);
03241 }
03242
03243 int depth_test_slot = DepthTestAttrib::get_class_slot();
03244 if (_target_rs->get_attrib(depth_test_slot) != _state_rs->get_attrib(depth_test_slot) ||
03245 !_state_mask.get_bit(depth_test_slot)) {
03246
03247 do_issue_depth_test();
03248 _state_mask.set_bit(depth_test_slot);
03249 }
03250
03251 int depth_write_slot = DepthWriteAttrib::get_class_slot();
03252 if (_target_rs->get_attrib(depth_write_slot) != _state_rs->get_attrib(depth_write_slot) ||
03253 !_state_mask.get_bit(depth_write_slot)) {
03254
03255 do_issue_depth_write();
03256 _state_mask.set_bit(depth_write_slot);
03257 }
03258
03259 int render_mode_slot = RenderModeAttrib::get_class_slot();
03260 if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
03261 !_state_mask.get_bit(render_mode_slot)) {
03262
03263 do_issue_render_mode();
03264 _state_mask.set_bit(render_mode_slot);
03265 }
03266
03267 int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
03268 if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
03269 !_state_mask.get_bit(rescale_normal_slot)) {
03270
03271 do_issue_rescale_normal();
03272 _state_mask.set_bit(rescale_normal_slot);
03273 }
03274
03275 int shade_model_slot = ShadeModelAttrib::get_class_slot();
03276 if (_target_rs->get_attrib(shade_model_slot) != _state_rs->get_attrib(shade_model_slot) ||
03277 !_state_mask.get_bit(shade_model_slot)) {
03278
03279 do_issue_shade_model();
03280 _state_mask.set_bit(shade_model_slot);
03281 }
03282
03283 int transparency_slot = TransparencyAttrib::get_class_slot();
03284 int color_write_slot = ColorWriteAttrib::get_class_slot();
03285 int color_blend_slot = ColorBlendAttrib::get_class_slot();
03286 if (_target_rs->get_attrib(transparency_slot) != _state_rs->get_attrib(transparency_slot) ||
03287 _target_rs->get_attrib(color_write_slot) != _state_rs->get_attrib(color_write_slot) ||
03288 _target_rs->get_attrib(color_blend_slot) != _state_rs->get_attrib(color_blend_slot) ||
03289 !_state_mask.get_bit(transparency_slot) ||
03290 !_state_mask.get_bit(color_write_slot) ||
03291 !_state_mask.get_bit(color_blend_slot) ||
03292 (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
03293 _state_shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
03294
03295 do_issue_blending();
03296 _state_mask.set_bit(transparency_slot);
03297 _state_mask.set_bit(color_write_slot);
03298 _state_mask.set_bit(color_blend_slot);
03299 }
03300
03301 if (_target_shader != _state_shader) {
03302
03303 do_issue_shader();
03304 _state_shader = _target_shader;
03305 _state_mask.clear_bit(TextureAttrib::get_class_slot());
03306 }
03307
03308 int texture_slot = TextureAttrib::get_class_slot();
03309 int tex_matrix_slot = TexMatrixAttrib::get_class_slot();
03310 int tex_gen_slot = TexGenAttrib::get_class_slot();
03311 if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
03312 _target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) ||
03313 _target_rs->get_attrib(tex_gen_slot) != _state_rs->get_attrib(tex_gen_slot) ||
03314 !_state_mask.get_bit(texture_slot) ||
03315 !_state_mask.get_bit(tex_matrix_slot) ||
03316 !_state_mask.get_bit(tex_gen_slot)) {
03317
03318 determine_target_texture();
03319 do_issue_texture();
03320
03321 _state_texture = _target_texture;
03322 _state_mask.set_bit(texture_slot);
03323 _state_mask.set_bit(tex_matrix_slot);
03324 _state_mask.set_bit(tex_gen_slot);
03325 }
03326
03327 int material_slot = MaterialAttrib::get_class_slot();
03328 if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
03329 !_state_mask.get_bit(material_slot)) {
03330
03331 do_issue_material();
03332 _state_mask.set_bit(material_slot);
03333 if (_current_shader_context) {
03334 _current_shader_context->issue_parameters(this, Shader::SSD_material);
03335 }
03336 }
03337
03338 int light_slot = LightAttrib::get_class_slot();
03339 if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
03340 !_state_mask.get_bit(light_slot)) {
03341
03342 do_issue_light();
03343 _state_mask.set_bit(light_slot);
03344 }
03345
03346 int stencil_slot = StencilAttrib::get_class_slot();
03347 if (_target_rs->get_attrib(stencil_slot) != _state_rs->get_attrib(stencil_slot) ||
03348 !_state_mask.get_bit(stencil_slot)) {
03349
03350 do_issue_stencil();
03351 _state_mask.set_bit(stencil_slot);
03352 }
03353
03354 int fog_slot = FogAttrib::get_class_slot();
03355 if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) ||
03356 !_state_mask.get_bit(fog_slot)) {
03357
03358 do_issue_fog();
03359 _state_mask.set_bit(fog_slot);
03360 if (_current_shader_context) {
03361 _current_shader_context->issue_parameters(this, Shader::SSD_fog);
03362 }
03363 }
03364
03365 int scissor_slot = ScissorAttrib::get_class_slot();
03366 if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
03367 !_state_mask.get_bit(scissor_slot)) {
03368
03369 do_issue_scissor();
03370 _state_mask.set_bit(scissor_slot);
03371 }
03372
03373 _state_rs = _target_rs;
03374 }
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384 void DXGraphicsStateGuardian9::
03385 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
03386
03387
03388
03389 CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
03390 const LMatrix4 &light_mat = transform->get_mat();
03391 LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
03392 LPoint3f pos = LCAST(float, light_obj->get_point() * rel_mat);
03393
03394 D3DCOLORVALUE black;
03395 black.r = black.g = black.b = black.a = 0.0f;
03396 D3DLIGHT9 alight;
03397 alight.Type = D3DLIGHT_POINT;
03398 alight.Diffuse = get_light_color(light_obj);
03399 alight.Ambient = black ;
03400 LColorf color = LCAST(float, light_obj->get_specular_color());
03401 alight.Specular = *(D3DCOLORVALUE *)(color.get_data());
03402
03403
03404
03405 alight.Position = *(D3DVECTOR *)pos.get_data();
03406
03407 alight.Range = __D3DLIGHT_RANGE_MAX;
03408 alight.Falloff = 1.0f;
03409
03410 const LVecBase3 &att = light_obj->get_attenuation();
03411 alight.Attenuation0 = att[0];
03412 alight.Attenuation1 = att[1];
03413 alight.Attenuation2 = att[2];
03414
03415 HRESULT hr = _d3d_device->SetLight(light_id, &alight);
03416 if (FAILED(hr)) {
03417 wdxdisplay9_cat.warning()
03418 << "Could not set light properties for " << light
03419 << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n";
03420 }
03421 }
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431 void DXGraphicsStateGuardian9::
03432 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
03433 static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
03434
03435
03436 pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT9()));
03437 D3DLIGHT9 &fdata = (*lookup.first).second;
03438 if (lookup.second) {
03439
03440
03441
03442 CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
03443 const LMatrix4 &light_mat = transform->get_mat();
03444 LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
03445 LVector3f dir = LCAST(float, light_obj->get_direction() * rel_mat);
03446
03447 D3DCOLORVALUE black;
03448 black.r = black.g = black.b = black.a = 0.0f;
03449
03450 ZeroMemory(&fdata, sizeof(D3DLIGHT9));
03451
03452 fdata.Type = D3DLIGHT_DIRECTIONAL;
03453 fdata.Ambient = black ;
03454 LColorf color = LCAST(float, light_obj->get_specular_color());
03455 fdata.Specular = *(D3DCOLORVALUE *)(color.get_data());
03456
03457 fdata.Direction = *(D3DVECTOR *)dir.get_data();
03458
03459 fdata.Range = __D3DLIGHT_RANGE_MAX;
03460 fdata.Falloff = 1.0f;
03461
03462 fdata.Attenuation0 = 1.0f;
03463 fdata.Attenuation1 = 0.0f;
03464 fdata.Attenuation2 = 0.0f;
03465 }
03466
03467
03468
03469
03470 fdata.Diffuse = get_light_color(light_obj);
03471
03472 HRESULT hr = _d3d_device->SetLight(light_id, &fdata);
03473 if (FAILED(hr)) {
03474 wdxdisplay9_cat.warning()
03475 << "Could not set light properties for " << light
03476 << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n";
03477 }
03478 }
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488 void DXGraphicsStateGuardian9::
03489 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
03490 Lens *lens = light_obj->get_lens();
03491 nassertv(lens != (Lens *)NULL);
03492
03493
03494
03495
03496 CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
03497 const LMatrix4 &light_mat = transform->get_mat();
03498 LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
03499 LPoint3f pos = LCAST(float, lens->get_nodal_point() * rel_mat);
03500 LVector3f dir = LCAST(float, lens->get_view_vector() * rel_mat);
03501
03502 D3DCOLORVALUE black;
03503 black.r = black.g = black.b = black.a = 0.0f;
03504
03505 D3DLIGHT9 alight;
03506 ZeroMemory(&alight, sizeof(D3DLIGHT9));
03507
03508 alight.Type = D3DLIGHT_SPOT;
03509 alight.Ambient = black ;
03510 alight.Diffuse = get_light_color(light_obj);
03511 LColorf color = LCAST(float, light_obj->get_specular_color());
03512 alight.Specular = *(D3DCOLORVALUE *)(color.get_data());
03513
03514 alight.Position = *(D3DVECTOR *)pos.get_data();
03515
03516 alight.Direction = *(D3DVECTOR *)dir.get_data();
03517
03518 alight.Range = __D3DLIGHT_RANGE_MAX;
03519
03520
03521
03522
03523 PN_stdfloat fov = lens->get_hfov();
03524 alight.Falloff = light_obj->get_exponent() * (fov * fov * fov) / 1620000.0f;
03525
03526 alight.Theta = 0.0f;
03527 alight.Phi = deg_2_rad(fov);
03528
03529 const LVecBase3 &att = light_obj->get_attenuation();
03530 alight.Attenuation0 = att[0];
03531 alight.Attenuation1 = att[1];
03532 alight.Attenuation2 = att[2];
03533
03534 HRESULT hr = _d3d_device->SetLight(light_id, &alight);
03535 if (FAILED(hr)) {
03536 wdxdisplay9_cat.warning()
03537 << "Could not set light properties for " << light
03538 << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n";
03539 }
03540 }
03541
03542
03543
03544
03545
03546
03547
03548 D3DFORMAT DXGraphicsStateGuardian9::
03549 get_index_type(Geom::NumericType numeric_type) {
03550 switch (numeric_type) {
03551 case Geom::NT_uint16:
03552 return D3DFMT_INDEX16;
03553
03554 case Geom::NT_uint32:
03555 return D3DFMT_INDEX32;
03556 }
03557
03558 dxgsg9_cat.error()
03559 << "Invalid index NumericType value (" << (int)numeric_type << ")\n";
03560 return D3DFMT_INDEX16;
03561 }
03562
03563
03564
03565
03566
03567
03568 void DXGraphicsStateGuardian9::
03569 do_issue_material() {
03570 static Material empty;
03571 const Material *material;
03572 const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
03573 if (target_material->is_off()) {
03574 material = ∅
03575 } else {
03576 material = target_material->get_material();
03577 }
03578
03579 D3DMATERIAL9 cur_material;
03580 LColorf color = LCAST(float, material->get_diffuse());
03581 cur_material.Diffuse = *(D3DCOLORVALUE *)(color.get_data());
03582 color = LCAST(float, material->get_ambient());
03583 cur_material.Ambient = *(D3DCOLORVALUE *)(color.get_data());
03584 color = LCAST(float, material->get_specular());
03585 cur_material.Specular = *(D3DCOLORVALUE *)(color.get_data());
03586 color = LCAST(float, material->get_emission());
03587 cur_material.Emissive = *(D3DCOLORVALUE *)(color.get_data());
03588 cur_material.Power = material->get_shininess();
03589
03590 if (material->has_diffuse()) {
03591
03592 set_render_state(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
03593 } else {
03594
03595 if (_has_material_force_color) {
03596 color = LCAST(float, _material_force_color);
03597 cur_material.Diffuse = *(D3DCOLORVALUE *)color.get_data();
03598 set_render_state(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
03599 } else {
03600 set_render_state(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
03601 }
03602 }
03603 if (material->has_ambient()) {
03604
03605 set_render_state(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
03606 } else {
03607
03608 if (_has_material_force_color) {
03609 color = LCAST(float, _material_force_color);
03610 cur_material.Ambient = *(D3DCOLORVALUE *)color.get_data();
03611 set_render_state(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
03612 } else {
03613 set_render_state(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
03614 }
03615 }
03616
03617 if (material->has_specular()) {
03618 set_render_state(D3DRS_SPECULARENABLE, TRUE);
03619 } else {
03620 set_render_state(D3DRS_SPECULARENABLE, FALSE);
03621 }
03622
03623 if (material->get_local()) {
03624 set_render_state(D3DRS_LOCALVIEWER, TRUE);
03625 } else {
03626 set_render_state(D3DRS_LOCALVIEWER, FALSE);
03627 }
03628
03629 _d3d_device->SetMaterial(&cur_material);
03630 }
03631
03632
03633
03634
03635
03636
03637 void DXGraphicsStateGuardian9::
03638 do_issue_texture() {
03639 DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
03640
03641 if (_texture_binding_shader_context==0) {
03642 if (_current_shader_context==0) {
03643 update_standard_texture_bindings();
03644 } else {
03645 disable_standard_texture_bindings();
03646 _current_shader_context->update_shader_texture_bindings(NULL,this);
03647 }
03648 } else {
03649 if (_current_shader_context==0) {
03650 _texture_binding_shader_context->disable_shader_texture_bindings(this);
03651 update_standard_texture_bindings();
03652 } else {
03653 _current_shader_context->
03654 update_shader_texture_bindings(_texture_binding_shader_context,this);
03655 }
03656 }
03657 _texture_binding_shader = _current_shader;
03658 _texture_binding_shader_context = _current_shader_context;
03659 }
03660
03661
03662
03663
03664
03665
03666 void DXGraphicsStateGuardian9::
03667 disable_standard_texture_bindings() {
03668
03669 for (int i = 0; i < _num_active_texture_stages; i++) {
03670 HRESULT hr;
03671
03672 hr = _d3d_device -> SetTexture (i, NULL);
03673 if (FAILED (hr)) {
03674 dxgsg9_cat.error()
03675 << "SetTexture ("
03676 << i
03677 << ", NULL) failed "
03678 << D3DERRORSTRING(hr);
03679 }
03680 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
03681 }
03682
03683 _num_active_texture_stages = 0;
03684 }
03685
03686
03687
03688
03689
03690
03691 void DXGraphicsStateGuardian9::
03692 update_standard_texture_bindings() {
03693 DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
03694
03695 int num_stages = _target_texture->get_num_on_ff_stages();
03696 int num_old_stages = _max_texture_stages;
03697 if (_state_texture != (TextureAttrib *)NULL) {
03698 num_old_stages = _state_texture->get_num_on_ff_stages();
03699 }
03700
03701 nassertv(num_stages <= _max_texture_stages &&
03702 _num_active_texture_stages <= _max_texture_stages);
03703
03704 _texture_involves_color_scale = false;
03705
03706
03707
03708
03709
03710 int si;
03711 for (si = 0; si < num_stages; si++) {
03712 TextureStage *stage = _target_texture->get_on_ff_stage(si);
03713 int texcoord_index = _target_texture->get_ff_tc_index(si);
03714
03715 Texture *texture = _target_texture->get_on_texture(stage);
03716 nassertv(texture != (Texture *)NULL);
03717
03718
03719
03720 int view = get_current_tex_view_offset() + stage->get_tex_view_offset();
03721 TextureContext *tc = texture->prepare_now(view, _prepared_objects, this);
03722 apply_texture(si, tc);
03723 set_texture_blend_mode(si, stage);
03724
03725 int texcoord_dimensions = 2;
03726
03727 CPT(TransformState) tex_mat = TransformState::make_identity();
03728 const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
03729 if (target_tex_matrix->has_stage(stage)) {
03730 tex_mat = target_tex_matrix->get_transform(stage);
03731 }
03732
03733
03734 TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage);
03735 bool any_point_sprite = false;
03736
03737 switch (mode) {
03738 case TexGenAttrib::M_off:
03739 case TexGenAttrib::M_light_vector:
03740 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX, texcoord_index);
03741 break;
03742
03743 case TexGenAttrib::M_eye_sphere_map:
03744 {
03745 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03746 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
03747
03748
03749
03750 static CPT(TransformState) sphere_map =
03751 TransformState::make_mat(LMatrix4(0.33, 0.0f, 0.0f, 0.0f,
03752 0.0f, 0.33, 0.0f, 0.0f,
03753 0.0f, 0.0f, 1.0f, 0.0f,
03754 0.5f, 0.5f, 0.0f, 1.0f));
03755 tex_mat = tex_mat->compose(sphere_map);
03756 texcoord_dimensions = 3;
03757 }
03758 break;
03759
03760 case TexGenAttrib::M_world_cube_map:
03761
03762
03763
03764
03765 {
03766 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03767 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
03768 texcoord_dimensions = 3;
03769 CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
03770 tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3::zero()));
03771 }
03772 break;
03773
03774 case TexGenAttrib::M_eye_cube_map:
03775 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03776 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
03777 tex_mat = tex_mat->compose(_inv_cs_transform);
03778 texcoord_dimensions = 3;
03779 break;
03780
03781 case TexGenAttrib::M_world_normal:
03782
03783
03784
03785
03786 {
03787 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03788 texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
03789 texcoord_dimensions = 3;
03790 CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
03791 tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3::zero()));
03792 }
03793 break;
03794
03795 case TexGenAttrib::M_eye_normal:
03796 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03797 texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
03798 texcoord_dimensions = 3;
03799 tex_mat = tex_mat->compose(_inv_cs_transform);
03800 break;
03801
03802 case TexGenAttrib::M_world_position:
03803
03804
03805
03806 {
03807 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03808 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
03809 texcoord_dimensions = 3;
03810 CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
03811 tex_mat = tex_mat->compose(camera_transform);
03812 }
03813 break;
03814
03815 case TexGenAttrib::M_eye_position:
03816 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03817 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
03818 texcoord_dimensions = 3;
03819 tex_mat = tex_mat->compose(_inv_cs_transform);
03820 break;
03821
03822 case TexGenAttrib::M_point_sprite:
03823 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX, texcoord_index);
03824 any_point_sprite = true;
03825 break;
03826
03827 case TexGenAttrib::M_constant:
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838 {
03839 set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX,
03840 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
03841 texcoord_dimensions = 3;
03842
03843 const LTexCoord3 &v = _target_tex_gen->get_constant_value(stage);
03844 CPT(TransformState) squash =
03845 TransformState::make_pos_hpr_scale(v, LVecBase3::zero(),
03846 LVecBase3::zero());
03847 tex_mat = tex_mat->compose(squash);
03848 }
03849 break;
03850 }
03851
03852 set_render_state(D3DRS_POINTSPRITEENABLE, any_point_sprite);
03853
03854 if (!tex_mat->is_identity()) {
03855 if ( texcoord_dimensions <= 2) {
03856
03857 LMatrix4 m = tex_mat->get_mat();
03858 LMatrix4f mf;
03859 mf.set(m(0, 0), m(0, 1), m(0, 3), 0.0f,
03860 m(1, 0), m(1, 1), m(1, 3), 0.0f,
03861 m(3, 0), m(3, 1), m(3, 3), 0.0f,
03862 0.0f, 0.0f, 0.0f, 1.0f);
03863 _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)mf.get_data());
03864 set_texture_stage_state(si, D3DTSS_TEXTURETRANSFORMFLAGS,
03865 D3DTTFF_COUNT2);
03866 } else {
03867 LMatrix4f mf = LCAST(float, tex_mat->get_mat());
03868 _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)mf.get_data());
03869 DWORD transform_flags = texcoord_dimensions;
03870 if (mf.get_col(3) != LVecBase4f(0.0f, 0.0f, 0.0f, 1.0f)) {
03871
03872
03873 transform_flags = D3DTTFF_COUNT4 | D3DTTFF_PROJECTED;
03874 }
03875 set_texture_stage_state(si, D3DTSS_TEXTURETRANSFORMFLAGS,
03876 transform_flags);
03877 }
03878
03879 } else {
03880 set_texture_stage_state(si, D3DTSS_TEXTURETRANSFORMFLAGS,
03881 D3DTTFF_DISABLE);
03882
03883
03884
03885 _d3d_device->SetTransform(get_tex_mat_sym(si), &_d3d_ident_mat);
03886 }
03887 }
03888
03889
03890 for (si = num_stages; si < _num_active_texture_stages; si++) {
03891 set_texture_stage_state(si, D3DTSS_COLOROP, D3DTOP_DISABLE);
03892 _d3d_device->SetTexture(si, NULL);
03893 }
03894
03895
03896 _num_active_texture_stages = num_stages;
03897 }
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907 void DXGraphicsStateGuardian9::
03908 do_issue_blending() {
03909
03910
03911
03912
03913 const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
03914 unsigned int color_channels =
03915 target_color_write->get_channels() & _color_write_mask;
03916 if (_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
03917 color_channels &= ~(ColorWriteAttrib::C_alpha);
03918 }
03919 if (color_channels == ColorWriteAttrib::C_off) {
03920 if (_screen->_can_direct_disable_color_writes) {
03921 set_render_state(D3DRS_ALPHABLENDENABLE, FALSE);
03922 set_render_state(D3DRS_COLORWRITEENABLE, (DWORD)0x0);
03923 } else {
03924 set_render_state(D3DRS_ALPHABLENDENABLE, TRUE);
03925 set_render_state(D3DRS_SRCBLEND, D3DBLEND_ZERO);
03926 set_render_state(D3DRS_DESTBLEND, D3DBLEND_ONE);
03927 }
03928 return;
03929 } else {
03930 if (_screen->_can_direct_disable_color_writes) {
03931 set_render_state(D3DRS_COLORWRITEENABLE, color_channels);
03932 }
03933 }
03934
03935 const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
03936 CPT(ColorBlendAttrib) color_blend = target_color_blend;
03937 ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode();
03938
03939 const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
03940 TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode();
03941
03942
03943 if (color_blend_mode != ColorBlendAttrib::M_none) {
03944 set_render_state(D3DRS_ALPHABLENDENABLE, TRUE);
03945
03946 switch (color_blend_mode) {
03947 case ColorBlendAttrib::M_add:
03948 set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD);
03949 break;
03950
03951 case ColorBlendAttrib::M_subtract:
03952 set_render_state(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
03953 break;
03954
03955 case ColorBlendAttrib::M_inv_subtract:
03956 set_render_state(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT);
03957 break;
03958
03959 case ColorBlendAttrib::M_min:
03960 set_render_state(D3DRS_BLENDOP, D3DBLENDOP_MIN);
03961 break;
03962
03963 case ColorBlendAttrib::M_max:
03964 set_render_state(D3DRS_BLENDOP, D3DBLENDOP_MAX);
03965 break;
03966 }
03967
03968 set_render_state(D3DRS_SRCBLEND,
03969 get_blend_func(color_blend->get_operand_a()));
03970 set_render_state(D3DRS_DESTBLEND,
03971 get_blend_func(color_blend->get_operand_b()));
03972 return;
03973 }
03974
03975
03976 switch (transparency_mode) {
03977 case TransparencyAttrib::M_none:
03978 case TransparencyAttrib::M_binary:
03979 break;
03980
03981 case TransparencyAttrib::M_alpha:
03982 case TransparencyAttrib::M_multisample:
03983 case TransparencyAttrib::M_multisample_mask:
03984 case TransparencyAttrib::M_dual:
03985 set_render_state(D3DRS_ALPHABLENDENABLE, TRUE);
03986 set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD);
03987 set_render_state(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
03988 set_render_state(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
03989 return;
03990
03991 default:
03992 dxgsg9_cat.error()
03993 << "invalid transparency mode " << (int)transparency_mode << endl;
03994 break;
03995 }
03996
03997
03998 set_render_state(D3DRS_ALPHABLENDENABLE, FALSE);
03999 }
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009 void DXGraphicsStateGuardian9::
04010 reissue_transforms() {
04011 prepare_lens();
04012 do_issue_transform();
04013 }
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023 void DXGraphicsStateGuardian9::
04024 enable_lighting(bool enable) {
04025 set_render_state(D3DRS_LIGHTING, (DWORD)enable);
04026 }
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036 void DXGraphicsStateGuardian9::
04037 set_ambient_light(const LColor &color) {
04038 LColor c = color;
04039 c.set(c[0] * _light_color_scale[0],
04040 c[1] * _light_color_scale[1],
04041 c[2] * _light_color_scale[2],
04042 c[3] * _light_color_scale[3]);
04043
04044 set_render_state(D3DRS_AMBIENT, LColor_to_D3DCOLOR(c));
04045 }
04046
04047
04048
04049
04050
04051
04052
04053
04054 void DXGraphicsStateGuardian9::
04055 enable_light(int light_id, bool enable) {
04056 HRESULT hr = _d3d_device->LightEnable(light_id, enable);
04057
04058 if (FAILED(hr)) {
04059 wdxdisplay9_cat.warning()
04060 << "Could not enable light " << light_id << ": "
04061 << D3DERRORSTRING(hr) << "\n";
04062 }
04063 }
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073 void DXGraphicsStateGuardian9::
04074 enable_clip_plane(int plane_id, bool enable) {
04075 if (enable) {
04076 _clip_plane_bits |= ((DWORD)1 << plane_id);
04077 } else {
04078 _clip_plane_bits &= ~((DWORD)1 << plane_id);
04079 }
04080 set_render_state(D3DRS_CLIPPLANEENABLE, _clip_plane_bits);
04081 }
04082
04083
04084
04085
04086
04087
04088
04089
04090
04091 void DXGraphicsStateGuardian9::
04092 bind_clip_plane(const NodePath &plane, int plane_id) {
04093
04094
04095
04096 CPT(TransformState) transform = plane.get_transform(_scene_setup->get_camera_path());
04097 const LMatrix4 &plane_mat = transform->get_mat();
04098 LMatrix4 rel_mat = plane_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
04099 const PlaneNode *plane_node;
04100 DCAST_INTO_V(plane_node, plane.node());
04101 LPlanef world_plane = LCAST(float, plane_node->get_plane() * rel_mat);
04102
04103 HRESULT hr = _d3d_device->SetClipPlane(plane_id, world_plane.get_data());
04104 if (FAILED(hr)) {
04105 wdxdisplay9_cat.warning()
04106 << "Could not set clip plane for " << plane
04107 << " to id " << plane_id << ": " << D3DERRORSTRING(hr) << "\n";
04108 }
04109 }
04110
04111
04112
04113
04114
04115
04116
04117
04118
04119 void DXGraphicsStateGuardian9::
04120 close_gsg() {
04121 GraphicsStateGuardian::close_gsg();
04122
04123 if (dxgsg9_cat.is_debug()) {
04124 dxgsg9_cat.debug()
04125 << "Closing GSG, prepared_objects count = "
04126 << _prepared_objects->get_ref_count() << "\n";
04127 }
04128
04129
04130
04131 if (_prepared_objects->get_ref_count() == 1) {
04132 release_all();
04133
04134
04135
04136 Thread *current_thread = Thread::get_current_thread();
04137 _prepared_objects->begin_frame(this, current_thread);
04138 _prepared_objects->end_frame(current_thread);
04139 }
04140 }
04141
04142
04143
04144
04145
04146
04147
04148 void DXGraphicsStateGuardian9::
04149 free_nondx_resources() {
04150 }
04151
04152
04153
04154
04155
04156
04157
04158 void DXGraphicsStateGuardian9::
04159 free_d3d_device() {
04160
04161 _state_rs = RenderState::make_empty();
04162 _state_mask.clear();
04163
04164
04165
04166 _dx_is_ready = false;
04167
04168 if (_d3d_device != NULL) {
04169 for(int i = 0; i < D3D_MAXTEXTURESTAGES; i++) {
04170
04171 _d3d_device->SetTexture(i, NULL);
04172 }
04173 }
04174
04175 release_all();
04176
04177 if (_d3d_device != NULL) {
04178 RELEASE(_d3d_device, dxgsg9, "d3dDevice", RELEASE_DOWN_TO_ZERO);
04179 }
04180
04181 free_nondx_resources();
04182
04183
04184 }
04185
04186
04187
04188
04189
04190
04191
04192
04193
04194 void DXGraphicsStateGuardian9::
04195 set_draw_buffer(const RenderBuffer &rb) {
04196 dxgsg9_cat.fatal() << "DX set_draw_buffer unimplemented!!!";
04197 return;
04198 }
04199
04200
04201
04202
04203
04204
04205 void DXGraphicsStateGuardian9::
04206 set_read_buffer(const RenderBuffer &rb) {
04207 if (rb._buffer_type & RenderBuffer::T_front) {
04208 _cur_read_pixel_buffer = RenderBuffer::T_front;
04209 } else if (rb._buffer_type & RenderBuffer::T_back) {
04210 _cur_read_pixel_buffer = RenderBuffer::T_back;
04211 } else if (rb._buffer_type & RenderBuffer::T_aux_rgba_ALL) {
04212 _cur_read_pixel_buffer = RenderBuffer::T_back;
04213 } else {
04214 dxgsg9_cat.error() << "Invalid or unimplemented Argument to set_read_buffer!\n";
04215 }
04216 return;
04217 }
04218
04219
04220
04221
04222
04223
04224
04225
04226 void DXGraphicsStateGuardian9::
04227 do_auto_rescale_normal() {
04228 if (_internal_transform->has_identity_scale()) {
04229
04230 set_render_state(D3DRS_NORMALIZENORMALS, false);
04231 } else {
04232
04233 set_render_state(D3DRS_NORMALIZENORMALS, true);
04234 }
04235 }
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245 const D3DCOLORVALUE &DXGraphicsStateGuardian9::
04246 get_light_color(Light *light) const {
04247 LColor c = light->get_color();
04248 static LColorf cf;
04249 cf.set(c[0] * _light_color_scale[0],
04250 c[1] * _light_color_scale[1],
04251 c[2] * _light_color_scale[2],
04252 c[3] * _light_color_scale[3]);
04253 return *(D3DCOLORVALUE *)cf.get_data();
04254 }
04255
04256
04257
04258
04259
04260
04261
04262 D3DBLEND DXGraphicsStateGuardian9::
04263 get_blend_func(ColorBlendAttrib::Operand operand) {
04264 switch (operand) {
04265 case ColorBlendAttrib::O_zero:
04266 return D3DBLEND_ZERO;
04267
04268 case ColorBlendAttrib::O_one:
04269 return D3DBLEND_ONE;
04270
04271 case ColorBlendAttrib::O_incoming_color:
04272 return D3DBLEND_SRCCOLOR;
04273
04274 case ColorBlendAttrib::O_one_minus_incoming_color:
04275 return D3DBLEND_INVSRCCOLOR;
04276
04277 case ColorBlendAttrib::O_fbuffer_color:
04278 return D3DBLEND_DESTCOLOR;
04279
04280 case ColorBlendAttrib::O_one_minus_fbuffer_color:
04281 return D3DBLEND_INVDESTCOLOR;
04282
04283 case ColorBlendAttrib::O_incoming_alpha:
04284 return D3DBLEND_SRCALPHA;
04285
04286 case ColorBlendAttrib::O_one_minus_incoming_alpha:
04287 return D3DBLEND_INVSRCALPHA;
04288
04289 case ColorBlendAttrib::O_fbuffer_alpha:
04290 return D3DBLEND_DESTALPHA;
04291
04292 case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
04293 return D3DBLEND_INVDESTALPHA;
04294
04295 case ColorBlendAttrib::O_constant_color:
04296
04297 return D3DBLEND_SRCCOLOR;
04298
04299 case ColorBlendAttrib::O_one_minus_constant_color:
04300
04301 return D3DBLEND_INVSRCCOLOR;
04302
04303 case ColorBlendAttrib::O_constant_alpha:
04304
04305 return D3DBLEND_SRCALPHA;
04306
04307 case ColorBlendAttrib::O_one_minus_constant_alpha:
04308
04309 return D3DBLEND_INVSRCALPHA;
04310
04311 case ColorBlendAttrib::O_incoming_color_saturate:
04312 return D3DBLEND_SRCALPHASAT;
04313 }
04314
04315 dxgsg9_cat.error()
04316 << "Unknown color blend operand " << (int)operand << endl;
04317 return D3DBLEND_ZERO;
04318 }
04319
04320
04321
04322
04323
04324
04325 void DXGraphicsStateGuardian9::
04326 report_texmgr_stats() {
04327
04328 #ifdef DO_PSTATS
04329 HRESULT hr;
04330 hr = 0;
04331
04332 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
04333 DWORD dwTexTotal, dwTexFree, dwVidTotal, dwVidFree;
04334
04335 if (_total_texmem_pcollector.is_active()) {
04336 DDSCAPS2 ddsCaps;
04337
04338 ZeroMemory(&ddsCaps, sizeof(ddsCaps));
04339
04340 ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
04341 if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwVidTotal, &dwVidFree))) {
04342 dxgsg9_cat.fatal() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << D3DERRORSTRING(hr);
04343 throw_event("panda3d-render-error");
04344 return;
04345 }
04346
04347 ddsCaps.dwCaps = DDSCAPS_TEXTURE;
04348 if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwTexTotal, &dwTexFree))) {
04349 dxgsg9_cat.fatal() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << D3DERRORSTRING(hr);
04350 throw_event("panda3d-render-error");
04351 return;
04352 }
04353 }
04354 #endif // TEXMGRSTATS_USES_GETAVAILVIDMEM
04355
04356 D3DDEVINFO_RESOURCEMANAGER all_resource_stats;
04357 ZeroMemory(&all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER));
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367
04368
04369
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381
04382
04383
04384 if (_texmgrmem_total_pcollector.is_active()) {
04385
04386 _texmgrmem_total_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].TotalBytes);
04387 _texmgrmem_resident_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].WorkingSetBytes);
04388 }
04389 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
04390 if (_total_texmem_pcollector.is_active()) {
04391 _total_texmem_pcollector.set_level(dwTexTotal);
04392 _used_texmem_pcollector.set_level(dwTexTotal - dwTexFree);
04393 }
04394 #endif // TEXMGRSTATS_USES_GETAVAILVIDMEM
04395 #endif // DO_PSTATS
04396 }
04397
04398
04399
04400
04401
04402
04403 void DXGraphicsStateGuardian9::
04404 set_context(DXScreenData *new_context) {
04405 nassertv(new_context != NULL);
04406 _screen = new_context;
04407 _d3d_device = _screen->_d3d_device;
04408 _swap_chain = _screen->_swap_chain;
04409
04410 _screen->_dxgsg9 = this;
04411 set_cg_device(_d3d_device);
04412 }
04413
04414
04415
04416
04417
04418
04419
04420 void DXGraphicsStateGuardian9::
04421 set_render_target() {
04422 if (_d3d_device == NULL) {
04423 return;
04424 }
04425
04426 LPDIRECT3DSURFACE9 back = NULL, stencil = NULL;
04427
04428 UINT swap_chain;
04429
04430
04431 swap_chain = 0;
04432
04433 if (!_swap_chain)
04434 _d3d_device->GetBackBuffer(swap_chain, 0, D3DBACKBUFFER_TYPE_MONO, &back);
04435 else
04436 _swap_chain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back);
04437
04438
04439
04440
04441 _d3d_device->GetDepthStencilSurface(&stencil);
04442
04443
04444 DWORD render_target_index;
04445 render_target_index = 0;
04446 _d3d_device->SetRenderTarget(render_target_index, back);
04447
04448 if (back) {
04449 back->Release();
04450 }
04451 if (stencil) {
04452 stencil->Release();
04453 }
04454 }
04455
04456
04457
04458
04459
04460
04461 void DXGraphicsStateGuardian9::
04462 set_texture_blend_mode(int i, const TextureStage *stage) {
04463 switch (stage->get_mode()) {
04464 case TextureStage::M_modulate:
04465 case TextureStage::M_modulate_glow:
04466 case TextureStage::M_modulate_gloss:
04467
04468 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_MODULATE);
04469 set_texture_stage_state(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
04470 set_texture_stage_state(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
04471 set_texture_stage_state(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
04472 set_texture_stage_state(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
04473 set_texture_stage_state(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
04474 break;
04475
04476 case TextureStage::M_decal:
04477
04478 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
04479 set_texture_stage_state(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
04480 set_texture_stage_state(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
04481
04482 set_texture_stage_state(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
04483 set_texture_stage_state(i, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
04484 break;
04485
04486 case TextureStage::M_replace:
04487 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
04488 set_texture_stage_state(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
04489
04490 set_texture_stage_state(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
04491 set_texture_stage_state(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
04492 break;
04493
04494 case TextureStage::M_add:
04495 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_ADD);
04496 set_texture_stage_state(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
04497 set_texture_stage_state(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
04498
04499 set_texture_stage_state(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
04500 set_texture_stage_state(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
04501 set_texture_stage_state(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
04502 break;
04503
04504 case TextureStage::M_blend:
04505 case TextureStage::M_blend_color_scale:
04506 {
04507 set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_LERP);
04508 set_texture_stage_state(i, D3DTSS_COLORARG0, D3DTA_TEXTURE);
04509 set_texture_stage_state(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
04510 set_texture_stage_state(i, D3DTSS_COLORARG1, _constant_color_operand);
04511
04512 set_texture_stage_state(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
04513 set_texture_stage_state(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
04514 set_texture_stage_state(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
04515 }
04516 break;
04517
04518 case TextureStage::M_combine:
04519
04520
04521 set_texture_stage_state
04522 (i, D3DTSS_COLOROP,
04523 get_texture_operation(stage->get_combine_rgb_mode(),
04524 stage->get_rgb_scale()));
04525
04526 switch (stage->get_num_combine_rgb_operands()) {
04527 case 3:
04528 set_texture_stage_state
04529 (i, D3DTSS_COLORARG0,
04530 get_texture_argument(stage->get_combine_rgb_source2(),
04531 stage->get_combine_rgb_operand2()));
04532
04533
04534 case 2:
04535 set_texture_stage_state
04536 (i, D3DTSS_COLORARG2,
04537 get_texture_argument(stage->get_combine_rgb_source1(),
04538 stage->get_combine_rgb_operand1()));
04539
04540
04541 case 1:
04542 set_texture_stage_state
04543 (i, D3DTSS_COLORARG1,
04544 get_texture_argument(stage->get_combine_rgb_source0(),
04545 stage->get_combine_rgb_operand0()));
04546
04547
04548 default:
04549 break;
04550 }
04551
04552 set_texture_stage_state
04553 (i, D3DTSS_ALPHAOP,
04554 get_texture_operation(stage->get_combine_alpha_mode(),
04555 stage->get_alpha_scale()));
04556
04557 switch (stage->get_num_combine_alpha_operands()) {
04558 case 3:
04559 set_texture_stage_state
04560 (i, D3DTSS_ALPHAARG0,
04561 get_texture_argument(stage->get_combine_alpha_source2(),
04562 stage->get_combine_alpha_operand2()));
04563
04564
04565 case 2:
04566 set_texture_stage_state
04567 (i, D3DTSS_ALPHAARG2,
04568 get_texture_argument(stage->get_combine_alpha_source1(),
04569 stage->get_combine_alpha_operand1()));
04570
04571
04572 case 1:
04573 set_texture_stage_state
04574 (i, D3DTSS_ALPHAARG1,
04575 get_texture_argument(stage->get_combine_alpha_source0(),
04576 stage->get_combine_alpha_operand0()));
04577
04578
04579 default:
04580 break;
04581 }
04582 break;
04583
04584 default:
04585 dxgsg9_cat.error()
04586 << "Unknown texture mode " << (int)stage->get_mode() << endl;
04587 break;
04588 }
04589
04590 if (stage->get_saved_result()) {
04591 set_texture_stage_state(i, D3DTSS_RESULTARG, D3DTA_TEMP);
04592 } else {
04593 set_texture_stage_state(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
04594 }
04595
04596 if (stage->uses_color()) {
04597
04598
04599 D3DCOLOR constant_color;
04600 if (stage->involves_color_scale() && _color_scale_enabled) {
04601 LColor color = stage->get_color();
04602 color.set(color[0] * _current_color_scale[0],
04603 color[1] * _current_color_scale[1],
04604 color[2] * _current_color_scale[2],
04605 color[3] * _current_color_scale[3]);
04606 _texture_involves_color_scale = true;
04607 constant_color = LColor_to_D3DCOLOR(color);
04608 } else {
04609 constant_color = LColor_to_D3DCOLOR(stage->get_color());
04610 }
04611 if (_supports_texture_constant_color) {
04612 set_texture_stage_state(i, D3DTSS_CONSTANT, constant_color);
04613 } else {
04614
04615
04616
04617 set_render_state(D3DRS_TEXTUREFACTOR, constant_color);
04618 }
04619 }
04620 }
04621
04622
04623
04624
04625
04626
04627 void DXGraphicsStateGuardian9::
04628 dx_cleanup() {
04629 if (!_d3d_device) {
04630 return;
04631 }
04632
04633 free_nondx_resources();
04634 PRINT_REFCNT(dxgsg9, _d3d_device);
04635
04636
04637
04638 RELEASE(_d3d_device, dxgsg9, "d3dDevice", RELEASE_DOWN_TO_ZERO);
04639 _screen->_d3d_device = NULL;
04640
04641
04642 }
04643
04644
04645
04646
04647
04648
04649
04650
04651
04652
04653
04654
04655 HRESULT DXGraphicsStateGuardian9::
04656 reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
04657 DXScreenData **screen) {
04658 HRESULT hr;
04659
04660 nassertr(IS_VALID_PTR(presentation_params), E_FAIL);
04661 nassertr(IS_VALID_PTR(_screen->_d3d9), E_FAIL);
04662 nassertr(IS_VALID_PTR(_d3d_device), E_FAIL);
04663
04664
04665
04666 _screen->_d3d9->GetAdapterDisplayMode(_screen->_card_id, &_screen->_display_mode);
04667 presentation_params->BackBufferFormat = _screen->_display_mode.Format;
04668
04669
04670
04671
04672
04673
04674 if (true || !(_screen->_swap_chain)
04675 || (_presentation_reset.BackBufferWidth < presentation_params->BackBufferWidth)
04676 || (_presentation_reset.BackBufferHeight < presentation_params->BackBufferHeight)) {
04677 if (wdxdisplay9_cat.is_debug()) {
04678 wdxdisplay9_cat.debug()
04679 << "swap_chain = " << _screen->_swap_chain << " _presentation_reset = "
04680 << _presentation_reset.BackBufferWidth << "x" << _presentation_reset.BackBufferHeight
04681 << " presentation_params = "
04682 << presentation_params->BackBufferWidth << "x" << presentation_params->BackBufferHeight << "\n";
04683 }
04684
04685 get_engine()->reset_all_windows(false);
04686
04687 if (_screen->_swap_chain) {
04688 _presentation_reset.BackBufferWidth = max(_presentation_reset.BackBufferWidth, presentation_params->BackBufferWidth);
04689 _presentation_reset.BackBufferHeight = max(_presentation_reset.BackBufferHeight, presentation_params->BackBufferHeight);
04690
04691 } else {
04692 _presentation_reset.BackBufferWidth = presentation_params->BackBufferWidth;
04693 _presentation_reset.BackBufferHeight = presentation_params->BackBufferHeight;
04694 }
04695
04696
04697
04698 release_all();
04699
04700
04701
04702
04703 release_all_vertex_buffers();
04704 release_all_index_buffers();
04705
04706
04707 Thread *current_thread = Thread::get_current_thread();
04708 _prepared_objects->begin_frame(this, current_thread);
04709
04710
04711 {
04712 wdxGraphicsBuffer9 *graphics_buffer;
04713 list <wdxGraphicsBuffer9 **>::iterator graphics_buffer_iterator;
04714
04715 for (graphics_buffer_iterator = _graphics_buffer_list.begin( ); graphics_buffer_iterator != _graphics_buffer_list.end( ); graphics_buffer_iterator++)
04716 {
04717 graphics_buffer = **graphics_buffer_iterator;
04718 if (graphics_buffer -> _color_backing_store)
04719 {
04720 graphics_buffer -> _color_backing_store -> Release ( );
04721 graphics_buffer -> _color_backing_store = 0;
04722 }
04723 if (graphics_buffer -> _depth_backing_store)
04724 {
04725 graphics_buffer -> _depth_backing_store -> Release ( );
04726 graphics_buffer -> _depth_backing_store = 0;
04727 }
04728 }
04729 }
04730
04731 this -> mark_new();
04732 hr = _d3d_device->Reset(&_presentation_reset);
04733 if (FAILED(hr) && hr != D3DERR_DEVICELOST) {
04734 return hr;
04735 }
04736
04737 get_engine()->reset_all_windows(true);
04738 if (screen) {
04739 *screen = NULL;
04740 }
04741
04742 if (presentation_params != &_screen->_presentation_params) {
04743 memcpy(&_screen->_presentation_params, presentation_params, sizeof(D3DPRESENT_PARAMETERS));
04744 }
04745
04746 return hr;
04747 }
04748
04749
04750 if (_screen && _screen->_swap_chain) {
04751 _screen->_swap_chain->Release();
04752 wdxdisplay9_cat.debug()
04753 << "swap chain " << _screen->_swap_chain << " is released\n";
04754 _screen->_swap_chain = NULL;
04755 hr = _d3d_device->CreateAdditionalSwapChain(presentation_params, &_screen->_swap_chain);
04756 }
04757 if (SUCCEEDED(hr)) {
04758 if (presentation_params != &_screen->_presentation_params) {
04759 memcpy(&_screen->_presentation_params, presentation_params, sizeof(D3DPRESENT_PARAMETERS));
04760 }
04761 if (screen) {
04762 *screen = _screen;
04763 }
04764 }
04765 return hr;
04766 }
04767
04768
04769
04770
04771
04772
04773 bool DXGraphicsStateGuardian9::
04774 check_cooperative_level() {
04775 bool bDoReactivateWindow = false;
04776 if (_d3d_device == NULL) {
04777 return false;
04778 }
04779
04780 HRESULT hr = _d3d_device->TestCooperativeLevel();
04781
04782 if (SUCCEEDED(hr)) {
04783 nassertr(SUCCEEDED(_last_testcooplevel_result), false);
04784 return true;
04785 }
04786
04787 switch (hr) {
04788 case D3DERR_DEVICENOTRESET:
04789 _dx_is_ready = false;
04790
04791
04792 _prepared_objects->begin_frame(this, Thread::get_current_thread());
04793
04794 hr = reset_d3d_device(&_screen->_presentation_params);
04795 if (FAILED(hr)) {
04796
04797
04798 dxgsg9_cat.error()
04799 << "check_cooperative_level Reset() failed, hr = " << D3DERRORSTRING(hr);
04800 }
04801
04802 hr = _d3d_device->TestCooperativeLevel();
04803 if (FAILED(hr)) {
04804
04805 dxgsg9_cat.error()
04806 << "TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr);
04807
04808 }
04809
04810 _dx_is_ready = TRUE;
04811 break;
04812
04813 case D3DERR_DEVICELOST:
04814
04815 Sleep (10);
04816
04817 if (SUCCEEDED(_last_testcooplevel_result)) {
04818 if (_dx_is_ready) {
04819 _dx_is_ready = false;
04820 if (dxgsg9_cat.is_debug()) {
04821 dxgsg9_cat.debug() << "D3D Device was Lost, waiting...\n";
04822 }
04823 }
04824 }
04825 }
04826
04827 _last_testcooplevel_result = hr;
04828 return SUCCEEDED(hr);
04829 }
04830
04831
04832
04833
04834
04835
04836 void DXGraphicsStateGuardian9::
04837 show_frame() {
04838 if (_d3d_device == NULL) {
04839 return;
04840 }
04841
04842 HRESULT hr;
04843
04844 if (_swap_chain) {
04845 DWORD flags;
04846 flags = 0;
04847
04848 hr = _swap_chain->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL, flags);
04849 } else {
04850 hr = _d3d_device->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL);
04851 }
04852
04853 if (FAILED(hr)) {
04854 if (hr == D3DERR_DEVICELOST) {
04855 check_cooperative_level();
04856 } else {
04857 dxgsg9_cat.error()
04858 << "show_frame() - Present() failed" << D3DERRORSTRING(hr);
04859 throw_event("panda3d-render-error");
04860 }
04861 }
04862 }
04863
04864
04865
04866
04867
04868
04869 bool DXGraphicsStateGuardian9::
04870 create_swap_chain(DXScreenData *new_context) {
04871
04872
04873
04874
04875
04876 HRESULT hr;
04877 hr = new_context->_d3d_device->CreateAdditionalSwapChain(&new_context->_presentation_params, &new_context->_swap_chain);
04878 if (FAILED(hr)) {
04879 wdxdisplay9_cat.debug() << "Swapchain creation failed :"<<D3DERRORSTRING(hr)<<"\n";
04880 return false;
04881 }
04882 return true;
04883 }
04884
04885
04886
04887
04888
04889
04890 bool DXGraphicsStateGuardian9::
04891 release_swap_chain(DXScreenData *new_context) {
04892 HRESULT hr;
04893 if (new_context->_swap_chain) {
04894 hr = new_context->_swap_chain->Release();
04895 if (FAILED(hr)) {
04896 wdxdisplay9_cat.debug() << "Swapchain release failed:" << D3DERRORSTRING(hr) << "\n";
04897 return false;
04898 }
04899 }
04900 return true;
04901 }
04902
04903
04904
04905
04906
04907
04908 void DXGraphicsStateGuardian9::
04909 copy_pres_reset(DXScreenData *screen) {
04910 memcpy(&_presentation_reset, &_screen->_presentation_params, sizeof(D3DPRESENT_PARAMETERS));
04911 }
04912
04913
04914
04915
04916
04917
04918 D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian9::
04919 get_d3d_min_type(Texture::FilterType filter_type) {
04920 switch (filter_type) {
04921 case Texture::FT_nearest:
04922 return D3DTEXF_POINT;
04923
04924 case Texture::FT_linear:
04925 return D3DTEXF_LINEAR;
04926
04927 case Texture::FT_nearest_mipmap_nearest:
04928 return D3DTEXF_POINT;
04929
04930 case Texture::FT_linear_mipmap_nearest:
04931 return D3DTEXF_LINEAR;
04932
04933 case Texture::FT_nearest_mipmap_linear:
04934 return D3DTEXF_POINT;
04935
04936 case Texture::FT_linear_mipmap_linear:
04937 return D3DTEXF_LINEAR;
04938
04939 case Texture::FT_shadow:
04940 case Texture::FT_default:
04941 return D3DTEXF_LINEAR;
04942 }
04943
04944 dxgsg9_cat.error()
04945 << "Invalid FilterType value (" << (int)filter_type << ")\n";
04946 return D3DTEXF_POINT;
04947 }
04948
04949
04950
04951
04952
04953
04954 D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian9::
04955 get_d3d_mip_type(Texture::FilterType filter_type) {
04956 switch (filter_type) {
04957 case Texture::FT_nearest:
04958 return D3DTEXF_NONE;
04959
04960 case Texture::FT_linear:
04961 return D3DTEXF_NONE;
04962
04963 case Texture::FT_nearest_mipmap_nearest:
04964 return D3DTEXF_POINT;
04965
04966 case Texture::FT_linear_mipmap_nearest:
04967 return D3DTEXF_POINT;
04968
04969 case Texture::FT_nearest_mipmap_linear:
04970 return D3DTEXF_LINEAR;
04971
04972 case Texture::FT_linear_mipmap_linear:
04973 return D3DTEXF_LINEAR;
04974
04975 case Texture::FT_shadow:
04976 case Texture::FT_default:
04977 return D3DTEXF_NONE;
04978 }
04979
04980 dxgsg9_cat.error()
04981 << "Invalid FilterType value (" << (int)filter_type << ")\n";
04982 return D3DTEXF_NONE;
04983 }
04984
04985
04986
04987
04988
04989
04990
04991 D3DTEXTUREOP DXGraphicsStateGuardian9::
04992 get_texture_operation(TextureStage::CombineMode mode, int scale) {
04993 switch (mode) {
04994 case TextureStage::CM_undefined:
04995 case TextureStage::CM_replace:
04996 return D3DTOP_SELECTARG1;
04997
04998 case TextureStage::CM_modulate:
04999 if (scale < 2) {
05000 return D3DTOP_MODULATE;
05001 } else if (scale < 4) {
05002 return D3DTOP_MODULATE2X;
05003 } else {
05004 return D3DTOP_MODULATE4X;
05005 }
05006
05007 case TextureStage::CM_add:
05008 return D3DTOP_ADD;
05009
05010 case TextureStage::CM_add_signed:
05011 if (scale < 2) {
05012 return D3DTOP_ADDSIGNED;
05013 } else {
05014 return D3DTOP_ADDSIGNED2X;
05015 }
05016
05017 case TextureStage::CM_interpolate:
05018 return D3DTOP_LERP;
05019
05020 case TextureStage::CM_subtract:
05021 return D3DTOP_SUBTRACT;
05022
05023 case TextureStage::CM_dot3_rgb:
05024 case TextureStage::CM_dot3_rgba:
05025 return D3DTOP_DOTPRODUCT3;
05026 }
05027
05028 dxgsg9_cat.error()
05029 << "Invalid TextureStage::CombineMode value (" << (int)mode << ")\n";
05030 return D3DTOP_DISABLE;
05031 }
05032
05033
05034
05035
05036
05037
05038
05039
05040 DWORD DXGraphicsStateGuardian9::
05041 get_texture_argument(TextureStage::CombineSource source,
05042 TextureStage::CombineOperand operand) const {
05043 switch (source) {
05044 case TextureStage::CS_undefined:
05045 case TextureStage::CS_texture:
05046 return D3DTA_TEXTURE | get_texture_argument_modifier(operand);
05047
05048 case TextureStage::CS_constant:
05049 case TextureStage::CS_constant_color_scale:
05050 return _constant_color_operand | get_texture_argument_modifier(operand);
05051
05052 case TextureStage::CS_primary_color:
05053 return D3DTA_DIFFUSE | get_texture_argument_modifier(operand);
05054
05055 case TextureStage::CS_previous:
05056 return D3DTA_CURRENT | get_texture_argument_modifier(operand);
05057
05058 case TextureStage::CS_last_saved_result:
05059 return D3DTA_TEMP | get_texture_argument_modifier(operand);
05060 }
05061 dxgsg9_cat.error()
05062 << "Invalid TextureStage::CombineSource value (" << (int)source << ")\n";
05063 return D3DTA_CURRENT;
05064 }
05065
05066
05067
05068
05069
05070
05071
05072
05073 DWORD DXGraphicsStateGuardian9::
05074 get_texture_argument_modifier(TextureStage::CombineOperand operand) {
05075 switch (operand) {
05076 case TextureStage::CO_src_color:
05077 return 0;
05078
05079 case TextureStage::CO_one_minus_src_color:
05080 return D3DTA_COMPLEMENT;
05081
05082 case TextureStage::CO_src_alpha:
05083 return D3DTA_ALPHAREPLICATE;
05084
05085 case TextureStage::CO_one_minus_src_alpha:
05086 return D3DTA_ALPHAREPLICATE | D3DTA_COMPLEMENT;
05087
05088 case TextureStage::CO_undefined:
05089 break;
05090 }
05091 dxgsg9_cat.error()
05092 << "Invalid TextureStage::CombineOperand value (" << (int)operand << ")\n";
05093 return 0;
05094 }
05095
05096
05097
05098
05099
05100
05101
05102
05103
05104 void DXGraphicsStateGuardian9::
05105 draw_primitive_up(D3DPRIMITIVETYPE primitive_type,
05106 unsigned int primitive_count,
05107 unsigned int first_vertex,
05108 unsigned int num_vertices,
05109 const unsigned char *buffer, size_t stride) {
05110
05111
05112
05113
05114
05115
05116
05117 const unsigned char *buffer_start = buffer + stride * first_vertex;
05118 const unsigned char *buffer_end = buffer_start + stride * num_vertices;
05119
05120 if (buffer_end - buffer_start > 0x10000) {
05121
05122
05123 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
05124 buffer_start, stride);
05125
05126 } else if ((((long)buffer_end ^ (long)buffer_start) & ~0xffff) == 0) {
05127
05128 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
05129 buffer_start, stride);
05130
05131 } else {
05132
05133
05134
05135 unsigned char *safe_buffer_start = get_safe_buffer_start();
05136 memcpy(safe_buffer_start, buffer_start, buffer_end - buffer_start);
05137 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
05138 safe_buffer_start, stride);
05139
05140 }
05141 }
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154 void DXGraphicsStateGuardian9::
05155 draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type,
05156 unsigned int min_index, unsigned int max_index,
05157 unsigned int num_primitives,
05158 const unsigned char *index_data,
05159 D3DFORMAT index_type,
05160 const unsigned char *buffer, size_t stride) {
05161
05162
05163 const unsigned char *buffer_start = buffer + stride * min_index;
05164 const unsigned char *buffer_end = buffer + stride * (max_index + 1);
05165
05166 if (buffer_end - buffer_start > 0x10000) {
05167
05168
05169 _d3d_device->DrawIndexedPrimitiveUP
05170 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
05171 index_data, index_type, buffer, stride);
05172
05173 } else if ((((long)buffer_end ^ (long)buffer_start) & ~0xffff) == 0) {
05174
05175 _d3d_device->DrawIndexedPrimitiveUP
05176 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
05177 index_data, index_type, buffer, stride);
05178
05179 } else {
05180
05181
05182
05183 unsigned char *safe_buffer_start = get_safe_buffer_start();
05184 memcpy(safe_buffer_start, buffer_start, buffer_end - buffer_start);
05185 _d3d_device->DrawIndexedPrimitiveUP
05186 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
05187 index_data, index_type, safe_buffer_start - stride * min_index, stride);
05188 }
05189 }
05190
05191
05192
05193
05194
05195
05196
05197
05198
05199
05200
05201
05202
05203 bool DXGraphicsStateGuardian9::
05204 check_dx_allocation (HRESULT result, int allocation_size, int attempts)
05205 {
05206 bool retry;
05207
05208 retry = false;
05209 if (attempts <= 4)
05210 {
05211 switch (result) {
05212 case D3D_OK:
05213 break;
05214
05215 case D3DERR_OUTOFVIDEOMEMORY:
05216 case E_OUTOFMEMORY:
05217
05218 {
05219 size_t current_size = _prepared_objects->_graphics_memory_lru.get_total_size();
05220 size_t target_size = max(current_size - allocation_size * attempts, 0);
05221 _prepared_objects->_graphics_memory_lru.evict_to(target_size);
05222 dxgsg9_cat.info()
05223 << "Evicted " << current_size - _prepared_objects->_graphics_memory_lru.get_total_size() << " bytes of texture memory to make room for more.\n";
05224 if (_prepared_objects->_graphics_memory_lru.get_total_size() < current_size) {
05225 retry = true;
05226 }
05227 }
05228 break;
05229
05230 default:
05231 break;
05232 }
05233 }
05234
05235 return retry;
05236 }
05237
05238
05239
05240
05241
05242 static int dx_stencil_comparison_function_array [ ] =
05243 {
05244 D3DCMP_NEVER,
05245 D3DCMP_LESS,
05246 D3DCMP_EQUAL,
05247 D3DCMP_LESSEQUAL,
05248 D3DCMP_GREATER,
05249 D3DCMP_NOTEQUAL,
05250 D3DCMP_GREATEREQUAL,
05251 D3DCMP_ALWAYS,
05252 };
05253
05254 static int dx_stencil_operation_array [ ] =
05255 {
05256 D3DSTENCILOP_KEEP,
05257 D3DSTENCILOP_ZERO,
05258 D3DSTENCILOP_REPLACE,
05259 D3DSTENCILOP_INCR,
05260 D3DSTENCILOP_DECR,
05261 D3DSTENCILOP_INVERT,
05262
05263 D3DSTENCILOP_INCRSAT,
05264 D3DSTENCILOP_DECRSAT,
05265 };
05266
05267 void dx_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) {
05268 StencilType render_state_value;
05269
05270 DXGraphicsStateGuardian9 *gsg;
05271
05272 gsg = (DXGraphicsStateGuardian9 *) stencil_render_states -> _gsg;
05273
05274 render_state_value = stencil_render_states -> get_stencil_render_state (stencil_render_state);
05275
05276
05277 if (false) {
05278 dxgsg9_cat.debug()
05279 << "SRS: " << StencilAttrib::stencil_render_state_name_array [stencil_render_state] << ", " << render_state_value << "\n";
05280 }
05281
05282 switch (stencil_render_state)
05283 {
05284 case StencilRenderStates::SRS_front_enable:
05285 gsg -> set_render_state (D3DRS_STENCILENABLE, render_state_value);
05286 break;
05287
05288 case StencilRenderStates::SRS_back_enable:
05289 if (gsg -> get_supports_two_sided_stencil()) {
05290 gsg -> set_render_state (D3DRS_TWOSIDEDSTENCILMODE, render_state_value);
05291 }
05292 break;
05293
05294 case StencilRenderStates::SRS_front_comparison_function:
05295 gsg -> set_render_state (D3DRS_STENCILFUNC, dx_stencil_comparison_function_array [render_state_value]);
05296 break;
05297 case StencilRenderStates::SRS_front_stencil_fail_operation:
05298 gsg -> set_render_state (D3DRS_STENCILFAIL, dx_stencil_operation_array [render_state_value]);
05299 break;
05300 case StencilRenderStates::SRS_front_stencil_pass_z_fail_operation:
05301 gsg -> set_render_state (D3DRS_STENCILZFAIL, dx_stencil_operation_array [render_state_value]);
05302 break;
05303 case StencilRenderStates::SRS_front_stencil_pass_z_pass_operation:
05304 gsg -> set_render_state (D3DRS_STENCILPASS, dx_stencil_operation_array [render_state_value]);
05305 break;
05306
05307 case StencilRenderStates::SRS_reference:
05308 gsg -> set_render_state (D3DRS_STENCILREF, render_state_value);
05309 break;
05310
05311 case StencilRenderStates::SRS_read_mask:
05312 gsg -> set_render_state (D3DRS_STENCILMASK, render_state_value);
05313 break;
05314 case StencilRenderStates::SRS_write_mask:
05315 gsg -> set_render_state (D3DRS_STENCILWRITEMASK, render_state_value);
05316 break;
05317
05318 case StencilRenderStates::SRS_back_comparison_function:
05319 if (gsg -> get_supports_two_sided_stencil()) {
05320 gsg -> set_render_state (D3DRS_CCW_STENCILFUNC, dx_stencil_comparison_function_array [render_state_value]);
05321 }
05322 break;
05323 case StencilRenderStates::SRS_back_stencil_fail_operation:
05324 if (gsg -> get_supports_two_sided_stencil()) {
05325 gsg -> set_render_state (D3DRS_CCW_STENCILFAIL, dx_stencil_operation_array [render_state_value]);
05326 }
05327 break;
05328 case StencilRenderStates::SRS_back_stencil_pass_z_fail_operation:
05329 if (gsg -> get_supports_two_sided_stencil()) {
05330 gsg -> set_render_state (D3DRS_CCW_STENCILZFAIL, dx_stencil_operation_array [render_state_value]);
05331 }
05332 break;
05333 case StencilRenderStates::SRS_back_stencil_pass_z_pass_operation:
05334 if (gsg -> get_supports_two_sided_stencil()) {
05335 gsg -> set_render_state (D3DRS_CCW_STENCILPASS, dx_stencil_operation_array [render_state_value]);
05336 }
05337 break;
05338
05339 default:
05340 break;
05341 }
05342 }
05343
05344 void dx_set_stencil_functions (StencilRenderStates *stencil_render_states) {
05345 if (stencil_render_states) {
05346 StencilRenderStates::StencilRenderState stencil_render_state;
05347
05348 for (stencil_render_state = StencilRenderStates::SRS_first; stencil_render_state < StencilRenderStates::SRS_total; stencil_render_state = (StencilRenderStates::StencilRenderState) ((int) stencil_render_state + 1)) {
05349 stencil_render_states -> set_stencil_function (stencil_render_state, dx_stencil_function);
05350 }
05351 }
05352 }
05353
05354
05355
05356
05357
05358
05359 void DXGraphicsStateGuardian9::
05360 do_issue_stencil() {
05361 if (!_supports_stencil) {
05362 return;
05363 }
05364
05365 StencilRenderStates *stencil_render_states;
05366 const StencilAttrib *stencil = DCAST(StencilAttrib, _target_rs->get_attrib_def(StencilAttrib::get_class_slot()));
05367 stencil_render_states = this -> _stencil_render_states;
05368 if (stencil && stencil_render_states) {
05369
05370
05371 if (false) {
05372 dxgsg9_cat.debug() << "STENCIL STATE CHANGE\n";
05373 dxgsg9_cat.debug() << "\n"
05374 << "SRS_front_enable " << stencil -> get_render_state (StencilAttrib::SRS_front_enable) << "\n"
05375 << "SRS_back_enable " << stencil -> get_render_state (StencilAttrib::SRS_back_enable) << "\n"
05376 << "SRS_front_comparison_function " << stencil -> get_render_state (StencilAttrib::SRS_front_comparison_function) << "\n"
05377 << "SRS_front_stencil_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_fail_operation) << "\n"
05378 << "SRS_front_stencil_pass_z_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_fail_operation) << "\n"
05379 << "SRS_front_stencil_pass_z_pass_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_pass_operation) << "\n"
05380 << "SRS_reference " << stencil -> get_render_state (StencilAttrib::SRS_reference) << "\n"
05381 << "SRS_read_mask " << stencil -> get_render_state (StencilAttrib::SRS_read_mask) << "\n"
05382 << "SRS_write_mask " << stencil -> get_render_state (StencilAttrib::SRS_write_mask) << "\n"
05383 << "SRS_back_comparison_function " << stencil -> get_render_state (StencilAttrib::SRS_back_comparison_function) << "\n"
05384 << "SRS_back_stencil_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_back_stencil_fail_operation) << "\n"
05385 << "SRS_back_stencil_pass_z_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_fail_operation) << "\n"
05386 << "SRS_back_stencil_pass_z_pass_operation " << stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_pass_operation) << "\n";
05387 }
05388
05389 bool on;
05390
05391 on = false;
05392 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_enable, stencil -> get_render_state (StencilAttrib::SRS_front_enable));
05393 if (stencil -> get_render_state (StencilAttrib::SRS_front_enable)) {
05394 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_comparison_function, stencil -> get_render_state (StencilAttrib::SRS_front_comparison_function));
05395 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_stencil_fail_operation, stencil -> get_render_state (StencilAttrib::SRS_front_stencil_fail_operation));
05396 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_stencil_pass_z_fail_operation, stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_fail_operation));
05397 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_stencil_pass_z_pass_operation, stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_pass_operation));
05398 on = true;
05399 }
05400
05401 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_back_enable, stencil -> get_render_state (StencilAttrib::SRS_back_enable));
05402 if (stencil -> get_render_state (StencilAttrib::SRS_back_enable)) {
05403 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_back_comparison_function, stencil -> get_render_state (StencilAttrib::SRS_back_comparison_function));
05404 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_back_stencil_fail_operation, stencil -> get_render_state (StencilAttrib::SRS_back_stencil_fail_operation));
05405 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_back_stencil_pass_z_fail_operation, stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_fail_operation));
05406 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_back_stencil_pass_z_pass_operation, stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_pass_operation));
05407 on = true;
05408 }
05409
05410 if (on) {
05411 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_reference, stencil -> get_render_state (StencilAttrib::SRS_reference));
05412 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_read_mask, stencil -> get_render_state (StencilAttrib::SRS_read_mask));
05413 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_write_mask, stencil -> get_render_state (StencilAttrib::SRS_write_mask));
05414 }
05415
05416 if (stencil -> get_render_state (StencilAttrib::SRS_clear)) {
05417 _d3d_device->Clear(0, NULL, D3DCLEAR_STENCIL, 0, 0.0f, stencil -> get_render_state (StencilAttrib::SRS_clear_value));
05418 }
05419 }
05420 else {
05421
05422
05423 if (false) {
05424 dxgsg9_cat.debug() << "STENCIL STATE CHANGE TO OFF \n";
05425 }
05426
05427 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_enable, 0);
05428 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_back_enable, 0);
05429 }
05430 }
05431
05432
05433
05434
05435
05436
05437 void DXGraphicsStateGuardian9::
05438 do_issue_scissor() {
05439 const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
05440 const LVecBase4 &frame = target_scissor->get_frame();
05441
05442 RECT r;
05443 r.left = _current_viewport.X + _current_viewport.Width * frame[0];
05444 r.top = _current_viewport.Y + _current_viewport.Height * (1.0f - frame[3]);
05445 r.right = _current_viewport.X + _current_viewport.Width * frame[1];
05446 r.bottom = _current_viewport.Y + _current_viewport.Height * (1.0f - frame[2]);
05447 _d3d_device->SetScissorRect(&r);
05448 set_render_state(D3DRS_SCISSORTESTENABLE, TRUE);
05449 }
05450
05451
05452
05453
05454
05455
05456
05457 FrameBufferProperties DXGraphicsStateGuardian9::
05458 calc_fb_properties(DWORD cformat, DWORD dformat,
05459 DWORD multisampletype, DWORD multisamplequality) {
05460 FrameBufferProperties props;
05461 int index=0;
05462 int alpha=0;
05463 int color=0;
05464 switch (cformat) {
05465 case D3DFMT_R8G8B8: index=0; color=24; alpha=0; break;
05466 case D3DFMT_A8R8G8B8: index=0; color=24; alpha=8; break;
05467 case D3DFMT_X8R8G8B8: index=0; color=24; alpha=0; break;
05468 case D3DFMT_R5G6B5: index=0; color=16; alpha=0; break;
05469 case D3DFMT_X1R5G5B5: index=0; color=15; alpha=0; break;
05470 case D3DFMT_A1R5G5B5: index=0; color=15; alpha=1; break;
05471 case D3DFMT_A4R4G4B4: index=0; color=12; alpha=4; break;
05472 case D3DFMT_R3G3B2: index=0; color= 8; alpha=0; break;
05473 case D3DFMT_A8R3G3B2: index=0; color= 8; alpha=8; break;
05474 case D3DFMT_X4R4G4B4: index=0; color=12; alpha=0; break;
05475 case D3DFMT_A2B10G10R10: index=0; color=30; alpha=2; break;
05476 case D3DFMT_A8P8: index=1; color= 8; alpha=8; break;
05477 case D3DFMT_P8: index=1; color= 8; alpha=0; break;
05478 }
05479 props.set_color_bits(color);
05480 props.set_alpha_bits(alpha);
05481 if (index) {
05482 props.set_rgb_color(0);
05483 props.set_indexed_color(1);
05484 } else if (color) {
05485 props.set_rgb_color(1);
05486 props.set_indexed_color(0);
05487 }
05488 int depth=0;
05489 int stencil=0;
05490 switch (dformat) {
05491 case D3DFMT_D32: depth=32; stencil=0; break;
05492 case D3DFMT_D15S1: depth=15; stencil=1; break;
05493 case D3DFMT_D24S8: depth=24; stencil=8; break;
05494 case D3DFMT_D16: depth=16; stencil=0; break;
05495 case D3DFMT_D24X8: depth=24; stencil=0; break;
05496 case D3DFMT_D24X4S4: depth=24; stencil=4; break;
05497 }
05498 props.set_depth_bits(depth);
05499 props.set_stencil_bits(stencil);
05500 if (multisampletype == D3DMULTISAMPLE_NONMASKABLE) {
05501 props.set_multisamples(2);
05502 } else {
05503 props.set_multisamples(multisampletype);
05504 }
05505 return props;
05506 }
05507
05508
05509 #define GAMMA_1 (255.0 * 256.0)
05510
05511 static bool _gamma_table_initialized = false;
05512 static unsigned short _orignial_gamma_table [256 * 3];
05513
05514 void _create_gamma_table (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) {
05515 int i;
05516 double gamma_correction;
05517
05518 if (gamma <= 0.0) {
05519
05520 gamma = 1.0;
05521 }
05522 gamma_correction = 1.0 / (double) gamma;
05523
05524 for (i = 0; i < 256; i++) {
05525 double r;
05526 double g;
05527 double b;
05528
05529 if (original_red_table) {
05530 r = (double) original_red_table [i] / GAMMA_1;
05531 g = (double) original_green_table [i] / GAMMA_1;
05532 b = (double) original_blue_table [i] / GAMMA_1;
05533 }
05534 else {
05535 r = ((double) i / 255.0);
05536 g = r;
05537 b = r;
05538 }
05539
05540 r = pow (r, gamma_correction);
05541 g = pow (g, gamma_correction);
05542 b = pow (b, gamma_correction);
05543
05544 if (r > 1.00) {
05545 r = 1.0;
05546 }
05547 if (g > 1.00) {
05548 g = 1.0;
05549 }
05550 if (b > 1.00) {
05551 b = 1.0;
05552 }
05553
05554 r = r * GAMMA_1;
05555 g = g * GAMMA_1;
05556 b = b * GAMMA_1;
05557
05558 red_table [i] = r;
05559 green_table [i] = g;
05560 blue_table [i] = b;
05561 }
05562 }
05563
05564
05565
05566
05567
05568
05569 bool DXGraphicsStateGuardian9::
05570 get_gamma_table(void) {
05571 bool get;
05572
05573 get = false;
05574 if (_gamma_table_initialized == false) {
05575 HDC hdc = GetDC(NULL);
05576
05577 if (hdc) {
05578 if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) {
05579 _gamma_table_initialized = true;
05580 get = true;
05581 }
05582
05583 ReleaseDC (NULL, hdc);
05584 }
05585 }
05586
05587 return get;
05588 }
05589
05590
05591
05592
05593
05594
05595
05596 bool DXGraphicsStateGuardian9::
05597 static_set_gamma(bool restore, PN_stdfloat gamma) {
05598 bool set;
05599 HDC hdc = GetDC(NULL);
05600
05601 set = false;
05602 if (hdc) {
05603 unsigned short ramp [256 * 3];
05604
05605 if (restore && _gamma_table_initialized) {
05606 _create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
05607 }
05608 else {
05609 _create_gamma_table (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
05610 }
05611
05612 if (SetDeviceGammaRamp (hdc, ramp)) {
05613 set = true;
05614 }
05615
05616 ReleaseDC (NULL, hdc);
05617 }
05618
05619 return set;
05620 }
05621
05622
05623
05624
05625
05626
05627
05628 bool DXGraphicsStateGuardian9::
05629 set_gamma(PN_stdfloat gamma) {
05630 bool set;
05631
05632 set = static_set_gamma(false, gamma);
05633 if (set) {
05634 _gamma = gamma;
05635 }
05636
05637 return set;
05638 }
05639
05640
05641
05642
05643
05644
05645 void DXGraphicsStateGuardian9::
05646 restore_gamma() {
05647 static_set_gamma(true, 1.0f);
05648 }
05649
05650
05651
05652
05653
05654
05655 void DXGraphicsStateGuardian9::
05656 atexit_function(void) {
05657 set_cg_device(NULL);
05658 static_set_gamma(true, 1.0f);
05659 }
05660
05661
05662
05663
05664
05665
05666
05667 bool DXGraphicsStateGuardian9::
05668 get_supports_cg_profile(const string &name) const {
05669 #ifndef HAVE_CG
05670 return false;
05671 #else
05672 CGprofile profile = cgGetProfile(name.c_str());
05673
05674 if (profile == CG_PROFILE_UNKNOWN) {
05675 dxgsg9_cat.error() << name <<", unknown Cg-profile\n";
05676 return false;
05677 }
05678 return cgD3D9IsProfileSupported(cgGetProfile(name.c_str())) != 0;
05679 #endif // HAVE_CG
05680 }
05681
05682
05683
05684
05685
05686
05687
05688
05689 void DXGraphicsStateGuardian9::
05690 set_cg_device(LPDIRECT3DDEVICE9 cg_device) {
05691 #ifdef HAVE_CG
05692 if (_cg_device != cg_device) {
05693 cgD3D9SetDevice(cg_device);
05694 _cg_device = cg_device;
05695 }
05696 #endif // HAVE_CG
05697 }
05698
05699
05700
05701
05702 typedef string KEY;
05703
05704 typedef struct _KEY_ELEMENT
05705 {
05706 KEY key;
05707 int count;
05708 int secondary_count;
05709
05710 struct _KEY_ELEMENT *next;
05711 }
05712 KEY_ELEMENT;
05713
05714 typedef struct _KEY_LIST
05715 {
05716 int total_key_elements;
05717 KEY_ELEMENT *key_element;
05718 }
05719 KEY_LIST;
05720
05721 KEY_ELEMENT *new_key_element (KEY key, KEY_LIST *key_list)
05722 {
05723 KEY_ELEMENT *key_element;
05724
05725 key_element = new KEY_ELEMENT;
05726 key_element -> key = key;
05727 key_element -> count = 1;
05728 key_element -> secondary_count = 0;
05729 key_element -> next = 0;
05730
05731 key_list -> total_key_elements++;
05732
05733 return key_element;
05734 }
05735
05736 KEY_ELEMENT *first_key_element (KEY_LIST *key_list)
05737 {
05738 return key_list -> key_element;
05739 }
05740
05741 KEY_ELEMENT *next_key_element (KEY_ELEMENT *key_element)
05742 {
05743 return key_element -> next;
05744 }
05745
05746 void delete_key_list (KEY_LIST *key_list)
05747 {
05748 if (key_list)
05749 {
05750 KEY_ELEMENT *key_element;
05751 KEY_ELEMENT *key_element_next;
05752
05753 key_element = first_key_element (key_list);
05754 while (key_element)
05755 {
05756 key_element_next = next_key_element (key_element);
05757 delete key_element;
05758 key_element = key_element_next;
05759 }
05760
05761 delete key_list;
05762 }
05763 }
05764
05765 KEY_LIST *new_key_list (void)
05766 {
05767 KEY_LIST *key_list;
05768
05769 key_list = new KEY_LIST;
05770 memset (key_list, 0, sizeof (KEY_LIST));
05771
05772 return key_list;
05773 }
05774
05775 KEY_ELEMENT *add_to_key_list (KEY key, KEY_LIST *key_list)
05776 {
05777 KEY_ELEMENT *key_element;
05778 KEY_ELEMENT *last_key_element;
05779 KEY_ELEMENT *current_key_element;
05780
05781 key_element = 0;
05782 last_key_element = 0;
05783 current_key_element = key_list -> key_element;
05784 if (current_key_element == 0)
05785 {
05786 key_element = new_key_element (key, key_list);
05787 key_list -> key_element = key_element;
05788 }
05789 else
05790 {
05791 while (current_key_element)
05792 {
05793 if (key < current_key_element -> key)
05794 {
05795 key_element = new_key_element (key, key_list);
05796 key_element -> next = current_key_element;
05797
05798 if (last_key_element == 0)
05799 {
05800 key_list -> key_element = key_element;
05801 }
05802 else
05803 {
05804 last_key_element -> next = key_element;
05805 }
05806 break;
05807 }
05808 else
05809 {
05810 if (key > current_key_element -> key)
05811 {
05812 if (current_key_element -> next == 0)
05813 {
05814 key_element = new_key_element (key, key_list);
05815 current_key_element -> next = key_element;
05816 break;
05817 }
05818 else
05819 {
05820
05821 }
05822 }
05823 else
05824 {
05825 current_key_element -> count++;
05826 break;
05827 }
05828 }
05829
05830 last_key_element = current_key_element;
05831 current_key_element = current_key_element -> next;
05832 }
05833 }
05834
05835 return key_element;
05836 }