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