Panda3D
Loading...
Searching...
No Matches
wdxGraphicsWindow9.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file wdxGraphicsWindow9.cxx
10 * @author mike
11 * @date 2000-01-09
12 */
13
14#include "wdxGraphicsPipe9.h"
15#include "wdxGraphicsWindow9.h"
16#include "config_dxgsg9.h"
17#include "config_display.h"
18#include "keyboardButton.h"
19#include "mouseButton.h"
20#include "throw_event.h"
21#include "pStatTimer.h"
22#include "pmap.h"
23#include <ddraw.h>
24#include <errno.h>
25#include <time.h>
26#include <math.h>
27#include <tchar.h>
28
29using std::endl;
30
31TypeHandle wdxGraphicsWindow9::_type_handle;
32
33/**
34 *
35 */
36wdxGraphicsWindow9::
37wdxGraphicsWindow9(GraphicsEngine *engine, GraphicsPipe *pipe,
38 const std::string &name,
39 const FrameBufferProperties &fb_prop,
40 const WindowProperties &win_prop,
41 int flags,
43 GraphicsOutput *host):
44 WinGraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
45{
46 // don't actually create the window in the constructor. reason: multi-
47 // threading requires panda C++ window object to exist in separate thread
48 // from actual API window
49
50 _dxgsg = DCAST(DXGraphicsStateGuardian9, gsg);
51 _depth_buffer_bpp = 0;
52 _awaiting_restore = false;
53 ZeroMemory(&_wcontext, sizeof(_wcontext));
54}
55
56/**
57 *
58 */
59wdxGraphicsWindow9::
60~wdxGraphicsWindow9() {
61}
62
63/**
64 *
65 */
66void wdxGraphicsWindow9::
67make_current() {
68 PStatTimer timer(_make_current_pcollector);
69
70 _dxgsg->set_context(&_wcontext);
71
72 // Now that we have made the context current to a window, we can reset the
73 // GSG state if this is the first time it has been used. (We can't just
74 // call reset() when we construct the GSG, because reset() requires having a
75 // current context.)
76 _dxgsg->reset_if_new();
77}
78
79/**
80 * This function will be called within the draw thread before beginning
81 * rendering for a given frame. It should do whatever setup is required, and
82 * return true if the frame should be rendered, or false if it should be
83 * skipped.
84 */
86begin_frame(FrameMode mode, Thread *current_thread) {
87 begin_frame_spam(mode);
88 if (_gsg == nullptr) {
89 return false;
90 }
91
92 if (!get_unexposed_draw() && !_got_expose_event) {
93 if (wdxdisplay9_cat.is_spam()) {
94 wdxdisplay9_cat.spam()
95 << "Not drawing " << this << ": unexposed.\n";
96 }
97 return false;
98 }
99
100 if (_awaiting_restore) {
101 // The fullscreen window was recently restored; we can't continue until
102 // the GSG says we can.
103 if (!_dxgsg->check_cooperative_level()) {
104 // Keep waiting.
105 return false;
106 }
107 _awaiting_restore = false;
108 init_resized_window();
109 }
110
111 make_current();
112
113 if (mode == FM_render) {
114 clear_cube_map_selection();
115 }
116
117 _gsg->set_current_properties(&get_fb_properties());
118 bool return_val = _gsg->begin_frame(current_thread);
119 _dxgsg->set_render_target();
120 return return_val;
121}
122
123/**
124 * This function will be called within the draw thread after rendering is
125 * completed for a given frame. It should do whatever finalization is
126 * required.
127 */
129end_frame(FrameMode mode, Thread *current_thread) {
130 end_frame_spam(mode);
131 nassertv(_gsg != nullptr);
132
133 if (mode == FM_render) {
134 copy_to_textures();
135 }
136
137 _gsg->end_frame(current_thread);
138
139 if (mode == FM_render) {
140 trigger_flip();
141 clear_cube_map_selection();
142 }
143}
144
145/**
146 * This function will be called within the draw thread after begin_flip() has
147 * been called on all windows, to finish the exchange of the front and back
148 * buffers.
149 *
150 * This should cause the window to wait for the flip, if necessary.
151 */
153end_flip() {
154 if (_dxgsg != nullptr && is_active()) {
155 _dxgsg->show_frame();
156 }
158}
159
160/**
161 * Determines which of the indicated window sizes are supported by available
162 * hardware (e.g. in fullscreen mode).
163 *
164 * On entry, dimen is an array containing contiguous x, y pairs specifying
165 * possible display sizes; it is numsizes*2 words long. The function will
166 * zero out any invalid x, y size pairs. The return value is the number of
167 * valid sizes that were found.
168 */
170verify_window_sizes(int numsizes, int *dimen) {
171 // unfortunately this only works AFTER you make the window initially, so its
172 // really mostly useful for resizes only
173 nassertr(IS_VALID_PTR(_dxgsg), 0);
174
175 int num_valid_modes = 0;
176
177 wdxGraphicsPipe9 *dxpipe;
178 DCAST_INTO_R(dxpipe, _pipe, 0);
179
180 // not requesting same refresh rate since changing res might not support
181 // same refresh rate at new size
182
183 int *pCurDim = dimen;
184
185 for (int i = 0; i < numsizes; i++, pCurDim += 2) {
186 int x_size = pCurDim[0];
187 int y_size = pCurDim[1];
188
189 bool bIsGoodMode = false;
190 bool CouldntFindAnyValidZBuf;
191 D3DFORMAT newPixFmt = D3DFMT_UNKNOWN;
192
193 if (dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) {
194 // bypass the test below for certain cards we know have valid modes
195 bIsGoodMode = true;
196
197 } else {
198 if (_wcontext._is_low_memory_card) {
199 bIsGoodMode = ((x_size == 640) && (y_size == 480));
200 } else {
202 (_wcontext, x_size, y_size, _wcontext._presentation_params.EnableAutoDepthStencil != false,
203 IS_STENCIL_FORMAT(_wcontext._presentation_params.AutoDepthStencilFormat),
204 &_wcontext._supported_screen_depths_mask,
205 &CouldntFindAnyValidZBuf, &newPixFmt, dx_force_16bpp_zbuffer, true);
206 bIsGoodMode = (newPixFmt != D3DFMT_UNKNOWN);
207 }
208 }
209
210 if (bIsGoodMode) {
211 num_valid_modes++;
212 } else {
213 // tell caller the mode is invalid
214 pCurDim[0] = 0;
215 pCurDim[1] = 0;
216 }
217
218 if (wdxdisplay9_cat.is_spam()) {
219 wdxdisplay9_cat.spam()
220 << "Fullscrn Mode (" << x_size << ", " << y_size << ")\t"
221 << (bIsGoodMode ? "V" : "Inv") << "alid\n";
222 }
223 }
224
225 return num_valid_modes;
226}
227
228/**
229 * Some cleanup is necessary for directx closeup of window. Handle close
230 * window events for this particular window.
231 */
232void wdxGraphicsWindow9::
233close_window() {
234 if (wdxdisplay9_cat.is_debug()) {
235 wdxdisplay9_cat.debug()
236 << "wdxGraphicsWindow9::close_window() " << this << "\n";
237 }
238
239 if (_gsg != nullptr) {
240 _gsg.clear();
241 }
242
244
245 _dxgsg->release_swap_chain(&_wcontext);
246 WinGraphicsWindow::close_window();
247}
248
249/**
250 * Opens the window right now. Called from the window thread. Returns true
251 * if the window is successfully opened, or false if there was a problem.
252 */
253bool wdxGraphicsWindow9::
254open_window() {
255 PT(DXGraphicsDevice9) dxdev;
256 WindowProperties props;
257
258 // For now, let's make this configurable. If this is true, then you can't
259 // open multiple different windows with the same GSG, but you may have more
260 // luck opening different windows with different GSG's.
261 static ConfigVariableBool always_discard_device("always-discard-device", true);
262 bool discard_device = always_discard_device;
263
264 if (_gsg == 0) {
265 _dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
266 _gsg = _dxgsg;
267 } else {
268 DCAST_INTO_R(_dxgsg, _gsg, false);
269 }
270
271 if (!choose_device()) {
272 return false;
273 }
274
275 // Ensure the window properties get set to the actual size of the window.
276 {
277 WindowProperties resized_props;
278 resized_props.set_size(_wcontext._display_mode.Width,
279 _wcontext._display_mode.Height);
280 _properties.add_properties(resized_props);
281 }
282
283 wdxdisplay9_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n";
284 if (!WinGraphicsWindow::open_window()) {
285 return false;
286 }
287 _wcontext._window = _hWnd;
288
289 wdxdisplay9_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n";
290
291 // Here check if a device already exists. If so, then this open_window call
292 // may be an extension to create multiple windows on same device In that
293 // case just create an additional swapchain for this window
294
295 while (true) {
296 if (_dxgsg->get_pipe()->get_device() == nullptr || discard_device) {
297 wdxdisplay9_cat.debug() << "device is null or fullscreen\n";
298
299 // If device exists, free it
300 if (_dxgsg->get_pipe()->get_device()) {
301 _dxgsg->dx_cleanup();
302 }
303
304 wdxdisplay9_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n";
305 if (!create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer)) {
306 wdxdisplay9_cat.error() << "Unable to create window with specified parameters.\n";
307 close_window();
308 return false;
309 }
310 _dxgsg->get_pipe()->make_device((void*)(&_wcontext));
311 _dxgsg->copy_pres_reset(&_wcontext);
312 _dxgsg->create_swap_chain(&_wcontext);
313 break;
314
315 } else {
316 // fill in the DXScreenData from dxdevice here and change the reference
317 // to _window.
318 wdxdisplay9_cat.debug() << "device is not null\n";
319
320 dxdev = (DXGraphicsDevice9*)_dxgsg->get_pipe()->get_device();
321 memcpy(&_wcontext, &dxdev->_Scrn, sizeof(DXScreenData));
322
323 _wcontext._presentation_params.Windowed = !is_fullscreen();
324 _wcontext._presentation_params.hDeviceWindow = _wcontext._window = _hWnd;
325 _wcontext._presentation_params.BackBufferWidth = _wcontext._display_mode.Width = _properties.get_x_size();
326 _wcontext._presentation_params.BackBufferHeight = _wcontext._display_mode.Height = _properties.get_y_size();
327
328 wdxdisplay9_cat.debug() << "device width " << _wcontext._presentation_params.BackBufferWidth << "\n";
329 if (!_dxgsg->create_swap_chain(&_wcontext)) {
330 discard_device = true;
331 continue; // try again
332 }
333 init_resized_window();
334 break;
335 }
336 }
337 wdxdisplay9_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n";
338 return true;
339}
340
341/**
342 * Resets the window framebuffer right now. Called from graphicsEngine. It
343 * releases the current swap chain / creates a new one. If this is the
344 * initial window and swapchain is false, then it calls reset_ main_device to
345 * Reset the device.
346 */
347void wdxGraphicsWindow9::
348reset_window(bool swapchain) {
349 if (swapchain) {
350 if (_wcontext._swap_chain) {
351 _dxgsg->create_swap_chain(&_wcontext);
352 wdxdisplay9_cat.debug() << "created swapchain " << _wcontext._swap_chain << "\n";
353 }
354 }
355 else {
356 if (_wcontext._swap_chain) {
357 _dxgsg->release_swap_chain(&_wcontext);
358 wdxdisplay9_cat.debug() << "released swapchain " << _wcontext._swap_chain << "\n";
359 }
360 }
361}
362
363/**
364 * This is a hook for derived classes to do something special, if necessary,
365 * when a fullscreen window has been restored after being minimized. The
366 * given WindowProperties struct will be applied to this window's properties
367 * after this function returns.
368 */
369void wdxGraphicsWindow9::
370fullscreen_restored(WindowProperties &properties) {
371 // In DX8, unlike DX7, for some reason we can't immediately start rendering
372 // as soon as the window is restored, even though BeginScene() says we can.
373 // Instead, we have to wait until TestCooperativeLevel() lets us in. We
374 // need to set a flag so we can handle this special case in begin_frame().
375 if (_dxgsg != nullptr) {
376 _awaiting_restore = true;
377 }
378}
379
380/**
381 * Called in the window thread when the window size or location is changed,
382 * this updates the properties structure accordingly.
383 */
384void wdxGraphicsWindow9::
385handle_reshape() {
386 GdiFlush();
387 WinGraphicsWindow::handle_reshape();
388
389 if (_dxgsg != nullptr && _dxgsg->_d3d_device != nullptr) {
390 // create the new resized rendertargets
392 int x_size = props.get_x_size();
393 int y_size = props.get_y_size();
394
395 if (_wcontext._presentation_params.BackBufferWidth != x_size ||
396 _wcontext._presentation_params.BackBufferHeight != y_size) {
397 bool resize_succeeded = reset_device_resize_window(x_size, y_size);
398
399 if (wdxdisplay9_cat.is_debug()) {
400 if (!resize_succeeded) {
401 wdxdisplay9_cat.debug()
402 << "windowed_resize to size: (" << x_size << ", " << y_size
403 << ") failed due to out-of-memory\n";
404 } else {
405 int x_origin = props.get_x_origin();
406 int y_origin = props.get_y_origin();
407 wdxdisplay9_cat.debug()
408 << "windowed_resize to origin: (" << x_origin << ", "
409 << y_origin << "), size: (" << x_size
410 << ", " << y_size << ")\n";
411 }
412 }
413 }
414 }
415}
416
417/**
418 * Called in the window thread to resize a fullscreen window.
419 */
420bool wdxGraphicsWindow9::
421do_fullscreen_resize(int x_size, int y_size) {
422 if (!WinGraphicsWindow::do_fullscreen_resize(x_size, y_size)) {
423 return false;
424 }
425
426 bool bCouldntFindValidZBuf;
427 D3DFORMAT pixFmt;
428 bool bNeedZBuffer = (_wcontext._presentation_params.EnableAutoDepthStencil != false);
429 bool bNeedStencilBuffer = IS_STENCIL_FORMAT(_wcontext._presentation_params.AutoDepthStencilFormat);
430
431 wdxGraphicsPipe9 *dxpipe;
432 DCAST_INTO_R(dxpipe, _pipe, false);
433
434 bool bIsGoodMode = false;
435 bool bResizeSucceeded = false;
436
437 if (!dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) {
438 // bypass the lowvidmem test below for certain "lowmem" cards we know have
439 // valid modes
440
441 if (_wcontext._is_low_memory_card && (!((x_size == 640) && (y_size == 480)))) {
442 wdxdisplay9_cat.error() << "resize() failed: will not try to resize low vidmem device #" << _wcontext._card_id << " to non-640x480!\n";
443 return bResizeSucceeded;
444 }
445 }
446
447 // must ALWAYS use search_for_valid_displaymode even if we know a-priori
448 // that res is valid so we can get a valid pixfmt
449 dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size,
450 bNeedZBuffer, bNeedStencilBuffer,
451 &_wcontext._supported_screen_depths_mask,
452 &bCouldntFindValidZBuf,
453 &pixFmt, dx_force_16bpp_zbuffer, true);
454 bIsGoodMode = (pixFmt != D3DFMT_UNKNOWN);
455
456 if (!bIsGoodMode) {
457 wdxdisplay9_cat.error() << "resize() failed: "
458 << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
459 << " at " << x_size << "x" << y_size << " for device #" << _wcontext._card_id << endl;
460 return bResizeSucceeded;
461 }
462
463 // reset_device_resize_window handles both windowed & fullscrn, so need to
464 // set new displaymode manually here
465 _wcontext._display_mode.Width = x_size;
466 _wcontext._display_mode.Height = y_size;
467 _wcontext._display_mode.Format = pixFmt;
468 _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
469 // keep the previous setting for
470 // _wcontext._presentation_params.BackBufferFormat
471
472 bResizeSucceeded = reset_device_resize_window(x_size, y_size);
473
474 if (!bResizeSucceeded) {
475 wdxdisplay9_cat.error() << "resize() failed with OUT-OF-MEMORY error!\n";
476
477 if ((!IS_16BPP_DISPLAY_FORMAT(_wcontext._presentation_params.BackBufferFormat)) &&
478 (_wcontext._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
479 // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers
480 _wcontext._display_mode.Format = ((_wcontext._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
481 dx_force_16bpp_zbuffer = true;
482 if (wdxdisplay9_cat.info())
483 wdxdisplay9_cat.info() << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #" << _wcontext._card_id << endl;
484
485 bResizeSucceeded = reset_device_resize_window(x_size, y_size); // create the new resized rendertargets
486 }
487 }
488
489 return bResizeSucceeded;
490}
491
492/**
493 * Called whenever the window is resized, this recreates the necessary buffers
494 * for rendering.
495 *
496 * Sets _depth_buffer_bpp appropriately.
497 */
498bool wdxGraphicsWindow9::
499create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer) {
500 wdxGraphicsPipe9 *dxpipe;
501 DCAST_INTO_R(dxpipe, _pipe, false);
502
503 DWORD dwRenderWidth = display._display_mode.Width;
504 DWORD dwRenderHeight = display._display_mode.Height;
505 DWORD dwBehaviorFlags = 0x0;
506 LPDIRECT3D9 _d3d9 = display._d3d9;
507 D3DCAPS9 *pD3DCaps = &display._d3dcaps;
508 D3DPRESENT_PARAMETERS* presentation_params = &display._presentation_params;
509 RECT view_rect;
510 UINT adapter;
511 D3DDEVTYPE device_type;
512 HRESULT hr;
513
514 adapter = display._card_id;
515 device_type = D3DDEVTYPE_HAL;
516
517 // NVIDIA NVPerfHUD
518 if (dx_use_nvperfhud) {
519 UINT adapter_id;
520 UINT total_adapters;
521
522 total_adapters = _d3d9 -> GetAdapterCount ( );
523 for (adapter_id = 0; adapter_id < total_adapters; adapter_id++) {
524 D3DADAPTER_IDENTIFIER9 identifier;
525
526 _d3d9 -> GetAdapterIdentifier (adapter_id, 0, &identifier);
527 if (strcmp ("NVIDIA NVPerfHUD", identifier.Description) == 0) {
528 adapter = adapter_id;
529 device_type = D3DDEVTYPE_REF;
530 break;
531 }
532 }
533 }
534
535 wdxdisplay9_cat.debug() << "Display Width " << dwRenderWidth << " and PresParam Width " << _wcontext._presentation_params.BackBufferWidth << "\n";
536
537 // BUGBUG: need to change panda to put frame buffer properties with
538 // GraphicsWindow, not GSG!! Update: Did I fix the bug? - Josh
539 bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
540 bool bWantAlpha = (_fb_properties.get_alpha_bits() > 0);
541
542 PRINT_REFCNT(wdxdisplay9, _d3d9);
543
544 nassertr(_d3d9 != nullptr, false);
545 nassertr(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION, false);
546
547 bool do_sync = sync_video;
548
549 if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
550 wdxdisplay9_cat.info()
551 << "HW doesnt support syncing to vertical refresh, ignoring sync-video\n";
552 do_sync = false;
553 }
554
555 presentation_params->BackBufferFormat = display._display_mode.Format;
556
557 // check for D3DFMT_A8R8G8B8 first
558 if (bWantAlpha) {
559 if (!FAILED(_d3d9->CheckDeviceFormat(adapter, device_type, display._display_mode.Format, D3DUSAGE_RENDERTARGET,
560 D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8))) {
561 if (!FAILED(_d3d9->CheckDeviceType(adapter, device_type, display._display_mode.Format, D3DFMT_A8R8G8B8,
562 is_fullscreen()))) {
563 // We can accept D3DFMT_A8R8G8B8, so use it.
564 presentation_params->BackBufferFormat = D3DFMT_A8R8G8B8;
565 }
566 }
567 }
568
569 // check for same format as display_mode verify the rendertarget fmt
570 if (FAILED(_d3d9->CheckDeviceFormat(adapter, device_type, display._display_mode.Format, D3DUSAGE_RENDERTARGET,
571 D3DRTYPE_SURFACE, presentation_params->BackBufferFormat))) {
572 wdxdisplay9_cat.error() << "adapter #" << adapter << " CheckDeviceFmt failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl;
573 goto Fallback_to_16bpp_buffers;
574 }
575
576 if (FAILED(_d3d9->CheckDeviceType(adapter, device_type, display._display_mode.Format, presentation_params->BackBufferFormat,
577 is_fullscreen()))) {
578 wdxdisplay9_cat.error() << "adapter #" << adapter << " CheckDeviceType failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl;
579 goto Fallback_to_16bpp_buffers;
580 }
581
582 if (display._presentation_params.EnableAutoDepthStencil) {
583 if (!dxpipe->find_best_depth_format(display, display._display_mode,
584 &display._presentation_params.AutoDepthStencilFormat,
585 bWantStencil, false)) {
586 wdxdisplay9_cat.error()
587 << "find_best_depth_format failed in CreateScreenBuffers for device #"
588 << adapter << endl;
589 goto Fallback_to_16bpp_buffers;
590 }
591 _depth_buffer_bpp = D3DFMT_to_DepthBits(display._presentation_params.AutoDepthStencilFormat);
592 } else {
593 _depth_buffer_bpp = 0;
594 }
595
596 presentation_params->Windowed = !is_fullscreen();
597
598 int supported_multisamples = 0;
599 if (framebuffer_multisample.get_value()){
600 supported_multisamples = multisamples.get_value();
601 }
602
603 while (supported_multisamples > 1){
604 // need to check both rendertarget and zbuffer fmts
605 hr = _d3d9->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, display._display_mode.Format,
606 is_fullscreen(), D3DMULTISAMPLE_TYPE(supported_multisamples), nullptr);
607 if (FAILED(hr)) {
608 supported_multisamples--;
609 continue;
610 }
611
612 if (display._presentation_params.EnableAutoDepthStencil) {
613 hr = _d3d9->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, display._presentation_params.AutoDepthStencilFormat,
614 is_fullscreen(), D3DMULTISAMPLE_TYPE(supported_multisamples), nullptr);
615 if (FAILED(hr)) {
616 supported_multisamples--;
617 continue;
618 }
619 }
620
621 presentation_params->MultiSampleType = D3DMULTISAMPLE_TYPE(supported_multisamples);
622
623 if (wdxdisplay9_cat.is_info())
624 wdxdisplay9_cat.info() << "adapter #" << adapter << " using multisample antialiasing level: " << supported_multisamples <<
625 ". Requested level was: " << multisamples.get_value() << endl;
626 break;
627 }
628
629 presentation_params->BackBufferCount = 1;
630 presentation_params->Flags = 0x0;
631 presentation_params->hDeviceWindow = display._window;
632 presentation_params->BackBufferWidth = display._display_mode.Width;
633 presentation_params->BackBufferHeight = display._display_mode.Height;
634
635 if (_wcontext._is_tnl_device) {
636 dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
637 // note: we could create a pure device in this case if I eliminated the
638 // GetRenderState calls in dxgsg
639
640 // also, no software vertex processing available since I specify
641 // D3DCREATE_HARDWARE_VERTEXPROCESSING and not
642 // D3DCREATE_MIXED_VERTEXPROCESSING
643 } else {
644 dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
645 }
646
647 if (dx_preserve_fpu_state)
648 dwBehaviorFlags |= D3DCREATE_FPU_PRESERVE;
649
650 // if window is not foreground in exclusive mode, ddraw thinks you are 'not
651 // active', so it changes your WM_ACTIVATEAPP from true to false, causing us
652 // to go into a 'wait-for WM_ACTIVATEAPP true' loop, and the event never
653 // comes so we hang in fullscreen wait. also doing this for windowed mode
654 // since it was requested.
655 if (!SetForegroundWindow(display._window)) {
656 wdxdisplay9_cat.warning() << "SetForegroundWindow() failed!\n";
657 }
658
659 if (dx_use_multithread) {
660 dwBehaviorFlags |= D3DCREATE_MULTITHREADED;
661 }
662 if (dx_use_puredevice) {
663 dwBehaviorFlags |= D3DCREATE_PUREDEVICE;
664 }
665
666 if (dx_disable_driver_management) {
667 dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT;
668 }
669 if (dx_disable_driver_management_ex) {
670 dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX;
671 }
672
673 if (is_fullscreen()) {
674 // CREATE FULLSCREEN BUFFERS
675
676 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; // we don't care about preserving contents of old frame
677 presentation_params->PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
678 presentation_params->FullScreen_RefreshRateInHz = display._display_mode.RefreshRate;
679
680 ClearToBlack(display._window, get_properties());
681
682 hr = _d3d9->CreateDevice(adapter, device_type, _hWnd,
683 dwBehaviorFlags, presentation_params, &display._d3d_device);
684
685 if (FAILED(hr)) {
686 wdxdisplay9_cat.fatal() << "D3D CreateDevice failed for adapter #" << adapter << ", " << D3DERRORSTRING(hr);
687
688 if (hr == D3DERR_OUTOFVIDEOMEMORY)
689 goto Fallback_to_16bpp_buffers;
690 else
691 return false;
692 }
693
694 SetRect(&view_rect, 0, 0, dwRenderWidth, dwRenderHeight);
695
696 } else {
697 // CREATE WINDOWED BUFFERS
698
699 D3DDISPLAYMODE dispmode;
700 hr = display._d3d9->GetAdapterDisplayMode(adapter, &dispmode);
701
702 if (FAILED(hr)) {
703 wdxdisplay9_cat.fatal()
704 << "GetAdapterDisplayMode failed" << D3DERRORSTRING(hr);
705 return false;
706 }
707
708 if (dispmode.Format == D3DFMT_P8) {
709 wdxdisplay9_cat.fatal()
710 << "Can't run windowed in an 8-bit or less display mode" << endl;
711 return false;
712 }
713
714 // From d3d8caps.h D3DPRESENT_INTERVAL_DEFAULT = 0x00000000L #define
715 // D3DPRESENT_INTERVAL_ONE 0x00000001L Next line is really sloppy,
716 // should either be D3DPRESENT_INTERVAL_DEFAULT or D3DPRESENT_INTERVAL_ONE
717 // not a direct number! but I'm not going to touch it because it's
718 // working as is. Zhao 12152011
719 presentation_params->PresentationInterval = 0;
720
721 // ATI 5450 doesn't like D3DSWAPEFFECT_FLIP
722 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD;
723 if (do_sync == false) {
724 presentation_params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
725 }
726/*
727 * if (supported_multisamples<2) { if (do_sync) { It turns out that COPY_VSYNC
728 * has real performance problems on many nVidia cards--it syncs at some random
729 * interval, possibly skipping over several video syncs. Screw it, we'll
730 * effectively disable sync-video with windowed mode using DirectX8.
731 * presentation_params->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
732 * presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; } else {
733 * presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; }
734 */
735
736/*
737 * override presentation parameters for windowed mode, render and display at
738 * maximum speed if (do_sync == false) { presentation_params->SwapEffect =
739 * D3DSWAPEFFECT_FLIP; presentation_params->PresentationInterval =
740 * D3DPRESENT_INTERVAL_IMMEDIATE; } } else { presentation_params->SwapEffect =
741 * D3DSWAPEFFECT_DISCARD; }
742 */
743
744 // assert((dwRenderWidth ==
745 // presentation_params->BackBufferWidth)&&(dwRenderHeight ==
746 // presentation_params->BackBufferHeight));
747
748 hr = _d3d9->CreateDevice(adapter, device_type, _hWnd,
749 dwBehaviorFlags, presentation_params, &display._d3d_device);
750
751 if (FAILED(hr)) {
752 wdxdisplay9_cat.warning() << "presentation_params->BackBufferWidth : " << presentation_params->BackBufferWidth << endl;
753 wdxdisplay9_cat.warning() << "presentation_params->BackBufferHeight : " << presentation_params->BackBufferHeight << endl;
754 wdxdisplay9_cat.warning() << "presentation_params->BackBufferFormat : " << presentation_params->BackBufferFormat << endl;
755 wdxdisplay9_cat.warning() << "presentation_params->BackBufferCount : " << presentation_params->BackBufferCount << endl;
756 wdxdisplay9_cat.warning() << "D3D CreateDevice failed for adapter #" << adapter << D3DERRORSTRING(hr);
757 goto Fallback_to_16bpp_buffers;
758 }
759 } // end create windowed buffers
760
761 // ========================================================
762
763 PRINT_REFCNT(wdxdisplay9, _wcontext._d3d_device);
764
765 if (presentation_params->EnableAutoDepthStencil) {
766 int depth_bits;
767 int stencil_bits;
768
769 depth_bits = 1;
770 stencil_bits = 0;
771 switch (presentation_params->AutoDepthStencilFormat)
772 {
773 case D3DFMT_D16_LOCKABLE:
774 depth_bits = 16;
775 break;
776 case D3DFMT_D32:
777 depth_bits = 32;
778 break;
779 case D3DFMT_D15S1:
780 depth_bits = 15;
781 stencil_bits = 1;
782 break;
783 case D3DFMT_D24S8:
784 depth_bits = 24;
785 stencil_bits = 8;
786 break;
787 case D3DFMT_D24X8:
788 depth_bits = 24;
789 break;
790 case D3DFMT_D24X4S4:
791 depth_bits = 24;
792 stencil_bits = 4;
793 break;
794 case D3DFMT_D32F_LOCKABLE:
795 depth_bits = 32;
796 break;
797 case D3DFMT_D24FS8:
798 depth_bits = 24;
799 stencil_bits = 8;
800 break;
801 case D3DFMT_D16:
802 depth_bits = 16;
803 break;
804 default:
805 wdxdisplay9_cat.error() << "unknown depth stencil format " << presentation_params->AutoDepthStencilFormat;
806 break;
807 }
808
809 _fb_properties.set_stencil_bits(stencil_bits);
810 _fb_properties.set_depth_bits(depth_bits);
811 } else {
812 _fb_properties.set_depth_bits(0);
813 _fb_properties.set_stencil_bits(0);
814 }
815
816 init_resized_window();
817
818 return true;
819
820 Fallback_to_16bpp_buffers:
821 if ((!IS_16BPP_DISPLAY_FORMAT(presentation_params->BackBufferFormat)) &&
822 (display._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
823 // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers
824
825 display._display_mode.Format = ((display._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
826
827 if (wdxdisplay9_cat.info()) {
828 wdxdisplay9_cat.info()
829 << "CreateDevice failed with out-of-vidmem or invalid BackBufferFormat, retrying w/16bpp buffers on adapter #"
830 << adapter << endl;
831 }
832 return create_screen_buffers_and_device(display, true);
833 // return;
834
835 } else if (!((dwRenderWidth == 640)&&(dwRenderHeight == 480))) {
836 if (wdxdisplay9_cat.info())
837 wdxdisplay9_cat.info() << "CreateDevice failed w/out-of-vidmem, retrying at 640x480 w/16bpp buffers on adapter #" << adapter << endl;
838 // try final fallback to 640x480x16
839 display._display_mode.Width = 640;
840 display._display_mode.Height = 480;
841 return create_screen_buffers_and_device(display, true);
842 // return;
843
844 } else {
845 wdxdisplay9_cat.fatal()
846 << "Can't create any screen buffers, bailing out.\n";
847 return false;
848 }
849}
850
851/**
852 * Looks at the list of available graphics adapters and chooses a suitable one
853 * for the window.
854 *
855 * Returns true if successful, false on failure.
856 */
857bool wdxGraphicsWindow9::
858choose_device() {
859 HRESULT hr;
860
861 wdxGraphicsPipe9 *dxpipe;
862 DCAST_INTO_R(dxpipe, _pipe, false);
863
864 int num_adapters = dxpipe->__d3d9->GetAdapterCount();
865 DXDeviceInfoVec device_infos;
866
867 for (int i = 0; i < num_adapters; i++) {
868 D3DADAPTER_IDENTIFIER9 adapter_info;
869 ZeroMemory(&adapter_info, sizeof(D3DADAPTER_IDENTIFIER9));
870 hr = dxpipe->__d3d9->GetAdapterIdentifier(i, 0, &adapter_info);
871 if (FAILED(hr)) {
872 wdxdisplay9_cat.fatal()
873 << "D3D GetAdapterID(" << i << ") failed: "
874 << D3DERRORSTRING(hr) << endl;
875 continue;
876 }
877
878 LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion;
879
880 wdxdisplay9_cat.info()
881 << "D3D9 Adapter[" << i << "]: " << adapter_info.Description
882 << ", Driver: " << adapter_info.Driver << ", DriverVersion: ("
883 << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "."
884 << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart)
885 << ")\nVendorID: 0x" << std::hex << adapter_info.VendorId
886 << " DeviceID: 0x" << adapter_info.DeviceId
887 << " SubsysID: 0x" << adapter_info.SubSysId
888 << " Revision: 0x" << adapter_info.Revision << std::dec << endl;
889
890 HMONITOR _monitor = dxpipe->__d3d9->GetAdapterMonitor(i);
891 if (_monitor == nullptr) {
892 wdxdisplay9_cat.info()
893 << "D3D9 Adapter[" << i << "]: seems to be disabled, skipping it\n";
894 continue;
895 }
896
897 DXDeviceInfo devinfo;
898 ZeroMemory(&devinfo, sizeof(devinfo));
899 memcpy(&devinfo.guidDeviceIdentifier, &adapter_info.DeviceIdentifier,
900 sizeof(GUID));
901 strncpy(devinfo.szDescription, adapter_info.Description,
902 MAX_DEVICE_IDENTIFIER_STRING);
903 strncpy(devinfo.szDriver, adapter_info.Driver,
904 MAX_DEVICE_IDENTIFIER_STRING);
905 devinfo.VendorID = adapter_info.VendorId;
906 devinfo.DeviceID = adapter_info.DeviceId;
907 devinfo._driver_version = adapter_info.DriverVersion;
908 devinfo._monitor = _monitor;
909 devinfo.cardID = i;
910
911 device_infos.push_back(devinfo);
912 }
913
914 if (device_infos.empty()) {
915 wdxdisplay9_cat.error()
916 << "No available D3D9 devices found.\n";
917 return false;
918 }
919
920 // Since some adapters may have been disabled, we should re-obtain the
921 // number of available adapters.
922 num_adapters = (int)device_infos.size();
923
924 // Now choose a suitable adapter.
925
926 int adapter_num = D3DADAPTER_DEFAULT;
927
928 // Eventually, we should have some interface for specifying a device index
929 // interactively, instead of only via Configrc.
930 if (dx_preferred_device_id != -1) {
931 if (dx_preferred_device_id < 0 || dx_preferred_device_id >= num_adapters) {
932 wdxdisplay9_cat.error()
933 << "invalid 'dx-preferred-device-id', valid values are 0-"
934 << num_adapters - 1 << ", using default adapter instead.\n";
935 } else {
936 adapter_num = dx_preferred_device_id;
937 }
938 }
939
940 // Try to select the default or requested device.
941 if (adapter_num >= 0 && adapter_num < (int)device_infos.size()) {
942 if (consider_device(dxpipe, &device_infos[adapter_num])) {
943 wdxdisplay9_cat.info()
944 << "Selected device " << adapter_num << " (of "
945 << device_infos.size() << ", zero-based)\n";
946 return true;
947 }
948 wdxdisplay9_cat.info()
949 << "Could not select device " << adapter_num << "\n";
950 }
951
952 // Iterate through all available devices to find the first suitable one.
953 for (UINT devnum = 0; devnum < device_infos.size(); ++devnum) {
954 if (consider_device(dxpipe, &device_infos[devnum])) {
955 wdxdisplay9_cat.info()
956 << "Chose device " << devnum << " (of "
957 << device_infos.size() << ", zero-based): first one that works.\n";
958 return true;
959 }
960 }
961
962 wdxdisplay9_cat.error() << "no usable display devices.\n";
963 return false;
964}
965
966/**
967 * If the specified device is acceptable, sets it as the current device and
968 * returns true; otherwise, returns false.
969 */
970bool wdxGraphicsWindow9::
971consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
972
973 nassertr(dxpipe != nullptr, false);
974 WindowProperties properties = get_properties();
975 DWORD dwRenderWidth = properties.get_x_size();
976 DWORD dwRenderHeight = properties.get_y_size();
977 HRESULT hr;
978 LPDIRECT3D9 _d3d9 = dxpipe->__d3d9;
979
980 nassertr(_dxgsg != nullptr, false);
981 _wcontext._d3d9 = _d3d9;
982 _wcontext._card_id = device_info->cardID; // could this change by end?
983
984 bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
985
986 hr = _d3d9->GetAdapterIdentifier(device_info->cardID, 0,
987 &_wcontext._dx_device_id);
988 if (FAILED(hr)) {
989 wdxdisplay9_cat.error()
990 << "D3D GetAdapterID failed" << D3DERRORSTRING(hr);
991 return false;
992 }
993
994 D3DCAPS9 _d3dcaps;
995 hr = _d3d9->GetDeviceCaps(device_info->cardID, D3DDEVTYPE_HAL, &_d3dcaps);
996 if (FAILED(hr)) {
997 if ((hr == D3DERR_INVALIDDEVICE)||(hr == D3DERR_NOTAVAILABLE)) {
998 wdxdisplay9_cat.error()
999 << "No DirectX 9 D3D-capable 3D hardware detected for device # "
1000 << device_info->cardID << " (" << device_info->szDescription
1001 << ")!\n";
1002 } else {
1003 wdxdisplay9_cat.error()
1004 << "GetDeviceCaps failed: " << D3DERRORSTRING(hr) << endl;
1005 }
1006 return false;
1007 }
1008
1009 // search_for_valid_displaymode needs these to be set
1010 memcpy(&_wcontext._d3dcaps, &_d3dcaps, sizeof(D3DCAPS9));
1011 _wcontext._card_id = device_info->cardID;
1012
1013 _wcontext._max_available_video_memory = UNKNOWN_VIDMEM_SIZE;
1014 _wcontext._is_low_memory_card = false;
1015
1016 // bugbug: wouldnt we like to do GetAVailVidMem so we can do upper-limit
1017 // memory computation for dx8 cards too? otherwise verify_window_sizes cant
1018 // do much
1019 if (_d3dcaps.MaxStreams == 0) {
1020 if (wdxdisplay9_cat.is_debug()) {
1021 wdxdisplay9_cat.debug()
1022 << "checking vidmem size\n";
1023 }
1024
1025 UINT IDnum;
1026
1027 // simple linear search to match DX7 card info wDX8 card ID
1028 for (IDnum = 0; IDnum < dxpipe->_card_ids.size(); IDnum++) {
1029 if ((device_info->VendorID == dxpipe->_card_ids[IDnum].VendorID) &&
1030 (device_info->DeviceID == dxpipe->_card_ids[IDnum].DeviceID) &&
1031 (device_info->_monitor == dxpipe->_card_ids[IDnum]._monitor))
1032 break;
1033 }
1034
1035 if (IDnum < dxpipe->_card_ids.size()) {
1036 _wcontext._max_available_video_memory = dxpipe->_card_ids[IDnum]._max_available_video_memory;
1037 _wcontext._is_low_memory_card = dxpipe->_card_ids[IDnum]._is_low_memory_card;
1038 } else {
1039 wdxdisplay9_cat.error()
1040 << "Error: couldnt find a CardID match in DX7 info, assuming card is not a lowmem card\n";
1041 }
1042 }
1043
1044 if ((bWantStencil) && (_d3dcaps.StencilCaps == 0x0)) {
1045 wdxdisplay9_cat.fatal()
1046 << "Stencil ability requested, but device #" << device_info->cardID
1047 << " (" << _wcontext._dx_device_id.Description
1048 << "), has no stencil capability!\n";
1049 return false;
1050 }
1051
1052 // just because TNL is true, it doesnt mean vtx shaders are supported in HW
1053 // (see GF2) for this case, you probably want MIXED processing to use HW for
1054 // fixed-fn vertex processing and SW for vtx shaders
1055 _wcontext._is_tnl_device =
1056 ((_d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0);
1057 _wcontext._can_use_hw_vertex_shaders =
1058 (_d3dcaps.VertexShaderVersion >= D3DVS_VERSION(1, 0));
1059 _wcontext._can_use_pixel_shaders =
1060 (_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(1, 0));
1061
1062 bool bNeedZBuffer =
1063 ((!(_d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
1064 (_fb_properties.get_depth_bits() > 0));
1065
1066 _wcontext._presentation_params.EnableAutoDepthStencil = bNeedZBuffer;
1067
1068 D3DFORMAT pixFmt = D3DFMT_UNKNOWN;
1069
1070 if (is_fullscreen()) {
1071 bool bCouldntFindValidZBuf;
1072
1073 dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight,
1074 bNeedZBuffer, bWantStencil,
1075 &_wcontext._supported_screen_depths_mask,
1076 &bCouldntFindValidZBuf,
1077 &pixFmt, dx_force_16bpp_zbuffer, true);
1078
1079 // note I'm not saving refresh rate, will just use adapter default at
1080 // given res for now
1081
1082 if (pixFmt == D3DFMT_UNKNOWN) {
1083 wdxdisplay9_cat.error()
1084 << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
1085 << " at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << _wcontext._card_id << endl;
1086 return false;
1087 }
1088 } else {
1089 // Windowed Mode
1090
1091 D3DDISPLAYMODE dispmode;
1092 hr = _d3d9->GetAdapterDisplayMode(device_info->cardID, &dispmode);
1093 if (FAILED(hr)) {
1094 wdxdisplay9_cat.error()
1095 << "GetAdapterDisplayMode(" << device_info->cardID
1096 << ") failed" << D3DERRORSTRING(hr);
1097 return false;
1098 }
1099 pixFmt = dispmode.Format;
1100 }
1101
1102 _wcontext._display_mode.Width = dwRenderWidth;
1103 _wcontext._display_mode.Height = dwRenderHeight;
1104 _wcontext._display_mode.Format = pixFmt;
1105 _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
1106 _wcontext._monitor = device_info->_monitor;
1107
1108 if (strcmp(device_info->szDriver, "igdumd32.dll") == 0 &&
1109 device_info->_driver_version.QuadPart <= 0x0007000e000affffLL &&
1110 dx_intel_compressed_texture_bug) {
1111 // Disable compressed textures for this buggy driver (7.14.10.65535 and
1112 // earlier--I don't know whether any other drivers also exhibit the bug).
1113 _wcontext._intel_compressed_texture_bug = true;
1114 }
1115
1116 return true;
1117}
1118
1119/**
1120 * Called after a window (either fullscreen or windowed) has been resized,
1121 * this recreates the D3D structures to match the new size.
1122 */
1123bool wdxGraphicsWindow9::
1124reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
1125 bool retval = true;
1126
1127 DXScreenData *screen = nullptr;
1128 D3DPRESENT_PARAMETERS d3dpp;
1129 memcpy(&d3dpp, &_wcontext._presentation_params, sizeof(D3DPRESENT_PARAMETERS));
1130 _wcontext._presentation_params.BackBufferWidth = new_xsize;
1131 _wcontext._presentation_params.BackBufferHeight = new_ysize;
1132 make_current();
1133 HRESULT hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen);
1134
1135 if (FAILED(hr)) {
1136 retval = false;
1137 wdxdisplay9_cat.error()
1138 << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr);
1139 if (hr == D3DERR_OUTOFVIDEOMEMORY) {
1140 memcpy(&_wcontext._presentation_params, &d3dpp, sizeof(D3DPRESENT_PARAMETERS));
1141 hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen);
1142 if (FAILED(hr)) {
1143 wdxdisplay9_cat.error()
1144 << "reset_device_resize_window Reset() failed OutOfVidmem, then failed again doing Reset w/original params:" << D3DERRORSTRING(hr);
1145 throw_event("panda3d-render-error");
1146 return false;
1147
1148 } else {
1149 if (wdxdisplay9_cat.is_info()) {
1150 wdxdisplay9_cat.info()
1151 << "reset of original size (" << _wcontext._presentation_params.BackBufferWidth
1152 << ", " << _wcontext._presentation_params.BackBufferHeight << ") succeeded\n";
1153 }
1154 }
1155 } else {
1156 wdxdisplay9_cat.fatal()
1157 << "Can't reset device, bailing out.\n";
1158 throw_event("panda3d-render-error");
1159 return false;
1160 }
1161 }
1162 // before you init_resized_window you need to copy certain changes to
1163 // _wcontext
1164 if (screen) {
1165 _wcontext._swap_chain = screen->_swap_chain;
1166 }
1167 wdxdisplay9_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n";
1168 _gsg->mark_new();
1169 init_resized_window();
1170 return retval;
1171}
1172
1173/**
1174 * Reinitializes the window after it has been resized, or after it is first
1175 * created.
1176 *
1177 * Assumes CreateDevice or Device->Reset() has just been called, and the new
1178 * size is specified in _wcontext._presentation_params.
1179 */
1180void wdxGraphicsWindow9::
1181init_resized_window() {
1182 HRESULT hr;
1183
1184 DWORD newWidth = _wcontext._presentation_params.BackBufferWidth;
1185 DWORD newHeight = _wcontext._presentation_params.BackBufferHeight;
1186
1187 nassertv((newWidth != 0) && (newHeight != 0));
1188 nassertv(_wcontext._window != nullptr);
1189
1190 if (_wcontext._presentation_params.Windowed) {
1191 POINT ul, lr;
1192 RECT client_rect;
1193
1194 // need to figure out x, y origin offset of window client area on screen
1195 // (we already know the client area size)
1196
1197 GetClientRect(_wcontext._window, &client_rect);
1198 ul.x = client_rect.left;
1199 ul.y = client_rect.top;
1200 lr.x = client_rect.right;
1201 lr.y = client_rect.bottom;
1202 ClientToScreen(_wcontext._window, &ul);
1203 ClientToScreen(_wcontext._window, &lr);
1204 client_rect.left = ul.x;
1205 client_rect.top = ul.y;
1206 client_rect.right = lr.x;
1207 client_rect.bottom = lr.y;
1208 }
1209
1210 // clear window to black ASAP
1211 nassertv(_wcontext._window != nullptr);
1212 ClearToBlack(_wcontext._window, get_properties());
1213
1214 // clear textures and VB's out of video&AGP mem, so cache is reset
1215 hr = _wcontext._d3d_device->EvictManagedResources ( );
1216 if (FAILED(hr)) {
1217 wdxdisplay9_cat.error()
1218 << "EvictManagedResources failed for device #"
1219 << _wcontext._card_id << D3DERRORSTRING(hr);
1220 }
1221
1222 make_current();
1223
1224 // set render target before clearing
1225 _dxgsg->set_render_target ( );
1226
1227 // clear back buffers
1228 DWORD flags;
1229 D3DCOLOR clear_color;
1230
1231 flags = D3DCLEAR_TARGET;
1232 if (_fb_properties.get_depth_bits() > 0) {
1233 flags |= D3DCLEAR_ZBUFFER;
1234 }
1235 clear_color = 0x00000000;
1236 hr = _wcontext._d3d_device-> Clear (0, nullptr, flags, clear_color, 0.0f, 0);
1237 if (FAILED(hr)) {
1238 wdxdisplay9_cat.error()
1239 << "Clear failed for device"
1240 << D3DERRORSTRING(hr);
1241 }
1242 hr = _wcontext._d3d_device-> Present (nullptr, nullptr, nullptr, nullptr);
1243 if (FAILED(hr)) {
1244 wdxdisplay9_cat.error()
1245 << "Present failed for device"
1246 << D3DERRORSTRING(hr);
1247 }
1248 hr = _wcontext._d3d_device-> Clear (0, nullptr, flags, clear_color, 0.0f, 0);
1249 if (FAILED(hr)) {
1250 wdxdisplay9_cat.error()
1251 << "Clear failed for device"
1252 << D3DERRORSTRING(hr);
1253 }
1254}
1255
1256/**
1257 * Returns the number of depth bits represented by the indicated D3DFORMAT
1258 * value.
1259 */
1260int wdxGraphicsWindow9::
1261D3DFMT_to_DepthBits(D3DFORMAT fmt) {
1262 switch(fmt) {
1263 case D3DFMT_D16:
1264 return 16;
1265
1266 case D3DFMT_D24X8:
1267 case D3DFMT_D24X4S4:
1268 case D3DFMT_D24S8:
1269 return 24;
1270
1271 case D3DFMT_D32:
1272 return 32;
1273
1274 case D3DFMT_D15S1:
1275 return 15;
1276
1277 default:
1278 wdxdisplay9_cat.debug()
1279 << "D3DFMT_DepthBits: unhandled D3DFMT!\n";
1280 return 0;
1281 }
1282}
1283
1284/**
1285 * Returns true if the indicated video adapter card is known to report an
1286 * inaccurate figure for available video memory.
1287 */
1288bool wdxGraphicsWindow9::
1289is_badvidmem_card(D3DADAPTER_IDENTIFIER9 *pDevID) {
1290 // don't trust Intel cards since they often use regular memory as vidmem
1291 if (pDevID->VendorId == 0x00008086) {
1292 return true;
1293 }
1294
1295 return false;
1296}
This is a convenience class to specialize ConfigVariable as a boolean type.
get_value
Returns the variable's value.
size_t size() const
Returns the number of unique words in the variable.
get_value
Returns the variable's value.
A GraphicsDevice necessary for multi-window rendering in DX.
A GraphicsStateGuardian for rendering into DirectX9 contexts.
static void set_cg_device(LPDIRECT3DDEVICE9 cg_device)
Sets the global Cg device pointer.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
An object to create GraphicsOutputs that share a particular 3-D API.
Encapsulates all the communication with a particular instance of a given rendering backend.
get_pipe
Returns the graphics pipe on which this GSG was created.
bool reset_if_new()
Calls reset() to initialize the GSG, but only if it hasn't been called yet.
get_unexposed_draw
See set_unexposed_draw().
get_properties
Returns the current properties of the window.
bool is_fullscreen() const
Returns true if the window has been opened as a fullscreen window, false otherwise.
virtual bool is_active() const
Returns true if the window is ready to be rendered into, false otherwise.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition pStatTimer.h:30
A thread; that is, a lightweight process.
Definition thread.h:46
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
An abstract base class for glGraphicsWindow and dxGraphicsWindow (and, in general,...
A container for the various kinds of properties we might ask to have on a graphics window before we o...
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
int get_y_origin() const
Returns the y coordinate of the window's top-left corner, not including decorations.
set_size
Specifies the requested size of the window, in pixels.
int get_x_origin() const
Returns the x coordinate of the window's top-left corner, not including decorations.
This graphics pipe represents the interface for creating DirectX9 graphics windows.
bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size, UINT y_size)
overrides of the general estimator for known working cases
void search_for_valid_displaymode(DXScreenData &scrn, UINT RequestedX_Size, UINT RequestedY_Size, bool bWantZBuffer, bool bWantStencil, UINT *p_supported_screen_depths_mask, bool *pCouldntFindAnyValidZBuf, D3DFORMAT *pSuggestedPixFmt, bool bForce16bppZBuffer, bool bVerboseMode=false)
All ptr args are output parameters.
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame.
virtual int verify_window_sizes(int numsizes, int *dimen)
Determines which of the indicated window sizes are supported by available hardware (e....
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.