Browse Source

resizing and cursor fixes

cxgeorge 24 years ago
parent
commit
4cade76e34

+ 4 - 0
panda/src/dxgsg8/config_dxgsg8.cxx

@@ -94,6 +94,10 @@ bool dx_debug_view_mipmaps = config_dxgsg.GetBool("dx-debug-view-mipmaps", false
 //int dx_print_texstats = config_dxgsg.GetBool("dx-print-texstats", 0);
 #endif
 
+// use dx8 or GDI mouse cursor in fullscreen mode?
+// Nvidia dx8 cursor is invisible as of 28.32 drivers, so using GDI in fullscrn by default for now
+bool dx_use_dx_cursor = config_dxgsg.GetBool("dx-use-dx-cursor", false);
+
 bool dx_force_anisotropic_filtering = config_dxgsg.GetBool("dx-force-anisotropic-filtering", false);
 
 // set 'retained-mode #t' and this to have prepare_geom concatenate all tristrips within a geom 

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

@@ -39,6 +39,7 @@ extern const bool link_tristrips;
 extern DWORD dx_multisample_antialiasing_level;
 extern bool dx_use_triangle_mipgen_filter;
 extern const char *D3DFormatStr(D3DFORMAT fmt);
+extern bool dx_use_dx_cursor;
 
 // debug flags we might want to use in full optimized build
 extern bool dx_ignore_mipmaps;

+ 7 - 1
panda/src/dxgsg8/d3dfont8.cxx

@@ -399,7 +399,13 @@ HRESULT CD3DFont::RestoreDeviceObjects() {
 // Desc: Destroys all device-dependent objects
 //-----------------------------------------------------------------------------
 HRESULT CD3DFont::InvalidateDeviceObjects() {
-
+    /*
+    #ifdef _DEBUG
+    if(m_pVB) {
+        cout << "XXXX Releasing Font VertexBuffer\n";
+    }
+    #endif
+    */
 
     SAFE_RELEASE( m_pVB );
 

+ 23 - 36
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -724,7 +724,7 @@ dx_init(HCURSOR hMouseCursor) {
     // must check (scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon85, no on TNT)
     scrn.pD3DDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD);
 
-    if(dx_full_screen) {
+    if((scrn.pProps->_fullscreen) && dx_use_dx_cursor) {
         hr = CreateDX8Cursor(scrn.pD3DDevice,hMouseCursor,dx_show_cursor_watermark);
         if(FAILED(hr))
             dxgsg_cat.error() << "CreateDX8Cursor failed!\n";
@@ -748,10 +748,10 @@ dx_init(HCURSOR hMouseCursor) {
             UINT xsize = scrn.pProps->_xsize;
             UINT ysize = scrn.pProps->_ysize;
 
-            #define FPS_MSG_FORMAT_STR " %dx%d\n%6.02f fps"
+            #define FPS_MSG_FORMAT_STR " %dx%dx%d\n%6.02f fps"
 
             char fps_msg[50];
-            sprintf(fps_msg,FPS_MSG_FORMAT_STR,xsize,ysize,800.00f); // 6 == NUM_FPSMETER_LETTERS
+            sprintf(fps_msg,FPS_MSG_FORMAT_STR,xsize,ysize,32,800.00f); // 6 == NUM_FPSMETER_LETTERS
 
             hr = _pStatMeterFont->GetTextExtent(fps_msg,&TextRectSize);
             if(SUCCEEDED(hr)) {
@@ -997,8 +997,11 @@ void INLINE TestDrawPrimFailure(DP_Type dptype,HRESULT hr,IDirect3DDevice8 *pD3D
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
 render_frame() {
-  if (!_bDXisReady) 
+  if (!_bDXisReady) {
+    //if(dxgsg_cat.is_spam())
+    //  dxgsg_cat.spam() << "dx is not ready, skipping render_frame()\n";
     return;
+  }
 
   _win->begin_frame();
 
@@ -3567,7 +3570,6 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
     state.set_transition(new ColorBlendTransition);
     state.set_transition(new StencilTransition);
 
-
     switch (pb->get_format()) {
         case PixelBuffer::F_depth_component:
             {
@@ -4814,7 +4816,8 @@ end_frame() {
     D3DCOLOR fontColor = D3DCOLOR_ARGB(255,255,255,0);  // yellow
 
     char fps_msg[50];
-    sprintf(fps_msg,FPS_MSG_FORMAT_STR,scrn.pProps->_xsize,scrn.pProps->_ysize,_current_fps);
+    sprintf(fps_msg,FPS_MSG_FORMAT_STR,scrn.pProps->_xsize,scrn.pProps->_ysize,
+            (IS_16BPP_DISPLAY_FORMAT(scrn.PresParams.BackBufferFormat) ? 16 : 32),_current_fps);
 
     // usually only want to call BeginText() & EndText() once/frame
     // to bracket all the text for a given cd3dfont obj
@@ -5758,35 +5761,6 @@ HRESULT DXGraphicsStateGuardian::ReleaseAllDeviceObjects(void) {
     return S_OK;
 }
 
-HRESULT DXGraphicsStateGuardian::RestoreAllDeviceObjects(void) {
-  // BUGBUG: this should also restore vertex buffer contents when they are implemented
-  // You will need to destroy and recreate
-  // optimized vertex buffers however, restoring is not enough.
-
-/*
-  HRESULT hr;
-  // note: could go through and just restore surfs that return IsLost() true
-  // apparently that isnt as reliable w/some drivers tho
-  if (FAILED(hr = scrn.pD3DDevice->RestoreAllSurfaces() )) {
-        dxgsg_cat.fatal() << "RestoreAllSurfs failed : result = " << D3DERRORSTRING(hr);
-    exit(1);
-  }
-*/
-
-  // DX8 should handle restoring contents of managed textures automatically
-
-  // cant access template in libpanda.dll directly due to vc++ limitations, use traverser to get around it
-//  traverse_prepared_textures(refill_tex_callback,this);
-
-  if(IS_VALID_PTR(_pStatMeterFont))
-    _pStatMeterFont->RestoreDeviceObjects();
-
-  if(dxgsg_cat.is_debug())
-      dxgsg_cat.debug() << "restore and refill of video surfaces complete...\n";
-  return S_OK;
-}
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: show_frame
 //       Access:
@@ -5899,8 +5873,20 @@ void DXGraphicsStateGuardian::show_windowed_frame(void) {
 HRESULT DXGraphicsStateGuardian::reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams) {
   HRESULT hr;
 
+  assert(IS_VALID_PTR(pPresParams));
+  assert(IS_VALID_PTR(scrn.pD3D8));
+  assert(IS_VALID_PTR(scrn.pD3DDevice));
+
   ReleaseAllDeviceObjects();
 
+  if(!dx_full_screen) {
+      // for windowed make sure out format matches the desktop fmt, in case the 
+      // desktop mode has been changed
+
+       scrn.pD3D8->GetAdapterDisplayMode(scrn.CardIDNum, &scrn.DisplayMode);
+       pPresParams->BackBufferFormat = scrn.DisplayMode.Format;
+  }
+
   hr=scrn.pD3DDevice->Reset(pPresParams);
   if(SUCCEEDED(hr)) {
      if(pPresParams!=&scrn.PresParams)
@@ -5929,7 +5915,6 @@ bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) {
 
              if(bDoReactivateWindow)
                  _win->reactivate_window();  //must reactivate window before you can restore surfaces (otherwise you are in WRONGVIDEOMODE, and DDraw RestoreAllSurfaces fails)
-             RestoreAllDeviceObjects();  
              hr = scrn.pD3DDevice->TestCooperativeLevel();
              if(FAILED(hr)) {
                 // internal chk, shouldnt fail 
@@ -5937,6 +5922,8 @@ bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) {
                 exit(1);
              }
 
+             _bDXisReady = TRUE;
+
             break;
 
         case D3DERR_DEVICELOST:

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

@@ -234,7 +234,6 @@ protected:
                     DWORD wNumRings, DWORD wNumSections, float sx, float sy, float sz,
                     DWORD *pNumVertices,DWORD *pNumTris,DWORD fvfFlags,DWORD dwVertSize);
   HRESULT ReleaseAllDeviceObjects(void);
-  HRESULT RestoreAllDeviceObjects(void);
   HRESULT RecreateAllDeviceObjects(void);
   HRESULT DeleteAllDeviceObjects(void);
 

+ 150 - 68
panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx

@@ -43,6 +43,7 @@ TypeHandle wdxGraphicsWindow::_type_handle;
 #define LAST_ERROR 0
 #define ERRORBOX_TITLE "Panda3D Error"
 #define WDX_WINDOWCLASSNAME "wdxDisplay"
+#define WDX_WINDOWCLASSNAME_NOCURSOR "wdxDisplay_NoCursor"
 #define DEFAULT_CURSOR IDC_ARROW
 
 typedef map<HWND,wdxGraphicsWindow *> HWND_PANDAWIN_MAP;
@@ -67,7 +68,7 @@ wdxGraphicsWindow* global_wdxwinptr = NULL;  // need this for temporary windproc
 #define MAX_DISPLAYS 20
 
 #define PAUSED_TIMER_ID  7   // completely arbitrary choice
-#define DXREADY ((_dxgsg!=NULL)&&(_dxgsg->GetDXReady()))
+#define DX_IS_READY ((_dxgsg!=NULL)&&(_dxgsg->GetDXReady()))
 
 LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam,LPARAM lparam);
 
@@ -168,6 +169,15 @@ extern void dbgPrintVidMem(LPDIRECTDRAW7 pDD, LPDDSCAPS2 lpddsCaps,const char *p
 }
 #endif
 
+void ClearToBlack(HWND hWnd,GraphicsWindow::Properties &props) {
+    // clear to black
+    HDC hDC=GetDC(hWnd);  // GetDC is not particularly fast.  if this needs to be super-quick, we should cache GetDC's hDC
+    RECT clrRect={props._xorg,props._yorg,props._xorg+props._xsize,props._yorg+props._ysize};
+    FillRect(hDC,&clrRect,(HBRUSH)GetStockObject(BLACK_BRUSH));
+//          PatBlt(hDC,_props._xorg,_props._yorg,_props._xsize,_props._ysize,BLACKNESS);
+    ReleaseDC(hWnd,hDC);
+}
+
 // fn exists so AtExitFn can call it without refcntr blowing up since its !=0
 void wdxGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
   if(wdxdisplay_cat.is_spam())
@@ -275,19 +285,23 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     int x, y, width, height;
 
     switch(msg) {
-
          case WM_PAINT: {
+            if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) {
+              // let DefWndProc do WM_ERASEBKGND & just draw black,
+              // rather than forcing Present to stretchblt the old window contents
+              // into the new size
+              break;
+            }
+
             PAINTSTRUCT ps;
             BeginPaint(hwnd, &ps);
-
-            if(DXREADY)
-                show_frame();
+            show_frame();
             EndPaint(hwnd, &ps);
             return 0;
         }
 
         case WM_MOUSEMOVE: {
-            if(!DXREADY)
+            if(!DX_IS_READY)
                 break;
 
             // Win32 doesn't return the same numbers as X does when the mouse
@@ -310,7 +324,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
             SET_MOUSE_COORD(y,newY);
 
             handle_mouse_motion(x, y);
-            if(dx_full_screen && (_dxgsg!=NULL) && (_dxgsg->scrn.pD3DDevice!=NULL))
+            if(_props._fullscreen && (_dxgsg!=NULL) && (_dxgsg->scrn.pD3DDevice!=NULL))
                 _dxgsg->scrn.pD3DDevice->SetCursorPosition(newX,newY,D3DCURSOR_IMMEDIATE_UPDATE);
             return 0;
         }
@@ -339,22 +353,16 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
         case WM_MOUSELEAVE: {
            // wdxdisplay_cat.fatal() << "XXXXX WM_MOUSELEAVE received\n";
 
-           _tracking_mouse_leaving=false;  
+           _tracking_mouse_leaving=false;
            handle_mouse_exit();
            break;
         }
 
         case WM_CREATE: {
           track_mouse_leaving(hwnd);
-
           _cursor_in_windowclientarea=false;
-          if(!_props._bCursorIsVisible)
-              ShowCursor(false);
-
-          HDC hDC=GetDC(hwnd);
-          PatBlt(hDC,_props._xorg,_props._yorg,_props._xsize,_props._ysize,BLACKNESS);
-          ReleaseDC(hwnd,hDC);
-
+          ClearToBlack(hwnd,_props);
+          set_cursor_visibility(true);
           break;
         }
 
@@ -422,7 +430,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
             if(button < 0)
                 button = 1;
         case WM_RBUTTONDOWN:
-            if(!DXREADY) 
+            if(!DX_IS_READY) 
               break;
 
             if(button < 0)
@@ -439,7 +447,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
             if(button < 0)
                 button = 1;
         case WM_RBUTTONUP:
-            if(!DXREADY) 
+            if(!DX_IS_READY) 
               break;
 
             if(button < 0)
@@ -455,15 +463,18 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
         case WM_SETCURSOR:
             // Turn off any GDI window cursor 
             //  dx8 cursor not working yet
-            if(dx_full_screen) {
-                SetCursor( NULL );
-                _dxgsg->scrn.pD3DDevice->ShowCursor(true);
+
+            if(_use_dx8_cursor && _props._fullscreen) {
+                //            SetCursor( NULL );
+            //                _dxgsg->scrn.pD3DDevice->ShowCursor(true);
+
+                set_cursor_visibility(true);
                 return TRUE; // prevent Windows from setting cursor to window class cursor (see docs on WM_SETCURSOR)
             }
             break;
 
         case WM_MOVE:
-            if(!DXREADY)
+            if(!DX_IS_READY)
                 break;
             handle_window_move(LOWORD(lparam), HIWORD(lparam) );
             return 0;
@@ -516,15 +527,24 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
             #endif
             
             if(_WindowAdjustingType==Resizing) {
-                handle_windowed_resize(hwnd,true);
+                bool bSucceeded=handle_windowed_resize(hwnd,true);
+
+                if(!bSucceeded) {
+#if 0
+ bugbug need to fix this stuff
+                     SetWindowPos(hwnd,NULL,0,0,lastxsize,lastysize,
+                                  SWP_NOMOVE |
+#endif
+                }
             }
 
             _WindowAdjustingType = NotAdjusting;
+            _dxgsg->SetDXReady(true);
             return 0;
 
         case WM_ENTERSIZEMOVE: {
                 if(_dxgsg!=NULL)
-                    _dxgsg->SetDXReady(true);   // dont disable here because I want to see pic as I resize
+                    _dxgsg->SetDXReady(false);   // dont see pic during resize
                 _WindowAdjustingType = MovingOrResizing;
             }
             break;
@@ -588,7 +608,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
 
         case WM_SETFOCUS: {
             // wdxdisplay_cat.info() << "got WM_SETFOCUS\n";
-            if(!DXREADY) {
+            if(!DX_IS_READY) {
               break;
             }
 
@@ -610,7 +630,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
 
         case WM_KILLFOCUS: {
             // wdxdisplay_cat.info() << "got WM_KILLFOCUS\n";
-            if(!DXREADY) {
+            if(!DX_IS_READY) {
               break;
             }
 
@@ -709,8 +729,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
 // should be used by both fullscrn and windowed resize
 bool wdxGraphicsWindow::reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
     DXScreenData *pScrn=&_dxgsg->scrn;
-
     assert((new_xsize>0)&&(new_ysize>0));
+    bool bRetval=true;
 
     D3DPRESENT_PARAMETERS d3dpp;
     memcpy(&d3dpp,&pScrn->PresParams,sizeof(D3DPRESENT_PARAMETERS));
@@ -719,14 +739,25 @@ bool wdxGraphicsWindow::reset_device_resize_window(UINT new_xsize, UINT new_ysiz
     HRESULT hr=_dxgsg->reset_d3d_device(&d3dpp);
 
     if(FAILED(hr)) {
-        if(hr==D3DERR_OUTOFVIDEOMEMORY)
-            return false;
+        bRetval=false;
         wdxdisplay_cat.error() << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr);
-        exit(1);
+        if(hr==D3DERR_OUTOFVIDEOMEMORY) {
+            hr=_dxgsg->reset_d3d_device(&pScrn->PresParams);
+            if(FAILED(hr)) {
+                wdxdisplay_cat.error() << "reset_device_resize_window Reset() failed OutOfVidmem, then failed again doing Reset w/original params:" << D3DERRORSTRING(hr);
+                exit(1);
+            } else {
+                if(wdxdisplay_cat.is_info())
+                    wdxdisplay_cat.info() << "reset of original size (" <<pScrn->PresParams.BackBufferWidth << "," 
+                    << pScrn->PresParams.BackBufferHeight << ") succeeded\n";
+            }
+        } else {
+            exit(1);
+        }
     }
 
     init_resized_window();
-    return true;
+    return bRetval;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -796,7 +827,7 @@ bool wdxGraphicsWindow::handle_windowed_resize(HWND hWnd,bool bDoDxReset) {
       bResizeSucceeded=reset_device_resize_window(xsize,ysize);  // create the new resized rendertargets
       if(!bResizeSucceeded) {
           if(wdxdisplay_cat.is_debug()) 
-              wdxdisplay_cat.debug() << "windowed_resize to size: (" << xsize << "," << ysize << ") failed due to out-of-memory, retrying w/reduced size\n";
+              wdxdisplay_cat.debug() << "windowed_resize to size: (" << xsize << "," << ysize << ") failed due to out-of-memory\n";
       } else {
           if(wdxdisplay_cat.is_debug()) 
               wdxdisplay_cat.debug() << "windowed_resize to origin: (" << _props._xorg << "," << _props._yorg << "), size: (" << _props._xsize << "," << _props._ysize << ")\n";
@@ -860,44 +891,37 @@ void wdxGraphicsWindow::deactivate_window(void) {
 //   }
 }
 
+// currently this should only be called from CheckCoopLvl to return from Alt-tab
 void wdxGraphicsWindow::reactivate_window(void) {
-    if(_window_inactive) {
+    if((_window_inactive)||(_active_minimized_fullscreen)) { 
     
         // first see if dx cooperative level is OK for reactivation
     //    if(!_dxgsg->CheckCooperativeLevel())
     //        return;
     
-        if(wdxdisplay_cat.is_spam())
-            wdxdisplay_cat.spam() << "WDX window re-activated...\n";
-    
-        _window_inactive = false;
-    
         if(_PandaPausedTimer!=NULL) {
             KillTimer(_dxgsg->scrn.hWnd,_PandaPausedTimer);
             _PandaPausedTimer = NULL;
         }
-    
-        // move window to top of zorder
-    //  if(_props._fullscreen)
-    //      SetWindowPos(_DisplayDataArray[0].hWnd, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
-        GdiFlush();
 
-    } else if(_active_minimized_fullscreen) {
-        if(wdxdisplay_cat.is_spam())
-            wdxdisplay_cat.spam() << "WDX window unminimized from active-minimized state...\n";
-    
-        if(_PandaPausedTimer!=NULL) {
-            KillTimer(_dxgsg->scrn.hWnd,_PandaPausedTimer);
-            _PandaPausedTimer = NULL;
+        if(_window_inactive) {
+            _window_inactive = false;
+            if(wdxdisplay_cat.is_spam())
+                wdxdisplay_cat.spam() << "WDX window re-activated...\n";
+        } else {
+            _active_minimized_fullscreen = false;
+            if(wdxdisplay_cat.is_spam())
+                wdxdisplay_cat.spam() << "WDX window unminimized from active-minimized state...\n";
         }
 
-        _active_minimized_fullscreen = false;
+        // need to call dx_init and ResourceManagerDiscardBytes since D3D Reset() was called
+        init_resized_window();
     
         // move window to top of zorder
     //  if(_props._fullscreen)
     //      SetWindowPos(_DisplayDataArray[0].hWnd, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
         GdiFlush();
-    }
+    } 
 
     if(_props._fullscreen) {
         throw_event("PandaRestarted");  // right now this is used to signal python event handler to re-enable audio
@@ -944,6 +968,18 @@ bool supports_color_cursors(D3DADAPTER_IDENTIFIER8 &DevID) {
     return false;
 }
 
+HCURSOR CreateNullCursor(HINSTANCE hInst) {
+  #define CURSORBYTESIZE (32*4)
+
+  // 1-bit 32x32
+  BYTE ANDPlane[CURSORBYTESIZE],XORPlane[CURSORBYTESIZE];
+
+  ZeroMemory(XORPlane,CURSORBYTESIZE);
+  memset(ANDPlane,0xFF,CURSORBYTESIZE);
+
+  return CreateCursor(hInst,0,0,32,32,ANDPlane,XORPlane);
+}
+
 void wdxGraphicsWindowGroup::CreateWindows(void) {
     HINSTANCE hProgramInstance = GetModuleHandle(NULL);
     WNDCLASS wc;
@@ -975,6 +1011,7 @@ void wdxGraphicsWindowGroup::CreateWindows(void) {
         wc.hIcon = NULL; // use default app icon
     }
 
+#if 0
     // Note: dx_init() uses the cursor handle to create the dx cursor surface
     string windows_color_cursor_filename = get_color_cursor_filename().to_os_specific();
 
@@ -1020,6 +1057,7 @@ void wdxGraphicsWindowGroup::CreateWindows(void) {
     }
 
     try_mono_cursor:
+#endif
 
     if(!_bLoadedCustomCursor) {
         string windows_mono_cursor_filename = get_mono_cursor_filename().to_os_specific();
@@ -1047,18 +1085,33 @@ void wdxGraphicsWindowGroup::CreateWindows(void) {
     if(!_bLoadedCustomCursor) 
       _hMouseCursor = LoadCursor(NULL, DEFAULT_CURSOR);
 
-    // bugbug:  probably need to make 2 classes, one w/cursor and one w/NULL cursor for fullscrn to support mixed types
+    // need both a mouse and no-mouse class in case we have mixed fullscrn/windowed
+    // windowed must use GDI mouse, fullscrn usually wont
     if (!wc_registered) {
       // We only need to register the window class once per session.
-      wc.hCursor = (dx_full_screen ? NULL : _hMouseCursor);  // for windowed mode use the GDI cursor.  
+
+      wc.hCursor = _hMouseCursor;  // for windowed mode use the GDI cursor.  
       // bugbug:  for fullscreen do we need to do a SetWindowLongNULL
       wc.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
       wc.lpszMenuName   = NULL;
       wc.lpszClassName  = WDX_WINDOWCLASSNAME;
       
       if(!RegisterClass(&wc)) {
-        wdxdisplay_cat.error() << "could not register window class!" << endl;
+        wdxdisplay_cat.error() << "could not register window class " << WDX_WINDOWCLASSNAME << endl;
+      }
+
+      if(dx_use_dx_cursor) {
+          wc.hCursor = CreateNullCursor(hProgramInstance);
+          if(wc.hCursor==NULL)
+            wdxdisplay_cat.error() << "failed to create NULL cursor, error=" << GetLastError() << endl;
+    
+          wc.lpszClassName  = WDX_WINDOWCLASSNAME_NOCURSOR;
+    
+          if(!RegisterClass(&wc)) {
+            wdxdisplay_cat.error() << "could not register window class " << WDX_WINDOWCLASSNAME_NOCURSOR << endl;
+          }
       }
+
       wc_registered = true;
     }
 
@@ -1074,6 +1127,7 @@ void wdxGraphicsWindowGroup::CreateWindows(void) {
         DWORD final_window_style;
 
         final_window_style=base_window_style;
+        char *pWindowClassName;
 
         if(_windows[devnum]->_props._fullscreen) {
             MONITORINFO minfo;
@@ -1086,6 +1140,8 @@ void wdxGraphicsWindowGroup::CreateWindows(void) {
             ytop=minfo.rcMonitor.top;
             xsize=props->_xsize;
             ysize=props->_ysize;
+
+            pWindowClassName= (dx_use_dx_cursor ? WDX_WINDOWCLASSNAME_NOCURSOR : WDX_WINDOWCLASSNAME);
         } else {
             RECT win_rect;
             SetRect(&win_rect, props->_xorg,  props->_yorg, props->_xorg + props->_xsize,
@@ -1108,11 +1164,13 @@ void wdxGraphicsWindowGroup::CreateWindows(void) {
             ytop= win_rect.top;
             xsize=RECT_XSIZE(win_rect);
             ysize=RECT_YSIZE(win_rect);
+
+            pWindowClassName=WDX_WINDOWCLASSNAME;
         }
 
         // BUGBUG: this sets window posns based on desktop arrangement of monitors (that is what GetMonInfo is for). 
         // need to move to chancfg stuff instead (i.e. use the properties x/yorg's) when that is ready
-        HWND hWin = CreateWindow(WDX_WINDOWCLASSNAME, props->_title.c_str(),
+        HWND hWin = CreateWindow(pWindowClassName, props->_title.c_str(),
                                   final_window_style, xleft,ytop,xsize,ysize,
                                   _hParentWindow, NULL, hProgramInstance, 0);
 
@@ -1202,10 +1260,14 @@ void wdxGraphicsWindow::config_window(wdxGraphicsWindowGroup *pParentGroup) {
     _return_control_to_app = false;
     _active_minimized_fullscreen = false;
 
-    if(_props._fullscreen || _props._fullscreen) {
-        _props._fullscreen = _props._fullscreen = true;
+    if(_props._fullscreen || dx_full_screen) {
+        _props._fullscreen = dx_full_screen= true;
     }
 
+    _use_dx8_cursor = dx_use_dx_cursor;
+    if(!_props._fullscreen)
+       _use_dx8_cursor = false;
+
     _WindowAdjustingType = NotAdjusting;
     _bSizeIsMaximized=FALSE;
 
@@ -1448,7 +1510,7 @@ find_all_card_memavails(void) {
 
     HINSTANCE hDDrawDLL = LoadLibrary(DDRAW_NAME);
     if(hDDrawDLL == 0) {
-        wdxdisplay_cat.fatal() << "can't locate " << DDRAW_NAME <<"!\n";
+        wdxdisplay_cat.fatal() << "LoadLibrary(" << DDRAW_NAME <<") failed!, error=" << GetLastError() << endl;
         exit(1);
     }
 
@@ -2308,8 +2370,8 @@ void wdxGraphicsWindow::init_resized_window(void) {
         GetClientRect( pDisplay->hWnd, &view_rect );
         ul.x=view_rect.left;  ul.y=view_rect.top;
         lr.x=view_rect.right;  lr.y=view_rect.bottom;
-        ClientToScreen(pDisplay->hWnd, &ul );
-        ClientToScreen(pDisplay->hWnd, &lr );
+        ClientToScreen(pDisplay->hWnd, &ul);
+        ClientToScreen(pDisplay->hWnd, &lr);
         view_rect.left=ul.x; view_rect.top=ul.y;
         view_rect.right=lr.x; view_rect.bottom=lr.y;
         _props._xorg = view_rect.left;  // _props should reflect view rectangle
@@ -2321,11 +2383,10 @@ void wdxGraphicsWindow::init_resized_window(void) {
 
     resized(newWidth,newHeight);  // update panda channel/display rgn info, _props.xsize, _props.ysize
 
-   // clear window to black ASAP
-    HDC hDC=GetDC(pDisplay->hWnd);
-    PatBlt(hDC,_props._xorg,_props._yorg,_props._xsize,_props._ysize,BLACKNESS);
-    ReleaseDC(pDisplay->hWnd,hDC);
+    // clear window to black ASAP
+    ClearToBlack(pDisplay->hWnd,_props);
 
+    // clear textures and VB's out of video&AGP mem, so cache is reset
     hr = pDisplay->pD3DDevice->ResourceManagerDiscardBytes(0);
     if(FAILED(hr)) {
         wdxdisplay_cat.error() << "ResourceManagerDiscardBytes failed for device #" << pDisplay->CardIDNum << D3DERRORSTRING(hr);
@@ -2341,6 +2402,30 @@ void wdxGraphicsWindow::init_resized_window(void) {
 
     _dxgsg->dx_init(_pParentWindowGroup->_hMouseCursor);
     // do not SetDXReady() yet since caller may want to do more work before letting rendering proceed
+
+    set_cursor_visibility(true);
+}
+
+// does NOT override _props._bCursorIsVisible
+INLINE void wdxGraphicsWindow::set_cursor_visibility(bool bVisible) {
+  bool bValidDXPtrs;
+   
+  if(_use_dx8_cursor)
+    bValidDXPtrs = (IS_VALID_PTR(_dxgsg) && IS_VALID_PTR(_dxgsg->scrn.pD3DDevice));
+
+  if(_props._bCursorIsVisible) {
+      if(_use_dx8_cursor) {
+          ShowCursor(false);
+          if(bValidDXPtrs)
+              _dxgsg->scrn.pD3DDevice->ShowCursor(bVisible);
+      } else {
+         ShowCursor(bVisible);
+      }
+  } else {
+      ShowCursor(false);
+      if(_use_dx8_cursor && bValidDXPtrs)
+          _dxgsg->scrn.pD3DDevice->ShowCursor(false);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2404,7 +2489,6 @@ void wdxGraphicsWindow::setup_colormap(void) {
     RealizePalette(_hdc);
 }
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: begin_frame
 //       Access:
@@ -2417,8 +2501,6 @@ void wdxGraphicsWindow::show_frame(void) {
     _dxgsg->show_frame();
 }
 
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: end_frame
 //       Access:

+ 2 - 0
panda/src/wdxdisplay8/wdxGraphicsWindow8.h

@@ -117,6 +117,7 @@ private:
   bool              _active_minimized_fullscreen;
   bool              _return_control_to_app;
   bool              _cursor_in_windowclientarea;
+  bool              _use_dx8_cursor;
   bool              _tracking_mouse_leaving;
   int               _depth_buffer_bpp;
 
@@ -130,6 +131,7 @@ public:
   virtual void do_close_window();
   void deactivate_window(void);
   void reactivate_window(void);
+  INLINE void set_cursor_visibility(bool bVisible);
   bool handle_windowed_resize(HWND hWnd,bool bDoDXReset);
 
 private: