00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "wdxGraphicsPipe9.h"
00016 #include "wdxGraphicsWindow9.h"
00017 #include "config_dxgsg9.h"
00018 #include "config_display.h"
00019 #include "keyboardButton.h"
00020 #include "mouseButton.h"
00021 #include "throw_event.h"
00022 #include "pStatTimer.h"
00023 #include "pmap.h"
00024 #include <ddraw.h>
00025 #include <errno.h>
00026 #include <time.h>
00027 #include <math.h>
00028 #include <tchar.h>
00029
00030 TypeHandle wdxGraphicsWindow9::_type_handle;
00031
00032
00033
00034
00035
00036
00037 wdxGraphicsWindow9::
00038 wdxGraphicsWindow9(GraphicsEngine *engine, GraphicsPipe *pipe,
00039 const string &name,
00040 const FrameBufferProperties &fb_prop,
00041 const WindowProperties &win_prop,
00042 int flags,
00043 GraphicsStateGuardian *gsg,
00044 GraphicsOutput *host):
00045 WinGraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00046 {
00047
00048
00049
00050
00051 _dxgsg = DCAST(DXGraphicsStateGuardian9, gsg);
00052 _depth_buffer_bpp = 0;
00053 _awaiting_restore = false;
00054 ZeroMemory(&_wcontext, sizeof(_wcontext));
00055 }
00056
00057
00058
00059
00060
00061
00062 wdxGraphicsWindow9::
00063 ~wdxGraphicsWindow9() {
00064 }
00065
00066
00067
00068
00069
00070
00071 void wdxGraphicsWindow9::
00072 make_current() {
00073 PStatTimer timer(_make_current_pcollector);
00074
00075 _dxgsg->set_context(&_wcontext);
00076
00077
00078
00079
00080
00081 _dxgsg->reset_if_new();
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 bool wdxGraphicsWindow9::
00094 begin_frame(FrameMode mode, Thread *current_thread) {
00095 begin_frame_spam(mode);
00096 if (_gsg == (GraphicsStateGuardian *)NULL) {
00097 return false;
00098 }
00099
00100 if (_awaiting_restore) {
00101
00102
00103 if (!_dxgsg->check_cooperative_level()) {
00104
00105 return false;
00106 }
00107 _awaiting_restore = false;
00108 init_resized_window();
00109 }
00110
00111 make_current();
00112
00113 if (mode == FM_render) {
00114 clear_cube_map_selection();
00115 }
00116
00117 _gsg->set_current_properties(&get_fb_properties());
00118 bool return_val = _gsg->begin_frame(current_thread);
00119 _dxgsg->set_render_target();
00120 return return_val;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130 void wdxGraphicsWindow9::
00131 end_frame(FrameMode mode, Thread *current_thread) {
00132
00133 end_frame_spam(mode);
00134 nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00135
00136 if (mode == FM_render) {
00137 copy_to_textures();
00138 }
00139
00140 _gsg->end_frame(current_thread);
00141
00142 if (mode == FM_render) {
00143 trigger_flip();
00144 if (_one_shot) {
00145 prepare_for_deletion();
00146 }
00147 clear_cube_map_selection();
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 void wdxGraphicsWindow9::
00162 end_flip() {
00163 if (_dxgsg != (DXGraphicsStateGuardian9 *)NULL && is_active()) {
00164 _dxgsg->show_frame();
00165 }
00166 GraphicsWindow::end_flip();
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 int wdxGraphicsWindow9::
00183 verify_window_sizes(int numsizes, int *dimen) {
00184
00185
00186 nassertr(IS_VALID_PTR(_dxgsg), 0);
00187
00188 int num_valid_modes = 0;
00189
00190 wdxGraphicsPipe9 *dxpipe;
00191 DCAST_INTO_R(dxpipe, _pipe, 0);
00192
00193
00194
00195
00196 int *pCurDim = dimen;
00197
00198 for (int i = 0; i < numsizes; i++, pCurDim += 2) {
00199 int x_size = pCurDim[0];
00200 int y_size = pCurDim[1];
00201
00202 bool bIsGoodMode = false;
00203 bool CouldntFindAnyValidZBuf;
00204 D3DFORMAT newPixFmt = D3DFMT_UNKNOWN;
00205
00206 if (dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) {
00207
00208 bIsGoodMode = true;
00209
00210 } else {
00211 if (_wcontext._is_low_memory_card) {
00212 bIsGoodMode = ((x_size == 640) && (y_size == 480));
00213 } else {
00214 dxpipe->search_for_valid_displaymode
00215 (_wcontext, x_size, y_size, _wcontext._presentation_params.EnableAutoDepthStencil != false,
00216 IS_STENCIL_FORMAT(_wcontext._presentation_params.AutoDepthStencilFormat),
00217 &_wcontext._supported_screen_depths_mask,
00218 &CouldntFindAnyValidZBuf, &newPixFmt, dx_force_16bpp_zbuffer, true);
00219 bIsGoodMode = (newPixFmt != D3DFMT_UNKNOWN);
00220 }
00221 }
00222
00223 if (bIsGoodMode) {
00224 num_valid_modes++;
00225 } else {
00226
00227 pCurDim[0] = 0;
00228 pCurDim[1] = 0;
00229 }
00230
00231 if (wdxdisplay9_cat.is_spam()) {
00232 wdxdisplay9_cat.spam()
00233 << "Fullscrn Mode (" << x_size << ", " << y_size << ")\t"
00234 << (bIsGoodMode ? "V" : "Inv") << "alid\n";
00235 }
00236 }
00237
00238 return num_valid_modes;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 void wdxGraphicsWindow9::
00249 close_window() {
00250 if (wdxdisplay9_cat.is_debug()) {
00251 wdxdisplay9_cat.debug()
00252 << "wdxGraphicsWindow9::close_window() " << this << "\n";
00253 }
00254
00255 if (_gsg != (GraphicsStateGuardian *)NULL) {
00256 _gsg.clear();
00257 _active = false;
00258 }
00259
00260 DXGraphicsStateGuardian9::set_cg_device(NULL);
00261
00262 _dxgsg->release_swap_chain(&_wcontext);
00263 WinGraphicsWindow::close_window();
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273 bool wdxGraphicsWindow9::
00274 open_window() {
00275 PT(DXGraphicsDevice9) dxdev;
00276 WindowProperties props;
00277
00278
00279
00280
00281
00282 static ConfigVariableBool always_discard_device("always-discard-device", true);
00283 bool discard_device = always_discard_device;
00284
00285 if (_gsg == 0) {
00286 _dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
00287 _gsg = _dxgsg;
00288 } else {
00289 DCAST_INTO_R(_dxgsg, _gsg, false);
00290 }
00291
00292 if (!choose_device()) {
00293 return false;
00294 }
00295
00296
00297
00298 {
00299 WindowProperties resized_props;
00300 resized_props.set_size(_wcontext._display_mode.Width,
00301 _wcontext._display_mode.Height);
00302 _properties.add_properties(resized_props);
00303 }
00304
00305 wdxdisplay9_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n";
00306 if (!WinGraphicsWindow::open_window()) {
00307 return false;
00308 }
00309 _wcontext._window = _hWnd;
00310
00311 wdxdisplay9_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n";
00312
00313
00314
00315
00316
00317 while (true) {
00318 if (_dxgsg->get_pipe()->get_device() == NULL || discard_device) {
00319 wdxdisplay9_cat.debug() << "device is null or fullscreen\n";
00320
00321
00322 if (_dxgsg->get_pipe()->get_device()) {
00323 _dxgsg->dx_cleanup();
00324 }
00325
00326 wdxdisplay9_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n";
00327 if (!create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer)) {
00328 wdxdisplay9_cat.error() << "Unable to create window with specified parameters.\n";
00329 close_window();
00330 return false;
00331 }
00332 _dxgsg->get_pipe()->make_device((void*)(&_wcontext));
00333 _dxgsg->copy_pres_reset(&_wcontext);
00334 _dxgsg->create_swap_chain(&_wcontext);
00335 break;
00336
00337 } else {
00338
00339
00340 wdxdisplay9_cat.debug() << "device is not null\n";
00341
00342 dxdev = (DXGraphicsDevice9*)_dxgsg->get_pipe()->get_device();
00343 memcpy(&_wcontext, &dxdev->_Scrn, sizeof(DXScreenData));
00344
00345 _wcontext._presentation_params.Windowed = !is_fullscreen();
00346 _wcontext._presentation_params.hDeviceWindow = _wcontext._window = _hWnd;
00347 _wcontext._presentation_params.BackBufferWidth = _wcontext._display_mode.Width = _properties.get_x_size();
00348 _wcontext._presentation_params.BackBufferHeight = _wcontext._display_mode.Height = _properties.get_y_size();
00349
00350 wdxdisplay9_cat.debug() << "device width " << _wcontext._presentation_params.BackBufferWidth << "\n";
00351 if (!_dxgsg->create_swap_chain(&_wcontext)) {
00352 discard_device = true;
00353 continue;
00354 }
00355 init_resized_window();
00356 break;
00357 }
00358 }
00359 wdxdisplay9_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n";
00360 return true;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 void wdxGraphicsWindow9::
00373 reset_window(bool swapchain) {
00374 if (swapchain) {
00375 if (_wcontext._swap_chain) {
00376 _dxgsg->create_swap_chain(&_wcontext);
00377 wdxdisplay9_cat.debug() << "created swapchain " << _wcontext._swap_chain << "\n";
00378 }
00379 }
00380 else {
00381 if (_wcontext._swap_chain) {
00382 _dxgsg->release_swap_chain(&_wcontext);
00383 wdxdisplay9_cat.debug() << "released swapchain " << _wcontext._swap_chain << "\n";
00384 }
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 void wdxGraphicsWindow9::
00398 fullscreen_restored(WindowProperties &properties) {
00399
00400
00401
00402
00403
00404 if (_dxgsg != NULL) {
00405 _awaiting_restore = true;
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416 void wdxGraphicsWindow9::
00417 handle_reshape() {
00418 GdiFlush();
00419 WinGraphicsWindow::handle_reshape();
00420
00421 if (_dxgsg != NULL) {
00422
00423 WindowProperties props = get_properties();
00424 int x_size = props.get_x_size();
00425 int y_size = props.get_y_size();
00426
00427 if (_wcontext._presentation_params.BackBufferWidth != x_size ||
00428 _wcontext._presentation_params.BackBufferHeight != y_size) {
00429 bool resize_succeeded = reset_device_resize_window(x_size, y_size);
00430
00431 if (wdxdisplay9_cat.is_debug()) {
00432 if (!resize_succeeded) {
00433 wdxdisplay9_cat.debug()
00434 << "windowed_resize to size: (" << x_size << ", " << y_size
00435 << ") failed due to out-of-memory\n";
00436 } else {
00437 int x_origin = props.get_x_origin();
00438 int y_origin = props.get_y_origin();
00439 wdxdisplay9_cat.debug()
00440 << "windowed_resize to origin: (" << x_origin << ", "
00441 << y_origin << "), size: (" << x_size
00442 << ", " << y_size << ")\n";
00443 }
00444 }
00445 }
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454
00455 bool wdxGraphicsWindow9::
00456 do_fullscreen_resize(int x_size, int y_size) {
00457 if (!WinGraphicsWindow::do_fullscreen_resize(x_size, y_size)) {
00458 return false;
00459 }
00460
00461 bool bCouldntFindValidZBuf;
00462 D3DFORMAT pixFmt;
00463 bool bNeedZBuffer = (_wcontext._presentation_params.EnableAutoDepthStencil != false);
00464 bool bNeedStencilBuffer = IS_STENCIL_FORMAT(_wcontext._presentation_params.AutoDepthStencilFormat);
00465
00466 wdxGraphicsPipe9 *dxpipe;
00467 DCAST_INTO_R(dxpipe, _pipe, false);
00468
00469 bool bIsGoodMode = false;
00470 bool bResizeSucceeded = false;
00471
00472 if (!dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) {
00473
00474
00475 if (_wcontext._is_low_memory_card && (!((x_size == 640) && (y_size == 480)))) {
00476 wdxdisplay9_cat.error() << "resize() failed: will not try to resize low vidmem device #" << _wcontext._card_id << " to non-640x480!\n";
00477 return bResizeSucceeded;
00478 }
00479 }
00480
00481
00482
00483 dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size,
00484 bNeedZBuffer, bNeedStencilBuffer,
00485 &_wcontext._supported_screen_depths_mask,
00486 &bCouldntFindValidZBuf,
00487 &pixFmt, dx_force_16bpp_zbuffer, true);
00488 bIsGoodMode = (pixFmt != D3DFMT_UNKNOWN);
00489
00490 if (!bIsGoodMode) {
00491 wdxdisplay9_cat.error() << "resize() failed: "
00492 << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
00493 << " at " << x_size << "x" << y_size << " for device #" << _wcontext._card_id << endl;
00494 return bResizeSucceeded;
00495 }
00496
00497
00498
00499 _wcontext._display_mode.Width = x_size;
00500 _wcontext._display_mode.Height = y_size;
00501 _wcontext._display_mode.Format = pixFmt;
00502 _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
00503
00504
00505 bResizeSucceeded = reset_device_resize_window(x_size, y_size);
00506
00507 if (!bResizeSucceeded) {
00508 wdxdisplay9_cat.error() << "resize() failed with OUT-OF-MEMORY error!\n";
00509
00510 if ((!IS_16BPP_DISPLAY_FORMAT(_wcontext._presentation_params.BackBufferFormat)) &&
00511 (_wcontext._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
00512
00513 _wcontext._display_mode.Format = ((_wcontext._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
00514 dx_force_16bpp_zbuffer = true;
00515 if (wdxdisplay9_cat.info())
00516 wdxdisplay9_cat.info() << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #" << _wcontext._card_id << endl;
00517
00518 bResizeSucceeded = reset_device_resize_window(x_size, y_size);
00519 }
00520 }
00521
00522 return bResizeSucceeded;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 bool wdxGraphicsWindow9::
00534 create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer) {
00535 wdxGraphicsPipe9 *dxpipe;
00536 DCAST_INTO_R(dxpipe, _pipe, false);
00537
00538 DWORD dwRenderWidth = display._display_mode.Width;
00539 DWORD dwRenderHeight = display._display_mode.Height;
00540 DWORD dwBehaviorFlags = 0x0;
00541 LPDIRECT3D9 _d3d9 = display._d3d9;
00542 D3DCAPS9 *pD3DCaps = &display._d3dcaps;
00543 D3DPRESENT_PARAMETERS* presentation_params = &display._presentation_params;
00544 RECT view_rect;
00545 UINT adapter;
00546 D3DDEVTYPE device_type;
00547 HRESULT hr;
00548
00549 adapter = display._card_id;
00550 device_type = D3DDEVTYPE_HAL;
00551
00552
00553 if (dx_use_nvperfhud) {
00554 UINT adapter_id;
00555 UINT total_adapters;
00556
00557 total_adapters = _d3d9 -> GetAdapterCount ( );
00558 for (adapter_id = 0; adapter_id < total_adapters; adapter_id++) {
00559 D3DADAPTER_IDENTIFIER9 identifier;
00560
00561 _d3d9 -> GetAdapterIdentifier (adapter_id, 0, &identifier);
00562 if (strcmp ("NVIDIA NVPerfHUD", identifier.Description) == 0) {
00563 adapter = adapter_id;
00564 device_type = D3DDEVTYPE_REF;
00565 break;
00566 }
00567 }
00568 }
00569
00570 wdxdisplay9_cat.debug() << "Display Width " << dwRenderWidth << " and PresParam Width " << _wcontext._presentation_params.BackBufferWidth << "\n";
00571
00572
00573
00574 bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
00575 bool bWantAlpha = (_fb_properties.get_alpha_bits() > 0);
00576
00577 PRINT_REFCNT(wdxdisplay9, _d3d9);
00578
00579 nassertr(_d3d9 != NULL, false);
00580 nassertr(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION, false);
00581
00582 bool do_sync = sync_video;
00583
00584 if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
00585 wdxdisplay9_cat.info()
00586 << "HW doesnt support syncing to vertical refresh, ignoring sync-video\n";
00587 do_sync = false;
00588 }
00589
00590 presentation_params->BackBufferFormat = display._display_mode.Format;
00591
00592
00593 if (bWantAlpha) {
00594 if (!FAILED(_d3d9->CheckDeviceFormat(adapter, device_type, display._display_mode.Format, D3DUSAGE_RENDERTARGET,
00595 D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8))) {
00596 if (!FAILED(_d3d9->CheckDeviceType(adapter, device_type, display._display_mode.Format, D3DFMT_A8R8G8B8,
00597 is_fullscreen()))) {
00598
00599 presentation_params->BackBufferFormat = D3DFMT_A8R8G8B8;
00600 }
00601 }
00602 }
00603
00604
00605
00606 if (FAILED(_d3d9->CheckDeviceFormat(adapter, device_type, display._display_mode.Format, D3DUSAGE_RENDERTARGET,
00607 D3DRTYPE_SURFACE, presentation_params->BackBufferFormat))) {
00608 wdxdisplay9_cat.error() << "adapter #" << adapter << " CheckDeviceFmt failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl;
00609 goto Fallback_to_16bpp_buffers;
00610 }
00611
00612 if (FAILED(_d3d9->CheckDeviceType(adapter, device_type, display._display_mode.Format, presentation_params->BackBufferFormat,
00613 is_fullscreen()))) {
00614 wdxdisplay9_cat.error() << "adapter #" << adapter << " CheckDeviceType failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl;
00615 goto Fallback_to_16bpp_buffers;
00616 }
00617
00618 if (display._presentation_params.EnableAutoDepthStencil) {
00619 if (!dxpipe->find_best_depth_format(display, display._display_mode,
00620 &display._presentation_params.AutoDepthStencilFormat,
00621 bWantStencil, false)) {
00622 wdxdisplay9_cat.error()
00623 << "find_best_depth_format failed in CreateScreenBuffers for device #"
00624 << adapter << endl;
00625 goto Fallback_to_16bpp_buffers;
00626 }
00627 _depth_buffer_bpp = D3DFMT_to_DepthBits(display._presentation_params.AutoDepthStencilFormat);
00628 } else {
00629 _depth_buffer_bpp = 0;
00630 }
00631
00632 presentation_params->Windowed = !is_fullscreen();
00633
00634 int supported_multisamples = 0;
00635 if (framebuffer_multisample.get_value()){
00636 supported_multisamples = multisamples.get_value();
00637 }
00638
00639 while (supported_multisamples > 1){
00640
00641 hr = _d3d9->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, display._display_mode.Format,
00642 is_fullscreen(), D3DMULTISAMPLE_TYPE(supported_multisamples), NULL);
00643 if (FAILED(hr)) {
00644 supported_multisamples--;
00645 continue;
00646 }
00647
00648 if (display._presentation_params.EnableAutoDepthStencil) {
00649 hr = _d3d9->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, display._presentation_params.AutoDepthStencilFormat,
00650 is_fullscreen(), D3DMULTISAMPLE_TYPE(supported_multisamples), NULL);
00651 if (FAILED(hr)) {
00652 supported_multisamples--;
00653 continue;
00654 }
00655 }
00656
00657 presentation_params->MultiSampleType = D3DMULTISAMPLE_TYPE(supported_multisamples);
00658
00659 if (wdxdisplay9_cat.is_info())
00660 wdxdisplay9_cat.info() << "adapter #" << adapter << " using multisample antialiasing level: " << supported_multisamples <<
00661 ". Requested level was: " << multisamples.get_value() << endl;
00662 break;
00663 }
00664
00665 presentation_params->BackBufferCount = 1;
00666 presentation_params->Flags = 0x0;
00667 presentation_params->hDeviceWindow = display._window;
00668 presentation_params->BackBufferWidth = display._display_mode.Width;
00669 presentation_params->BackBufferHeight = display._display_mode.Height;
00670
00671 if (_wcontext._is_tnl_device) {
00672 dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
00673
00674
00675
00676
00677
00678
00679 } else {
00680 dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
00681 }
00682
00683 if (dx_preserve_fpu_state)
00684 dwBehaviorFlags |= D3DCREATE_FPU_PRESERVE;
00685
00686
00687
00688
00689
00690
00691 if (!SetForegroundWindow(display._window)) {
00692 wdxdisplay9_cat.warning() << "SetForegroundWindow() failed!\n";
00693 }
00694
00695 if (dx_use_multithread) {
00696 dwBehaviorFlags |= D3DCREATE_MULTITHREADED;
00697 }
00698 if (dx_use_puredevice) {
00699 dwBehaviorFlags |= D3DCREATE_PUREDEVICE;
00700 }
00701
00702 if (dx_disable_driver_management) {
00703 dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT;
00704 }
00705 if (dx_disable_driver_management_ex) {
00706 dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX;
00707 }
00708
00709 if (is_fullscreen()) {
00710
00711
00712 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD;
00713 presentation_params->PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
00714 presentation_params->FullScreen_RefreshRateInHz = display._display_mode.RefreshRate;
00715
00716 ClearToBlack(display._window, get_properties());
00717
00718 hr = _d3d9->CreateDevice(adapter, device_type, _hWnd,
00719 dwBehaviorFlags, presentation_params, &display._d3d_device);
00720
00721 if (FAILED(hr)) {
00722 wdxdisplay9_cat.fatal() << "D3D CreateDevice failed for adapter #" << adapter << ", " << D3DERRORSTRING(hr);
00723
00724 if (hr == D3DERR_OUTOFVIDEOMEMORY)
00725 goto Fallback_to_16bpp_buffers;
00726 else
00727 return false;
00728 }
00729
00730 SetRect(&view_rect, 0, 0, dwRenderWidth, dwRenderHeight);
00731
00732 } else {
00733
00734
00735 D3DDISPLAYMODE dispmode;
00736 hr = display._d3d9->GetAdapterDisplayMode(adapter, &dispmode);
00737
00738 if (FAILED(hr)) {
00739 wdxdisplay9_cat.fatal()
00740 << "GetAdapterDisplayMode failed" << D3DERRORSTRING(hr);
00741 return false;
00742 }
00743
00744 if (dispmode.Format == D3DFMT_P8) {
00745 wdxdisplay9_cat.fatal()
00746 << "Can't run windowed in an 8-bit or less display mode" << endl;
00747 return false;
00748 }
00749
00750 presentation_params->PresentationInterval = 0;
00751
00752 if (supported_multisamples<2) {
00753 if (do_sync) {
00754
00755
00756
00757
00758
00759
00760 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD;
00761 } else {
00762 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD;
00763 }
00764
00765
00766 if (do_sync == false) {
00767 presentation_params->SwapEffect = D3DSWAPEFFECT_FLIP;
00768 presentation_params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
00769 }
00770 } else {
00771 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD;
00772 }
00773
00774
00775
00776 hr = _d3d9->CreateDevice(adapter, device_type, _hWnd,
00777 dwBehaviorFlags, presentation_params, &display._d3d_device);
00778
00779 if (FAILED(hr)) {
00780 wdxdisplay9_cat.warning() << "presentation_params->BackBufferWidth : " << presentation_params->BackBufferWidth << endl;
00781 wdxdisplay9_cat.warning() << "presentation_params->BackBufferHeight : " << presentation_params->BackBufferHeight << endl;
00782 wdxdisplay9_cat.warning() << "presentation_params->BackBufferFormat : " << presentation_params->BackBufferFormat << endl;
00783 wdxdisplay9_cat.warning() << "presentation_params->BackBufferCount : " << presentation_params->BackBufferCount << endl;
00784 wdxdisplay9_cat.warning() << "D3D CreateDevice failed for adapter #" << adapter << D3DERRORSTRING(hr);
00785 goto Fallback_to_16bpp_buffers;
00786 }
00787 }
00788
00789
00790
00791 PRINT_REFCNT(wdxdisplay9, _wcontext._d3d_device);
00792
00793 if (presentation_params->EnableAutoDepthStencil) {
00794 int depth_bits;
00795 int stencil_bits;
00796
00797 depth_bits = 1;
00798 stencil_bits = 0;
00799 switch (presentation_params->AutoDepthStencilFormat)
00800 {
00801 case D3DFMT_D16_LOCKABLE:
00802 depth_bits = 16;
00803 break;
00804 case D3DFMT_D32:
00805 depth_bits = 32;
00806 break;
00807 case D3DFMT_D15S1:
00808 depth_bits = 15;
00809 stencil_bits = 1;
00810 break;
00811 case D3DFMT_D24S8:
00812 depth_bits = 24;
00813 stencil_bits = 8;
00814 break;
00815 case D3DFMT_D24X8:
00816 depth_bits = 24;
00817 break;
00818 case D3DFMT_D24X4S4:
00819 depth_bits = 24;
00820 stencil_bits = 4;
00821 break;
00822 case D3DFMT_D32F_LOCKABLE:
00823 depth_bits = 32;
00824 break;
00825 case D3DFMT_D24FS8:
00826 depth_bits = 24;
00827 stencil_bits = 8;
00828 break;
00829 case D3DFMT_D16:
00830 depth_bits = 16;
00831 break;
00832 default:
00833 wdxdisplay9_cat.error() << "unknown depth stencil format " << presentation_params->AutoDepthStencilFormat;
00834 break;
00835 }
00836
00837 _fb_properties.set_stencil_bits(stencil_bits);
00838 _fb_properties.set_depth_bits(depth_bits);
00839 } else {
00840 _fb_properties.set_depth_bits(0);
00841 _fb_properties.set_stencil_bits(0);
00842 }
00843
00844 init_resized_window();
00845
00846 return true;
00847
00848 Fallback_to_16bpp_buffers:
00849 if ((!IS_16BPP_DISPLAY_FORMAT(presentation_params->BackBufferFormat)) &&
00850 (display._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
00851
00852
00853 display._display_mode.Format = ((display._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
00854
00855 if (wdxdisplay9_cat.info()) {
00856 wdxdisplay9_cat.info()
00857 << "CreateDevice failed with out-of-vidmem or invalid BackBufferFormat, retrying w/16bpp buffers on adapter #"
00858 << adapter << endl;
00859 }
00860 return create_screen_buffers_and_device(display, true);
00861
00862
00863 } else if (!((dwRenderWidth == 640)&&(dwRenderHeight == 480))) {
00864 if (wdxdisplay9_cat.info())
00865 wdxdisplay9_cat.info() << "CreateDevice failed w/out-of-vidmem, retrying at 640x480 w/16bpp buffers on adapter #" << adapter << endl;
00866
00867 display._display_mode.Width = 640;
00868 display._display_mode.Height = 480;
00869 return create_screen_buffers_and_device(display, true);
00870
00871
00872 } else {
00873 wdxdisplay9_cat.fatal()
00874 << "Can't create any screen buffers, bailing out.\n";
00875 return false;
00876 }
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 bool wdxGraphicsWindow9::
00888 choose_device() {
00889 HRESULT hr;
00890
00891 wdxGraphicsPipe9 *dxpipe;
00892 DCAST_INTO_R(dxpipe, _pipe, false);
00893
00894 int num_adapters = dxpipe->__d3d9->GetAdapterCount();
00895 DXDeviceInfoVec device_infos;
00896
00897 for (int i = 0; i < num_adapters; i++) {
00898 D3DADAPTER_IDENTIFIER9 adapter_info;
00899 ZeroMemory(&adapter_info, sizeof(D3DADAPTER_IDENTIFIER9));
00900 hr = dxpipe->__d3d9->GetAdapterIdentifier(i, 0, &adapter_info);
00901 if (FAILED(hr)) {
00902 wdxdisplay9_cat.fatal()
00903 << "D3D GetAdapterID(" << i << ") failed: "
00904 << D3DERRORSTRING(hr) << endl;
00905 continue;
00906 }
00907
00908 LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion;
00909
00910 wdxdisplay9_cat.info()
00911 << "D3D9." << (dxpipe->__is_dx9_1 ?"1":"0") << " Adapter[" << i << "]: " << adapter_info.Description
00912 << ", Driver: " << adapter_info.Driver << ", DriverVersion: ("
00913 << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "."
00914 << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart)
00915 << ")\nVendorID: 0x" << (void*) adapter_info.VendorId
00916 << " DeviceID: 0x" << (void*) adapter_info.DeviceId
00917 << " SubsysID: 0x" << (void*) adapter_info.SubSysId
00918 << " Revision: 0x" << (void*) adapter_info.Revision << endl;
00919
00920 HMONITOR _monitor = dxpipe->__d3d9->GetAdapterMonitor(i);
00921 if (_monitor == NULL) {
00922 wdxdisplay9_cat.info()
00923 << "D3D9 Adapter[" << i << "]: seems to be disabled, skipping it\n";
00924 continue;
00925 }
00926
00927 DXDeviceInfo devinfo;
00928 ZeroMemory(&devinfo, sizeof(devinfo));
00929 memcpy(&devinfo.guidDeviceIdentifier, &adapter_info.DeviceIdentifier,
00930 sizeof(GUID));
00931 strncpy(devinfo.szDescription, adapter_info.Description,
00932 MAX_DEVICE_IDENTIFIER_STRING);
00933 strncpy(devinfo.szDriver, adapter_info.Driver,
00934 MAX_DEVICE_IDENTIFIER_STRING);
00935 devinfo.VendorID = adapter_info.VendorId;
00936 devinfo.DeviceID = adapter_info.DeviceId;
00937 devinfo._driver_version = adapter_info.DriverVersion;
00938 devinfo._monitor = _monitor;
00939 devinfo.cardID = i;
00940
00941 device_infos.push_back(devinfo);
00942 }
00943
00944 if (device_infos.empty()) {
00945 wdxdisplay9_cat.error()
00946 << "No available D3D9 devices found.\n";
00947 return false;
00948 }
00949
00950
00951
00952 num_adapters = (int)device_infos.size();
00953
00954
00955
00956 int adapter_num = D3DADAPTER_DEFAULT;
00957
00958
00959
00960 if (dx_preferred_device_id != -1) {
00961 if (dx_preferred_device_id < 0 || dx_preferred_device_id >= num_adapters) {
00962 wdxdisplay9_cat.error()
00963 << "invalid 'dx-preferred-device-id', valid values are 0-"
00964 << num_adapters - 1 << ", using default adapter instead.\n";
00965 } else {
00966 adapter_num = dx_preferred_device_id;
00967 }
00968 }
00969
00970
00971 if (adapter_num >= 0 && adapter_num < (int)device_infos.size()) {
00972 if (consider_device(dxpipe, &device_infos[adapter_num])) {
00973 wdxdisplay9_cat.info()
00974 << "Selected device " << adapter_num << " (of "
00975 << device_infos.size() << ", zero-based)\n";
00976 return true;
00977 }
00978 wdxdisplay9_cat.info()
00979 << "Could not select device " << adapter_num << "\n";
00980 }
00981
00982
00983
00984 for (UINT devnum = 0; devnum < device_infos.size(); ++devnum) {
00985 if (consider_device(dxpipe, &device_infos[devnum])) {
00986 wdxdisplay9_cat.info()
00987 << "Chose device " << devnum << " (of "
00988 << device_infos.size() << ", zero-based): first one that works.\n";
00989 return true;
00990 }
00991 }
00992
00993 wdxdisplay9_cat.error() << "no usable display devices.\n";
00994 return false;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004 bool wdxGraphicsWindow9::
01005 consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
01006
01007 nassertr(dxpipe != NULL, false);
01008 WindowProperties properties = get_properties();
01009 DWORD dwRenderWidth = properties.get_x_size();
01010 DWORD dwRenderHeight = properties.get_y_size();
01011 HRESULT hr;
01012 LPDIRECT3D9 _d3d9 = dxpipe->__d3d9;
01013
01014 nassertr(_dxgsg != NULL, false);
01015 _wcontext._d3d9 = _d3d9;
01016 _wcontext._is_dx9_1 = dxpipe->__is_dx9_1;
01017 _wcontext._card_id = device_info->cardID;
01018
01019 bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
01020
01021 hr = _d3d9->GetAdapterIdentifier(device_info->cardID, 0,
01022 &_wcontext._dx_device_id);
01023 if (FAILED(hr)) {
01024 wdxdisplay9_cat.error()
01025 << "D3D GetAdapterID failed" << D3DERRORSTRING(hr);
01026 return false;
01027 }
01028
01029 D3DCAPS9 _d3dcaps;
01030 hr = _d3d9->GetDeviceCaps(device_info->cardID, D3DDEVTYPE_HAL, &_d3dcaps);
01031 if (FAILED(hr)) {
01032 if ((hr == D3DERR_INVALIDDEVICE)||(hr == D3DERR_NOTAVAILABLE)) {
01033 wdxdisplay9_cat.error()
01034 << "No DirectX 9 D3D-capable 3D hardware detected for device # "
01035 << device_info->cardID << " (" << device_info->szDescription
01036 << ")!\n";
01037 } else {
01038 wdxdisplay9_cat.error()
01039 << "GetDeviceCaps failed: " << D3DERRORSTRING(hr) << endl;
01040 }
01041 return false;
01042 }
01043
01044
01045 memcpy(&_wcontext._d3dcaps, &_d3dcaps, sizeof(D3DCAPS9));
01046 _wcontext._card_id = device_info->cardID;
01047
01048 _wcontext._max_available_video_memory = UNKNOWN_VIDMEM_SIZE;
01049 _wcontext._is_low_memory_card = false;
01050
01051
01052
01053
01054 if (_d3dcaps.MaxStreams == 0) {
01055 if (wdxdisplay9_cat.is_debug()) {
01056 wdxdisplay9_cat.debug()
01057 << "checking vidmem size\n";
01058 }
01059
01060 UINT IDnum;
01061
01062
01063 for (IDnum = 0; IDnum < dxpipe->_card_ids.size(); IDnum++) {
01064 if ((device_info->VendorID == dxpipe->_card_ids[IDnum].VendorID) &&
01065 (device_info->DeviceID == dxpipe->_card_ids[IDnum].DeviceID) &&
01066 (device_info->_monitor == dxpipe->_card_ids[IDnum]._monitor))
01067 break;
01068 }
01069
01070 if (IDnum < dxpipe->_card_ids.size()) {
01071 _wcontext._max_available_video_memory = dxpipe->_card_ids[IDnum]._max_available_video_memory;
01072 _wcontext._is_low_memory_card = dxpipe->_card_ids[IDnum]._is_low_memory_card;
01073 } else {
01074 wdxdisplay9_cat.error()
01075 << "Error: couldnt find a CardID match in DX7 info, assuming card is not a lowmem card\n";
01076 }
01077 }
01078
01079 if ((bWantStencil) && (_d3dcaps.StencilCaps == 0x0)) {
01080 wdxdisplay9_cat.fatal()
01081 << "Stencil ability requested, but device #" << device_info->cardID
01082 << " (" << _wcontext._dx_device_id.Description
01083 << "), has no stencil capability!\n";
01084 return false;
01085 }
01086
01087
01088
01089
01090
01091 _wcontext._is_tnl_device =
01092 ((_d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0);
01093 _wcontext._can_use_hw_vertex_shaders =
01094 (_d3dcaps.VertexShaderVersion >= D3DVS_VERSION(1, 0));
01095 _wcontext._can_use_pixel_shaders =
01096 (_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(1, 0));
01097
01098 bool bNeedZBuffer =
01099 ((!(_d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
01100 (_fb_properties.get_depth_bits() > 0));
01101
01102 _wcontext._presentation_params.EnableAutoDepthStencil = bNeedZBuffer;
01103
01104 D3DFORMAT pixFmt = D3DFMT_UNKNOWN;
01105
01106 if (is_fullscreen()) {
01107 bool bCouldntFindValidZBuf;
01108
01109 dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight,
01110 bNeedZBuffer, bWantStencil,
01111 &_wcontext._supported_screen_depths_mask,
01112 &bCouldntFindValidZBuf,
01113 &pixFmt, dx_force_16bpp_zbuffer, true);
01114
01115
01116
01117
01118 if (pixFmt == D3DFMT_UNKNOWN) {
01119 wdxdisplay9_cat.error()
01120 << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
01121 << " at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << _wcontext._card_id << endl;
01122 return false;
01123 }
01124 } else {
01125
01126
01127 D3DDISPLAYMODE dispmode;
01128 hr = _d3d9->GetAdapterDisplayMode(device_info->cardID, &dispmode);
01129 if (FAILED(hr)) {
01130 wdxdisplay9_cat.error()
01131 << "GetAdapterDisplayMode(" << device_info->cardID
01132 << ") failed" << D3DERRORSTRING(hr);
01133 return false;
01134 }
01135 pixFmt = dispmode.Format;
01136 }
01137
01138 _wcontext._display_mode.Width = dwRenderWidth;
01139 _wcontext._display_mode.Height = dwRenderHeight;
01140 _wcontext._display_mode.Format = pixFmt;
01141 _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
01142 _wcontext._monitor = device_info->_monitor;
01143
01144 if (strcmp(device_info->szDriver, "igdumd32.dll") == 0 &&
01145 device_info->_driver_version.QuadPart <= 0x0007000e000affffLL &&
01146 dx_intel_compressed_texture_bug) {
01147
01148
01149
01150 _wcontext._intel_compressed_texture_bug = true;
01151 }
01152
01153 return true;
01154 }
01155
01156
01157
01158
01159
01160
01161
01162
01163 bool wdxGraphicsWindow9::
01164 reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
01165 nassertr((new_xsize > 0) && (new_ysize > 0), false);
01166 bool retval = true;
01167
01168 DXScreenData *screen = NULL;
01169 D3DPRESENT_PARAMETERS d3dpp;
01170 memcpy(&d3dpp, &_wcontext._presentation_params, sizeof(D3DPRESENT_PARAMETERS));
01171 _wcontext._presentation_params.BackBufferWidth = new_xsize;
01172 _wcontext._presentation_params.BackBufferHeight = new_ysize;
01173 make_current();
01174 HRESULT hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen);
01175
01176 if (FAILED(hr)) {
01177 retval = false;
01178 wdxdisplay9_cat.error()
01179 << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr);
01180 if (hr == D3DERR_OUTOFVIDEOMEMORY) {
01181 memcpy(&_wcontext._presentation_params, &d3dpp, sizeof(D3DPRESENT_PARAMETERS));
01182 hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen);
01183 if (FAILED(hr)) {
01184 wdxdisplay9_cat.error()
01185 << "reset_device_resize_window Reset() failed OutOfVidmem, then failed again doing Reset w/original params:" << D3DERRORSTRING(hr);
01186 throw_event("panda3d-render-error");
01187 return false;
01188
01189 } else {
01190 if (wdxdisplay9_cat.is_info()) {
01191 wdxdisplay9_cat.info()
01192 << "reset of original size (" << _wcontext._presentation_params.BackBufferWidth
01193 << ", " << _wcontext._presentation_params.BackBufferHeight << ") succeeded\n";
01194 }
01195 }
01196 } else {
01197 wdxdisplay9_cat.fatal()
01198 << "Can't reset device, bailing out.\n";
01199 throw_event("panda3d-render-error");
01200 return false;
01201 }
01202 }
01203
01204 if (screen) {
01205 _wcontext._swap_chain = screen->_swap_chain;
01206 }
01207 wdxdisplay9_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n";
01208 _gsg->mark_new();
01209 init_resized_window();
01210 return retval;
01211 }
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 void wdxGraphicsWindow9::
01224 init_resized_window() {
01225 HRESULT hr;
01226
01227 DWORD newWidth = _wcontext._presentation_params.BackBufferWidth;
01228 DWORD newHeight = _wcontext._presentation_params.BackBufferHeight;
01229
01230 nassertv((newWidth != 0) && (newHeight != 0));
01231 nassertv(_wcontext._window != NULL);
01232
01233 if (_wcontext._presentation_params.Windowed) {
01234 POINT ul, lr;
01235 RECT client_rect;
01236
01237
01238
01239
01240 GetClientRect(_wcontext._window, &client_rect);
01241 ul.x = client_rect.left;
01242 ul.y = client_rect.top;
01243 lr.x = client_rect.right;
01244 lr.y = client_rect.bottom;
01245 ClientToScreen(_wcontext._window, &ul);
01246 ClientToScreen(_wcontext._window, &lr);
01247 client_rect.left = ul.x;
01248 client_rect.top = ul.y;
01249 client_rect.right = lr.x;
01250 client_rect.bottom = lr.y;
01251 }
01252
01253
01254 nassertv(_wcontext._window != NULL);
01255 ClearToBlack(_wcontext._window, get_properties());
01256
01257
01258 hr = _wcontext._d3d_device->EvictManagedResources ( );
01259 if (FAILED(hr)) {
01260 wdxdisplay9_cat.error()
01261 << "EvictManagedResources failed for device #"
01262 << _wcontext._card_id << D3DERRORSTRING(hr);
01263 }
01264
01265 make_current();
01266
01267
01268 _dxgsg->set_render_target ( );
01269
01270
01271 DWORD flags;
01272 D3DCOLOR clear_color;
01273
01274 flags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER;
01275 clear_color = 0x00000000;
01276 hr = _wcontext._d3d_device-> Clear (0, NULL, flags, clear_color, 0.0f, 0);
01277 if (FAILED(hr)) {
01278 wdxdisplay9_cat.error()
01279 << "Clear failed for device"
01280 << D3DERRORSTRING(hr);
01281 }
01282 hr = _wcontext._d3d_device-> Present (NULL, NULL, NULL, NULL);
01283 if (FAILED(hr)) {
01284 wdxdisplay9_cat.error()
01285 << "Present failed for device"
01286 << D3DERRORSTRING(hr);
01287 }
01288 hr = _wcontext._d3d_device-> Clear (0, NULL, flags, clear_color, 0.0f, 0);
01289 if (FAILED(hr)) {
01290 wdxdisplay9_cat.error()
01291 << "Clear failed for device"
01292 << D3DERRORSTRING(hr);
01293 }
01294 }
01295
01296
01297
01298
01299
01300
01301
01302 int wdxGraphicsWindow9::
01303 D3DFMT_to_DepthBits(D3DFORMAT fmt) {
01304 switch(fmt) {
01305 case D3DFMT_D16:
01306 return 16;
01307
01308 case D3DFMT_D24X8:
01309 case D3DFMT_D24X4S4:
01310 case D3DFMT_D24S8:
01311 return 24;
01312
01313 case D3DFMT_D32:
01314 return 32;
01315
01316 case D3DFMT_D15S1:
01317 return 15;
01318
01319 default:
01320 wdxdisplay9_cat.debug()
01321 << "D3DFMT_DepthBits: unhandled D3DFMT!\n";
01322 return 0;
01323 }
01324 }
01325
01326
01327
01328
01329
01330
01331
01332
01333 bool wdxGraphicsWindow9::
01334 is_badvidmem_card(D3DADAPTER_IDENTIFIER9 *pDevID) {
01335
01336 if (pDevID->VendorId == 0x00008086) {
01337 return true;
01338 }
01339
01340 return false;
01341 }
01342