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