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 _dxgsg = nullptr;
247 WinGraphicsWindow::close_window();
248}
249
250/**
251 * Opens the window right now. Called from the window thread. Returns true
252 * if the window is successfully opened, or false if there was a problem.
253 */
254bool wdxGraphicsWindow9::
255open_window() {
256 PT(DXGraphicsDevice9) dxdev;
257 WindowProperties props;
258
259 // For now, let's make this configurable. If this is true, then you can't
260 // open multiple different windows with the same GSG, but you may have more
261 // luck opening different windows with different GSG's.
262 static ConfigVariableBool always_discard_device("always-discard-device", true);
263 bool discard_device = always_discard_device;
264
265 if (_gsg == 0) {
266 _dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
267 _gsg = _dxgsg;
268 } else {
269 DCAST_INTO_R(_dxgsg, _gsg, false);
270 }
271
272 if (!choose_device()) {
273 return false;
274 }
275
276 // Ensure the window properties get set to the actual size of the window.
277 {
278 WindowProperties resized_props;
279 resized_props.set_size(_wcontext._display_mode.Width,
280 _wcontext._display_mode.Height);
281 _properties.add_properties(resized_props);
282 }
283
284 wdxdisplay9_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n";
285 if (!WinGraphicsWindow::open_window()) {
286 return false;
287 }
288 _wcontext._window = _hWnd;
289
290 wdxdisplay9_cat.debug() << "_wcontext._window is " << _wcontext._window << "\n";
291
292 // Here check if a device already exists. If so, then this open_window call
293 // may be an extension to create multiple windows on same device In that
294 // case just create an additional swapchain for this window
295
296 while (true) {
297 if (_dxgsg->get_pipe()->get_device() == nullptr || discard_device) {
298 wdxdisplay9_cat.debug() << "device is null or fullscreen\n";
299
300 // If device exists, free it
301 if (_dxgsg->get_pipe()->get_device()) {
302 _dxgsg->dx_cleanup();
303 }
304
305 wdxdisplay9_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n";
306 if (!create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer)) {
307 wdxdisplay9_cat.error() << "Unable to create window with specified parameters.\n";
308 close_window();
309 return false;
310 }
311 _dxgsg->get_pipe()->make_device((void*)(&_wcontext));
312 _dxgsg->copy_pres_reset(&_wcontext);
313 _dxgsg->create_swap_chain(&_wcontext);
314 break;
315
316 } else {
317 // fill in the DXScreenData from dxdevice here and change the reference
318 // to _window.
319 wdxdisplay9_cat.debug() << "device is not null\n";
320
321 dxdev = (DXGraphicsDevice9*)_dxgsg->get_pipe()->get_device();
322 memcpy(&_wcontext, &dxdev->_Scrn, sizeof(DXScreenData));
323
324 _wcontext._presentation_params.Windowed = !is_fullscreen();
325 _wcontext._presentation_params.hDeviceWindow = _wcontext._window = _hWnd;
326 _wcontext._presentation_params.BackBufferWidth = _wcontext._display_mode.Width = _properties.get_x_size();
327 _wcontext._presentation_params.BackBufferHeight = _wcontext._display_mode.Height = _properties.get_y_size();
328
329 wdxdisplay9_cat.debug() << "device width " << _wcontext._presentation_params.BackBufferWidth << "\n";
330 if (!_dxgsg->create_swap_chain(&_wcontext)) {
331 discard_device = true;
332 continue; // try again
333 }
334 init_resized_window();
335 break;
336 }
337 }
338 wdxdisplay9_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n";
339 return true;
340}
341
342/**
343 * Resets the window framebuffer right now. Called from graphicsEngine. It
344 * releases the current swap chain / creates a new one. If this is the
345 * initial window and swapchain is false, then it calls reset_ main_device to
346 * Reset the device.
347 */
348void wdxGraphicsWindow9::
349reset_window(bool swapchain) {
350 if (swapchain) {
351 if (_wcontext._swap_chain) {
352 _dxgsg->create_swap_chain(&_wcontext);
353 wdxdisplay9_cat.debug() << "created swapchain " << _wcontext._swap_chain << "\n";
354 }
355 }
356 else {
357 if (_wcontext._swap_chain) {
358 _dxgsg->release_swap_chain(&_wcontext);
359 wdxdisplay9_cat.debug() << "released swapchain " << _wcontext._swap_chain << "\n";
360 }
361 }
362}
363
364/**
365 * This is a hook for derived classes to do something special, if necessary,
366 * when a fullscreen window has been restored after being minimized. The
367 * given WindowProperties struct will be applied to this window's properties
368 * after this function returns.
369 */
370void wdxGraphicsWindow9::
371fullscreen_restored(WindowProperties &properties) {
372 // In DX8, unlike DX7, for some reason we can't immediately start rendering
373 // as soon as the window is restored, even though BeginScene() says we can.
374 // Instead, we have to wait until TestCooperativeLevel() lets us in. We
375 // need to set a flag so we can handle this special case in begin_frame().
376 if (_dxgsg != nullptr) {
377 _awaiting_restore = true;
378 }
379}
380
381/**
382 * Called in the window thread when the window size or location is changed,
383 * this updates the properties structure accordingly.
384 */
385void wdxGraphicsWindow9::
386handle_reshape() {
387 GdiFlush();
388 WinGraphicsWindow::handle_reshape();
389
390 if (_dxgsg != nullptr && _dxgsg->_d3d_device != nullptr) {
391 // create the new resized rendertargets
393 int x_size = props.get_x_size();
394 int y_size = props.get_y_size();
395
396 if (_wcontext._presentation_params.BackBufferWidth != x_size ||
397 _wcontext._presentation_params.BackBufferHeight != y_size) {
398 bool resize_succeeded = reset_device_resize_window(x_size, y_size);
399
400 if (wdxdisplay9_cat.is_debug()) {
401 if (!resize_succeeded) {
402 wdxdisplay9_cat.debug()
403 << "windowed_resize to size: (" << x_size << ", " << y_size
404 << ") failed due to out-of-memory\n";
405 } else {
406 int x_origin = props.get_x_origin();
407 int y_origin = props.get_y_origin();
408 wdxdisplay9_cat.debug()
409 << "windowed_resize to origin: (" << x_origin << ", "
410 << y_origin << "), size: (" << x_size
411 << ", " << y_size << ")\n";
412 }
413 }
414 }
415 }
416}
417
418/**
419 * Called in the window thread to resize a fullscreen window.
420 */
421bool wdxGraphicsWindow9::
422do_fullscreen_resize(int x_size, int y_size) {
423 if (!WinGraphicsWindow::do_fullscreen_resize(x_size, y_size)) {
424 return false;
425 }
426
427 bool bCouldntFindValidZBuf;
428 D3DFORMAT pixFmt;
429 bool bNeedZBuffer = (_wcontext._presentation_params.EnableAutoDepthStencil != false);
430 bool bNeedStencilBuffer = IS_STENCIL_FORMAT(_wcontext._presentation_params.AutoDepthStencilFormat);
431
432 wdxGraphicsPipe9 *dxpipe;
433 DCAST_INTO_R(dxpipe, _pipe, false);
434
435 bool bIsGoodMode = false;
436 bool bResizeSucceeded = false;
437
438 if (!dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) {
439 // bypass the lowvidmem test below for certain "lowmem" cards we know have
440 // valid modes
441
442 if (_wcontext._is_low_memory_card && (!((x_size == 640) && (y_size == 480)))) {
443 wdxdisplay9_cat.error() << "resize() failed: will not try to resize low vidmem device #" << _wcontext._card_id << " to non-640x480!\n";
444 return bResizeSucceeded;
445 }
446 }
447
448 // must ALWAYS use search_for_valid_displaymode even if we know a-priori
449 // that res is valid so we can get a valid pixfmt
450 dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size,
451 bNeedZBuffer, bNeedStencilBuffer,
452 &_wcontext._supported_screen_depths_mask,
453 &bCouldntFindValidZBuf,
454 &pixFmt, dx_force_16bpp_zbuffer, true);
455 bIsGoodMode = (pixFmt != D3DFMT_UNKNOWN);
456
457 if (!bIsGoodMode) {
458 wdxdisplay9_cat.error() << "resize() failed: "
459 << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
460 << " at " << x_size << "x" << y_size << " for device #" << _wcontext._card_id << endl;
461 return bResizeSucceeded;
462 }
463
464 // reset_device_resize_window handles both windowed & fullscrn, so need to
465 // set new displaymode manually here
466 _wcontext._display_mode.Width = x_size;
467 _wcontext._display_mode.Height = y_size;
468 _wcontext._display_mode.Format = pixFmt;
469 _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
470 // keep the previous setting for
471 // _wcontext._presentation_params.BackBufferFormat
472
473 bResizeSucceeded = reset_device_resize_window(x_size, y_size);
474
475 if (!bResizeSucceeded) {
476 wdxdisplay9_cat.error() << "resize() failed with OUT-OF-MEMORY error!\n";
477
478 if ((!IS_16BPP_DISPLAY_FORMAT(_wcontext._presentation_params.BackBufferFormat)) &&
479 (_wcontext._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
480 // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers
481 _wcontext._display_mode.Format = ((_wcontext._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
482 dx_force_16bpp_zbuffer = true;
483 if (wdxdisplay9_cat.info())
484 wdxdisplay9_cat.info() << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #" << _wcontext._card_id << endl;
485
486 bResizeSucceeded = reset_device_resize_window(x_size, y_size); // create the new resized rendertargets
487 }
488 }
489
490 return bResizeSucceeded;
491}
492
493/**
494 * Called whenever the window is resized, this recreates the necessary buffers
495 * for rendering.
496 *
497 * Sets _depth_buffer_bpp appropriately.
498 */
499bool wdxGraphicsWindow9::
500create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer) {
501 wdxGraphicsPipe9 *dxpipe;
502 DCAST_INTO_R(dxpipe, _pipe, false);
503
504 DWORD dwRenderWidth = display._display_mode.Width;
505 DWORD dwRenderHeight = display._display_mode.Height;
506 DWORD dwBehaviorFlags = 0x0;
507 LPDIRECT3D9 _d3d9 = display._d3d9;
508 D3DCAPS9 *pD3DCaps = &display._d3dcaps;
509 D3DPRESENT_PARAMETERS* presentation_params = &display._presentation_params;
510 RECT view_rect;
511 UINT adapter;
512 D3DDEVTYPE device_type;
513 HRESULT hr;
514
515 adapter = display._card_id;
516 device_type = D3DDEVTYPE_HAL;
517
518 // NVIDIA NVPerfHUD
519 if (dx_use_nvperfhud) {
520 UINT adapter_id;
521 UINT total_adapters;
522
523 total_adapters = _d3d9 -> GetAdapterCount ( );
524 for (adapter_id = 0; adapter_id < total_adapters; adapter_id++) {
525 D3DADAPTER_IDENTIFIER9 identifier;
526
527 _d3d9 -> GetAdapterIdentifier (adapter_id, 0, &identifier);
528 if (strcmp ("NVIDIA NVPerfHUD", identifier.Description) == 0) {
529 adapter = adapter_id;
530 device_type = D3DDEVTYPE_REF;
531 break;
532 }
533 }
534 }
535
536 wdxdisplay9_cat.debug() << "Display Width " << dwRenderWidth << " and PresParam Width " << _wcontext._presentation_params.BackBufferWidth << "\n";
537
538 // BUGBUG: need to change panda to put frame buffer properties with
539 // GraphicsWindow, not GSG!! Update: Did I fix the bug? - Josh
540 bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
541 bool bWantAlpha = (_fb_properties.get_alpha_bits() > 0);
542
543 PRINT_REFCNT(wdxdisplay9, _d3d9);
544
545 nassertr(_d3d9 != nullptr, false);
546 nassertr(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION, false);
547
548 bool do_sync = sync_video;
549
550 if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
551 wdxdisplay9_cat.info()
552 << "HW doesnt support syncing to vertical refresh, ignoring sync-video\n";
553 do_sync = false;
554 }
555
556 presentation_params->BackBufferFormat = display._display_mode.Format;
557
558 // check for D3DFMT_A8R8G8B8 first
559 if (bWantAlpha) {
560 if (!FAILED(_d3d9->CheckDeviceFormat(adapter, device_type, display._display_mode.Format, D3DUSAGE_RENDERTARGET,
561 D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8))) {
562 if (!FAILED(_d3d9->CheckDeviceType(adapter, device_type, display._display_mode.Format, D3DFMT_A8R8G8B8,
563 is_fullscreen()))) {
564 // We can accept D3DFMT_A8R8G8B8, so use it.
565 presentation_params->BackBufferFormat = D3DFMT_A8R8G8B8;
566 }
567 }
568 }
569
570 // check for same format as display_mode verify the rendertarget fmt
571 if (FAILED(_d3d9->CheckDeviceFormat(adapter, device_type, display._display_mode.Format, D3DUSAGE_RENDERTARGET,
572 D3DRTYPE_SURFACE, presentation_params->BackBufferFormat))) {
573 wdxdisplay9_cat.error() << "adapter #" << adapter << " CheckDeviceFmt failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl;
574 goto Fallback_to_16bpp_buffers;
575 }
576
577 if (FAILED(_d3d9->CheckDeviceType(adapter, device_type, display._display_mode.Format, presentation_params->BackBufferFormat,
578 is_fullscreen()))) {
579 wdxdisplay9_cat.error() << "adapter #" << adapter << " CheckDeviceType failed for surface fmt " << D3DFormatStr(presentation_params->BackBufferFormat) << endl;
580 goto Fallback_to_16bpp_buffers;
581 }
582
583 if (display._presentation_params.EnableAutoDepthStencil) {
584 if (!dxpipe->find_best_depth_format(display, display._display_mode,
585 &display._presentation_params.AutoDepthStencilFormat,
586 bWantStencil, false)) {
587 wdxdisplay9_cat.error()
588 << "find_best_depth_format failed in CreateScreenBuffers for device #"
589 << adapter << endl;
590 goto Fallback_to_16bpp_buffers;
591 }
592 _depth_buffer_bpp = D3DFMT_to_DepthBits(display._presentation_params.AutoDepthStencilFormat);
593 } else {
594 _depth_buffer_bpp = 0;
595 }
596
597 presentation_params->Windowed = !is_fullscreen();
598
599 int supported_multisamples = 0;
600 if (framebuffer_multisample.get_value()){
601 supported_multisamples = multisamples.get_value();
602 }
603
604 while (supported_multisamples > 1){
605 // need to check both rendertarget and zbuffer fmts
606 hr = _d3d9->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, display._display_mode.Format,
607 is_fullscreen(), D3DMULTISAMPLE_TYPE(supported_multisamples), nullptr);
608 if (FAILED(hr)) {
609 supported_multisamples--;
610 continue;
611 }
612
613 if (display._presentation_params.EnableAutoDepthStencil) {
614 hr = _d3d9->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, display._presentation_params.AutoDepthStencilFormat,
615 is_fullscreen(), D3DMULTISAMPLE_TYPE(supported_multisamples), nullptr);
616 if (FAILED(hr)) {
617 supported_multisamples--;
618 continue;
619 }
620 }
621
622 presentation_params->MultiSampleType = D3DMULTISAMPLE_TYPE(supported_multisamples);
623
624 if (wdxdisplay9_cat.is_info())
625 wdxdisplay9_cat.info() << "adapter #" << adapter << " using multisample antialiasing level: " << supported_multisamples <<
626 ". Requested level was: " << multisamples.get_value() << endl;
627 break;
628 }
629
630 presentation_params->BackBufferCount = 1;
631 presentation_params->Flags = 0x0;
632 presentation_params->hDeviceWindow = display._window;
633 presentation_params->BackBufferWidth = display._display_mode.Width;
634 presentation_params->BackBufferHeight = display._display_mode.Height;
635
636 if (_wcontext._is_tnl_device) {
637 dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
638 // note: we could create a pure device in this case if I eliminated the
639 // GetRenderState calls in dxgsg
640
641 // also, no software vertex processing available since I specify
642 // D3DCREATE_HARDWARE_VERTEXPROCESSING and not
643 // D3DCREATE_MIXED_VERTEXPROCESSING
644 } else {
645 dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
646 }
647
648 if (dx_preserve_fpu_state)
649 dwBehaviorFlags |= D3DCREATE_FPU_PRESERVE;
650
651 // if window is not foreground in exclusive mode, ddraw thinks you are 'not
652 // active', so it changes your WM_ACTIVATEAPP from true to false, causing us
653 // to go into a 'wait-for WM_ACTIVATEAPP true' loop, and the event never
654 // comes so we hang in fullscreen wait. also doing this for windowed mode
655 // since it was requested.
656 if (!SetForegroundWindow(display._window)) {
657 wdxdisplay9_cat.warning() << "SetForegroundWindow() failed!\n";
658 }
659
660 if (dx_use_multithread) {
661 dwBehaviorFlags |= D3DCREATE_MULTITHREADED;
662 }
663 if (dx_use_puredevice) {
664 dwBehaviorFlags |= D3DCREATE_PUREDEVICE;
665 }
666
667 if (dx_disable_driver_management) {
668 dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT;
669 }
670 if (dx_disable_driver_management_ex) {
671 dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX;
672 }
673
674 if (is_fullscreen()) {
675 // CREATE FULLSCREEN BUFFERS
676
677 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; // we don't care about preserving contents of old frame
678 presentation_params->PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
679 presentation_params->FullScreen_RefreshRateInHz = display._display_mode.RefreshRate;
680
681 ClearToBlack(display._window, get_properties());
682
683 hr = _d3d9->CreateDevice(adapter, device_type, _hWnd,
684 dwBehaviorFlags, presentation_params, &display._d3d_device);
685
686 if (FAILED(hr)) {
687 wdxdisplay9_cat.fatal() << "D3D CreateDevice failed for adapter #" << adapter << ", " << D3DERRORSTRING(hr);
688
689 if (hr == D3DERR_OUTOFVIDEOMEMORY)
690 goto Fallback_to_16bpp_buffers;
691 else
692 return false;
693 }
694
695 SetRect(&view_rect, 0, 0, dwRenderWidth, dwRenderHeight);
696
697 } else {
698 // CREATE WINDOWED BUFFERS
699
700 D3DDISPLAYMODE dispmode;
701 hr = display._d3d9->GetAdapterDisplayMode(adapter, &dispmode);
702
703 if (FAILED(hr)) {
704 wdxdisplay9_cat.fatal()
705 << "GetAdapterDisplayMode failed" << D3DERRORSTRING(hr);
706 return false;
707 }
708
709 if (dispmode.Format == D3DFMT_P8) {
710 wdxdisplay9_cat.fatal()
711 << "Can't run windowed in an 8-bit or less display mode" << endl;
712 return false;
713 }
714
715 // From d3d8caps.h D3DPRESENT_INTERVAL_DEFAULT = 0x00000000L #define
716 // D3DPRESENT_INTERVAL_ONE 0x00000001L Next line is really sloppy,
717 // should either be D3DPRESENT_INTERVAL_DEFAULT or D3DPRESENT_INTERVAL_ONE
718 // not a direct number! but I'm not going to touch it because it's
719 // working as is. Zhao 12152011
720 presentation_params->PresentationInterval = 0;
721
722 // ATI 5450 doesn't like D3DSWAPEFFECT_FLIP
723 presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD;
724 if (do_sync == false) {
725 presentation_params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
726 }
727/*
728 * if (supported_multisamples<2) { if (do_sync) { It turns out that COPY_VSYNC
729 * has real performance problems on many nVidia cards--it syncs at some random
730 * interval, possibly skipping over several video syncs. Screw it, we'll
731 * effectively disable sync-video with windowed mode using DirectX8.
732 * presentation_params->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
733 * presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; } else {
734 * presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD; }
735 */
736
737/*
738 * override presentation parameters for windowed mode, render and display at
739 * maximum speed if (do_sync == false) { presentation_params->SwapEffect =
740 * D3DSWAPEFFECT_FLIP; presentation_params->PresentationInterval =
741 * D3DPRESENT_INTERVAL_IMMEDIATE; } } else { presentation_params->SwapEffect =
742 * D3DSWAPEFFECT_DISCARD; }
743 */
744
745 // assert((dwRenderWidth ==
746 // presentation_params->BackBufferWidth)&&(dwRenderHeight ==
747 // presentation_params->BackBufferHeight));
748
749 hr = _d3d9->CreateDevice(adapter, device_type, _hWnd,
750 dwBehaviorFlags, presentation_params, &display._d3d_device);
751
752 if (FAILED(hr)) {
753 wdxdisplay9_cat.warning() << "presentation_params->BackBufferWidth : " << presentation_params->BackBufferWidth << endl;
754 wdxdisplay9_cat.warning() << "presentation_params->BackBufferHeight : " << presentation_params->BackBufferHeight << endl;
755 wdxdisplay9_cat.warning() << "presentation_params->BackBufferFormat : " << presentation_params->BackBufferFormat << endl;
756 wdxdisplay9_cat.warning() << "presentation_params->BackBufferCount : " << presentation_params->BackBufferCount << endl;
757 wdxdisplay9_cat.warning() << "D3D CreateDevice failed for adapter #" << adapter << D3DERRORSTRING(hr);
758 goto Fallback_to_16bpp_buffers;
759 }
760 } // end create windowed buffers
761
762 // ========================================================
763
764 PRINT_REFCNT(wdxdisplay9, _wcontext._d3d_device);
765
766 if (presentation_params->EnableAutoDepthStencil) {
767 int depth_bits;
768 int stencil_bits;
769
770 depth_bits = 1;
771 stencil_bits = 0;
772 switch (presentation_params->AutoDepthStencilFormat)
773 {
774 case D3DFMT_D16_LOCKABLE:
775 depth_bits = 16;
776 break;
777 case D3DFMT_D32:
778 depth_bits = 32;
779 break;
780 case D3DFMT_D15S1:
781 depth_bits = 15;
782 stencil_bits = 1;
783 break;
784 case D3DFMT_D24S8:
785 depth_bits = 24;
786 stencil_bits = 8;
787 break;
788 case D3DFMT_D24X8:
789 depth_bits = 24;
790 break;
791 case D3DFMT_D24X4S4:
792 depth_bits = 24;
793 stencil_bits = 4;
794 break;
795 case D3DFMT_D32F_LOCKABLE:
796 depth_bits = 32;
797 break;
798 case D3DFMT_D24FS8:
799 depth_bits = 24;
800 stencil_bits = 8;
801 break;
802 case D3DFMT_D16:
803 depth_bits = 16;
804 break;
805 default:
806 wdxdisplay9_cat.error() << "unknown depth stencil format " << presentation_params->AutoDepthStencilFormat;
807 break;
808 }
809
810 _fb_properties.set_stencil_bits(stencil_bits);
811 _fb_properties.set_depth_bits(depth_bits);
812 } else {
813 _fb_properties.set_depth_bits(0);
814 _fb_properties.set_stencil_bits(0);
815 }
816
817 init_resized_window();
818
819 return true;
820
821 Fallback_to_16bpp_buffers:
822 if ((!IS_16BPP_DISPLAY_FORMAT(presentation_params->BackBufferFormat)) &&
823 (display._supported_screen_depths_mask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
824 // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers
825
826 display._display_mode.Format = ((display._supported_screen_depths_mask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
827
828 if (wdxdisplay9_cat.info()) {
829 wdxdisplay9_cat.info()
830 << "CreateDevice failed with out-of-vidmem or invalid BackBufferFormat, retrying w/16bpp buffers on adapter #"
831 << adapter << endl;
832 }
833 return create_screen_buffers_and_device(display, true);
834 // return;
835
836 } else if (!((dwRenderWidth == 640)&&(dwRenderHeight == 480))) {
837 if (wdxdisplay9_cat.info())
838 wdxdisplay9_cat.info() << "CreateDevice failed w/out-of-vidmem, retrying at 640x480 w/16bpp buffers on adapter #" << adapter << endl;
839 // try final fallback to 640x480x16
840 display._display_mode.Width = 640;
841 display._display_mode.Height = 480;
842 return create_screen_buffers_and_device(display, true);
843 // return;
844
845 } else {
846 wdxdisplay9_cat.fatal()
847 << "Can't create any screen buffers, bailing out.\n";
848 return false;
849 }
850}
851
852/**
853 * Looks at the list of available graphics adapters and chooses a suitable one
854 * for the window.
855 *
856 * Returns true if successful, false on failure.
857 */
858bool wdxGraphicsWindow9::
859choose_device() {
860 HRESULT hr;
861
862 wdxGraphicsPipe9 *dxpipe;
863 DCAST_INTO_R(dxpipe, _pipe, false);
864
865 int num_adapters = dxpipe->__d3d9->GetAdapterCount();
866 DXDeviceInfoVec device_infos;
867
868 for (int i = 0; i < num_adapters; i++) {
869 D3DADAPTER_IDENTIFIER9 adapter_info;
870 ZeroMemory(&adapter_info, sizeof(D3DADAPTER_IDENTIFIER9));
871 hr = dxpipe->__d3d9->GetAdapterIdentifier(i, 0, &adapter_info);
872 if (FAILED(hr)) {
873 wdxdisplay9_cat.fatal()
874 << "D3D GetAdapterID(" << i << ") failed: "
875 << D3DERRORSTRING(hr) << endl;
876 continue;
877 }
878
879 LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion;
880
881 wdxdisplay9_cat.info()
882 << "D3D9 Adapter[" << i << "]: " << adapter_info.Description
883 << ", Driver: " << adapter_info.Driver << ", DriverVersion: ("
884 << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "."
885 << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart)
886 << ")\nVendorID: 0x" << std::hex << adapter_info.VendorId
887 << " DeviceID: 0x" << adapter_info.DeviceId
888 << " SubsysID: 0x" << adapter_info.SubSysId
889 << " Revision: 0x" << adapter_info.Revision << std::dec << endl;
890
891 HMONITOR _monitor = dxpipe->__d3d9->GetAdapterMonitor(i);
892 if (_monitor == nullptr) {
893 wdxdisplay9_cat.info()
894 << "D3D9 Adapter[" << i << "]: seems to be disabled, skipping it\n";
895 continue;
896 }
897
898 DXDeviceInfo devinfo;
899 ZeroMemory(&devinfo, sizeof(devinfo));
900 memcpy(&devinfo.guidDeviceIdentifier, &adapter_info.DeviceIdentifier,
901 sizeof(GUID));
902 strncpy(devinfo.szDescription, adapter_info.Description,
903 MAX_DEVICE_IDENTIFIER_STRING);
904 strncpy(devinfo.szDriver, adapter_info.Driver,
905 MAX_DEVICE_IDENTIFIER_STRING);
906 devinfo.VendorID = adapter_info.VendorId;
907 devinfo.DeviceID = adapter_info.DeviceId;
908 devinfo._driver_version = adapter_info.DriverVersion;
909 devinfo._monitor = _monitor;
910 devinfo.cardID = i;
911
912 device_infos.push_back(devinfo);
913 }
914
915 if (device_infos.empty()) {
916 wdxdisplay9_cat.error()
917 << "No available D3D9 devices found.\n";
918 return false;
919 }
920
921 // Since some adapters may have been disabled, we should re-obtain the
922 // number of available adapters.
923 num_adapters = (int)device_infos.size();
924
925 // Now choose a suitable adapter.
926
927 int adapter_num = D3DADAPTER_DEFAULT;
928
929 // Eventually, we should have some interface for specifying a device index
930 // interactively, instead of only via Configrc.
931 if (dx_preferred_device_id != -1) {
932 if (dx_preferred_device_id < 0 || dx_preferred_device_id >= num_adapters) {
933 wdxdisplay9_cat.error()
934 << "invalid 'dx-preferred-device-id', valid values are 0-"
935 << num_adapters - 1 << ", using default adapter instead.\n";
936 } else {
937 adapter_num = dx_preferred_device_id;
938 }
939 }
940
941 // Try to select the default or requested device.
942 if (adapter_num >= 0 && adapter_num < (int)device_infos.size()) {
943 if (consider_device(dxpipe, &device_infos[adapter_num])) {
944 wdxdisplay9_cat.info()
945 << "Selected device " << adapter_num << " (of "
946 << device_infos.size() << ", zero-based)\n";
947 return true;
948 }
949 wdxdisplay9_cat.info()
950 << "Could not select device " << adapter_num << "\n";
951 }
952
953 // Iterate through all available devices to find the first suitable one.
954 for (UINT devnum = 0; devnum < device_infos.size(); ++devnum) {
955 if (consider_device(dxpipe, &device_infos[devnum])) {
956 wdxdisplay9_cat.info()
957 << "Chose device " << devnum << " (of "
958 << device_infos.size() << ", zero-based): first one that works.\n";
959 return true;
960 }
961 }
962
963 wdxdisplay9_cat.error() << "no usable display devices.\n";
964 return false;
965}
966
967/**
968 * If the specified device is acceptable, sets it as the current device and
969 * returns true; otherwise, returns false.
970 */
971bool wdxGraphicsWindow9::
972consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
973
974 nassertr(dxpipe != nullptr, false);
975 WindowProperties properties = get_properties();
976 DWORD dwRenderWidth = properties.get_x_size();
977 DWORD dwRenderHeight = properties.get_y_size();
978 HRESULT hr;
979 LPDIRECT3D9 _d3d9 = dxpipe->__d3d9;
980
981 nassertr(_dxgsg != nullptr, false);
982 _wcontext._d3d9 = _d3d9;
983 _wcontext._card_id = device_info->cardID; // could this change by end?
984
985 bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
986
987 hr = _d3d9->GetAdapterIdentifier(device_info->cardID, 0,
988 &_wcontext._dx_device_id);
989 if (FAILED(hr)) {
990 wdxdisplay9_cat.error()
991 << "D3D GetAdapterID failed" << D3DERRORSTRING(hr);
992 return false;
993 }
994
995 D3DCAPS9 _d3dcaps;
996 hr = _d3d9->GetDeviceCaps(device_info->cardID, D3DDEVTYPE_HAL, &_d3dcaps);
997 if (FAILED(hr)) {
998 if ((hr == D3DERR_INVALIDDEVICE)||(hr == D3DERR_NOTAVAILABLE)) {
999 wdxdisplay9_cat.error()
1000 << "No DirectX 9 D3D-capable 3D hardware detected for device # "
1001 << device_info->cardID << " (" << device_info->szDescription
1002 << ")!\n";
1003 } else {
1004 wdxdisplay9_cat.error()
1005 << "GetDeviceCaps failed: " << D3DERRORSTRING(hr) << endl;
1006 }
1007 return false;
1008 }
1009
1010 // search_for_valid_displaymode needs these to be set
1011 memcpy(&_wcontext._d3dcaps, &_d3dcaps, sizeof(D3DCAPS9));
1012 _wcontext._card_id = device_info->cardID;
1013
1014 _wcontext._max_available_video_memory = UNKNOWN_VIDMEM_SIZE;
1015 _wcontext._is_low_memory_card = false;
1016
1017 // bugbug: wouldnt we like to do GetAVailVidMem so we can do upper-limit
1018 // memory computation for dx8 cards too? otherwise verify_window_sizes cant
1019 // do much
1020 if (_d3dcaps.MaxStreams == 0) {
1021 if (wdxdisplay9_cat.is_debug()) {
1022 wdxdisplay9_cat.debug()
1023 << "checking vidmem size\n";
1024 }
1025
1026 UINT IDnum;
1027
1028 // simple linear search to match DX7 card info wDX8 card ID
1029 for (IDnum = 0; IDnum < dxpipe->_card_ids.size(); IDnum++) {
1030 if ((device_info->VendorID == dxpipe->_card_ids[IDnum].VendorID) &&
1031 (device_info->DeviceID == dxpipe->_card_ids[IDnum].DeviceID) &&
1032 (device_info->_monitor == dxpipe->_card_ids[IDnum]._monitor))
1033 break;
1034 }
1035
1036 if (IDnum < dxpipe->_card_ids.size()) {
1037 _wcontext._max_available_video_memory = dxpipe->_card_ids[IDnum]._max_available_video_memory;
1038 _wcontext._is_low_memory_card = dxpipe->_card_ids[IDnum]._is_low_memory_card;
1039 } else {
1040 wdxdisplay9_cat.error()
1041 << "Error: couldnt find a CardID match in DX7 info, assuming card is not a lowmem card\n";
1042 }
1043 }
1044
1045 if ((bWantStencil) && (_d3dcaps.StencilCaps == 0x0)) {
1046 wdxdisplay9_cat.fatal()
1047 << "Stencil ability requested, but device #" << device_info->cardID
1048 << " (" << _wcontext._dx_device_id.Description
1049 << "), has no stencil capability!\n";
1050 return false;
1051 }
1052
1053 // just because TNL is true, it doesnt mean vtx shaders are supported in HW
1054 // (see GF2) for this case, you probably want MIXED processing to use HW for
1055 // fixed-fn vertex processing and SW for vtx shaders
1056 _wcontext._is_tnl_device =
1057 ((_d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0);
1058 _wcontext._can_use_hw_vertex_shaders =
1059 (_d3dcaps.VertexShaderVersion >= D3DVS_VERSION(1, 0));
1060 _wcontext._can_use_pixel_shaders =
1061 (_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(1, 0));
1062
1063 bool bNeedZBuffer =
1064 ((!(_d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
1065 (_fb_properties.get_depth_bits() > 0));
1066
1067 _wcontext._presentation_params.EnableAutoDepthStencil = bNeedZBuffer;
1068
1069 D3DFORMAT pixFmt = D3DFMT_UNKNOWN;
1070
1071 if (is_fullscreen()) {
1072 bool bCouldntFindValidZBuf;
1073
1074 dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight,
1075 bNeedZBuffer, bWantStencil,
1076 &_wcontext._supported_screen_depths_mask,
1077 &bCouldntFindValidZBuf,
1078 &pixFmt, dx_force_16bpp_zbuffer, true);
1079
1080 // note I'm not saving refresh rate, will just use adapter default at
1081 // given res for now
1082
1083 if (pixFmt == D3DFMT_UNKNOWN) {
1084 wdxdisplay9_cat.error()
1085 << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
1086 << " at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << _wcontext._card_id << endl;
1087 return false;
1088 }
1089 } else {
1090 // Windowed Mode
1091
1092 D3DDISPLAYMODE dispmode;
1093 hr = _d3d9->GetAdapterDisplayMode(device_info->cardID, &dispmode);
1094 if (FAILED(hr)) {
1095 wdxdisplay9_cat.error()
1096 << "GetAdapterDisplayMode(" << device_info->cardID
1097 << ") failed" << D3DERRORSTRING(hr);
1098 return false;
1099 }
1100 pixFmt = dispmode.Format;
1101 }
1102
1103 _wcontext._display_mode.Width = dwRenderWidth;
1104 _wcontext._display_mode.Height = dwRenderHeight;
1105 _wcontext._display_mode.Format = pixFmt;
1106 _wcontext._display_mode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
1107 _wcontext._monitor = device_info->_monitor;
1108
1109 if (strcmp(device_info->szDriver, "igdumd32.dll") == 0 &&
1110 device_info->_driver_version.QuadPart <= 0x0007000e000affffLL &&
1111 dx_intel_compressed_texture_bug) {
1112 // Disable compressed textures for this buggy driver (7.14.10.65535 and
1113 // earlier--I don't know whether any other drivers also exhibit the bug).
1114 _wcontext._intel_compressed_texture_bug = true;
1115 }
1116
1117 return true;
1118}
1119
1120/**
1121 * Called after a window (either fullscreen or windowed) has been resized,
1122 * this recreates the D3D structures to match the new size.
1123 */
1124bool wdxGraphicsWindow9::
1125reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
1126 bool retval = true;
1127
1128 DXScreenData *screen = nullptr;
1129 D3DPRESENT_PARAMETERS d3dpp;
1130 memcpy(&d3dpp, &_wcontext._presentation_params, sizeof(D3DPRESENT_PARAMETERS));
1131 _wcontext._presentation_params.BackBufferWidth = new_xsize;
1132 _wcontext._presentation_params.BackBufferHeight = new_ysize;
1133 make_current();
1134 HRESULT hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen);
1135
1136 if (FAILED(hr)) {
1137 retval = false;
1138 wdxdisplay9_cat.error()
1139 << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr);
1140 if (hr == D3DERR_OUTOFVIDEOMEMORY) {
1141 memcpy(&_wcontext._presentation_params, &d3dpp, sizeof(D3DPRESENT_PARAMETERS));
1142 hr = _dxgsg->reset_d3d_device(&_wcontext._presentation_params, &screen);
1143 if (FAILED(hr)) {
1144 wdxdisplay9_cat.error()
1145 << "reset_device_resize_window Reset() failed OutOfVidmem, then failed again doing Reset w/original params:" << D3DERRORSTRING(hr);
1146 throw_event("panda3d-render-error");
1147 return false;
1148
1149 } else {
1150 if (wdxdisplay9_cat.is_info()) {
1151 wdxdisplay9_cat.info()
1152 << "reset of original size (" << _wcontext._presentation_params.BackBufferWidth
1153 << ", " << _wcontext._presentation_params.BackBufferHeight << ") succeeded\n";
1154 }
1155 }
1156 } else {
1157 wdxdisplay9_cat.fatal()
1158 << "Can't reset device, bailing out.\n";
1159 throw_event("panda3d-render-error");
1160 return false;
1161 }
1162 }
1163 // before you init_resized_window you need to copy certain changes to
1164 // _wcontext
1165 if (screen) {
1166 _wcontext._swap_chain = screen->_swap_chain;
1167 }
1168 wdxdisplay9_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n";
1169 _dxgsg->mark_new();
1170 init_resized_window();
1171 return retval;
1172}
1173
1174/**
1175 * Reinitializes the window after it has been resized, or after it is first
1176 * created.
1177 *
1178 * Assumes CreateDevice or Device->Reset() has just been called, and the new
1179 * size is specified in _wcontext._presentation_params.
1180 */
1181void wdxGraphicsWindow9::
1182init_resized_window() {
1183 HRESULT hr;
1184
1185 DWORD newWidth = _wcontext._presentation_params.BackBufferWidth;
1186 DWORD newHeight = _wcontext._presentation_params.BackBufferHeight;
1187
1188 nassertv((newWidth != 0) && (newHeight != 0));
1189 nassertv(_wcontext._window != nullptr);
1190
1191 if (_wcontext._presentation_params.Windowed) {
1192 POINT ul, lr;
1193 RECT client_rect;
1194
1195 // need to figure out x, y origin offset of window client area on screen
1196 // (we already know the client area size)
1197
1198 GetClientRect(_wcontext._window, &client_rect);
1199 ul.x = client_rect.left;
1200 ul.y = client_rect.top;
1201 lr.x = client_rect.right;
1202 lr.y = client_rect.bottom;
1203 ClientToScreen(_wcontext._window, &ul);
1204 ClientToScreen(_wcontext._window, &lr);
1205 client_rect.left = ul.x;
1206 client_rect.top = ul.y;
1207 client_rect.right = lr.x;
1208 client_rect.bottom = lr.y;
1209 }
1210
1211 // clear window to black ASAP
1212 nassertv(_wcontext._window != nullptr);
1213 ClearToBlack(_wcontext._window, get_properties());
1214
1215 // clear textures and VB's out of video&AGP mem, so cache is reset
1216 hr = _wcontext._d3d_device->EvictManagedResources ( );
1217 if (FAILED(hr)) {
1218 wdxdisplay9_cat.error()
1219 << "EvictManagedResources failed for device #"
1220 << _wcontext._card_id << D3DERRORSTRING(hr);
1221 }
1222
1223 make_current();
1224
1225 // set render target before clearing
1226 _dxgsg->set_render_target ( );
1227
1228 // clear back buffers
1229 DWORD flags;
1230 D3DCOLOR clear_color;
1231
1232 flags = D3DCLEAR_TARGET;
1233 if (_fb_properties.get_depth_bits() > 0) {
1234 flags |= D3DCLEAR_ZBUFFER;
1235 }
1236 clear_color = 0x00000000;
1237 hr = _wcontext._d3d_device-> Clear (0, nullptr, flags, clear_color, 0.0f, 0);
1238 if (FAILED(hr)) {
1239 wdxdisplay9_cat.error()
1240 << "Clear failed for device"
1241 << D3DERRORSTRING(hr);
1242 }
1243 hr = _wcontext._d3d_device-> Present (nullptr, nullptr, nullptr, nullptr);
1244 if (FAILED(hr)) {
1245 wdxdisplay9_cat.error()
1246 << "Present failed for device"
1247 << D3DERRORSTRING(hr);
1248 }
1249 hr = _wcontext._d3d_device-> Clear (0, nullptr, flags, clear_color, 0.0f, 0);
1250 if (FAILED(hr)) {
1251 wdxdisplay9_cat.error()
1252 << "Clear failed for device"
1253 << D3DERRORSTRING(hr);
1254 }
1255}
1256
1257/**
1258 * Returns the number of depth bits represented by the indicated D3DFORMAT
1259 * value.
1260 */
1261int wdxGraphicsWindow9::
1262D3DFMT_to_DepthBits(D3DFORMAT fmt) {
1263 switch(fmt) {
1264 case D3DFMT_D16:
1265 return 16;
1266
1267 case D3DFMT_D24X8:
1268 case D3DFMT_D24X4S4:
1269 case D3DFMT_D24S8:
1270 return 24;
1271
1272 case D3DFMT_D32:
1273 return 32;
1274
1275 case D3DFMT_D15S1:
1276 return 15;
1277
1278 default:
1279 wdxdisplay9_cat.debug()
1280 << "D3DFMT_DepthBits: unhandled D3DFMT!\n";
1281 return 0;
1282 }
1283}
1284
1285/**
1286 * Returns true if the indicated video adapter card is known to report an
1287 * inaccurate figure for available video memory.
1288 */
1289bool wdxGraphicsWindow9::
1290is_badvidmem_card(D3DADAPTER_IDENTIFIER9 *pDevID) {
1291 // don't trust Intel cards since they often use regular memory as vidmem
1292 if (pDevID->VendorId == 0x00008086) {
1293 return true;
1294 }
1295
1296 return false;
1297}
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.
void mark_new()
Marks the GSG as "new", so that the next call to reset_if_new() will be effective.
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.