00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "dxGraphicsStateGuardian8.h"
00016 #include "config_dxgsg8.h"
00017 #include "displayRegion.h"
00018 #include "renderBuffer.h"
00019 #include "geom.h"
00020 #include "graphicsWindow.h"
00021 #include "graphicsEngine.h"
00022 #include "lens.h"
00023 #include "ambientLight.h"
00024 #include "directionalLight.h"
00025 #include "pointLight.h"
00026 #include "spotlight.h"
00027 #include "textureAttrib.h"
00028 #include "texGenAttrib.h"
00029 #include "shadeModelAttrib.h"
00030 #include "cullFaceAttrib.h"
00031 #include "transparencyAttrib.h"
00032 #include "alphaTestAttrib.h"
00033 #include "depthTestAttrib.h"
00034 #include "depthWriteAttrib.h"
00035 #include "colorWriteAttrib.h"
00036 #include "texMatrixAttrib.h"
00037 #include "materialAttrib.h"
00038 #include "renderModeAttrib.h"
00039 #include "rescaleNormalAttrib.h"
00040 #include "fogAttrib.h"
00041 #include "depthOffsetAttrib.h"
00042 #include "lightAttrib.h"
00043 #include "stencilAttrib.h"
00044 #include "scissorAttrib.h"
00045 #include "fog.h"
00046 #include "throw_event.h"
00047 #include "geomVertexFormat.h"
00048 #include "geomVertexData.h"
00049 #include "geomTriangles.h"
00050 #include "geomTristrips.h"
00051 #include "geomTrifans.h"
00052 #include "geomLines.h"
00053 #include "geomLinestrips.h"
00054 #include "geomPoints.h"
00055 #include "geomVertexReader.h"
00056 #include "dxGeomMunger8.h"
00057 #include "config_gobj.h"
00058 #include "dxVertexBufferContext8.h"
00059 #include "dxIndexBufferContext8.h"
00060 #include "pStatTimer.h"
00061 #include "pStatCollector.h"
00062 #include "dxgsg8base.h"
00063 #include "wdxGraphicsBuffer8.h"
00064
00065 #include <mmsystem.h>
00066
00067 TypeHandle DXGraphicsStateGuardian8::_type_handle;
00068
00069 D3DMATRIX DXGraphicsStateGuardian8::_d3d_ident_mat;
00070
00071 unsigned char *DXGraphicsStateGuardian8::_temp_buffer = NULL;
00072 unsigned char *DXGraphicsStateGuardian8::_safe_buffer_start = NULL;
00073
00074 #define __D3DLIGHT_RANGE_MAX ((float)sqrt(FLT_MAX)) //for some reason this is missing in dx8 hdrs
00075
00076 #define MY_D3DRGBA(r, g, b, a) ((D3DCOLOR) D3DCOLOR_COLORVALUE(r, g, b, a))
00077
00078
00079
00080
00081
00082
00083 DXGraphicsStateGuardian8::
00084 DXGraphicsStateGuardian8(GraphicsEngine *engine, GraphicsPipe *pipe) :
00085 GraphicsStateGuardian(CS_yup_left, engine, pipe)
00086 {
00087
00088
00089 _is_hardware = true;
00090
00091 _screen = NULL;
00092 _d3d_device = NULL;
00093
00094 _dx_is_ready = false;
00095 _vertex_blending_enabled = false;
00096 _overlay_windows_supported = false;
00097 _tex_stats_retrieval_impossible = false;
00098
00099 _active_vbuffer = NULL;
00100 _active_ibuffer = NULL;
00101
00102
00103
00104
00105 ZeroMemory(&_d3d_ident_mat, sizeof(D3DMATRIX));
00106 _d3d_ident_mat._11 = _d3d_ident_mat._22 = _d3d_ident_mat._33 = _d3d_ident_mat._44 = 1.0f;
00107
00108 _cur_read_pixel_buffer = RenderBuffer::T_front;
00109
00110
00111
00112 _copy_texture_inverted = true;
00113
00114
00115
00116
00117 _supported_geom_rendering =
00118 Geom::GR_point | Geom::GR_point_uniform_size |
00119 Geom::GR_point_perspective | Geom::GR_point_sprite |
00120 Geom::GR_indexed_other |
00121 Geom::GR_triangle_strip | Geom::GR_triangle_fan |
00122 Geom::GR_flat_first_vertex;
00123
00124 _scissor_mat = TransformState::make_identity();
00125
00126 get_gamma_table();
00127 atexit (atexit_function);
00128 }
00129
00130
00131
00132
00133
00134
00135 DXGraphicsStateGuardian8::
00136 ~DXGraphicsStateGuardian8() {
00137 if (IS_VALID_PTR(_d3d_device)) {
00138 _d3d_device->SetTexture(0, NULL);
00139 }
00140 free_nondx_resources();
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 TextureContext *DXGraphicsStateGuardian8::
00157 prepare_texture(Texture *tex) {
00158 DXTextureContext8 *dtc = new DXTextureContext8(_prepared_objects, tex);
00159
00160 if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
00161 dxgsg8_cat.error()
00162 << *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
00163 return NULL;
00164 }
00165
00166 return dtc;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175 void DXGraphicsStateGuardian8::
00176 apply_texture(int i, TextureContext *tc) {
00177 if (tc == (TextureContext *)NULL) {
00178
00179
00180 _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
00181 return;
00182 }
00183 if (!update_texture(tc, false)) {
00184
00185 _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
00186 return;
00187 }
00188
00189 tc->set_active(true);
00190
00191 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
00192 Texture *tex = tc->get_texture();
00193
00194 Texture::WrapMode wrap_u, wrap_v, wrap_w;
00195 wrap_u = tex->get_wrap_u();
00196 wrap_v = tex->get_wrap_v();
00197 wrap_w = tex->get_wrap_w();
00198
00199 _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSU, get_texture_wrap_mode(wrap_u));
00200 _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSV, get_texture_wrap_mode(wrap_v));
00201 _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSW, get_texture_wrap_mode(wrap_w));
00202
00203 _d3d_device->SetTextureStageState(i, D3DTSS_BORDERCOLOR,
00204 Colorf_to_D3DCOLOR(tex->get_border_color()));
00205
00206 uint aniso_degree = tex->get_effective_anisotropic_degree();
00207 Texture::FilterType ft = tex->get_effective_magfilter();
00208
00209 if (aniso_degree >= 1) {
00210 _d3d_device->SetTextureStageState(i, D3DTSS_MAXANISOTROPY, aniso_degree);
00211 }
00212
00213 D3DTEXTUREFILTERTYPE new_mag_filter;
00214 if (aniso_degree <= 1) {
00215 new_mag_filter = ((ft != Texture::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT);
00216 } else {
00217 new_mag_filter = D3DTEXF_ANISOTROPIC;
00218 }
00219
00220 _d3d_device->SetTextureStageState(i, D3DTSS_MAGFILTER, new_mag_filter);
00221
00222
00223 D3DTEXTUREFILTERTYPE new_min_filter = get_d3d_min_type(tex->get_effective_minfilter());
00224 D3DTEXTUREFILTERTYPE new_mip_filter = get_d3d_mip_type(tex->get_effective_minfilter());
00225
00226 if (!tex->might_have_ram_image()) {
00227
00228
00229
00230 new_mip_filter = D3DTEXF_NONE;
00231 }
00232
00233
00234 if (!dtc->has_mipmaps()) {
00235 new_mip_filter = D3DTEXF_NONE;
00236 }
00237
00238 if (aniso_degree >= 2) {
00239 new_min_filter = D3DTEXF_ANISOTROPIC;
00240 }
00241
00242 _d3d_device->SetTextureStageState(i, D3DTSS_MINFILTER, new_min_filter);
00243 _d3d_device->SetTextureStageState(i, D3DTSS_MIPFILTER, new_mip_filter);
00244
00245 _d3d_device->SetTexture(i, dtc->get_d3d_texture());
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 bool DXGraphicsStateGuardian8::
00265 update_texture(TextureContext *tc, bool force) {
00266 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
00267
00268
00269
00270
00271 if (dtc->was_modified()) {
00272 if (!upload_texture(dtc, force)) {
00273
00274 Texture *tex = tc->get_texture();
00275 dxgsg8_cat.error()
00276 << "Unable to re-create texture " << *tex << endl;
00277 cerr << "b\n";
00278 return false;
00279 }
00280 }
00281 dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
00282
00283 return true;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 bool DXGraphicsStateGuardian8::
00293 upload_texture(DXTextureContext8 *dtc, bool force) {
00294 Texture *tex = dtc->get_texture();
00295 if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
00296 dxgsg8_cat.error()
00297 << *tex << " is stored in an unsupported compressed format.\n";
00298 return false;
00299 }
00300
00301 dtc->delete_texture();
00302 dtc->update_data_size_bytes(0);
00303 dtc->mark_unloaded();
00304
00305 if (_effective_incomplete_render && !force) {
00306 bool has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image();
00307 if (!has_image && tex->might_have_ram_image() &&
00308 tex->has_simple_ram_image() &&
00309 !_loader.is_null()) {
00310
00311
00312 async_reload_texture(dtc);
00313 has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image();
00314 if (!has_image) {
00315 if (dtc->was_simple_image_modified()) {
00316 return dtc->create_simple_texture(*_screen);
00317 }
00318 return true;
00319 }
00320 }
00321 }
00322
00323 return dtc->create_texture(*_screen);
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 void DXGraphicsStateGuardian8::
00333 release_texture(TextureContext *tc) {
00334 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
00335 delete dtc;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 bool DXGraphicsStateGuardian8::
00351 extract_texture_data(Texture *tex) {
00352 TextureContext *tc = tex->prepare_now(get_prepared_objects(), this);
00353 nassertr(tc != (TextureContext *)NULL, false);
00354 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
00355
00356 return dtc->extract_texture_data();
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 VertexBufferContext *DXGraphicsStateGuardian8::
00373 prepare_vertex_buffer(GeomVertexArrayData *data) {
00374 DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(_prepared_objects, data);
00375 return dvbc;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 bool DXGraphicsStateGuardian8::
00385 apply_vertex_buffer(VertexBufferContext *vbc,
00386 const GeomVertexArrayDataHandle *reader, bool force) {
00387 DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc);
00388
00389 if (dvbc->_vbuffer == NULL) {
00390
00391 if (vertex_buffers &&
00392 reader->get_usage_hint() != Geom::UH_client) {
00393 dvbc->create_vbuffer(*_screen, reader);
00394 }
00395
00396 if (dvbc->_vbuffer != NULL) {
00397 if (!dvbc->upload_data(reader, force)) {
00398 return false;
00399 }
00400
00401 dvbc->mark_loaded(reader);
00402
00403 _d3d_device->SetStreamSource
00404 (0, dvbc->_vbuffer, reader->get_array_format()->get_stride());
00405 _active_vbuffer = dvbc;
00406 _active_ibuffer = NULL;
00407 dvbc->set_active(true);
00408
00409 } else {
00410 _active_vbuffer = NULL;
00411 }
00412
00413 } else {
00414 if (dvbc->was_modified(reader)) {
00415 if (dvbc->changed_size(reader)) {
00416
00417
00418 dvbc->create_vbuffer(*_screen, reader);
00419 }
00420
00421 if (!dvbc->upload_data(reader, force)) {
00422 return false;
00423 }
00424 dvbc->mark_loaded(reader);
00425 _active_vbuffer = NULL;
00426 }
00427
00428 if (_active_vbuffer != dvbc) {
00429 _d3d_device->SetStreamSource
00430 (0, dvbc->_vbuffer, reader->get_array_format()->get_stride());
00431 _active_vbuffer = dvbc;
00432 _active_ibuffer = NULL;
00433 dvbc->set_active(true);
00434 }
00435 }
00436 dvbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
00437
00438 HRESULT hr = _d3d_device->SetVertexShader(dvbc->_fvf);
00439 #ifndef NDEBUG
00440 if (FAILED(hr)) {
00441 dxgsg8_cat.error()
00442 << "SetVertexShader(0x" << (void*)dvbc->_fvf
00443 << ") failed" << D3DERRORSTRING(hr);
00444 }
00445 #endif
00446 return true;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 void DXGraphicsStateGuardian8::
00458 release_vertex_buffer(VertexBufferContext *vbc) {
00459 DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc);
00460 delete dvbc;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 IndexBufferContext *DXGraphicsStateGuardian8::
00477 prepare_index_buffer(GeomPrimitive *data) {
00478 DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(_prepared_objects, data);
00479 return dibc;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488 bool DXGraphicsStateGuardian8::
00489 apply_index_buffer(IndexBufferContext *ibc,
00490 const GeomPrimitivePipelineReader *reader, bool force) {
00491 DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc);
00492
00493 if (dibc->_ibuffer == NULL) {
00494
00495 dibc->create_ibuffer(*_screen, reader);
00496
00497 if (dibc->_ibuffer != NULL) {
00498 if (!dibc->upload_data(reader, force)) {
00499 return false;
00500 }
00501 dibc->mark_loaded(reader);
00502
00503 _d3d_device->SetIndices(dibc->_ibuffer, 0);
00504 _active_ibuffer = dibc;
00505 dibc->set_active(true);
00506
00507 } else {
00508 _d3d_device->SetIndices(NULL, 0);
00509 _active_ibuffer = NULL;
00510 }
00511
00512 } else {
00513 if (dibc->was_modified(reader)) {
00514 if (dibc->changed_size(reader)) {
00515
00516
00517 dibc->create_ibuffer(*_screen, reader);
00518 }
00519
00520 if (!dibc->upload_data(reader, force)) {
00521 return false;
00522 }
00523
00524 dibc->mark_loaded(reader);
00525 _active_ibuffer = NULL;
00526 }
00527
00528 if (_active_ibuffer != dibc) {
00529 _d3d_device->SetIndices(dibc->_ibuffer, 0);
00530 _active_ibuffer = dibc;
00531 dibc->set_active(true);
00532 }
00533 }
00534 dibc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
00535
00536 return true;
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 void DXGraphicsStateGuardian8::
00548 release_index_buffer(IndexBufferContext *ibc) {
00549 DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc);
00550 delete dibc;
00551 }
00552
00553
00554
00555
00556
00557
00558
00559 PT(GeomMunger) DXGraphicsStateGuardian8::
00560 make_geom_munger(const RenderState *state, Thread *current_thread) {
00561 PT(DXGeomMunger8) munger = new DXGeomMunger8(this, state);
00562 return GeomMunger::register_munger(munger, current_thread);
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 void DXGraphicsStateGuardian8::
00572 clear(DrawableRegion *clearable) {
00573
00574 DWORD main_flags = 0;
00575 DWORD aux_flags = 0;
00576
00577 D3DCOLOR color_clear_value = Colorf_to_D3DCOLOR(clearable->get_clear_color());
00578 float depth_clear_value = clearable->get_clear_depth();
00579 DWORD stencil_clear_value = (DWORD)(clearable->get_clear_stencil());
00580
00581
00582 if (clearable->get_clear_color_active()) {
00583 main_flags |= D3DCLEAR_TARGET;
00584 }
00585
00586 if (clearable->get_clear_depth_active()) {
00587 aux_flags |= D3DCLEAR_ZBUFFER;
00588 nassertv(_screen->_presentation_params.EnableAutoDepthStencil);
00589 }
00590
00591 if (clearable->get_clear_stencil_active()) {
00592
00593 if (_screen->_presentation_params.EnableAutoDepthStencil &&
00594 IS_STENCIL_FORMAT(_screen->_presentation_params.AutoDepthStencilFormat)) {
00595 aux_flags |= D3DCLEAR_STENCIL;
00596 }
00597 }
00598
00599 if ((main_flags | aux_flags) != 0) {
00600 HRESULT hr = _d3d_device->Clear(0, NULL, main_flags | aux_flags, color_clear_value,
00601 depth_clear_value, stencil_clear_value);
00602 if (FAILED(hr) && main_flags == D3DCLEAR_TARGET && aux_flags != 0) {
00603
00604
00605 hr = _d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, color_clear_value,
00606 depth_clear_value, stencil_clear_value);
00607 if (!FAILED(hr)) {
00608
00609
00610 if (clearable->get_clear_depth_active()) {
00611 aux_flags |= D3DCLEAR_ZBUFFER;
00612 HRESULT hr2 = _d3d_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color_clear_value,
00613 depth_clear_value, stencil_clear_value);
00614 if (FAILED(hr2)) {
00615 dxgsg8_cat.error()
00616 << "Unable to clear depth buffer; removing.\n";
00617
00618 ((FrameBufferProperties *)_current_properties)->set_depth_bits(0);
00619 }
00620 }
00621 if (clearable->get_clear_stencil_active()) {
00622 aux_flags |= D3DCLEAR_STENCIL;
00623 HRESULT hr2 = _d3d_device->Clear(0, NULL, D3DCLEAR_STENCIL, color_clear_value,
00624 stencil_clear_value, stencil_clear_value);
00625 if (FAILED(hr2)) {
00626 dxgsg8_cat.error()
00627 << "Unable to clear stencil buffer; removing.\n";
00628
00629 ((FrameBufferProperties *)_current_properties)->set_stencil_bits(0);
00630 _supports_stencil = false;
00631 }
00632 }
00633 }
00634 }
00635
00636 if (FAILED(hr)) {
00637 dxgsg8_cat.error()
00638 << "clear_buffer failed: Clear returned " << D3DERRORSTRING(hr);
00639 }
00640 }
00641 }
00642
00643
00644
00645
00646
00647
00648
00649 void DXGraphicsStateGuardian8::
00650 prepare_display_region(DisplayRegionPipelineReader *dr,
00651 Lens::StereoChannel stereo_channel) {
00652 nassertv(dr != (DisplayRegionPipelineReader *)NULL);
00653 GraphicsStateGuardian::prepare_display_region(dr, stereo_channel);
00654
00655 int l, u, w, h;
00656 dr->get_region_pixels_i(l, u, w, h);
00657
00658
00659 D3DVIEWPORT8 vp = { l, u, w, h, 0.0f, 1.0f };
00660 _current_viewport = vp;
00661 set_scissor(0.0f, 1.0f, 0.0f, 1.0f);
00662
00663 if (_screen->_can_direct_disable_color_writes) {
00664 _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, _color_write_mask);
00665 }
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 CPT(TransformState) DXGraphicsStateGuardian8::
00680 calc_projection_mat(const Lens *lens) {
00681 if (lens == (Lens *)NULL) {
00682 return NULL;
00683 }
00684
00685 if (!lens->is_linear()) {
00686 return NULL;
00687 }
00688
00689
00690
00691
00692 static const LMatrix4f rescale_mat
00693 (1, 0, 0, 0,
00694 0, 1, 0, 0,
00695 0, 0, 0.5, 0,
00696 0, 0, 0.5, 1);
00697
00698 LMatrix4f result =
00699 LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
00700 lens->get_projection_mat(_current_stereo_channel) *
00701 rescale_mat;
00702
00703 if (_scene_setup->get_inverted()) {
00704
00705
00706 result *= LMatrix4f::scale_mat(1.0f, -1.0f, 1.0f);
00707 }
00708
00709 return TransformState::make_mat(result);
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 bool DXGraphicsStateGuardian8::
00725 prepare_lens() {
00726 CPT(TransformState) scissor_proj_mat = _scissor_mat->compose(_projection_mat);
00727 HRESULT hr =
00728 _d3d_device->SetTransform(D3DTS_PROJECTION,
00729 (D3DMATRIX*)scissor_proj_mat->get_mat().get_data());
00730 return SUCCEEDED(hr);
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 bool DXGraphicsStateGuardian8::
00747 begin_frame(Thread *current_thread) {
00748 if (!GraphicsStateGuardian::begin_frame(current_thread)) {
00749 return false;
00750 }
00751
00752 if (_d3d_device == NULL) {
00753 dxgsg8_cat.debug()
00754 << this << "::begin_frame(): no device.\n";
00755 return false;
00756 }
00757
00758 return true;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 bool DXGraphicsStateGuardian8::
00777 begin_scene() {
00778 if (!GraphicsStateGuardian::begin_scene()) {
00779 return false;
00780 }
00781
00782 HRESULT hr = _d3d_device->BeginScene();
00783
00784 if (FAILED(hr)) {
00785 if (hr == D3DERR_DEVICELOST) {
00786 if (dxgsg8_cat.is_debug()) {
00787 dxgsg8_cat.debug()
00788 << "BeginScene returns D3DERR_DEVICELOST" << endl;
00789 }
00790
00791 check_cooperative_level();
00792
00793 } else {
00794 dxgsg8_cat.error()
00795 << "BeginScene failed, unhandled error hr == "
00796 << D3DERRORSTRING(hr) << endl;
00797 throw_event("panda3d-render-error");
00798 }
00799 return false;
00800 }
00801
00802 return true;
00803 }
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 void DXGraphicsStateGuardian8::
00815 end_scene() {
00816 GraphicsStateGuardian::end_scene();
00817 _dlights.clear();
00818
00819 HRESULT hr = _d3d_device->EndScene();
00820
00821 if (FAILED(hr)) {
00822 if (hr == D3DERR_DEVICELOST) {
00823 if (dxgsg8_cat.is_debug()) {
00824 dxgsg8_cat.debug()
00825 << "EndScene returns DeviceLost\n";
00826 }
00827 check_cooperative_level();
00828
00829 } else {
00830 dxgsg8_cat.error()
00831 << "EndScene failed, unhandled error hr == " << D3DERRORSTRING(hr);
00832 throw_event("panda3d-render-error");
00833 }
00834 return;
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845 void DXGraphicsStateGuardian8::
00846 end_frame(Thread *current_thread) {
00847
00848 #if defined(DO_PSTATS)
00849 if (_texmgrmem_total_pcollector.is_active()) {
00850 #define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval
00851 static DWORD last_tick_count = 0;
00852 DWORD cur_tick_count = GetTickCount();
00853
00854 if (cur_tick_count - last_tick_count > TICKS_PER_GETTEXINFO) {
00855 last_tick_count = cur_tick_count;
00856 report_texmgr_stats();
00857 }
00858 }
00859 #endif
00860
00861
00862
00863
00864 GraphicsStateGuardian::end_frame(current_thread);
00865 }
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 bool DXGraphicsStateGuardian8::
00876 begin_draw_primitives(const GeomPipelineReader *geom_reader,
00877 const GeomMunger *munger,
00878 const GeomVertexDataPipelineReader *data_reader,
00879 bool force) {
00880 if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger,
00881 data_reader, force)) {
00882 return false;
00883 }
00884 nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false);
00885
00886 const GeomVertexFormat *format = _data_reader->get_format();
00887
00888
00889 const GeomVertexArrayDataHandle *data = _data_reader->get_array_reader(0);
00890
00891 VertexBufferContext *vbc = ((GeomVertexArrayData *)(data->get_object()))->prepare_now(get_prepared_objects(), this);
00892 nassertr(vbc != (VertexBufferContext *)NULL, false);
00893 if (!apply_vertex_buffer(vbc, data, force)) {
00894 return false;
00895 }
00896
00897 const GeomVertexAnimationSpec &animation =
00898 data_reader->get_format()->get_animation();
00899 if (animation.get_animation_type() == Geom::AT_hardware) {
00900
00901 switch (animation.get_num_transforms()) {
00902 case 1:
00903
00904
00905
00906
00907
00908
00909 _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
00910 break;
00911 case 2:
00912 _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS);
00913 break;
00914 case 3:
00915 _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_2WEIGHTS);
00916 break;
00917 case 4:
00918 _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_3WEIGHTS);
00919 break;
00920 }
00921
00922 if (animation.get_indexed_transforms()) {
00923
00924 _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
00925 } else {
00926 _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
00927 }
00928
00929 const TransformTable *table = data_reader->get_transform_table();
00930 if (table != (TransformTable *)NULL) {
00931 for (int i = 0; i < table->get_num_transforms(); i++) {
00932 LMatrix4f mat;
00933 table->get_transform(i)->mult_matrix(mat, _internal_transform->get_mat());
00934 const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data();
00935 _d3d_device->SetTransform(D3DTS_WORLDMATRIX(i), d3d_mat);
00936 }
00937
00938
00939
00940 _transform_stale = true;
00941 }
00942 _vertex_blending_enabled = true;
00943
00944 } else {
00945
00946 if (_vertex_blending_enabled) {
00947 _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
00948 _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
00949 _vertex_blending_enabled = false;
00950 }
00951
00952 if (_transform_stale && !_data_reader->is_vertex_transformed()) {
00953 const D3DMATRIX *d3d_mat = (const D3DMATRIX *)_internal_transform->get_mat().get_data();
00954 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
00955 _transform_stale = false;
00956 }
00957 }
00958
00959 if (_data_reader->is_vertex_transformed()) {
00960
00961
00962
00963
00964
00965
00966
00967
00968 _d3d_device->SetTransform(D3DTS_WORLD, &_d3d_ident_mat);
00969 static const LMatrix4f rescale_mat
00970 (1, 0, 0, 0,
00971 0, 1, 0, 0,
00972 0, 0, 0.5, 0,
00973 0, 0, 0.5, 1);
00974 _transform_stale = true;
00975
00976 _d3d_device->SetTransform(D3DTS_PROJECTION, (const D3DMATRIX *)rescale_mat.get_data());
00977 }
00978
00979 return true;
00980 }
00981
00982
00983
00984
00985
00986
00987 bool DXGraphicsStateGuardian8::
00988 draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
00989
00990 _vertices_tri_pcollector.add_level(reader->get_num_vertices());
00991 _primitive_batches_tri_pcollector.add_level(1);
00992 if (reader->is_indexed()) {
00993 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
00994 int max_vertex = reader->get_max_vertex();
00995
00996 if (_active_vbuffer != NULL) {
00997
00998 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
00999 nassertr(ibc != (IndexBufferContext *)NULL, false);
01000 if (!apply_index_buffer(ibc, reader, force)) {
01001 return false;
01002 }
01003
01004 _d3d_device->DrawIndexedPrimitive
01005 (D3DPT_TRIANGLELIST,
01006 min_vertex, max_vertex - min_vertex + 1,
01007 0, reader->get_num_primitives());
01008
01009 } else {
01010
01011 const unsigned char *index_pointer = reader->get_read_pointer(force);
01012 if (index_pointer == NULL) {
01013 return false;
01014 }
01015 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01016 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01017 if (vertex_pointer == NULL) {
01018 return false;
01019 }
01020 draw_indexed_primitive_up
01021 (D3DPT_TRIANGLELIST,
01022 min_vertex, max_vertex,
01023 reader->get_num_primitives(),
01024 index_pointer, index_type, vertex_pointer,
01025 _data_reader->get_format()->get_array(0)->get_stride());
01026 }
01027 } else {
01028 if (_active_vbuffer != NULL) {
01029
01030 _d3d_device->DrawPrimitive
01031 (D3DPT_TRIANGLELIST,
01032 reader->get_first_vertex(),
01033 reader->get_num_primitives());
01034
01035 } else {
01036
01037 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01038 if (vertex_pointer == NULL) {
01039 return false;
01040 }
01041 draw_primitive_up(D3DPT_TRIANGLELIST, reader->get_num_primitives(),
01042 reader->get_first_vertex(),
01043 reader->get_num_vertices(),
01044 vertex_pointer,
01045 _data_reader->get_format()->get_array(0)->get_stride());
01046 }
01047 }
01048 return true;
01049 }
01050
01051
01052
01053
01054
01055
01056 bool DXGraphicsStateGuardian8::
01057 draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
01058
01059 if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
01060
01061
01062 _vertices_tristrip_pcollector.add_level(reader->get_num_vertices());
01063 _primitive_batches_tristrip_pcollector.add_level(1);
01064 if (reader->is_indexed()) {
01065 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
01066 int max_vertex = reader->get_max_vertex();
01067
01068 if (_active_vbuffer != NULL) {
01069
01070 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01071 nassertr(ibc != (IndexBufferContext *)NULL, false);
01072 if (!apply_index_buffer(ibc, reader, force)) {
01073 return false;
01074 }
01075
01076 _d3d_device->DrawIndexedPrimitive
01077 (D3DPT_TRIANGLESTRIP,
01078 min_vertex, max_vertex - min_vertex + 1,
01079 0, reader->get_num_vertices() - 2);
01080
01081 } else {
01082
01083 const unsigned char *index_pointer = reader->get_read_pointer(force);
01084 if (index_pointer == NULL) {
01085 return false;
01086 }
01087 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01088 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01089 if (vertex_pointer == NULL) {
01090 return false;
01091 }
01092 draw_indexed_primitive_up
01093 (D3DPT_TRIANGLESTRIP,
01094 min_vertex, max_vertex,
01095 reader->get_num_vertices() - 2,
01096 index_pointer, index_type, vertex_pointer,
01097 _data_reader->get_format()->get_array(0)->get_stride());
01098 }
01099 } else {
01100 if (_active_vbuffer != NULL) {
01101
01102 _d3d_device->DrawPrimitive
01103 (D3DPT_TRIANGLESTRIP,
01104 reader->get_first_vertex(),
01105 reader->get_num_vertices() - 2);
01106
01107 } else {
01108
01109 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01110 if (vertex_pointer == NULL) {
01111 return false;
01112 }
01113 draw_primitive_up(D3DPT_TRIANGLESTRIP,
01114 reader->get_num_vertices() - 2,
01115 reader->get_first_vertex(),
01116 reader->get_num_vertices(),
01117 vertex_pointer,
01118 _data_reader->get_format()->get_array(0)->get_stride());
01119 }
01120 }
01121
01122 } else {
01123
01124
01125 CPTA_int ends = reader->get_ends();
01126 _primitive_batches_tristrip_pcollector.add_level(ends.size());
01127
01128 if (reader->is_indexed()) {
01129 CPTA_int ends = reader->get_ends();
01130 int index_stride = reader->get_index_stride();
01131 _primitive_batches_tristrip_pcollector.add_level(ends.size());
01132
01133 GeomVertexReader mins(reader->get_mins(), 0);
01134 GeomVertexReader maxs(reader->get_maxs(), 0);
01135 nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
01136 reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
01137
01138 if (_active_vbuffer != NULL) {
01139
01140 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01141 nassertr(ibc != (IndexBufferContext *)NULL, false);
01142 if (!apply_index_buffer(ibc, reader, force)) {
01143 return false;
01144 }
01145
01146 unsigned int start = 0;
01147 for (size_t i = 0; i < ends.size(); i++) {
01148 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01149 unsigned int min = mins.get_data1i();
01150 unsigned int max = maxs.get_data1i();
01151 _d3d_device->DrawIndexedPrimitive
01152 (D3DPT_TRIANGLESTRIP,
01153 min, max - min + 1,
01154 start, ends[i] - start - 2);
01155
01156 start = ends[i] + 2;
01157 }
01158
01159 } else {
01160
01161 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01162 const unsigned char *index_pointer = reader->get_read_pointer(force);
01163 if (index_pointer == NULL) {
01164 return false;
01165 }
01166 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01167 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01168 if (vertex_pointer == NULL) {
01169 return false;
01170 }
01171
01172 unsigned int start = 0;
01173 for (size_t i = 0; i < ends.size(); i++) {
01174 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01175 unsigned int min = mins.get_data1i();
01176 unsigned int max = maxs.get_data1i();
01177 draw_indexed_primitive_up
01178 (D3DPT_TRIANGLESTRIP,
01179 min, max,
01180 ends[i] - start - 2,
01181 index_pointer + start * index_stride, index_type,
01182 vertex_pointer, stride);
01183
01184 start = ends[i] + 2;
01185 }
01186 }
01187 } else {
01188 unsigned int first_vertex = reader->get_first_vertex();
01189
01190 if (_active_vbuffer != NULL) {
01191
01192 unsigned int start = 0;
01193 for (size_t i = 0; i < ends.size(); i++) {
01194 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01195 _d3d_device->DrawPrimitive
01196 (D3DPT_TRIANGLESTRIP,
01197 first_vertex + start, ends[i] - start - 2);
01198
01199 start = ends[i] + 2;
01200 }
01201
01202 } else {
01203
01204 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01205 if (vertex_pointer == NULL) {
01206 return false;
01207 }
01208 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01209
01210 unsigned int start = 0;
01211 for (size_t i = 0; i < ends.size(); i++) {
01212 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01213 draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2,
01214 first_vertex + start,
01215 ends[i] - start,
01216 vertex_pointer, stride);
01217
01218 start = ends[i] + 2;
01219 }
01220 }
01221 }
01222 }
01223 return true;
01224 }
01225
01226
01227
01228
01229
01230
01231 bool DXGraphicsStateGuardian8::
01232 draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
01233
01234 CPTA_int ends = reader->get_ends();
01235 _primitive_batches_trifan_pcollector.add_level(ends.size());
01236
01237 if (reader->is_indexed()) {
01238 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
01239 int max_vertex = reader->get_max_vertex();
01240
01241
01242
01243 int index_stride = reader->get_index_stride();
01244
01245 GeomVertexReader mins(reader->get_mins(), 0);
01246 GeomVertexReader maxs(reader->get_maxs(), 0);
01247 nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
01248 reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
01249
01250 if (_active_vbuffer != NULL) {
01251
01252 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01253 nassertr(ibc != (IndexBufferContext *)NULL, false);
01254 if (!apply_index_buffer(ibc, reader, force)) {
01255 return false;
01256 }
01257
01258 unsigned int start = 0;
01259 for (size_t i = 0; i < ends.size(); i++) {
01260 _vertices_trifan_pcollector.add_level(ends[i] - start);
01261 unsigned int min = mins.get_data1i();
01262 unsigned int max = maxs.get_data1i();
01263 _d3d_device->DrawIndexedPrimitive
01264 (D3DPT_TRIANGLEFAN,
01265 min, max - min + 1,
01266 start, ends[i] - start - 2);
01267
01268 start = ends[i];
01269 }
01270
01271 } else {
01272
01273 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01274 const unsigned char *index_pointer = reader->get_read_pointer(force);
01275 if (index_pointer == NULL) {
01276 return false;
01277 }
01278 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01279 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01280 if (vertex_pointer == NULL) {
01281 return false;
01282 }
01283
01284 unsigned int start = 0;
01285 for (size_t i = 0; i < ends.size(); i++) {
01286 _vertices_trifan_pcollector.add_level(ends[i] - start);
01287 unsigned int min = mins.get_data1i();
01288 unsigned int max = maxs.get_data1i();
01289 draw_indexed_primitive_up
01290 (D3DPT_TRIANGLEFAN,
01291 min, max,
01292 ends[i] - start - 2,
01293 index_pointer + start * index_stride, index_type,
01294 vertex_pointer, stride);
01295
01296 start = ends[i];
01297 }
01298 }
01299 } else {
01300 unsigned int first_vertex = reader->get_first_vertex();
01301
01302 if (_active_vbuffer != NULL) {
01303
01304 unsigned int start = 0;
01305 for (size_t i = 0; i < ends.size(); i++) {
01306 _vertices_trifan_pcollector.add_level(ends[i] - start);
01307 _d3d_device->DrawPrimitive
01308 (D3DPT_TRIANGLEFAN,
01309 first_vertex + start, ends[i] - start - 2);
01310
01311 start = ends[i];
01312 }
01313
01314 } else {
01315
01316 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01317 if (vertex_pointer == NULL) {
01318 return false;
01319 }
01320 int stride = _data_reader->get_format()->get_array(0)->get_stride();
01321
01322 unsigned int start = 0;
01323 for (size_t i = 0; i < ends.size(); i++) {
01324 _vertices_trifan_pcollector.add_level(ends[i] - start);
01325 draw_primitive_up(D3DPT_TRIANGLEFAN,
01326 ends[i] - start - 2,
01327 first_vertex,
01328 ends[i] - start,
01329 vertex_pointer, stride);
01330 start = ends[i];
01331 }
01332 }
01333 }
01334 return true;
01335 }
01336
01337
01338
01339
01340
01341
01342 bool DXGraphicsStateGuardian8::
01343 draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
01344
01345 _vertices_other_pcollector.add_level(reader->get_num_vertices());
01346 _primitive_batches_other_pcollector.add_level(1);
01347
01348 if (reader->is_indexed()) {
01349 int min_vertex = dx_broken_max_index ? 0 : reader->get_min_vertex();
01350 int max_vertex = reader->get_max_vertex();
01351
01352 if (_active_vbuffer != NULL) {
01353
01354 IndexBufferContext *ibc = ((GeomPrimitive *)(reader->get_object()))->prepare_now(get_prepared_objects(), this);
01355 nassertr(ibc != (IndexBufferContext *)NULL, false);
01356 if (!apply_index_buffer(ibc, reader, force)) {
01357 return false;
01358 }
01359
01360 _d3d_device->DrawIndexedPrimitive
01361 (D3DPT_LINELIST,
01362 min_vertex, max_vertex - min_vertex + 1,
01363 0, reader->get_num_primitives());
01364
01365 } else {
01366
01367 const unsigned char *index_pointer = reader->get_read_pointer(force);
01368 if (index_pointer == NULL) {
01369 return false;
01370 }
01371 D3DFORMAT index_type = get_index_type(reader->get_index_type());
01372 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01373 if (vertex_pointer == NULL) {
01374 return false;
01375 }
01376
01377 draw_indexed_primitive_up
01378 (D3DPT_LINELIST,
01379 min_vertex, max_vertex,
01380 reader->get_num_primitives(),
01381 index_pointer, index_type, vertex_pointer,
01382 _data_reader->get_format()->get_array(0)->get_stride());
01383 }
01384 } else {
01385 if (_active_vbuffer != NULL) {
01386
01387 _d3d_device->DrawPrimitive
01388 (D3DPT_LINELIST,
01389 reader->get_first_vertex(),
01390 reader->get_num_primitives());
01391
01392 } else {
01393
01394 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01395 if (vertex_pointer == NULL) {
01396 return false;
01397 }
01398 draw_primitive_up(D3DPT_LINELIST, reader->get_num_primitives(),
01399 reader->get_first_vertex(),
01400 reader->get_num_vertices(),
01401 vertex_pointer,
01402 _data_reader->get_format()->get_array(0)->get_stride());
01403 }
01404 }
01405 return true;
01406 }
01407
01408
01409
01410
01411
01412
01413 bool DXGraphicsStateGuardian8::
01414 draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
01415 return false;
01416 }
01417
01418
01419
01420
01421
01422
01423 bool DXGraphicsStateGuardian8::
01424 draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
01425
01426 _vertices_other_pcollector.add_level(reader->get_num_vertices());
01427 _primitive_batches_other_pcollector.add_level(1);
01428
01429
01430
01431 nassertr(!reader->is_indexed(), false);
01432
01433 if (_active_vbuffer != NULL) {
01434
01435 _d3d_device->DrawPrimitive
01436 (D3DPT_POINTLIST,
01437 reader->get_first_vertex(),
01438 reader->get_num_primitives());
01439
01440 } else {
01441
01442 const unsigned char *vertex_pointer = _data_reader->get_array_reader(0)->get_read_pointer(force);
01443 if (vertex_pointer == NULL) {
01444 return false;
01445 }
01446 draw_primitive_up(D3DPT_POINTLIST, reader->get_num_primitives(),
01447 reader->get_first_vertex(),
01448 reader->get_num_vertices(),
01449 vertex_pointer,
01450 _data_reader->get_format()->get_array(0)->get_stride());
01451 }
01452 return true;
01453 }
01454
01455
01456
01457
01458
01459
01460
01461
01462 void DXGraphicsStateGuardian8::
01463 end_draw_primitives() {
01464
01465
01466 if (_vertex_blending_enabled) {
01467 _d3d_device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
01468 _d3d_device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
01469 _vertex_blending_enabled = false;
01470 }
01471
01472 if (_data_reader->is_vertex_transformed()) {
01473
01474 _d3d_device->SetTransform(D3DTS_PROJECTION,
01475 (D3DMATRIX*)_projection_mat->get_mat().get_data());
01476 }
01477
01478 GraphicsStateGuardian::end_draw_primitives();
01479 }
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490 bool DXGraphicsStateGuardian8::
01491 framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
01492 const RenderBuffer &rb) {
01493 set_read_buffer(rb);
01494
01495 int orig_x = tex->get_x_size();
01496 int orig_y = tex->get_y_size();
01497
01498 HRESULT hr;
01499 int xo, yo, w, h;
01500 dr->get_region_pixels_i(xo, yo, w, h);
01501 tex->set_size_padded(w, h);
01502
01503 TextureContext *tc = tex->prepare_now(get_prepared_objects(), this);
01504 if (tc == (TextureContext *)NULL) {
01505 return false;
01506 }
01507 DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
01508 if (!dtc->create_texture(*_screen)) {
01509
01510 dxgsg8_cat.error()
01511 << "Unable to re-create texture " << *dtc->get_texture() << endl;
01512 return false;
01513 }
01514
01515 if (tex->get_texture_type() != Texture::TT_2d_texture) {
01516
01517
01518 return do_framebuffer_copy_to_ram(tex, z, dr, rb, true);
01519 }
01520 nassertr(dtc->get_d3d_2d_texture() != NULL, false);
01521
01522 IDirect3DSurface8 *tex_level_0;
01523 hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0);
01524 if (FAILED(hr)) {
01525 dxgsg8_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
01526 return false;
01527 }
01528
01529
01530 D3DSURFACE_DESC texdesc;
01531 hr = tex_level_0->GetDesc(&texdesc);
01532 if (FAILED(hr)) {
01533 dxgsg8_cat.error() << "GetDesc failed in copy_texture" << D3DERRORSTRING(hr);
01534 SAFE_RELEASE(tex_level_0);
01535 return false;
01536 }
01537 if ((texdesc.Width != tex->get_x_size())||(texdesc.Height != tex->get_y_size())) {
01538 if ((orig_x != tex->get_x_size()) || (orig_y != tex->get_y_size())) {
01539
01540 SAFE_RELEASE(tex_level_0);
01541 if (!dtc->create_texture(*_screen)) {
01542
01543 dxgsg8_cat.error()
01544 << "Unable to re-create texture " << *dtc->get_texture() << endl;
01545 return false;
01546 }
01547 hr = dtc->get_d3d_2d_texture()->GetSurfaceLevel(0, &tex_level_0);
01548 if (FAILED(hr)) {
01549 dxgsg8_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
01550 return false;
01551 }
01552 hr = tex_level_0->GetDesc(&texdesc);
01553 if (FAILED(hr)) {
01554 dxgsg8_cat.error() << "GetDesc 2 failed in copy_texture" << D3DERRORSTRING(hr);
01555 SAFE_RELEASE(tex_level_0);
01556 return false;
01557 }
01558 }
01559 if ((texdesc.Width != tex->get_x_size())||(texdesc.Height != tex->get_y_size())) {
01560
01561
01562 dxgsg8_cat.error()
01563 << "Unable to copy to texture, texture is wrong size: " << *dtc->get_texture() << endl;
01564 SAFE_RELEASE(tex_level_0);
01565 return false;
01566 }
01567 }
01568
01569 IDirect3DSurface8 *render_target;
01570 hr = _d3d_device->GetRenderTarget(&render_target);
01571 if (FAILED(hr)) {
01572 dxgsg8_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr);
01573 SAFE_RELEASE(tex_level_0);
01574 return false;
01575 }
01576
01577 RECT src_rect;
01578
01579 src_rect.left = xo;
01580 src_rect.right = xo+w;
01581 src_rect.top = yo;
01582 src_rect.bottom = yo+h;
01583
01584
01585 bool okflag = true;
01586 hr = _d3d_device->CopyRects(render_target, &src_rect, 1, tex_level_0, 0);
01587 if (FAILED(hr)) {
01588 dxgsg8_cat.info()
01589 << "CopyRects failed in copy_texture " << D3DERRORSTRING(hr);
01590 okflag = framebuffer_copy_to_ram(tex, z, dr, rb);
01591 }
01592
01593 SAFE_RELEASE(render_target);
01594 SAFE_RELEASE(tex_level_0);
01595
01596 if (okflag) {
01597 dtc->mark_loaded();
01598 dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
01599
01600 } else {
01601
01602
01603 return do_framebuffer_copy_to_ram(tex, z, dr, rb, true);
01604 }
01605
01606 return true;
01607 }
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620 bool DXGraphicsStateGuardian8::
01621 framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb) {
01622 return do_framebuffer_copy_to_ram(tex, z, dr, rb, false);
01623 }
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634 bool DXGraphicsStateGuardian8::
01635 do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
01636 const RenderBuffer &rb, bool inverted) {
01637 set_read_buffer(rb);
01638
01639 RECT rect;
01640 nassertr(tex != NULL && dr != NULL, false);
01641
01642 int xo, yo, w, h;
01643 dr->get_region_pixels_i(xo, yo, w, h);
01644
01645 Texture::Format format = tex->get_format();
01646 Texture::ComponentType component_type = tex->get_component_type();
01647
01648 switch (format) {
01649 case Texture::F_depth_stencil:
01650
01651 return false;
01652
01653 default:
01654 format = Texture::F_rgb;
01655 component_type = Texture::T_unsigned_byte;
01656 }
01657
01658 Texture::TextureType texture_type;
01659 if (z >= 0) {
01660 texture_type = Texture::TT_cube_map;
01661 } else {
01662 texture_type = Texture::TT_2d_texture;
01663 }
01664
01665 if (tex->get_x_size() != w || tex->get_y_size() != h ||
01666 tex->get_component_type() != component_type ||
01667 tex->get_format() != format ||
01668 tex->get_texture_type() != texture_type) {
01669
01670 tex->setup_texture(texture_type, w, h, tex->get_z_size(),
01671 component_type, format);
01672 }
01673
01674 rect.top = yo;
01675 rect.left = xo;
01676 rect.right = xo + w;
01677 rect.bottom = yo + h;
01678 bool copy_inverted = false;
01679
01680 IDirect3DSurface8 *temp_surface = NULL;
01681 HRESULT hr;
01682
01683
01684
01685
01686 if (_cur_read_pixel_buffer & RenderBuffer::T_back) {
01687 IDirect3DSurface8 *backbuffer = NULL;
01688
01689
01690
01691 hr = _d3d_device->GetRenderTarget(&backbuffer);
01692
01693 if (FAILED(hr)) {
01694 dxgsg8_cat.error() << "GetRenderTarget failed" << D3DERRORSTRING(hr);
01695 return false;
01696 }
01697
01698
01699
01700
01701 hr = _d3d_device->CreateImageSurface(w, h, _screen->_display_mode.Format,
01702 &temp_surface);
01703 if (FAILED(hr)) {
01704 dxgsg8_cat.error()
01705 << "CreateImageSurface failed in copy_pixel_buffer()"
01706 << D3DERRORSTRING(hr);
01707 backbuffer->Release();
01708 return false;
01709 }
01710
01711
01712 hr = _d3d_device->CopyRects(backbuffer, &rect, 1, temp_surface, NULL);
01713 if (FAILED(hr)) {
01714 dxgsg8_cat.error() << "CopyRects failed" << D3DERRORSTRING(hr);
01715 temp_surface->Release();
01716 backbuffer->Release();
01717 return false;
01718 }
01719
01720 copy_inverted = true;
01721
01722 RELEASE(backbuffer, dxgsg8, "backbuffer", RELEASE_ONCE);
01723
01724 } else if (_cur_read_pixel_buffer & RenderBuffer::T_front) {
01725
01726 if (_screen->_presentation_params.Windowed) {
01727
01728
01729
01730
01731
01732 MONITORINFO minfo;
01733 minfo.cbSize = sizeof(MONITORINFO);
01734 GetMonitorInfo(_screen->_monitor, &minfo);
01735
01736 w = RECT_XSIZE(minfo.rcMonitor);
01737 h = RECT_YSIZE(minfo.rcMonitor);
01738
01739
01740 ClientToScreen(_screen->_window, (POINT*)&rect.left);
01741 ClientToScreen(_screen->_window, (POINT*)&rect.right);
01742 }
01743
01744
01745
01746
01747 hr = _d3d_device->CreateImageSurface(w, h, D3DFMT_A8R8G8B8, &temp_surface);
01748 if (FAILED(hr)) {
01749 dxgsg8_cat.error()
01750 << "CreateImageSurface failed in copy_pixel_buffer()"
01751 << D3DERRORSTRING(hr);
01752 return false;
01753 }
01754
01755 hr = _d3d_device->GetFrontBuffer(temp_surface);
01756
01757 if (hr == D3DERR_DEVICELOST) {
01758 dxgsg8_cat.error()
01759 << "copy_pixel_buffer failed: device lost\n";
01760 temp_surface->Release();
01761 return false;
01762 }
01763
01764 copy_inverted = true;
01765
01766 } else {
01767 dxgsg8_cat.error()
01768 << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n";
01769 temp_surface->Release();
01770 return false;
01771 }
01772
01773 if (inverted) {
01774 copy_inverted = !copy_inverted;
01775 }
01776 DXTextureContext8::d3d_surface_to_texture(rect, temp_surface,
01777 copy_inverted, tex, z);
01778
01779 RELEASE(temp_surface, dxgsg8, "temp_surface", RELEASE_ONCE);
01780
01781 nassertr(tex->has_ram_image(), false);
01782 return true;
01783 }
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794 void DXGraphicsStateGuardian8::
01795 reset() {
01796 GraphicsStateGuardian::reset();
01797
01798 _auto_rescale_normal = false;
01799
01800
01801
01802 HRESULT hr;
01803
01804
01805
01806
01807
01808
01809 if (_d3d_device == NULL) {
01810 return;
01811 }
01812
01813 nassertv(_screen->_d3d8 != NULL);
01814
01815 D3DCAPS8 d3d_caps;
01816 _d3d_device->GetDeviceCaps(&d3d_caps);
01817
01818 if (dxgsg8_cat.is_debug()) {
01819 dxgsg8_cat.debug()
01820 << "\nHwTransformAndLight = " << ((d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
01821 << "\nMaxTextureWidth = " << d3d_caps.MaxTextureWidth
01822 << "\nMaxTextureHeight = " << d3d_caps.MaxTextureHeight
01823 << "\nMaxVolumeExtent = " << d3d_caps.MaxVolumeExtent
01824 << "\nMaxTextureAspectRatio = " << d3d_caps.MaxTextureAspectRatio
01825 << "\nTexCoordCount = " << (d3d_caps.FVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK)
01826 << "\nMaxTextureBlendStages = " << d3d_caps.MaxTextureBlendStages
01827 << "\nMaxSimultaneousTextures = " << d3d_caps.MaxSimultaneousTextures
01828 << "\nMaxActiveLights = " << d3d_caps.MaxActiveLights
01829 << "\nMaxUserClipPlanes = " << d3d_caps.MaxUserClipPlanes
01830 << "\nMaxVertexBlendMatrices = " << d3d_caps.MaxVertexBlendMatrices
01831 << "\nMaxVertexBlendMatrixIndex = " << d3d_caps.MaxVertexBlendMatrixIndex
01832 << "\nMaxPointSize = " << d3d_caps.MaxPointSize
01833 << "\nMaxPrimitiveCount = " << d3d_caps.MaxPrimitiveCount
01834 << "\nMaxVertexIndex = " << d3d_caps.MaxVertexIndex
01835 << "\nMaxStreams = " << d3d_caps.MaxStreams
01836 << "\nMaxStreamStride = " << d3d_caps.MaxStreamStride
01837 << "\nD3DTEXOPCAPS_MULTIPLYADD = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) != 0)
01838 << "\nD3DTEXOPCAPS_LERP = " << ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0)
01839 << "\nD3DPMISCCAPS_TSSARGTEMP = " << ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0)
01840 << "\nVertexShaderVersion = " << D3DSHADER_VERSION_MAJOR (d3d_caps.VertexShaderVersion) << "." << D3DSHADER_VERSION_MINOR (d3d_caps.VertexShaderVersion)
01841 << "\nPixelShaderVersion = " << D3DSHADER_VERSION_MAJOR (d3d_caps.PixelShaderVersion) << "." << D3DSHADER_VERSION_MINOR (d3d_caps.PixelShaderVersion)
01842 << "\nMaxVertexShaderConst = " << d3d_caps.MaxVertexShaderConst
01843 << "\n";
01844 }
01845
01846 if (support_stencil) {
01847 int min_stencil = D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR;
01848 if ((d3d_caps.StencilCaps & min_stencil) == min_stencil) {
01849 if (dxgsg8_cat.is_debug()) {
01850 dxgsg8_cat.debug()
01851 << "Checking for stencil; mode = "
01852 << D3DFormatStr(_screen->_presentation_params.AutoDepthStencilFormat)
01853 << "\n";
01854 }
01855 switch (_screen->_presentation_params.AutoDepthStencilFormat) {
01856
01857 case D3DFMT_D15S1:
01858 case D3DFMT_D24S8:
01859 case D3DFMT_D24X4S4:
01860 _supports_stencil = true;
01861 if (dxgsg8_cat.is_debug()) {
01862 dxgsg8_cat.debug()
01863 << "Stencils supported.\n";
01864 }
01865 break;
01866
01867 default:
01868 if (dxgsg8_cat.is_debug()) {
01869 dxgsg8_cat.debug()
01870 << "Stencils NOT supported.\n";
01871 }
01872 }
01873 }
01874 }
01875
01876 _max_vertices_per_array = d3d_caps.MaxVertexIndex;
01877 _max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount;
01878
01879 _max_texture_stages = d3d_caps.MaxSimultaneousTextures;
01880
01881 _max_texture_dimension = min(d3d_caps.MaxTextureWidth, d3d_caps.MaxTextureHeight);
01882
01883 _supports_texture_combine = ((d3d_caps.TextureOpCaps & D3DTEXOPCAPS_LERP) != 0);
01884 _supports_texture_saved_result = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0);
01885 _supports_texture_dot3 = true;
01886
01887
01888 D3DDEVICE_CREATION_PARAMETERS creation_parameters;
01889
01890 _supports_render_texture = false;
01891 _screen->_render_to_texture_d3d_format = D3DFMT_UNKNOWN;
01892 _screen->_framebuffer_d3d_format = D3DFMT_UNKNOWN;
01893
01894 #define TOTAL_RENDER_TO_TEXTURE_FORMATS 3
01895
01896 D3DFORMAT render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS] =
01897 {
01898 D3DFMT_A8R8G8B8,
01899 D3DFMT_X8R8G8B8,
01900 D3DFMT_UNKNOWN,
01901 };
01902
01903 render_to_texture_formats [TOTAL_RENDER_TO_TEXTURE_FORMATS - 1] = _screen->_display_mode.Format;
01904
01905 hr = _d3d_device->GetCreationParameters (&creation_parameters);
01906 if (SUCCEEDED (hr)) {
01907 _screen->_framebuffer_d3d_format = _screen->_display_mode.Format;
01908
01909 int index;
01910 for (index = 0; index < TOTAL_RENDER_TO_TEXTURE_FORMATS; index++) {
01911 hr = _screen->_d3d8->CheckDeviceFormat (
01912 creation_parameters.AdapterOrdinal,
01913 creation_parameters.DeviceType,
01914 _screen->_display_mode.Format,
01915 D3DUSAGE_RENDERTARGET,
01916 D3DRTYPE_TEXTURE,
01917 render_to_texture_formats [index]);
01918 if (SUCCEEDED (hr)) {
01919 _screen->_render_to_texture_d3d_format = render_to_texture_formats [index];
01920 _supports_render_texture = true;
01921 }
01922 if (_supports_render_texture) {
01923 break;
01924 }
01925 }
01926 }
01927 if (dxgsg8_cat.is_debug()) {
01928 dxgsg8_cat.debug() << "Render to Texture Support = " << _supports_render_texture << "\n";
01929 }
01930
01931 _supports_3d_texture = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) != 0);
01932 if (_supports_3d_texture) {
01933 _max_3d_texture_dimension = d3d_caps.MaxVolumeExtent;
01934 }
01935 _supports_cube_map = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) != 0);
01936 if (_supports_cube_map) {
01937 _max_cube_map_dimension = _max_texture_dimension;
01938 }
01939
01940 _num_active_texture_stages = 0;
01941
01942 _max_lights = (int)d3d_caps.MaxActiveLights;
01943 _max_clip_planes = (int)d3d_caps.MaxUserClipPlanes;
01944 _max_vertex_transforms = d3d_caps.MaxVertexBlendMatrices;
01945 _max_vertex_transform_indices = d3d_caps.MaxVertexBlendMatrixIndex;
01946
01947 _d3d_device->SetRenderState(D3DRS_AMBIENT, 0x0);
01948
01949 _clip_plane_bits = 0;
01950 _d3d_device->SetRenderState(D3DRS_CLIPPLANEENABLE , 0x0);
01951
01952 _d3d_device->SetRenderState(D3DRS_CLIPPING, true);
01953
01954 _d3d_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
01955
01956 _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
01957
01958 _d3d_device->SetRenderState(D3DRS_EDGEANTIALIAS, false);
01959
01960 _d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
01961
01962 _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
01963
01964 _d3d_device->SetRenderState(D3DRS_FOGENABLE, FALSE);
01965
01966 _has_scene_graph_color = false;
01967
01968 _last_testcooplevel_result = D3D_OK;
01969
01970 for(int i = 0; i < MAX_POSSIBLE_TEXFMTS; i++) {
01971
01972 D3DFORMAT_FLAG fmtflag = D3DFORMAT_FLAG(1 << i);
01973 hr = _screen->_d3d8->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format,
01974 0x0, D3DRTYPE_TEXTURE, g_D3DFORMATmap[fmtflag]);
01975 if (SUCCEEDED(hr)){
01976 _screen->_supported_tex_formats_mask |= fmtflag;
01977 }
01978 }
01979
01980
01981 #define CHECK_FOR_DXTVERSION(num) \
01982 if (_screen->_supported_tex_formats_mask & DXT##num##_FLAG) {\
01983 if (dxgsg8_cat.is_debug()) {\
01984 dxgsg8_cat.debug() << "Compressed texture format DXT" << #num << " supported \n";\
01985 }\
01986 _supports_compressed_texture = true;\
01987 _compressed_texture_formats.set_bit(Texture::CM_dxt##num);\
01988 }
01989
01990 CHECK_FOR_DXTVERSION(1)
01991 CHECK_FOR_DXTVERSION(2)
01992 CHECK_FOR_DXTVERSION(3)
01993 CHECK_FOR_DXTVERSION(4)
01994 CHECK_FOR_DXTVERSION(5)
01995
01996 #undef CHECK_FOR_DXTVERSION
01997
01998
01999 if (_screen->_d3dcaps.MaxTextureWidth == 0)
02000 _screen->_d3dcaps.MaxTextureWidth = 256;
02001
02002 if (_screen->_d3dcaps.MaxTextureHeight == 0)
02003 _screen->_d3dcaps.MaxTextureHeight = 256;
02004
02005 if (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) {
02006
02007
02008
02009
02010 _do_fog_type = PerPixelFog;
02011 } else {
02012
02013
02014 nassertv((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0);
02015
02016
02017
02018
02019 if (dx_no_vertex_fog) {
02020 _do_fog_type = None;
02021 } else {
02022 _do_fog_type = PerVertexFog;
02023
02024
02025 if (dx_use_rangebased_fog && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)) {
02026 _d3d_device->SetRenderState(D3DRS_RANGEFOGENABLE, true);
02027 }
02028 }
02029 }
02030
02031 _screen->_can_direct_disable_color_writes = ((_screen->_d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0);
02032
02033
02034 _d3d_device->SetRenderState(D3DRS_LIGHTING, false);
02035
02036
02037 bool dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(_screen->_presentation_params.BackBufferFormat)
02038 && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER));
02039 _d3d_device->SetRenderState(D3DRS_DITHERENABLE, dither_enabled);
02040
02041 _d3d_device->SetRenderState(D3DRS_CLIPPING, true);
02042
02043
02044 _d3d_device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
02045
02046
02047 _d3d_device->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);
02048
02049 _current_fill_mode = RenderModeAttrib::M_filled;
02050 _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
02051
02052
02053
02054
02055 _d3d_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
02056
02057 _cull_face_mode = CullFaceAttrib::M_cull_none;
02058 _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
02059
02060 _d3d_device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
02061 _d3d_device->SetRenderState(D3DRS_ALPHAREF, 255);
02062 _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
02063
02064
02065
02066 _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
02067
02068 PRINT_REFCNT(dxgsg8, _d3d_device);
02069
02070 void dx_set_stencil_functions (StencilRenderStates *stencil_render_states);
02071 dx_set_stencil_functions (_stencil_render_states);
02072
02073
02074
02075 add_gsg(this);
02076 }
02077
02078
02079
02080
02081
02082
02083 void DXGraphicsStateGuardian8::
02084 apply_fog(Fog *fog) {
02085 if (_do_fog_type == None)
02086 return;
02087
02088 Fog::Mode panda_fogmode = fog->get_mode();
02089 D3DFOGMODE d3dfogmode = get_fog_mode_type(panda_fogmode);
02090
02091 _d3d_device->SetRenderState((D3DRENDERSTATETYPE)_do_fog_type, d3dfogmode);
02092
02093 const Colorf &fog_colr = fog->get_color();
02094 _d3d_device->SetRenderState(D3DRS_FOGCOLOR,
02095 MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f));
02096
02097
02098
02099
02100 switch (panda_fogmode) {
02101 case Fog::M_linear:
02102 {
02103 float onset, opaque;
02104 fog->get_linear_range(onset, opaque);
02105
02106 _d3d_device->SetRenderState(D3DRS_FOGSTART,
02107 *((LPDWORD) (&onset)));
02108 _d3d_device->SetRenderState(D3DRS_FOGEND,
02109 *((LPDWORD) (&opaque)));
02110 }
02111 break;
02112 case Fog::M_exponential:
02113 case Fog::M_exponential_squared:
02114 {
02115
02116 float fog_density = fog->get_exp_density();
02117 _d3d_device->SetRenderState(D3DRS_FOGDENSITY,
02118 *((LPDWORD) (&fog_density)));
02119 }
02120 break;
02121 }
02122 }
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133 void DXGraphicsStateGuardian8::
02134 do_issue_transform() {
02135 const TransformState *transform = _internal_transform;
02136 DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1));
02137
02138 const D3DMATRIX *d3d_mat = (const D3DMATRIX *)transform->get_mat().get_data();
02139 _d3d_device->SetTransform(D3DTS_WORLD, d3d_mat);
02140 _transform_stale = false;
02141
02142 if (_auto_rescale_normal) {
02143 do_auto_rescale_normal();
02144 }
02145 }
02146
02147
02148
02149
02150
02151
02152 void DXGraphicsStateGuardian8::
02153 do_issue_alpha_test() {
02154 const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
02155 AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode();
02156 if (mode == AlphaTestAttrib::M_none) {
02157 _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
02158
02159 } else {
02160
02161 _d3d_device->SetRenderState(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode);
02162 _d3d_device->SetRenderState(D3DRS_ALPHAREF, (UINT) (target_alpha_test->get_reference_alpha()*255.0f));
02163 _d3d_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
02164 }
02165 }
02166
02167
02168
02169
02170
02171
02172 void DXGraphicsStateGuardian8::
02173 do_issue_render_mode() {
02174 const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()));
02175 RenderModeAttrib::Mode mode = target_render_mode->get_mode();
02176
02177 switch (mode) {
02178 case RenderModeAttrib::M_unchanged:
02179 case RenderModeAttrib::M_filled:
02180 case RenderModeAttrib::M_filled_flat:
02181 _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
02182 break;
02183
02184 case RenderModeAttrib::M_wireframe:
02185 _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
02186 break;
02187
02188 case RenderModeAttrib::M_point:
02189 _d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT);
02190 break;
02191
02192 default:
02193 dxgsg8_cat.error()
02194 << "Unknown render mode " << (int)mode << endl;
02195 }
02196
02197
02198 float point_size = target_render_mode->get_thickness();
02199 _d3d_device->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&point_size));
02200
02201 if (target_render_mode->get_perspective()) {
02202 _d3d_device->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
02203
02204 LVector3f height(0.0f, point_size, 1.0f);
02205 height = height * _projection_mat->get_mat();
02206 float s = height[1] / point_size;
02207
02208 float zero = 0.0f;
02209 float one_over_s2 = 1.0f / (s * s);
02210 _d3d_device->SetRenderState(D3DRS_POINTSCALE_A, *((DWORD*)&zero));
02211 _d3d_device->SetRenderState(D3DRS_POINTSCALE_B, *((DWORD*)&zero));
02212 _d3d_device->SetRenderState(D3DRS_POINTSCALE_C, *((DWORD*)&one_over_s2));
02213
02214 } else {
02215 _d3d_device->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
02216 }
02217
02218 _current_fill_mode = mode;
02219 }
02220
02221
02222
02223
02224
02225
02226 void DXGraphicsStateGuardian8::
02227 do_issue_rescale_normal() {
02228 const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()));
02229 RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
02230
02231 _auto_rescale_normal = false;
02232
02233 switch (mode) {
02234 case RescaleNormalAttrib::M_none:
02235 _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, false);
02236 break;
02237
02238 case RescaleNormalAttrib::M_rescale:
02239 case RescaleNormalAttrib::M_normalize:
02240 _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
02241 break;
02242
02243 case RescaleNormalAttrib::M_auto:
02244 _auto_rescale_normal = true;
02245 do_auto_rescale_normal();
02246 break;
02247
02248 default:
02249 dxgsg8_cat.error()
02250 << "Unknown rescale_normal mode " << (int)mode << endl;
02251 }
02252 }
02253
02254
02255
02256
02257
02258
02259 void DXGraphicsStateGuardian8::
02260 do_issue_depth_test() {
02261 const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
02262 DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode();
02263 if (mode == DepthTestAttrib::M_none) {
02264 _d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
02265 } else {
02266 _d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
02267 _d3d_device->SetRenderState(D3DRS_ZFUNC, (D3DCMPFUNC) mode);
02268 }
02269 }
02270
02271
02272
02273
02274
02275
02276 void DXGraphicsStateGuardian8::
02277 do_issue_depth_write() {
02278 const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
02279 if (target_depth_write->get_mode() == DepthWriteAttrib::M_on) {
02280 _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
02281 } else {
02282 _d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
02283 }
02284 }
02285
02286
02287
02288
02289
02290
02291 void DXGraphicsStateGuardian8::
02292 do_issue_cull_face() {
02293 const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()));
02294 _cull_face_mode = target_cull_face->get_effective_mode();
02295
02296 switch (_cull_face_mode) {
02297 case CullFaceAttrib::M_cull_none:
02298 _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
02299 break;
02300 case CullFaceAttrib::M_cull_clockwise:
02301 _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
02302 break;
02303 case CullFaceAttrib::M_cull_counter_clockwise:
02304 _d3d_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
02305 break;
02306 default:
02307 dxgsg8_cat.error()
02308 << "invalid cull face mode " << (int)_cull_face_mode << endl;
02309 break;
02310 }
02311 }
02312
02313
02314
02315
02316
02317
02318 void DXGraphicsStateGuardian8::
02319 do_issue_fog() {
02320 const FogAttrib *target_fog = DCAST(FogAttrib, _target_rs->get_attrib_def(FogAttrib::get_class_slot()));
02321 if (!target_fog->is_off()) {
02322 _d3d_device->SetRenderState(D3DRS_FOGENABLE, TRUE);
02323 Fog *fog = target_fog->get_fog();
02324 nassertv(fog != (Fog *)NULL);
02325 apply_fog(fog);
02326 } else {
02327 _d3d_device->SetRenderState(D3DRS_FOGENABLE, FALSE);
02328 }
02329 }
02330
02331
02332
02333
02334
02335
02336 void DXGraphicsStateGuardian8::
02337 do_issue_depth_offset() {
02338 const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
02339 int offset = target_depth_offset->get_offset();
02340 _d3d_device->SetRenderState(D3DRS_ZBIAS, offset);
02341 }
02342
02343
02344
02345
02346
02347
02348 void DXGraphicsStateGuardian8::
02349 do_issue_shade_model() {
02350 const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()));
02351 switch (target_shade_model->get_mode()) {
02352 case ShadeModelAttrib::M_smooth:
02353 _d3d_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
02354 break;
02355
02356 case ShadeModelAttrib::M_flat:
02357 _d3d_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
02358 break;
02359 }
02360 }
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379 void DXGraphicsStateGuardian8::
02380 set_state_and_transform(const RenderState *target,
02381 const TransformState *transform) {
02382 #ifndef NDEBUG
02383 if (gsg_cat.is_spam()) {
02384 gsg_cat.spam() << "Setting GSG state to " << (void *)target << ":\n";
02385 target->write(gsg_cat.spam(false), 2);
02386 }
02387 #endif
02388 _state_pcollector.add_level(1);
02389 PStatTimer timer1(_draw_set_state_pcollector);
02390
02391 if (transform != _internal_transform) {
02392
02393 _state_pcollector.add_level(1);
02394 _internal_transform = transform;
02395 do_issue_transform();
02396 }
02397
02398 if (target == _state_rs) {
02399 return;
02400 }
02401 _target_rs = target;
02402
02403 int alpha_test_slot = AlphaTestAttrib::get_class_slot();
02404 if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
02405 !_state_mask.get_bit(alpha_test_slot)) {
02406
02407 do_issue_alpha_test();
02408 _state_mask.set_bit(alpha_test_slot);
02409 }
02410
02411 int clip_plane_slot = ClipPlaneAttrib::get_class_slot();
02412 if (_target_rs->get_attrib(clip_plane_slot) != _state_rs->get_attrib(clip_plane_slot) ||
02413 !_state_mask.get_bit(clip_plane_slot)) {
02414
02415 do_issue_clip_plane();
02416 _state_mask.set_bit(clip_plane_slot);
02417 }
02418
02419 int color_slot = ColorAttrib::get_class_slot();
02420 int color_scale_slot = ColorScaleAttrib::get_class_slot();
02421 if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
02422 _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
02423 !_state_mask.get_bit(color_slot) ||
02424 !_state_mask.get_bit(color_scale_slot)) {
02425
02426 do_issue_color();
02427 do_issue_color_scale();
02428 _state_mask.set_bit(color_slot);
02429 _state_mask.set_bit(color_scale_slot);
02430 }
02431
02432 int cull_face_slot = CullFaceAttrib::get_class_slot();
02433 if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
02434 !_state_mask.get_bit(cull_face_slot)) {
02435
02436 do_issue_cull_face();
02437 _state_mask.set_bit(cull_face_slot);
02438 }
02439
02440 int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
02441 if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
02442 !_state_mask.get_bit(depth_offset_slot)) {
02443
02444 do_issue_depth_offset();
02445 _state_mask.set_bit(depth_offset_slot);
02446 }
02447
02448 int depth_test_slot = DepthTestAttrib::get_class_slot();
02449 if (_target_rs->get_attrib(depth_test_slot) != _state_rs->get_attrib(depth_test_slot) ||
02450 !_state_mask.get_bit(depth_test_slot)) {
02451
02452 do_issue_depth_test();
02453 _state_mask.set_bit(depth_test_slot);
02454 }
02455
02456 int depth_write_slot = DepthWriteAttrib::get_class_slot();
02457 if (_target_rs->get_attrib(depth_write_slot) != _state_rs->get_attrib(depth_write_slot) ||
02458 !_state_mask.get_bit(depth_write_slot)) {
02459
02460 do_issue_depth_write();
02461 _state_mask.set_bit(depth_write_slot);
02462 }
02463
02464 int fog_slot = FogAttrib::get_class_slot();
02465 if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) ||
02466 !_state_mask.get_bit(fog_slot)) {
02467
02468 do_issue_fog();
02469 _state_mask.set_bit(fog_slot);
02470 }
02471
02472 int render_mode_slot = RenderModeAttrib::get_class_slot();
02473 if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
02474 !_state_mask.get_bit(render_mode_slot)) {
02475
02476 do_issue_render_mode();
02477 _state_mask.set_bit(render_mode_slot);
02478 }
02479
02480 int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
02481 if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
02482 !_state_mask.get_bit(rescale_normal_slot)) {
02483
02484 do_issue_rescale_normal();
02485 _state_mask.set_bit(rescale_normal_slot);
02486 }
02487
02488 int shade_model_slot = ShadeModelAttrib::get_class_slot();
02489 if (_target_rs->get_attrib(shade_model_slot) != _state_rs->get_attrib(shade_model_slot) ||
02490 !_state_mask.get_bit(shade_model_slot)) {
02491
02492 do_issue_shade_model();
02493 _state_mask.set_bit(shade_model_slot);
02494 }
02495
02496 int transparency_slot = TransparencyAttrib::get_class_slot();
02497 int color_write_slot = ColorWriteAttrib::get_class_slot();
02498 int color_blend_slot = ColorBlendAttrib::get_class_slot();
02499 if (_target_rs->get_attrib(transparency_slot) != _state_rs->get_attrib(transparency_slot) ||
02500 _target_rs->get_attrib(color_write_slot) != _state_rs->get_attrib(color_write_slot) ||
02501 _target_rs->get_attrib(color_blend_slot) != _state_rs->get_attrib(color_blend_slot) ||
02502 !_state_mask.get_bit(transparency_slot) ||
02503 !_state_mask.get_bit(color_write_slot) ||
02504 !_state_mask.get_bit(color_blend_slot)) {
02505
02506 do_issue_blending();
02507 _state_mask.set_bit(transparency_slot);
02508 _state_mask.set_bit(color_write_slot);
02509 _state_mask.set_bit(color_blend_slot);
02510 }
02511
02512 int texture_slot = TextureAttrib::get_class_slot();
02513 int tex_matrix_slot = TexMatrixAttrib::get_class_slot();
02514 int tex_gen_slot = TexGenAttrib::get_class_slot();
02515 if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
02516 _target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) ||
02517 _target_rs->get_attrib(tex_gen_slot) != _state_rs->get_attrib(tex_gen_slot) ||
02518 !_state_mask.get_bit(texture_slot) ||
02519 !_state_mask.get_bit(tex_matrix_slot) ||
02520 !_state_mask.get_bit(tex_gen_slot)) {
02521
02522 determine_target_texture();
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532 do_issue_texture();
02533
02534 _state_texture = _target_texture;
02535 _state_mask.set_bit(texture_slot);
02536 _state_mask.set_bit(tex_matrix_slot);
02537 _state_mask.set_bit(tex_gen_slot);
02538 }
02539
02540 int material_slot = MaterialAttrib::get_class_slot();
02541 if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
02542 !_state_mask.get_bit(material_slot)) {
02543
02544 do_issue_material();
02545 _state_mask.set_bit(material_slot);
02546 }
02547
02548 int light_slot = LightAttrib::get_class_slot();
02549 if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
02550 !_state_mask.get_bit(light_slot)) {
02551
02552 do_issue_light();
02553 _state_mask.set_bit(light_slot);
02554 }
02555
02556 int stencil_slot = StencilAttrib::get_class_slot();
02557 if (_target_rs->get_attrib(stencil_slot) != _state_rs->get_attrib(stencil_slot) ||
02558 !_state_mask.get_bit(stencil_slot)) {
02559
02560 do_issue_stencil();
02561 _state_mask.set_bit(stencil_slot);
02562 }
02563
02564 int scissor_slot = ScissorAttrib::get_class_slot();
02565 if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
02566 !_state_mask.get_bit(scissor_slot)) {
02567
02568 do_issue_scissor();
02569 _state_mask.set_bit(scissor_slot);
02570 }
02571
02572 _state_rs = _target_rs;
02573 }
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583 void DXGraphicsStateGuardian8::
02584 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
02585
02586
02587
02588 CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
02589 const LMatrix4f &light_mat = transform->get_mat();
02590 LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
02591 LPoint3f pos = light_obj->get_point() * rel_mat;
02592
02593 D3DCOLORVALUE black;
02594 black.r = black.g = black.b = black.a = 0.0f;
02595 D3DLIGHT8 alight;
02596 alight.Type = D3DLIGHT_POINT;
02597 alight.Diffuse = get_light_color(light_obj);
02598 alight.Ambient = black ;
02599 alight.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
02600
02601
02602
02603 alight.Position = *(D3DVECTOR *)pos.get_data();
02604
02605 alight.Range = __D3DLIGHT_RANGE_MAX;
02606 alight.Falloff = 1.0f;
02607
02608 const LVecBase3f &att = light_obj->get_attenuation();
02609 alight.Attenuation0 = att[0];
02610 alight.Attenuation1 = att[1];
02611 alight.Attenuation2 = att[2];
02612
02613 HRESULT hr = _d3d_device->SetLight(light_id, &alight);
02614 if (FAILED(hr)) {
02615 wdxdisplay8_cat.warning()
02616 << "Could not set light properties for " << light
02617 << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n";
02618 }
02619 }
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629 void DXGraphicsStateGuardian8::
02630 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
02631 static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
02632
02633
02634 pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT8()));
02635 D3DLIGHT8 &fdata = (*lookup.first).second;
02636 if (lookup.second) {
02637
02638
02639
02640 CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
02641 const LMatrix4f &light_mat = transform->get_mat();
02642 LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
02643 LVector3f dir = light_obj->get_direction() * rel_mat;
02644
02645 D3DCOLORVALUE black;
02646 black.r = black.g = black.b = black.a = 0.0f;
02647
02648 ZeroMemory(&fdata, sizeof(D3DLIGHT8));
02649
02650 fdata.Type = D3DLIGHT_DIRECTIONAL;
02651 fdata.Ambient = black ;
02652 fdata.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
02653
02654 fdata.Direction = *(D3DVECTOR *)dir.get_data();
02655
02656 fdata.Range = __D3DLIGHT_RANGE_MAX;
02657 fdata.Falloff = 1.0f;
02658
02659 fdata.Attenuation0 = 1.0f;
02660 fdata.Attenuation1 = 0.0f;
02661 fdata.Attenuation2 = 0.0f;
02662 }
02663
02664
02665
02666
02667 fdata.Diffuse = get_light_color(light_obj);
02668
02669 HRESULT hr = _d3d_device->SetLight(light_id, &fdata);
02670 if (FAILED(hr)) {
02671 wdxdisplay8_cat.warning()
02672 << "Could not set light properties for " << light
02673 << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n";
02674 }
02675 }
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685 void DXGraphicsStateGuardian8::
02686 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
02687 Lens *lens = light_obj->get_lens();
02688 nassertv(lens != (Lens *)NULL);
02689
02690
02691
02692
02693 CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
02694 const LMatrix4f &light_mat = transform->get_mat();
02695 LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
02696 LPoint3f pos = lens->get_nodal_point() * rel_mat;
02697 LVector3f dir = lens->get_view_vector() * rel_mat;
02698
02699 D3DCOLORVALUE black;
02700 black.r = black.g = black.b = black.a = 0.0f;
02701
02702 D3DLIGHT8 alight;
02703 ZeroMemory(&alight, sizeof(D3DLIGHT8));
02704
02705 alight.Type = D3DLIGHT_SPOT;
02706 alight.Ambient = black ;
02707 alight.Diffuse = get_light_color(light_obj);
02708 alight.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
02709
02710 alight.Position = *(D3DVECTOR *)pos.get_data();
02711
02712 alight.Direction = *(D3DVECTOR *)dir.get_data();
02713
02714 alight.Range = __D3DLIGHT_RANGE_MAX;
02715
02716
02717
02718
02719 float fov = lens->get_hfov();
02720 alight.Falloff = light_obj->get_exponent() * (fov * fov * fov) / 1620000.0f;
02721
02722 alight.Theta = 0.0f;
02723 alight.Phi = deg_2_rad(fov);
02724
02725 const LVecBase3f &att = light_obj->get_attenuation();
02726 alight.Attenuation0 = att[0];
02727 alight.Attenuation1 = att[1];
02728 alight.Attenuation2 = att[2];
02729
02730 HRESULT hr = _d3d_device->SetLight(light_id, &alight);
02731 if (FAILED(hr)) {
02732 wdxdisplay8_cat.warning()
02733 << "Could not set light properties for " << light
02734 << " to id " << light_id << ": " << D3DERRORSTRING(hr) << "\n";
02735 }
02736 }
02737
02738
02739
02740
02741
02742
02743
02744 D3DFORMAT DXGraphicsStateGuardian8::
02745 get_index_type(Geom::NumericType numeric_type) {
02746 switch (numeric_type) {
02747 case Geom::NT_uint16:
02748 return D3DFMT_INDEX16;
02749
02750 case Geom::NT_uint32:
02751 return D3DFMT_INDEX32;
02752 }
02753
02754 dxgsg8_cat.error()
02755 << "Invalid index NumericType value (" << (int)numeric_type << ")\n";
02756 return D3DFMT_INDEX16;
02757 }
02758
02759
02760
02761
02762
02763
02764 void DXGraphicsStateGuardian8::
02765 do_issue_material() {
02766 static Material empty;
02767 const Material *material;
02768 const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
02769 if (target_material->is_off()) {
02770 material = ∅
02771 } else {
02772 material = target_material->get_material();
02773 }
02774
02775 D3DMATERIAL8 cur_material;
02776 cur_material.Diffuse = *(D3DCOLORVALUE *)(material->get_diffuse().get_data());
02777 cur_material.Ambient = *(D3DCOLORVALUE *)(material->get_ambient().get_data());
02778 cur_material.Specular = *(D3DCOLORVALUE *)(material->get_specular().get_data());
02779 cur_material.Emissive = *(D3DCOLORVALUE *)(material->get_emission().get_data());
02780 cur_material.Power = material->get_shininess();
02781
02782 if (material->has_diffuse()) {
02783
02784 _d3d_device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
02785 } else {
02786
02787 if (_has_material_force_color) {
02788 cur_material.Diffuse = *(D3DCOLORVALUE *)_material_force_color.get_data();
02789 _d3d_device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
02790 } else {
02791 _d3d_device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
02792 }
02793 }
02794 if (material->has_ambient()) {
02795
02796 _d3d_device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
02797 } else {
02798
02799 if (_has_material_force_color) {
02800 cur_material.Ambient = *(D3DCOLORVALUE *)_material_force_color.get_data();
02801 _d3d_device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
02802 } else {
02803 _d3d_device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
02804 }
02805 }
02806
02807 if (material->has_specular()) {
02808 _d3d_device->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
02809 } else {
02810 _d3d_device->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
02811 }
02812
02813 if (material->get_local()) {
02814 _d3d_device->SetRenderState(D3DRS_LOCALVIEWER, TRUE);
02815 } else {
02816 _d3d_device->SetRenderState(D3DRS_LOCALVIEWER, FALSE);
02817 }
02818
02819 _d3d_device->SetMaterial(&cur_material);
02820 }
02821
02822
02823
02824
02825
02826
02827 void DXGraphicsStateGuardian8::
02828 do_issue_texture() {
02829 DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
02830
02831 int num_stages = _target_texture->get_num_on_ff_stages();
02832 nassertv(num_stages <= _max_texture_stages &&
02833 _num_active_texture_stages <= _max_texture_stages);
02834
02835 _texture_involves_color_scale = false;
02836
02837
02838
02839
02840
02841 int si;
02842 for (si = 0; si < num_stages; si++) {
02843 TextureStage *stage = _target_texture->get_on_ff_stage(si);
02844 int texcoord_index = _target_texture->get_ff_tc_index(si);
02845
02846 Texture *texture = _target_texture->get_on_texture(stage);
02847 nassertv(texture != (Texture *)NULL);
02848
02849
02850
02851 TextureContext *tc = texture->prepare_now(_prepared_objects, this);
02852 apply_texture(si, tc);
02853 set_texture_blend_mode(si, stage);
02854
02855 int texcoord_dimensions = 2;
02856
02857 CPT(TransformState) tex_mat = TransformState::make_identity();
02858 const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
02859 if (target_tex_matrix->has_stage(stage)) {
02860 tex_mat = target_tex_matrix->get_transform(stage);
02861 }
02862
02863
02864 TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage);
02865 bool any_point_sprite = false;
02866
02867 switch (mode) {
02868 case TexGenAttrib::M_off:
02869 case TexGenAttrib::M_light_vector:
02870 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, texcoord_index);
02871 break;
02872
02873 case TexGenAttrib::M_eye_sphere_map:
02874 {
02875 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02876 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
02877
02878
02879
02880 static CPT(TransformState) sphere_map =
02881 TransformState::make_mat(LMatrix4f(0.33f, 0.0f, 0.0f, 0.0f,
02882 0.0f, 0.33f, 0.0f, 0.0f,
02883 0.0f, 0.0f, 1.0f, 0.0f,
02884 0.5f, 0.5f, 0.0f, 1.0f));
02885 tex_mat = tex_mat->compose(sphere_map);
02886 texcoord_dimensions = 3;
02887 }
02888 break;
02889
02890 case TexGenAttrib::M_world_cube_map:
02891
02892
02893
02894
02895 {
02896 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02897 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
02898 texcoord_dimensions = 3;
02899 CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
02900 tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3f::zero()));
02901 }
02902 break;
02903
02904 case TexGenAttrib::M_eye_cube_map:
02905 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02906 texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
02907 tex_mat = tex_mat->compose(_inv_cs_transform);
02908 texcoord_dimensions = 3;
02909 break;
02910
02911 case TexGenAttrib::M_world_normal:
02912
02913
02914
02915
02916 {
02917 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02918 texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
02919 texcoord_dimensions = 3;
02920 CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
02921 tex_mat = tex_mat->compose(camera_transform->set_pos(LVecBase3f::zero()));
02922 }
02923 break;
02924
02925 case TexGenAttrib::M_eye_normal:
02926 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02927 texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL);
02928 texcoord_dimensions = 3;
02929 tex_mat = tex_mat->compose(_inv_cs_transform);
02930 break;
02931
02932 case TexGenAttrib::M_world_position:
02933
02934
02935
02936 {
02937 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02938 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
02939 texcoord_dimensions = 3;
02940 CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
02941 tex_mat = tex_mat->compose(camera_transform);
02942 }
02943 break;
02944
02945 case TexGenAttrib::M_eye_position:
02946 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02947 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
02948 texcoord_dimensions = 3;
02949 tex_mat = tex_mat->compose(_inv_cs_transform);
02950 break;
02951
02952 case TexGenAttrib::M_point_sprite:
02953 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX, texcoord_index);
02954 any_point_sprite = true;
02955 break;
02956
02957 case TexGenAttrib::M_constant:
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968 {
02969 _d3d_device->SetTextureStageState(si, D3DTSS_TEXCOORDINDEX,
02970 texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION);
02971 texcoord_dimensions = 3;
02972
02973 const TexCoord3f &v = _target_tex_gen->get_constant_value(stage);
02974 CPT(TransformState) squash =
02975 TransformState::make_pos_hpr_scale(v, LVecBase3f::zero(),
02976 LVecBase3f::zero());
02977 tex_mat = tex_mat->compose(squash);
02978 }
02979 break;
02980 }
02981
02982 _d3d_device->SetRenderState(D3DRS_POINTSPRITEENABLE, any_point_sprite);
02983
02984 if (!tex_mat->is_identity()) {
02985 if ( texcoord_dimensions <= 2) {
02986
02987 LMatrix4f m = tex_mat->get_mat();
02988 m.set(m(0, 0), m(0, 1), m(0, 3), 0.0f,
02989 m(1, 0), m(1, 1), m(1, 3), 0.0f,
02990 m(3, 0), m(3, 1), m(3, 3), 0.0f,
02991 0.0f, 0.0f, 0.0f, 1.0f);
02992 _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)m.get_data());
02993 _d3d_device->SetTextureStageState(si, D3DTSS_TEXTURETRANSFORMFLAGS,
02994 D3DTTFF_COUNT2);
02995 } else {
02996 LMatrix4f m = tex_mat->get_mat();
02997 _d3d_device->SetTransform(get_tex_mat_sym(si), (D3DMATRIX *)m.get_data());
02998 DWORD transform_flags = texcoord_dimensions;
02999 if (m.get_col(3) != LVecBase4f(0.0f, 0.0f, 0.0f, 1.0f)) {
03000
03001
03002 transform_flags = D3DTTFF_COUNT4 | D3DTTFF_PROJECTED;
03003 }
03004 _d3d_device->SetTextureStageState(si, D3DTSS_TEXTURETRANSFORMFLAGS,
03005 transform_flags);
03006 }
03007
03008 } else {
03009 _d3d_device->SetTextureStageState(si, D3DTSS_TEXTURETRANSFORMFLAGS,
03010 D3DTTFF_DISABLE);
03011
03012
03013
03014 _d3d_device->SetTransform(get_tex_mat_sym(si), &_d3d_ident_mat);
03015 }
03016 }
03017
03018
03019 for (si = num_stages; si < _num_active_texture_stages; si++) {
03020 _d3d_device->SetTextureStageState(si, D3DTSS_COLOROP, D3DTOP_DISABLE);
03021 }
03022
03023
03024 _num_active_texture_stages = num_stages;
03025 }
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035 void DXGraphicsStateGuardian8::
03036 reissue_transforms() {
03037 prepare_lens();
03038 do_issue_transform();
03039 }
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049 void DXGraphicsStateGuardian8::
03050 enable_lighting(bool enable) {
03051 _d3d_device->SetRenderState(D3DRS_LIGHTING, (DWORD)enable);
03052 }
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062 void DXGraphicsStateGuardian8::
03063 set_ambient_light(const Colorf &color) {
03064 Colorf c = color;
03065 c.set(c[0] * _light_color_scale[0],
03066 c[1] * _light_color_scale[1],
03067 c[2] * _light_color_scale[2],
03068 c[3] * _light_color_scale[3]);
03069
03070 _d3d_device->SetRenderState(D3DRS_AMBIENT, Colorf_to_D3DCOLOR(c));
03071 }
03072
03073
03074
03075
03076
03077
03078
03079
03080 void DXGraphicsStateGuardian8::
03081 enable_light(int light_id, bool enable) {
03082 HRESULT hr = _d3d_device->LightEnable(light_id, enable);
03083
03084 if (FAILED(hr)) {
03085 wdxdisplay8_cat.warning()
03086 << "Could not enable light " << light_id << ": "
03087 << D3DERRORSTRING(hr) << "\n";
03088 }
03089 }
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099 void DXGraphicsStateGuardian8::
03100 enable_clip_plane(int plane_id, bool enable) {
03101 if (enable) {
03102 _clip_plane_bits |= ((DWORD)1 << plane_id);
03103 } else {
03104 _clip_plane_bits &= ~((DWORD)1 << plane_id);
03105 }
03106 _d3d_device->SetRenderState(D3DRS_CLIPPLANEENABLE, _clip_plane_bits);
03107 }
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117 void DXGraphicsStateGuardian8::
03118 bind_clip_plane(const NodePath &plane, int plane_id) {
03119
03120
03121
03122 CPT(TransformState) transform = plane.get_transform(_scene_setup->get_camera_path());
03123 const LMatrix4f &plane_mat = transform->get_mat();
03124 LMatrix4f rel_mat = plane_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
03125 const PlaneNode *plane_node;
03126 DCAST_INTO_V(plane_node, plane.node());
03127 Planef world_plane = plane_node->get_plane() * rel_mat;
03128
03129 HRESULT hr = _d3d_device->SetClipPlane(plane_id, world_plane.get_data());
03130 if (FAILED(hr)) {
03131 wdxdisplay8_cat.warning()
03132 << "Could not set clip plane for " << plane
03133 << " to id " << plane_id << ": " << D3DERRORSTRING(hr) << "\n";
03134 }
03135 }
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145 void DXGraphicsStateGuardian8::
03146 do_issue_blending() {
03147
03148
03149
03150
03151
03152 const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
03153 unsigned int color_channels =
03154 target_color_write->get_channels() & _color_write_mask;
03155 if (color_channels == ColorWriteAttrib::C_off) {
03156 if (_screen->_can_direct_disable_color_writes) {
03157 _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
03158 _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)0x0);
03159 } else {
03160 _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
03161 _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
03162 _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
03163 }
03164 return;
03165 }
03166
03167 if (_screen->_can_direct_disable_color_writes) {
03168 _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, color_channels);
03169 }
03170
03171 const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
03172 ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode();
03173
03174 const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
03175 TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode();
03176
03177
03178 if (color_blend_mode != ColorBlendAttrib::M_none) {
03179 _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
03180
03181 switch (color_blend_mode) {
03182 case ColorBlendAttrib::M_add:
03183 _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
03184 break;
03185
03186 case ColorBlendAttrib::M_subtract:
03187 _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
03188 break;
03189
03190 case ColorBlendAttrib::M_inv_subtract:
03191 _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT);
03192 break;
03193
03194 case ColorBlendAttrib::M_min:
03195 _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN);
03196 break;
03197
03198 case ColorBlendAttrib::M_max:
03199 _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX);
03200 break;
03201 }
03202
03203 _d3d_device->SetRenderState(D3DRS_SRCBLEND,
03204 get_blend_func(target_color_blend->get_operand_a()));
03205 _d3d_device->SetRenderState(D3DRS_DESTBLEND,
03206 get_blend_func(target_color_blend->get_operand_b()));
03207 return;
03208 }
03209
03210
03211 switch (transparency_mode) {
03212 case TransparencyAttrib::M_none:
03213 case TransparencyAttrib::M_binary:
03214 break;
03215
03216 case TransparencyAttrib::M_alpha:
03217 case TransparencyAttrib::M_multisample:
03218 case TransparencyAttrib::M_multisample_mask:
03219 case TransparencyAttrib::M_dual:
03220 _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
03221 _d3d_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
03222 _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
03223 _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
03224 return;
03225
03226 default:
03227 dxgsg8_cat.error()
03228 << "invalid transparency mode " << (int)transparency_mode << endl;
03229 break;
03230 }
03231
03232
03233 _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
03234 }
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244 void DXGraphicsStateGuardian8::
03245 close_gsg() {
03246 GraphicsStateGuardian::close_gsg();
03247
03248
03249
03250 if (_prepared_objects->get_ref_count() == 1) {
03251 release_all();
03252
03253
03254
03255 Thread *current_thread = Thread::get_current_thread();
03256 _prepared_objects->begin_frame(this, current_thread);
03257 _prepared_objects->end_frame(current_thread);
03258 }
03259 }
03260
03261
03262
03263
03264
03265
03266
03267 void DXGraphicsStateGuardian8::
03268 free_nondx_resources() {
03269 }
03270
03271
03272
03273
03274
03275
03276
03277 void DXGraphicsStateGuardian8::
03278 free_d3d_device() {
03279
03280 _state_rs = RenderState::make_empty();
03281 _state_mask.clear();
03282
03283
03284
03285 _dx_is_ready = false;
03286
03287 if (_d3d_device != NULL)
03288 for(int i = 0;i<D3D_MAXTEXTURESTAGES;i++)
03289 _d3d_device->SetTexture(i, NULL);
03290
03291 release_all();
03292
03293 if (_d3d_device != NULL)
03294 RELEASE(_d3d_device, dxgsg8, "d3dDevice", RELEASE_DOWN_TO_ZERO);
03295
03296 free_nondx_resources();
03297
03298
03299 }
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309 void DXGraphicsStateGuardian8::
03310 set_draw_buffer(const RenderBuffer &rb) {
03311 dxgsg8_cat.fatal() << "DX set_draw_buffer unimplemented!!!";
03312 return;
03313 }
03314
03315
03316
03317
03318
03319
03320 void DXGraphicsStateGuardian8::
03321 set_read_buffer(const RenderBuffer &rb) {
03322 if (rb._buffer_type & RenderBuffer::T_front) {
03323 _cur_read_pixel_buffer = RenderBuffer::T_front;
03324 } else if (rb._buffer_type & RenderBuffer::T_back) {
03325 _cur_read_pixel_buffer = RenderBuffer::T_back;
03326 } else {
03327 dxgsg8_cat.error() << "Invalid or unimplemented Argument to set_read_buffer!\n";
03328 }
03329 return;
03330 }
03331
03332
03333
03334
03335
03336
03337
03338
03339 void DXGraphicsStateGuardian8::
03340 do_auto_rescale_normal() {
03341 if (_internal_transform->has_identity_scale()) {
03342
03343 _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, false);
03344
03345 } else {
03346
03347 _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
03348 }
03349 }
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359 const D3DCOLORVALUE &DXGraphicsStateGuardian8::
03360 get_light_color(Light *light) const {
03361 static Colorf c;
03362 c = light->get_color();
03363 c.set(c[0] * _light_color_scale[0],
03364 c[1] * _light_color_scale[1],
03365 c[2] * _light_color_scale[2],
03366 c[3] * _light_color_scale[3]);
03367 return *(D3DCOLORVALUE *)c.get_data();
03368 }
03369
03370
03371
03372
03373
03374
03375
03376 D3DBLEND DXGraphicsStateGuardian8::
03377 get_blend_func(ColorBlendAttrib::Operand operand) {
03378 switch (operand) {
03379 case ColorBlendAttrib::O_zero:
03380 return D3DBLEND_ZERO;
03381
03382 case ColorBlendAttrib::O_one:
03383 return D3DBLEND_ONE;
03384
03385 case ColorBlendAttrib::O_incoming_color:
03386 return D3DBLEND_SRCCOLOR;
03387
03388 case ColorBlendAttrib::O_one_minus_incoming_color:
03389 return D3DBLEND_INVSRCCOLOR;
03390
03391 case ColorBlendAttrib::O_fbuffer_color:
03392 return D3DBLEND_DESTCOLOR;
03393
03394 case ColorBlendAttrib::O_one_minus_fbuffer_color:
03395 return D3DBLEND_INVDESTCOLOR;
03396
03397 case ColorBlendAttrib::O_incoming_alpha:
03398 return D3DBLEND_SRCALPHA;
03399
03400 case ColorBlendAttrib::O_one_minus_incoming_alpha:
03401 return D3DBLEND_INVSRCALPHA;
03402
03403 case ColorBlendAttrib::O_fbuffer_alpha:
03404 return D3DBLEND_DESTALPHA;
03405
03406 case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
03407 return D3DBLEND_INVDESTALPHA;
03408
03409 case ColorBlendAttrib::O_constant_color:
03410
03411 return D3DBLEND_SRCCOLOR;
03412
03413 case ColorBlendAttrib::O_one_minus_constant_color:
03414
03415 return D3DBLEND_INVSRCCOLOR;
03416
03417 case ColorBlendAttrib::O_constant_alpha:
03418
03419 return D3DBLEND_SRCALPHA;
03420
03421 case ColorBlendAttrib::O_one_minus_constant_alpha:
03422
03423 return D3DBLEND_INVSRCALPHA;
03424
03425 case ColorBlendAttrib::O_incoming_color_saturate:
03426 return D3DBLEND_SRCALPHASAT;
03427 }
03428
03429 dxgsg8_cat.error()
03430 << "Unknown color blend operand " << (int)operand << endl;
03431 return D3DBLEND_ZERO;
03432 }
03433
03434
03435
03436
03437
03438
03439 void DXGraphicsStateGuardian8::
03440 report_texmgr_stats() {
03441
03442 #ifdef DO_PSTATS
03443 HRESULT hr;
03444 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
03445 DWORD dwTexTotal, dwTexFree, dwVidTotal, dwVidFree;
03446
03447 if (_total_texmem_pcollector.is_active()) {
03448 DDSCAPS2 ddsCaps;
03449
03450 ZeroMemory(&ddsCaps, sizeof(ddsCaps));
03451
03452 ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
03453 if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwVidTotal, &dwVidFree))) {
03454 dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << D3DERRORSTRING(hr);
03455 throw_event("panda3d-render-error");
03456 return;
03457 }
03458
03459 ddsCaps.dwCaps = DDSCAPS_TEXTURE;
03460 if (FAILED( hr = _d3d_device->GetAvailableVidMem(&ddsCaps, &dwTexTotal, &dwTexFree))) {
03461 dxgsg8_cat.fatal() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << D3DERRORSTRING(hr);
03462 throw_event("panda3d-render-error");
03463 return;
03464 }
03465 }
03466 #endif // TEXMGRSTATS_USES_GETAVAILVIDMEM
03467
03468 D3DDEVINFO_RESOURCEMANAGER all_resource_stats;
03469 ZeroMemory(&all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER));
03470
03471 if (!_tex_stats_retrieval_impossible) {
03472 hr = _d3d_device->GetInfo(D3DDEVINFOID_RESOURCEMANAGER, &all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER));
03473 if (hr != D3D_OK) {
03474 if (hr == S_FALSE) {
03475 static int PrintedMsg = 2;
03476 if (PrintedMsg>0) {
03477 if (dxgsg8_cat.is_debug()) {
03478 dxgsg8_cat.debug()
03479 << "texstats GetInfo() requires debug DX DLLs to be installed!!\n";
03480 }
03481 ZeroMemory(&all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER));
03482 _tex_stats_retrieval_impossible = true;
03483 }
03484 } else {
03485 dxgsg8_cat.error() << "GetInfo(RESOURCEMANAGER) failed to get tex stats: result = " << D3DERRORSTRING(hr);
03486 return;
03487 }
03488 }
03489 }
03490
03491
03492
03493 if (_texmgrmem_total_pcollector.is_active()) {
03494
03495 _texmgrmem_total_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].TotalBytes);
03496 _texmgrmem_resident_pcollector.set_level(all_resource_stats.stats[D3DRTYPE_TEXTURE].WorkingSetBytes);
03497 }
03498 #ifdef TEXMGRSTATS_USES_GETAVAILVIDMEM
03499 if (_total_texmem_pcollector.is_active()) {
03500 _total_texmem_pcollector.set_level(dwTexTotal);
03501 _used_texmem_pcollector.set_level(dwTexTotal - dwTexFree);
03502 }
03503 #endif // TEXMGRSTATS_USES_GETAVAILVIDMEM
03504 #endif // DO_PSTATS
03505 }
03506
03507
03508
03509
03510
03511
03512 void DXGraphicsStateGuardian8::
03513 set_context(DXScreenData *new_context) {
03514 nassertv(new_context != NULL);
03515 _screen = new_context;
03516 _d3d_device = _screen->_d3d_device;
03517 _swap_chain = _screen->_swap_chain;
03518
03519 _screen->_dxgsg8 = this;
03520 }
03521
03522
03523
03524
03525
03526
03527
03528 void DXGraphicsStateGuardian8::
03529 set_render_target() {
03530 if (_d3d_device == NULL) {
03531 return;
03532 }
03533
03534 LPDIRECT3DSURFACE8 back = NULL, stencil = NULL;
03535
03536 if (!_swap_chain)
03537 _d3d_device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back);
03538 else
03539 _swap_chain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back);
03540
03541
03542
03543
03544 _d3d_device->GetDepthStencilSurface(&stencil);
03545 _d3d_device->SetRenderTarget(back, stencil);
03546 if (back) {
03547 back->Release();
03548 }
03549 if (stencil) {
03550 stencil->Release();
03551 }
03552 }
03553
03554
03555
03556
03557
03558
03559 void DXGraphicsStateGuardian8::
03560 set_texture_blend_mode(int i, const TextureStage *stage) {
03561 switch (stage->get_mode()) {
03562 case TextureStage::M_modulate:
03563 case TextureStage::M_modulate_glow:
03564 case TextureStage::M_modulate_gloss:
03565
03566 _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE);
03567 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
03568 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
03569 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
03570 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
03571 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
03572 break;
03573
03574 case TextureStage::M_decal:
03575
03576 _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
03577 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
03578 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
03579
03580 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
03581 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
03582 break;
03583
03584 case TextureStage::M_replace:
03585 _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
03586 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
03587
03588 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
03589 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
03590 break;
03591
03592 case TextureStage::M_add:
03593 _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_ADD);
03594 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
03595 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
03596
03597 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
03598 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
03599 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
03600 break;
03601
03602 case TextureStage::M_blend:
03603 case TextureStage::M_blend_color_scale:
03604 {
03605 _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_LERP);
03606 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_TEXTURE);
03607 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
03608 _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TFACTOR);
03609
03610 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
03611 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
03612 _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
03613 }
03614 break;
03615
03616 case TextureStage::M_combine:
03617
03618
03619 _d3d_device->SetTextureStageState
03620 (i, D3DTSS_COLOROP,
03621 get_texture_operation(stage->get_combine_rgb_mode(),
03622 stage->get_rgb_scale()));
03623
03624 switch (stage->get_num_combine_rgb_operands()) {
03625 case 3:
03626 _d3d_device->SetTextureStageState
03627 (i, D3DTSS_COLORARG0,
03628 get_texture_argument(stage->get_combine_rgb_source2(),
03629 stage->get_combine_rgb_operand2()));
03630
03631
03632 case 2:
03633 _d3d_device->SetTextureStageState
03634 (i, D3DTSS_COLORARG2,
03635 get_texture_argument(stage->get_combine_rgb_source1(),
03636 stage->get_combine_rgb_operand1()));
03637
03638
03639 case 1:
03640 _d3d_device->SetTextureStageState
03641 (i, D3DTSS_COLORARG1,
03642 get_texture_argument(stage->get_combine_rgb_source0(),
03643 stage->get_combine_rgb_operand0()));
03644
03645
03646 default:
03647 break;
03648 }
03649
03650 _d3d_device->SetTextureStageState
03651 (i, D3DTSS_ALPHAOP,
03652 get_texture_operation(stage->get_combine_alpha_mode(),
03653 stage->get_alpha_scale()));
03654
03655 switch (stage->get_num_combine_alpha_operands()) {
03656 case 3:
03657 _d3d_device->SetTextureStageState
03658 (i, D3DTSS_ALPHAARG0,
03659 get_texture_argument(stage->get_combine_alpha_source2(),
03660 stage->get_combine_alpha_operand2()));
03661
03662
03663 case 2:
03664 _d3d_device->SetTextureStageState
03665 (i, D3DTSS_ALPHAARG2,
03666 get_texture_argument(stage->get_combine_alpha_source1(),
03667 stage->get_combine_alpha_operand1()));
03668
03669
03670 case 1:
03671 _d3d_device->SetTextureStageState
03672 (i, D3DTSS_ALPHAARG1,
03673 get_texture_argument(stage->get_combine_alpha_source0(),
03674 stage->get_combine_alpha_operand0()));
03675
03676
03677 default:
03678 break;
03679 }
03680 break;
03681
03682 default:
03683 dxgsg8_cat.error()
03684 << "Unknown texture mode " << (int)stage->get_mode() << endl;
03685 break;
03686 }
03687
03688 if (stage->get_saved_result()) {
03689 _d3d_device->SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_TEMP);
03690 } else {
03691 _d3d_device->SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
03692 }
03693
03694 if (stage->uses_color()) {
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705 D3DCOLOR texture_factor;
03706 if (stage->involves_color_scale() && _color_scale_enabled) {
03707 Colorf color = stage->get_color();
03708 color.set(color[0] * _current_color_scale[0],
03709 color[1] * _current_color_scale[1],
03710 color[2] * _current_color_scale[2],
03711 color[3] * _current_color_scale[3]);
03712 _texture_involves_color_scale = true;
03713 texture_factor = Colorf_to_D3DCOLOR(color);
03714 } else {
03715 texture_factor = Colorf_to_D3DCOLOR(stage->get_color());
03716 }
03717 _d3d_device->SetRenderState(D3DRS_TEXTUREFACTOR, texture_factor);
03718 }
03719 }
03720
03721
03722
03723
03724
03725
03726 void DXGraphicsStateGuardian8::
03727 dx_cleanup() {
03728 if (!_d3d_device) {
03729 return;
03730 }
03731
03732 free_nondx_resources();
03733 PRINT_REFCNT(dxgsg8, _d3d_device);
03734
03735
03736
03737 RELEASE(_d3d_device, dxgsg8, "d3dDevice", RELEASE_DOWN_TO_ZERO);
03738 _screen->_d3d_device = NULL;
03739
03740
03741 }
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754 HRESULT DXGraphicsStateGuardian8::
03755 reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
03756 DXScreenData **screen) {
03757 HRESULT hr;
03758
03759 nassertr(IS_VALID_PTR(presentation_params), E_FAIL);
03760 nassertr(IS_VALID_PTR(_screen->_d3d8), E_FAIL);
03761 nassertr(IS_VALID_PTR(_d3d_device), E_FAIL);
03762
03763
03764
03765 _screen->_d3d8->GetAdapterDisplayMode(_screen->_card_id, &_screen->_display_mode);
03766 presentation_params->BackBufferFormat = _screen->_display_mode.Format;
03767
03768
03769
03770
03771
03772
03773 if (true || !(_screen->_swap_chain)
03774 || (_presentation_reset.BackBufferWidth < presentation_params->BackBufferWidth)
03775 || (_presentation_reset.BackBufferHeight < presentation_params->BackBufferHeight)) {
03776 if (wdxdisplay8_cat.is_debug()) {
03777 wdxdisplay8_cat.debug()
03778 << "swap_chain = " << _screen->_swap_chain << " _presentation_reset = "
03779 << _presentation_reset.BackBufferWidth << "x" << _presentation_reset.BackBufferHeight
03780 << " presentation_params = "
03781 << presentation_params->BackBufferWidth << "x" << presentation_params->BackBufferHeight << "\n";
03782 }
03783
03784 get_engine()->reset_all_windows(false);
03785
03786 if (_screen->_swap_chain) {
03787 _presentation_reset.BackBufferWidth = max(_presentation_reset.BackBufferWidth, presentation_params->BackBufferWidth);
03788 _presentation_reset.BackBufferHeight = max(_presentation_reset.BackBufferHeight, presentation_params->BackBufferHeight);
03789
03790 } else {
03791 _presentation_reset.BackBufferWidth = presentation_params->BackBufferWidth;
03792 _presentation_reset.BackBufferHeight = presentation_params->BackBufferHeight;
03793 }
03794
03795
03796
03797
03798
03799 release_all();
03800
03801
03802
03803
03804 release_all_vertex_buffers();
03805 release_all_index_buffers();
03806
03807 Thread *current_thread = Thread::get_current_thread();
03808 _prepared_objects->begin_frame(this, current_thread);
03809
03810
03811 {
03812 wdxGraphicsBuffer8 *graphics_buffer;
03813 list <wdxGraphicsBuffer8 **>::iterator graphics_buffer_iterator;
03814
03815 for (graphics_buffer_iterator = _graphics_buffer_list.begin( ); graphics_buffer_iterator != _graphics_buffer_list.end( ); graphics_buffer_iterator++)
03816 {
03817 graphics_buffer = **graphics_buffer_iterator;
03818 if (graphics_buffer -> _color_backing_store)
03819 {
03820 graphics_buffer -> _color_backing_store -> Release ( );
03821 graphics_buffer -> _color_backing_store = 0;
03822 }
03823 if (graphics_buffer -> _depth_backing_store)
03824 {
03825 graphics_buffer -> _depth_backing_store -> Release ( );
03826 graphics_buffer -> _depth_backing_store = 0;
03827 }
03828 }
03829 }
03830
03831 this -> mark_new();
03832 hr = _d3d_device->Reset(&_presentation_reset);
03833 if (FAILED(hr)) {
03834 return hr;
03835 }
03836
03837 get_engine()->reset_all_windows(true);
03838 if (screen) {
03839 *screen = NULL;
03840 }
03841
03842 if (presentation_params != &_screen->_presentation_params) {
03843 memcpy(&_screen->_presentation_params, presentation_params, sizeof(D3DPRESENT_PARAMETERS));
03844 }
03845
03846 return hr;
03847 }
03848
03849
03850 if (_screen && _screen->_swap_chain) {
03851 _screen->_swap_chain->Release();
03852 wdxdisplay8_cat.debug()
03853 << "swap chain " << _screen->_swap_chain << " is released\n";
03854 _screen->_swap_chain = NULL;
03855 hr = _d3d_device->CreateAdditionalSwapChain(presentation_params, &_screen->_swap_chain);
03856 }
03857 if (SUCCEEDED(hr)) {
03858 if (presentation_params != &_screen->_presentation_params) {
03859 memcpy(&_screen->_presentation_params, presentation_params, sizeof(D3DPRESENT_PARAMETERS));
03860 }
03861 if (screen) {
03862 *screen = _screen;
03863 }
03864 }
03865 return hr;
03866 }
03867
03868
03869
03870
03871
03872
03873 bool DXGraphicsStateGuardian8::
03874 check_cooperative_level() {
03875 bool bDoReactivateWindow = false;
03876 if (_d3d_device == NULL) {
03877 return false;
03878 }
03879 HRESULT hr = _d3d_device->TestCooperativeLevel();
03880
03881 if (SUCCEEDED(hr)) {
03882 nassertr(SUCCEEDED(_last_testcooplevel_result), false);
03883 return true;
03884 }
03885
03886 switch (hr) {
03887 case D3DERR_DEVICENOTRESET:
03888 _dx_is_ready = false;
03889
03890
03891 _prepared_objects->begin_frame(this, Thread::get_current_thread());
03892
03893 hr = reset_d3d_device(&_screen->_presentation_params);
03894 if (FAILED(hr)) {
03895
03896
03897 dxgsg8_cat.error()
03898 << "check_cooperative_level Reset() failed, hr = " << D3DERRORSTRING(hr);
03899 }
03900
03901 hr = _d3d_device->TestCooperativeLevel();
03902 if (FAILED(hr)) {
03903
03904 dxgsg8_cat.error()
03905 << "TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr);
03906
03907 }
03908
03909 _dx_is_ready = TRUE;
03910 break;
03911
03912 case D3DERR_DEVICELOST:
03913
03914 Sleep (10);
03915
03916 if (SUCCEEDED(_last_testcooplevel_result)) {
03917 if (_dx_is_ready) {
03918 _dx_is_ready = false;
03919 if (dxgsg8_cat.is_debug()) {
03920 dxgsg8_cat.debug() << "D3D Device was Lost, waiting...\n";
03921 }
03922 }
03923 }
03924 }
03925
03926 _last_testcooplevel_result = hr;
03927 return SUCCEEDED(hr);
03928 }
03929
03930
03931
03932
03933
03934
03935 void DXGraphicsStateGuardian8::
03936 show_frame() {
03937 if (_d3d_device == NULL) {
03938 return;
03939 }
03940
03941 HRESULT hr;
03942
03943 if (_swap_chain) {
03944 hr = _swap_chain->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL);
03945 } else {
03946 hr = _d3d_device->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL);
03947 }
03948
03949 if (FAILED(hr)) {
03950 if (hr == D3DERR_DEVICELOST) {
03951 check_cooperative_level();
03952 } else {
03953 dxgsg8_cat.error()
03954 << "show_frame() - Present() failed" << D3DERRORSTRING(hr);
03955 throw_event("panda3d-render-error");
03956 }
03957 }
03958 }
03959
03960
03961
03962
03963
03964
03965 bool DXGraphicsStateGuardian8::
03966 create_swap_chain(DXScreenData *new_context) {
03967
03968
03969
03970
03971
03972 HRESULT hr;
03973 hr = new_context->_d3d_device->CreateAdditionalSwapChain(&new_context->_presentation_params, &new_context->_swap_chain);
03974 if (FAILED(hr)) {
03975 wdxdisplay8_cat.debug() << "Swapchain creation failed :"<<D3DERRORSTRING(hr)<<"\n";
03976 return false;
03977 }
03978 wdxdisplay8_cat.debug()
03979 << "Created swap chain " << new_context->_swap_chain << "\n";
03980 return true;
03981 }
03982
03983
03984
03985
03986
03987
03988 bool DXGraphicsStateGuardian8::
03989 release_swap_chain(DXScreenData *new_context) {
03990 HRESULT hr;
03991 wdxdisplay8_cat.debug()
03992 << "Releasing swap chain " << new_context->_swap_chain << "\n";
03993 if (new_context->_swap_chain) {
03994 hr = new_context->_swap_chain->Release();
03995 if (FAILED(hr)) {
03996 wdxdisplay8_cat.debug() << "Swapchain release failed:" << D3DERRORSTRING(hr) << "\n";
03997 return false;
03998 }
03999 }
04000 return true;
04001 }
04002
04003
04004
04005
04006
04007
04008 void DXGraphicsStateGuardian8::
04009 copy_pres_reset(DXScreenData *screen) {
04010 memcpy(&_presentation_reset, &_screen->_presentation_params, sizeof(D3DPRESENT_PARAMETERS));
04011 }
04012
04013
04014
04015
04016
04017
04018 D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian8::
04019 get_d3d_min_type(Texture::FilterType filter_type) {
04020 switch (filter_type) {
04021 case Texture::FT_nearest:
04022 return D3DTEXF_POINT;
04023
04024 case Texture::FT_linear:
04025 return D3DTEXF_LINEAR;
04026
04027 case Texture::FT_nearest_mipmap_nearest:
04028 return D3DTEXF_POINT;
04029
04030 case Texture::FT_linear_mipmap_nearest:
04031 return D3DTEXF_LINEAR;
04032
04033 case Texture::FT_nearest_mipmap_linear:
04034 return D3DTEXF_POINT;
04035
04036 case Texture::FT_linear_mipmap_linear:
04037 return D3DTEXF_LINEAR;
04038
04039 case Texture::FT_shadow:
04040 case Texture::FT_default:
04041 return D3DTEXF_LINEAR;
04042 }
04043
04044 dxgsg8_cat.error()
04045 << "Invalid FilterType value (" << (int)filter_type << ")\n";
04046 return D3DTEXF_POINT;
04047 }
04048
04049
04050
04051
04052
04053
04054 D3DTEXTUREFILTERTYPE DXGraphicsStateGuardian8::
04055 get_d3d_mip_type(Texture::FilterType filter_type) {
04056 switch (filter_type) {
04057 case Texture::FT_nearest:
04058 return D3DTEXF_NONE;
04059
04060 case Texture::FT_linear:
04061 return D3DTEXF_NONE;
04062
04063 case Texture::FT_nearest_mipmap_nearest:
04064 return D3DTEXF_POINT;
04065
04066 case Texture::FT_linear_mipmap_nearest:
04067 return D3DTEXF_POINT;
04068
04069 case Texture::FT_nearest_mipmap_linear:
04070 return D3DTEXF_LINEAR;
04071
04072 case Texture::FT_linear_mipmap_linear:
04073 return D3DTEXF_LINEAR;
04074
04075 case Texture::FT_shadow:
04076 case Texture::FT_default:
04077 return D3DTEXF_NONE;
04078 }
04079
04080 dxgsg8_cat.error()
04081 << "Invalid FilterType value (" << (int)filter_type << ")\n";
04082 return D3DTEXF_NONE;
04083 }
04084
04085
04086
04087
04088
04089
04090
04091 D3DTEXTUREOP DXGraphicsStateGuardian8::
04092 get_texture_operation(TextureStage::CombineMode mode, int scale) {
04093 switch (mode) {
04094 case TextureStage::CM_undefined:
04095 case TextureStage::CM_replace:
04096 return D3DTOP_SELECTARG1;
04097
04098 case TextureStage::CM_modulate:
04099 if (scale < 2) {
04100 return D3DTOP_MODULATE;
04101 } else if (scale < 4) {
04102 return D3DTOP_MODULATE2X;
04103 } else {
04104 return D3DTOP_MODULATE4X;
04105 }
04106
04107 case TextureStage::CM_add:
04108 return D3DTOP_ADD;
04109
04110 case TextureStage::CM_add_signed:
04111 if (scale < 2) {
04112 return D3DTOP_ADDSIGNED;
04113 } else {
04114 return D3DTOP_ADDSIGNED2X;
04115 }
04116
04117 case TextureStage::CM_interpolate:
04118 return D3DTOP_LERP;
04119
04120 case TextureStage::CM_subtract:
04121 return D3DTOP_SUBTRACT;
04122
04123 case TextureStage::CM_dot3_rgb:
04124 case TextureStage::CM_dot3_rgba:
04125 return D3DTOP_DOTPRODUCT3;
04126 }
04127
04128 dxgsg8_cat.error()
04129 << "Invalid TextureStage::CombineMode value (" << (int)mode << ")\n";
04130 return D3DTOP_DISABLE;
04131 }
04132
04133
04134
04135
04136
04137
04138
04139
04140 DWORD DXGraphicsStateGuardian8::
04141 get_texture_argument(TextureStage::CombineSource source,
04142 TextureStage::CombineOperand operand) {
04143 switch (source) {
04144 case TextureStage::CS_undefined:
04145 case TextureStage::CS_texture:
04146 return D3DTA_TEXTURE | get_texture_argument_modifier(operand);
04147
04148 case TextureStage::CS_constant:
04149 case TextureStage::CS_constant_color_scale:
04150 return D3DTA_TFACTOR | get_texture_argument_modifier(operand);
04151
04152 case TextureStage::CS_primary_color:
04153 return D3DTA_DIFFUSE | get_texture_argument_modifier(operand);
04154
04155 case TextureStage::CS_previous:
04156 return D3DTA_CURRENT | get_texture_argument_modifier(operand);
04157
04158 case TextureStage::CS_last_saved_result:
04159 return D3DTA_TEMP | get_texture_argument_modifier(operand);
04160 }
04161 dxgsg8_cat.error()
04162 << "Invalid TextureStage::CombineSource value (" << (int)source << ")\n";
04163 return D3DTA_CURRENT;
04164 }
04165
04166
04167
04168
04169
04170
04171
04172
04173 DWORD DXGraphicsStateGuardian8::
04174 get_texture_argument_modifier(TextureStage::CombineOperand operand) {
04175 switch (operand) {
04176 case TextureStage::CO_src_color:
04177 return 0;
04178
04179 case TextureStage::CO_one_minus_src_color:
04180 return D3DTA_COMPLEMENT;
04181
04182 case TextureStage::CO_src_alpha:
04183 return D3DTA_ALPHAREPLICATE;
04184
04185 case TextureStage::CO_one_minus_src_alpha:
04186 return D3DTA_ALPHAREPLICATE | D3DTA_COMPLEMENT;
04187
04188 case TextureStage::CO_undefined:
04189 break;
04190 }
04191 dxgsg8_cat.error()
04192 << "Invalid TextureStage::CombineOperand value (" << (int)operand << ")\n";
04193 return 0;
04194 }
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204 void DXGraphicsStateGuardian8::
04205 draw_primitive_up(D3DPRIMITIVETYPE primitive_type,
04206 unsigned int primitive_count,
04207 unsigned int first_vertex,
04208 unsigned int num_vertices,
04209 const unsigned char *buffer, size_t stride) {
04210
04211
04212
04213
04214
04215
04216
04217 const unsigned char *buffer_start = buffer + stride * first_vertex;
04218 const unsigned char *buffer_end = buffer_start + stride * num_vertices;
04219
04220 if (buffer_end - buffer_start > 0x10000) {
04221
04222
04223 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
04224 buffer_start, stride);
04225
04226 } else if ((((long)buffer_end ^ (long)buffer_start) & ~0xffff) == 0) {
04227
04228 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
04229 buffer_start, stride);
04230
04231 } else {
04232
04233
04234
04235 unsigned char *safe_buffer_start = get_safe_buffer_start();
04236 memcpy(safe_buffer_start, buffer_start, buffer_end - buffer_start);
04237 _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count,
04238 safe_buffer_start, stride);
04239
04240 }
04241 }
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254 void DXGraphicsStateGuardian8::
04255 draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type,
04256 unsigned int min_index, unsigned int max_index,
04257 unsigned int num_primitives,
04258 const unsigned char *index_data,
04259 D3DFORMAT index_type,
04260 const unsigned char *buffer, size_t stride) {
04261
04262
04263 const unsigned char *buffer_start = buffer + stride * min_index;
04264 const unsigned char *buffer_end = buffer + stride * (max_index + 1);
04265
04266 if (buffer_end - buffer > 0x10000) {
04267
04268
04269 _d3d_device->DrawIndexedPrimitiveUP
04270 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
04271 index_data, index_type, buffer, stride);
04272
04273 } else if ((((long)buffer_end ^ (long)buffer) & ~0xffff) == 0) {
04274
04275 _d3d_device->DrawIndexedPrimitiveUP
04276 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
04277 index_data, index_type, buffer, stride);
04278
04279 } else {
04280
04281
04282
04283 unsigned char *safe_buffer_start = get_safe_buffer_start();
04284 size_t offset = buffer_start - buffer;
04285 memcpy(safe_buffer_start + offset, buffer_start, buffer_end - buffer_start);
04286 _d3d_device->DrawIndexedPrimitiveUP
04287 (primitive_type, min_index, max_index - min_index + 1, num_primitives,
04288 index_data, index_type, safe_buffer_start, stride);
04289 }
04290 }
04291
04292
04293
04294
04295
04296 static int dx_stencil_comparison_function_array [ ] =
04297 {
04298 D3DCMP_NEVER,
04299 D3DCMP_LESS,
04300 D3DCMP_EQUAL,
04301 D3DCMP_LESSEQUAL,
04302 D3DCMP_GREATER,
04303 D3DCMP_NOTEQUAL,
04304 D3DCMP_GREATEREQUAL,
04305 D3DCMP_ALWAYS,
04306 };
04307
04308 static int dx_stencil_operation_array [ ] =
04309 {
04310 D3DSTENCILOP_KEEP,
04311 D3DSTENCILOP_ZERO,
04312 D3DSTENCILOP_REPLACE,
04313 D3DSTENCILOP_INCR,
04314 D3DSTENCILOP_DECR,
04315 D3DSTENCILOP_INVERT,
04316
04317 D3DSTENCILOP_INCRSAT,
04318 D3DSTENCILOP_DECRSAT,
04319 };
04320
04321 void dx_stencil_function (StencilRenderStates::StencilRenderState stencil_render_state, StencilRenderStates *stencil_render_states) {
04322 StencilType render_state_value;
04323
04324 DXGraphicsStateGuardian8 *gsg;
04325 LPDIRECT3DDEVICE8 device;
04326
04327 gsg = (DXGraphicsStateGuardian8 *) stencil_render_states -> _gsg;
04328 device = gsg->get_d3d_device();
04329
04330 render_state_value = stencil_render_states -> get_stencil_render_state (stencil_render_state);
04331
04332 if (dxgsg8_cat.is_debug()) {
04333 dxgsg8_cat.debug()
04334 << "SRS: " << StencilAttrib::stencil_render_state_name_array [stencil_render_state] << ", " << render_state_value << "\n";
04335 }
04336
04337 switch (stencil_render_state)
04338 {
04339 case StencilRenderStates::SRS_front_enable:
04340 device->SetRenderState (D3DRS_STENCILENABLE, render_state_value);
04341 break;
04342
04343 case StencilRenderStates::SRS_back_enable:
04344
04345 break;
04346
04347 case StencilRenderStates::SRS_front_comparison_function:
04348 device->SetRenderState (D3DRS_STENCILFUNC, dx_stencil_comparison_function_array [render_state_value]);
04349 break;
04350 case StencilRenderStates::SRS_front_stencil_fail_operation:
04351 device->SetRenderState (D3DRS_STENCILFAIL, dx_stencil_operation_array [render_state_value]);
04352 break;
04353 case StencilRenderStates::SRS_front_stencil_pass_z_fail_operation:
04354 device->SetRenderState (D3DRS_STENCILZFAIL, dx_stencil_operation_array [render_state_value]);
04355 break;
04356 case StencilRenderStates::SRS_front_stencil_pass_z_pass_operation:
04357 device->SetRenderState (D3DRS_STENCILPASS, dx_stencil_operation_array [render_state_value]);
04358 break;
04359
04360 case StencilRenderStates::SRS_reference:
04361 device->SetRenderState (D3DRS_STENCILREF, render_state_value);
04362 break;
04363
04364 case StencilRenderStates::SRS_read_mask:
04365 device->SetRenderState (D3DRS_STENCILMASK, render_state_value);
04366 break;
04367 case StencilRenderStates::SRS_write_mask:
04368 device->SetRenderState (D3DRS_STENCILWRITEMASK, render_state_value);
04369 break;
04370
04371 case StencilRenderStates::SRS_back_comparison_function:
04372
04373 break;
04374 case StencilRenderStates::SRS_back_stencil_fail_operation:
04375
04376 break;
04377 case StencilRenderStates::SRS_back_stencil_pass_z_fail_operation:
04378
04379 break;
04380 case StencilRenderStates::SRS_back_stencil_pass_z_pass_operation:
04381
04382 break;
04383
04384 default:
04385 break;
04386 }
04387 }
04388
04389 void dx_set_stencil_functions (StencilRenderStates *stencil_render_states) {
04390 if (stencil_render_states) {
04391 StencilRenderStates::StencilRenderState stencil_render_state;
04392
04393 for (stencil_render_state = StencilRenderStates::SRS_first; stencil_render_state < StencilRenderStates::SRS_total; stencil_render_state = (StencilRenderStates::StencilRenderState) ((int) stencil_render_state + 1)) {
04394 stencil_render_states -> set_stencil_function (stencil_render_state, dx_stencil_function);
04395 }
04396 }
04397 }
04398
04399
04400
04401
04402
04403
04404 void DXGraphicsStateGuardian8::
04405 do_issue_stencil() {
04406
04407 if (!_supports_stencil) {
04408 return;
04409 }
04410
04411 StencilRenderStates *stencil_render_states;
04412 const StencilAttrib *stencil = DCAST(StencilAttrib, _target_rs->get_attrib_def(StencilAttrib::get_class_slot()));
04413 stencil_render_states = this -> _stencil_render_states;
04414 if (stencil && stencil_render_states) {
04415
04416 if (dxgsg8_cat.is_debug()) {
04417 dxgsg8_cat.debug() << "STENCIL STATE CHANGE\n";
04418 dxgsg8_cat.debug() << "\n"
04419 << "SRS_front_enable " << stencil -> get_render_state (StencilAttrib::SRS_front_enable) << "\n"
04420 << "SRS_front_comparison_function " << stencil -> get_render_state (StencilAttrib::SRS_front_comparison_function) << "\n"
04421 << "SRS_front_stencil_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_fail_operation) << "\n"
04422 << "SRS_front_stencil_pass_z_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_fail_operation) << "\n"
04423 << "SRS_front_stencil_pass_z_pass_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_pass_operation) << "\n"
04424 << "SRS_reference " << stencil -> get_render_state (StencilAttrib::SRS_reference) << "\n"
04425 << "SRS_read_mask " << stencil -> get_render_state (StencilAttrib::SRS_read_mask) << "\n"
04426 << "SRS_write_mask " << stencil -> get_render_state (StencilAttrib::SRS_write_mask) << "\n";
04427 }
04428
04429 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_enable, stencil -> get_render_state (StencilAttrib::SRS_front_enable));
04430 if (stencil -> get_render_state (StencilAttrib::SRS_front_enable)) {
04431 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_comparison_function, stencil -> get_render_state (StencilAttrib::SRS_front_comparison_function));
04432 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_stencil_fail_operation, stencil -> get_render_state (StencilAttrib::SRS_front_stencil_fail_operation));
04433 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));
04434 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));
04435
04436 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_reference, stencil -> get_render_state (StencilAttrib::SRS_reference));
04437 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_read_mask, stencil -> get_render_state (StencilAttrib::SRS_read_mask));
04438 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_write_mask, stencil -> get_render_state (StencilAttrib::SRS_write_mask));
04439 }
04440 }
04441 else {
04442
04443 if (dxgsg8_cat.is_debug()) {
04444 dxgsg8_cat.debug() << "STENCIL STATE CHANGE TO OFF \n";
04445 }
04446
04447 stencil_render_states -> set_stencil_render_state (true, StencilRenderStates::SRS_front_enable, 0);
04448 }
04449 }
04450
04451 LPDIRECT3DDEVICE8 DXGraphicsStateGuardian8::
04452 get_d3d_device() {
04453 return _d3d_device;
04454 }
04455
04456
04457
04458
04459
04460
04461 void DXGraphicsStateGuardian8::
04462 do_issue_scissor() {
04463 const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
04464 const LVecBase4f &frame = target_scissor->get_frame();
04465 set_scissor(frame[0], frame[1], frame[2], frame[3]);
04466 }
04467
04468
04469
04470
04471
04472
04473
04474 void DXGraphicsStateGuardian8::
04475 set_scissor(float left, float right, float bottom, float top) {
04476
04477
04478
04479
04480
04481 D3DVIEWPORT8 vp;
04482 vp.Width = _current_viewport.Width * (right - left);
04483 vp.X = _current_viewport.X + _current_viewport.Width * left;
04484 vp.Height = _current_viewport.Height * (top - bottom);
04485 vp.Y = _current_viewport.Y + _current_viewport.Height * (1.0f - top);
04486 vp.MinZ = 0.0f;
04487 vp.MaxZ = 1.0f;
04488
04489 HRESULT hr = _d3d_device->SetViewport(&vp);
04490 if (FAILED(hr)) {
04491 dxgsg8_cat.error()
04492 << "_screen->_swap_chain = " << _screen->_swap_chain << " _swap_chain = " << _swap_chain << "\n";
04493 dxgsg8_cat.error()
04494 << "SetViewport(" << vp.X << ", " << vp.Y << ", " << vp.Width << ", " << vp.Height
04495 << ") failed" << D3DERRORSTRING(hr);
04496
04497 D3DVIEWPORT8 vp_old;
04498 _d3d_device->GetViewport(&vp_old);
04499 dxgsg8_cat.error()
04500 << "GetViewport(" << vp_old.X << ", " << vp_old.Y << ", " << vp_old.Width << ", "
04501 << vp_old.Height << ") returned: Trying to set that vp---->\n";
04502 hr = _d3d_device->SetViewport(&vp_old);
04503
04504 if (FAILED(hr)) {
04505 dxgsg8_cat.error() << "Failed again\n";
04506 throw_event("panda3d-render-error");
04507 nassertv(false);
04508 }
04509 }
04510
04511
04512
04513 float xsize = right - left;
04514 float ysize = top - bottom;
04515 float xcenter = (left + right) - 1.0f;
04516 float ycenter = (bottom + top) - 1.0f;
04517 if (xsize == 0.0f || ysize == 0.0f) {
04518
04519
04520 _scissor_mat = TransformState::make_identity();
04521 } else {
04522 _scissor_mat = TransformState::make_scale(LVecBase3f(1.0f / xsize, 1.0f / ysize, 1.0f))->compose(TransformState::make_pos(LPoint3f(-xcenter, -ycenter, 0.0f)));
04523 }
04524 prepare_lens();
04525 }
04526
04527
04528
04529
04530
04531
04532
04533 FrameBufferProperties DXGraphicsStateGuardian8::
04534 calc_fb_properties(DWORD cformat, DWORD dformat, DWORD multisampletype) {
04535 FrameBufferProperties props;
04536 int index=0;
04537 int alpha=0;
04538 int color=0;
04539 switch (cformat) {
04540 case D3DFMT_R8G8B8: index=0; color=24; alpha=0; break;
04541 case D3DFMT_A8R8G8B8: index=0; color=24; alpha=8; break;
04542 case D3DFMT_X8R8G8B8: index=0; color=24; alpha=0; break;
04543 case D3DFMT_R5G6B5: index=0; color=16; alpha=0; break;
04544 case D3DFMT_X1R5G5B5: index=0; color=15; alpha=0; break;
04545 case D3DFMT_A1R5G5B5: index=0; color=15; alpha=1; break;
04546 case D3DFMT_A4R4G4B4: index=0; color=12; alpha=4; break;
04547 case D3DFMT_R3G3B2: index=0; color= 8; alpha=0; break;
04548 case D3DFMT_A8R3G3B2: index=0; color= 8; alpha=8; break;
04549 case D3DFMT_X4R4G4B4: index=0; color=12; alpha=0; break;
04550 case D3DFMT_A2B10G10R10: index=0; color=30; alpha=2; break;
04551 case D3DFMT_A8P8: index=1; color= 8; alpha=8; break;
04552 case D3DFMT_P8: index=1; color= 8; alpha=0; break;
04553 }
04554 props.set_color_bits(color);
04555 props.set_alpha_bits(alpha);
04556 if (index) {
04557 props.set_rgb_color(0);
04558 props.set_indexed_color(1);
04559 } else if (color) {
04560 props.set_rgb_color(1);
04561 props.set_indexed_color(0);
04562 }
04563 int depth=0;
04564 int stencil=0;
04565 switch (dformat) {
04566 case D3DFMT_D32: depth=32; stencil=0; break;
04567 case D3DFMT_D15S1: depth=15; stencil=1; break;
04568 case D3DFMT_D24S8: depth=24; stencil=8; break;
04569 case D3DFMT_D16: depth=16; stencil=0; break;
04570 case D3DFMT_D24X8: depth=24; stencil=0; break;
04571 case D3DFMT_D24X4S4: depth=24; stencil=4; break;
04572 }
04573 props.set_depth_bits(depth);
04574 props.set_stencil_bits(stencil);
04575 props.set_multisamples(multisampletype);
04576 return props;
04577 }
04578
04579 #define GAMMA_1 (255.0 * 256.0)
04580
04581 static bool _gamma_table_initialized = false;
04582 static unsigned short _orignial_gamma_table [256 * 3];
04583
04584 void _create_gamma_table (float 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) {
04585 int i;
04586 double gamma_correction;
04587
04588 if (gamma <= 0.0) {
04589
04590 gamma = 1.0;
04591 }
04592 gamma_correction = 1.0 / (double) gamma;
04593
04594 for (i = 0; i < 256; i++) {
04595 double r;
04596 double g;
04597 double b;
04598
04599 if (original_red_table) {
04600 r = (double) original_red_table [i] / GAMMA_1;
04601 g = (double) original_green_table [i] / GAMMA_1;
04602 b = (double) original_blue_table [i] / GAMMA_1;
04603 }
04604 else {
04605 r = ((double) i / 255.0);
04606 g = r;
04607 b = r;
04608 }
04609
04610 r = pow (r, gamma_correction);
04611 g = pow (g, gamma_correction);
04612 b = pow (b, gamma_correction);
04613
04614 if (r > 1.00) {
04615 r = 1.0;
04616 }
04617 if (g > 1.00) {
04618 g = 1.0;
04619 }
04620 if (b > 1.00) {
04621 b = 1.0;
04622 }
04623
04624 r = r * GAMMA_1;
04625 g = g * GAMMA_1;
04626 b = b * GAMMA_1;
04627
04628 red_table [i] = r;
04629 green_table [i] = g;
04630 blue_table [i] = b;
04631 }
04632 }
04633
04634
04635
04636
04637
04638
04639 bool DXGraphicsStateGuardian8::
04640 get_gamma_table(void) {
04641 bool get;
04642
04643 get = false;
04644 if (_gamma_table_initialized == false) {
04645 HDC hdc = GetDC(NULL);
04646
04647 if (hdc) {
04648 if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) {
04649 _gamma_table_initialized = true;
04650 get = true;
04651 }
04652
04653 ReleaseDC (NULL, hdc);
04654 }
04655 }
04656
04657 return get;
04658 }
04659
04660
04661
04662
04663
04664
04665
04666 bool DXGraphicsStateGuardian8::
04667 static_set_gamma(bool restore, float gamma) {
04668 bool set;
04669 HDC hdc = GetDC(NULL);
04670
04671 set = false;
04672 if (hdc) {
04673 unsigned short ramp [256 * 3];
04674
04675 if (restore && _gamma_table_initialized) {
04676 _create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
04677 }
04678 else {
04679 _create_gamma_table (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
04680 }
04681
04682 if (SetDeviceGammaRamp (hdc, ramp)) {
04683 set = true;
04684 }
04685
04686 ReleaseDC (NULL, hdc);
04687 }
04688
04689 return set;
04690 }
04691
04692
04693
04694
04695
04696
04697
04698 bool DXGraphicsStateGuardian8::
04699 set_gamma(float gamma) {
04700 bool set;
04701
04702 set = static_set_gamma(false, gamma);
04703 if (set) {
04704 _gamma = gamma;
04705 }
04706
04707 return set;
04708 }
04709
04710
04711
04712
04713
04714
04715 void DXGraphicsStateGuardian8::
04716 restore_gamma() {
04717 static_set_gamma(true, 1.0f);
04718 }
04719
04720
04721
04722
04723
04724
04725 void DXGraphicsStateGuardian8::
04726 atexit_function(void) {
04727 static_set_gamma(true, 1.0);
04728 }