浏览代码

single gsg multiple window: fixed all known bugs

Asad M. Zaman 22 年之前
父节点
当前提交
f9dc7178e8

+ 3 - 3
panda/src/dxgsg8/dxGraphicsDevice8.cxx

@@ -29,9 +29,9 @@ DXGraphicsDevice8::
 DXGraphicsDevice8(wdxGraphicsPipe8 *pipe) :
   GraphicsDevice(pipe) {
 
-    _pScrn = NULL;
-    _pD3DDevice = NULL;
-    _pSwapChain = NULL;
+  ZeroMemory(&_Scrn,sizeof(_Scrn));
+  _pD3DDevice = NULL;
+  _pSwapChain = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/dxgsg8/dxGraphicsDevice8.h

@@ -38,8 +38,8 @@ public:
   DXGraphicsDevice8(wdxGraphicsPipe8 *pipe);
   ~DXGraphicsDevice8();
 
-  DXScreenData *_pScrn;
-  LPDIRECT3DDEVICE8 _pD3DDevice;  // same as pScrn->_pD3DDevice, cached for spd
+  DXScreenData _Scrn;
+  LPDIRECT3DDEVICE8 _pD3DDevice;  // same as Scrn._pD3DDevice, cached for spd
   IDirect3DSwapChain8 *_pSwapChain;
 
 #if 0

+ 44 - 17
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -997,11 +997,24 @@ prepare_display_region() {
     D3DVIEWPORT8 vp = { l, u, w, h, 0.0f, 1.0f };
     HRESULT hr = _pD3DDevice->SetViewport( &vp );
     if (FAILED(hr)) {
+      dxgsg8_cat.error()
+        << "pScrn_SwapChain = " << _pScrn->pSwapChain << " SwapChain = " << _pSwapChain << "\n";
       dxgsg8_cat.error()
         << "SetViewport(" << l << ", " << u << ", " << w << ", " << h
         << ") failed" << D3DERRORSTRING(hr);
-      throw_event("panda3d-render-error");
-      nassertv(false);
+#if 0
+      D3DVIEWPORT8 vp_old;
+      _pD3DDevice->GetViewport( &vp_old );
+      dxgsg8_cat.error()
+        << "GetViewport(" << vp_old.X << ", " << vp_old.Y << ", " << vp_old.Width << ", " 
+        << vp_old.Height << ") returned: Trying to set that vp---->\n";
+      hr = _pD3DDevice->SetViewport( &vp_old );
+#endif
+      if (FAILED(hr)) {
+        dxgsg8_cat.error() << "Failed again\n";
+        throw_event("panda3d-render-error");
+        nassertv(false);
+      }
     }
     // Note: for DX9, also change scissor clipping state here
   }
@@ -4522,6 +4535,7 @@ dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) {
     // unsafe to do the D3D releases after exit() called, since DLL_PROCESS_DETACH
     // msg already delivered to d3d.dll and it's unloaded itself
 
+    wdxdisplay8_cat.debug() << "called dx_cleanup\n";
     free_nondx_resources();
 
     PRINT_REFCNT(dxgsg8,_pD3DDevice);
@@ -4555,7 +4569,7 @@ set_context(DXScreenData *pNewContextData) {
     _pD3DDevice = _pScrn->pD3DDevice;   //copy this one field for speed of deref
     _pSwapChain = _pScrn->pSwapChain;   //copy this one field for speed of deref
  
-    //    wdxdisplay8_cat.debug() << "SwapChain = "<< _pSwapChain << "\n";
+    //wdxdisplay8_cat.debug() << "SwapChain = "<< _pSwapChain << "\n";
 }
 
 void DXGraphicsStateGuardian8::  
@@ -4569,13 +4583,15 @@ create_swap_chain(DXScreenData *pNewContextData) {
     hr = pNewContextData->pD3DDevice->CreateAdditionalSwapChain(&pNewContextData->PresParams, &pNewContextData->pSwapChain);
     if (FAILED(hr))
       wdxdisplay8_cat.debug() << "Swapchain creation failed :"<<D3DERRORSTRING(hr)<<"\n";
-    //    set_context(pNewContextData);
 }
 
 void DXGraphicsStateGuardian8::  
 release_swap_chain(DXScreenData *pNewContextData) {
     // Release the swap chain on this DXScreenData
-    pNewContextData->pSwapChain->Release();
+  HRESULT hr;
+  hr = pNewContextData->pSwapChain->Release();
+  if (FAILED(hr))
+    wdxdisplay8_cat.debug() << "Swapchain release failed:" << D3DERRORSTRING(hr) << "\n";
 }
 
 bool refill_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) {
@@ -4808,42 +4824,53 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams, DXScreenData **pScrn) {
        _pScrn->pD3D8->GetAdapterDisplayMode(_pScrn->CardIDNum, &_pScrn->DisplayMode);
        pPresParams->BackBufferFormat = _pScrn->DisplayMode.Format;
   }
-  // here we have to look at the device's frame buffer dimension
-  // if current window's dimension is bigger than device's frame buffer
+  // here we have to look at the _PresReset frame buffer dimension
+  // if current window's dimension is bigger than _PresReset 
   // we have to reset the device before creating new swapchain.
   // inorder to reset properly, we need to release all swapchains
-  D3DSURFACE_DESC DeviceDesc;
-  LPDIRECT3DSURFACE8 pDeviceBack;
-  _pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pDeviceBack);
-  pDeviceBack->GetDesc(&DeviceDesc);
-  pDeviceBack->Release();
+
   if ( !(_pScrn->pSwapChain)
-       || (DeviceDesc.Width < pPresParams->BackBufferWidth)
-       || (DeviceDesc.Height < pPresParams->BackBufferHeight) ) {
+       || (_PresReset.BackBufferWidth < pPresParams->BackBufferWidth)
+       || (_PresReset.BackBufferHeight < pPresParams->BackBufferHeight) ) {
+
+    wdxdisplay8_cat.debug() << "Swpachain = " << _pScrn->pSwapChain << " _PresReset = "
+                            << _PresReset.BackBufferWidth << "x" << _PresReset.BackBufferHeight << "pPresParams = "
+                            << pPresParams->BackBufferWidth << "x" << pPresParams->BackBufferHeight << "\n";
 
     get_engine()->reset_all_windows(false);// reset old swapchain by releasing
 
-    _PresReset.BackBufferWidth = pPresParams->BackBufferWidth;
-    _PresReset.BackBufferHeight = pPresParams->BackBufferHeight;
+    _PresReset.BackBufferWidth = max(_PresReset.BackBufferWidth, pPresParams->BackBufferWidth);
+    _PresReset.BackBufferHeight = max(_PresReset.BackBufferHeight, pPresParams->BackBufferHeight);
     hr=_pD3DDevice->Reset(&_PresReset);
     if (FAILED(hr)) {
       return hr;
     }
 
     get_engine()->reset_all_windows(true);// reset with new swapchains by creating
+
+    *pScrn = NULL;
+    if(pPresParams!=&_pScrn->PresParams)
+      memcpy(&_pScrn->PresParams,pPresParams,sizeof(D3DPRESENT_PARAMETERS));
+    return hr;
   }
+
   // release the old swapchain and create a new one
   if (_pScrn->pSwapChain) {
     _pScrn->pSwapChain->Release();
+    wdxdisplay8_cat.debug() << "SwapChain " << _pScrn->pSwapChain << " is released\n";
     _pScrn->pSwapChain = NULL;
     hr=_pD3DDevice->CreateAdditionalSwapChain(pPresParams,&_pScrn->pSwapChain);
   }
   if(SUCCEEDED(hr)) {
      if(pPresParams!=&_pScrn->PresParams)
          memcpy(&_pScrn->PresParams,pPresParams,sizeof(D3DPRESENT_PARAMETERS));
-     if (pScrn)
+     if (pScrn) {
        *pScrn = _pScrn;
+       wdxdisplay8_cat.debug() << "_pScrn = " << _pScrn << ", _pScrn_device = " << _pScrn->pD3DDevice << "\n";
+     }
   }
+  else
+    while(1);
   return hr;
 }
 

+ 3 - 3
panda/src/dxgsg8/wdxGraphicsPipe8.cxx

@@ -396,7 +396,7 @@ find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,
   *pBestFmt = D3DFMT_UNKNOWN;
   HRESULT hr;
 
-    // nvidia likes zbuf depth to match rendertarget depth
+  // nvidia likes zbuf depth to match rendertarget depth
   bool bOnlySelect16bpp = (bForce16bpp ||
                            (IS_NVIDIA(Display.DXDeviceID) && IS_16BPP_DISPLAY_FORMAT(TestDisplayMode.Format)));
 
@@ -760,8 +760,8 @@ search_for_valid_displaymode(DXScreenData &scrn,
 PT(GraphicsDevice) wdxGraphicsPipe8::
 make_device(void *scrn) {
   PT(DXGraphicsDevice8) device = new DXGraphicsDevice8(this);
-  device->_pScrn = (DXScreenData*) scrn;
-  device->_pD3DDevice = device->_pScrn->pD3DDevice;
+  memcpy(&device->_Scrn, scrn, sizeof(device->_Scrn));
+  device->_pD3DDevice = device->_Scrn.pD3DDevice;
 
   _device = device;
   wdxdisplay8_cat.error() << "walla: device" << device << "\n";

+ 2 - 2
panda/src/dxgsg8/wdxGraphicsPipe8.h

@@ -54,7 +54,7 @@ public:
 
   bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,
                        D3DFORMAT *pBestFmt, bool bWantStencil,
-                       bool bForce16bpp, bool bVerboseMode = false) const;
+                       bool bForce16bpp, bool bVerboseMode = true) const;
 
   void search_for_valid_displaymode(DXScreenData &scrn,
                              UINT RequestedX_Size, UINT RequestedY_Size,
@@ -63,7 +63,7 @@ public:
                              bool *pCouldntFindAnyValidZBuf,
                              D3DFORMAT *pSuggestedPixFmt,
                              bool bForce16bppZBuffer,
-                             bool bVerboseMode = false);
+                             bool bVerboseMode = true);
 
    bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size,UINT y_size);
 

+ 45 - 13
panda/src/dxgsg8/wdxGraphicsWindow8.cxx

@@ -108,7 +108,7 @@ make_current(void) {
   // reset() requires having a current context.)
   dxgsg->reset_if_new();
 
-  //  wdxdisplay8_cat.debug() << "this is " << this << "\n";
+  //wdxdisplay8_cat.debug() << "this is " << _wcontext.pSwapChain << "\n";
 }
 
 /* BUGBUG:  need to reinstate these methods ASAP.  they were incorrectly moved from the GraphicsWindow to the GSG
@@ -414,6 +414,21 @@ support_overlay_window(bool flag) {
   }
 }
 
+//////////////////////////////////////////////////////////////////
+//     Function: wdxGraphicsWindow::close_window
+//       Access: Public
+//  Description: Some cleanup is necessary for directx closeup of window.
+//               Handle close window events for this particular
+//               window.
+////////////////////////////////////////////////////////////////////
+void wdxGraphicsWindow8::
+close_window() {
+  wdxdisplay8_cat.debug() << "wdx closed window\n";
+  if (multiple_windows)
+    _dxgsg->release_swap_chain(&_wcontext);
+  WinGraphicsWindow::close_window();
+}
+
 #if 1
 //////////////////////////////////////////////////////////////////
 //     Function: WinGraphicsWindow::window_proc
@@ -1520,16 +1535,17 @@ reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
   DXScreenData *pScrn;
   D3DPRESENT_PARAMETERS d3dpp;
   memcpy(&d3dpp, &_wcontext.PresParams, sizeof(D3DPRESENT_PARAMETERS));
-  d3dpp.BackBufferWidth = new_xsize;
-  d3dpp.BackBufferHeight = new_ysize;
+  _wcontext.PresParams.BackBufferWidth = new_xsize;
+  _wcontext.PresParams.BackBufferHeight = new_ysize;
   make_current();
-  HRESULT hr = _dxgsg->reset_d3d_device(&d3dpp, &pScrn);
-  
+  HRESULT hr = _dxgsg->reset_d3d_device(&_wcontext.PresParams, &pScrn);
+
   if (FAILED(hr)) {
     bRetval = false;
     wdxdisplay8_cat.error()
       << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr);
     if (hr == D3DERR_OUTOFVIDEOMEMORY) {
+      memcpy(&_wcontext.PresParams, &d3dpp, sizeof(D3DPRESENT_PARAMETERS));
       hr = _dxgsg->reset_d3d_device(&_wcontext.PresParams, &pScrn);
       if (FAILED(hr)) {
         wdxdisplay8_cat.error()
@@ -1548,7 +1564,8 @@ reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
     }
   }
   // before you init_resized_window you need to copy certain changes to _wcontext
-  _wcontext.pSwapChain = pScrn->pSwapChain;
+  if (pScrn)
+    _wcontext.pSwapChain = pScrn->pSwapChain;
   wdxdisplay8_cat.debug() << "swapchain is " << _wcontext.pSwapChain << "\n";
   init_resized_window();
   return bRetval;
@@ -1620,6 +1637,9 @@ init_resized_window() {
   assert(_wcontext.hWnd!=NULL);
   ClearToBlack(_wcontext.hWnd, get_properties());
 
+  //wdxdisplay8_cat.debug() << "wcontext = " << &_wcontext << " and device = " << _wcontext.pD3DDevice << "\n";
+
+#if 0
   // clear textures and VB's out of video&AGP mem, so cache is reset
   hr = _wcontext.pD3DDevice->ResourceManagerDiscardBytes(0);
   if (FAILED(hr)) {
@@ -1627,6 +1647,7 @@ init_resized_window() {
       << "ResourceManagerDiscardBytes failed for device #" 
       << _wcontext.CardIDNum << D3DERRORSTRING(hr);
   }
+#endif
 
   _dxgsg->set_context(&_wcontext); 
   // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts
@@ -1749,6 +1770,11 @@ open_window(void) {
   // In that case just create an additional swapchain for this window
 
   if (dxgsg->get_pipe()->get_device() == NULL) {
+
+    if (wdxdisplay8_cat.is_debug()) {
+      wdxdisplay8_cat.debug() << "device is null \n";
+    }
+
     create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer);
     dxgsg->get_pipe()->make_device((void*)(&_wcontext));
     dxgsg->copy_pres_reset(&_wcontext);
@@ -1760,23 +1786,29 @@ open_window(void) {
   } else {
     // fill in the DXScreenData from dxdevice here and change the
     // reference to hWnd.
+    if (wdxdisplay8_cat.is_debug()) {
+      wdxdisplay8_cat.debug() << "device is not null\n";
+    }
     dxdev = (DXGraphicsDevice8*)dxgsg->get_pipe()->get_device();
     props = get_properties();
 
-    memcpy(&_wcontext,dxdev->_pScrn,sizeof(DXScreenData));
+    wdxdisplay8_cat.debug() << "dxdev_pScrn = " << &dxdev->_Scrn << ", _pScrn_device = " << dxdev->_Scrn.pD3DDevice
+                            << ", dxdev_device = " << dxdev->_pD3DDevice << "\n";
+    wdxdisplay8_cat.debug() << "_wcontext = " << &_wcontext << ", device = " << _wcontext.pD3DDevice << "\n";
+
+    memcpy(&_wcontext,&dxdev->_Scrn,sizeof(DXScreenData));
     _wcontext.hWnd = _hWnd;
+    //    _wcontext.pD3DDevice = dxdev->_pD3DDevice; // copy the current device
     _wcontext.PresParams.hDeviceWindow = _hWnd;
     _wcontext.PresParams.BackBufferWidth = props.get_x_size();
     _wcontext.PresParams.BackBufferHeight = props.get_y_size();
 
-    wdxdisplay8_cat.debug()<<"device width "<<_wcontext.PresParams.BackBufferWidth<<"\n";
-
+    //wdxdisplay8_cat.debug()<<"device width "<<_wcontext.PresParams.BackBufferWidth<<"\n";
+    //wdxdisplay8_cat.debug()<<"debug pSwapChain "<<_wcontext.pSwapChain<<"\n";
+    dxgsg->create_swap_chain(&_wcontext);
     init_resized_window();
 
-    if (wdxdisplay8_cat.is_debug()) {
-      wdxdisplay8_cat.debug() << "Current device is " << dxdev << "\n";
-    }
-    dxgsg->create_swap_chain(&_wcontext);
+    //wdxdisplay8_cat.debug() << "Current device is " << dxdev << "\n";
   }
   wdxdisplay8_cat.debug() << "swapchain is " << _wcontext.pSwapChain << "\n";
   return true;

+ 1 - 0
panda/src/dxgsg8/wdxGraphicsWindow8.h

@@ -43,6 +43,7 @@ public:
                      const string &name);
   virtual ~wdxGraphicsWindow8();
   virtual bool open_window(void);
+  virtual void close_window(void);
   virtual void reset_window(bool swapchain);
 
   virtual int verify_window_sizes(int numsizes, int *dimen);