Преглед изворни кода

more fixes from Gogg: Windows 7 fullscreen workaround

David Rose пре 16 година
родитељ
комит
c172d80a41

+ 5 - 2
panda/src/pnmtext/freetypeFace.I

@@ -13,7 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 ////////////////////////////////////////////////////////////////////
-//     Function: TextFont::get_face
+//     Function: FreetypeFace::get_face
 //       Access: Published
 //  Description: Retrieves the internal freetype face.
 ////////////////////////////////////////////////////////////////////
@@ -23,11 +23,14 @@ get_face() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: TextFont::set_face
+//     Function: FreetypeFace::set_face
 //       Access: Published
 //  Description: Sets the internal freetype face.
 ////////////////////////////////////////////////////////////////////
 INLINE void FreetypeFace::
 set_face(FT_Face face) {
+  if (_face != NULL){
+    FT_Done_Face(_face);
+  }
   _face = face;
 }

+ 3 - 1
panda/src/pnmtext/freetypeFont.cxx

@@ -42,7 +42,7 @@ FreetypeFont::
 FreetypeFont() {
   _font_loaded = false;
 
-  _face = new FreetypeFace();
+  _face = NULL;
 
   _point_size = text_point_size;
   _requested_pixels_per_unit = text_pixels_per_unit;
@@ -91,6 +91,7 @@ load_font(const Filename &font_filename, int face_index) {
                                (const FT_Byte *)_raw_font_data.data(),
                                _raw_font_data.length(),
                                face_index, &face);
+    _face = new FreetypeFace();
     _face->set_face(face);
   }
 
@@ -135,6 +136,7 @@ load_font(const char *font_data, int data_length, int face_index) {
   error = FT_New_Memory_Face(_ft_library, 
                              (const FT_Byte *)font_data, data_length,
                              face_index, &face);
+  _face = new FreetypeFace();
   _face->set_face(face);
 
   if (error == FT_Err_Unknown_File_Format) {

+ 126 - 143
panda/src/windisplay/winGraphicsWindow.cxx

@@ -379,12 +379,7 @@ open_window() {
   // even before it gives us a handle.  Warning: this is not thread
   // safe!
   _creating_window = this;
-  bool opened;
-  if (is_fullscreen()) {
-    opened = open_fullscreen_window();
-  } else {
-    opened = open_regular_window();
-  }
+  bool opened = open_graphic_window(is_fullscreen());
   _creating_window = (WinGraphicsWindow *)NULL;
 
   if (!opened) {
@@ -737,96 +732,12 @@ support_overlay_window(bool) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: WinGraphicsWindow::open_fullscreen_window
-//       Access: Private
-//  Description: Creates a fullscreen-style window.
-////////////////////////////////////////////////////////////////////
-bool WinGraphicsWindow::
-open_fullscreen_window()
-{
-  //  from MSDN:
-  //  An OpenGL window has its own pixel format. Because of this, only
-  //  device contexts retrieved for the client area of an OpenGL
-  //  window are allowed to draw into the window. As a result, an
-  //  OpenGL window should be created with the WS_CLIPCHILDREN and
-  //  WS_CLIPSIBLINGS styles. Additionally, the window class attribute
-  //  should not include the CS_PARENTDC style.
-  DWORD window_style = 
-    WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
-
-  if (!_properties.has_size()) {
-    // Just pick a stupid default size if one isn't specified.
-    _properties.set_size(640, 480);
-  }
-
-  // No parent window for a fullscreen window.
-  _parent_window_handle = NULL;
-
-  HWND hDesktopWindow = GetDesktopWindow();
-  HDC scrnDC = GetDC(hDesktopWindow);
-  DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL);
-  //  DWORD drvr_ver = GetDeviceCaps(scrnDC, DRIVERVERSION);
-  //  DWORD cur_scrnwidth = GetDeviceCaps(scrnDC, HORZRES);
-  //  DWORD cur_scrnheight = GetDeviceCaps(scrnDC, VERTRES);
-  ReleaseDC(hDesktopWindow, scrnDC);
-
-  DWORD dwWidth = _properties.get_x_size();
-  DWORD dwHeight = _properties.get_y_size();
-  DWORD dwFullScreenBitDepth = cur_bitdepth;
-  
-  reconsider_fullscreen_size(dwWidth, dwHeight, dwFullScreenBitDepth);
-  if (!find_acceptable_display_mode(dwWidth, dwHeight, dwFullScreenBitDepth,
-                                    _fullscreen_display_mode)) {
-    windisplay_cat.error() 
-      << "Videocard has no supported display resolutions at specified res ("
-      << dwWidth << " x " << dwHeight << " x " << dwFullScreenBitDepth <<")\n";
-    return false;
-  }
-
-  string title;
-  if (_properties.has_title()) {
-    title = _properties.get_title();
-  }
-
-  // I'd prefer to CreateWindow after DisplayChange in case it messes
-  // up GL somehow, but I need the window's black background to cover
-  // up the desktop during the mode change
-  const WindowClass &wclass = register_window_class(_properties);
-  HINSTANCE hinstance = GetModuleHandle(NULL);
-  
-  _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style,
-                       0, 0, dwWidth, dwHeight, 
-                       hDesktopWindow, NULL, hinstance, 0);
-  if (!_hWnd) {
-    windisplay_cat.error()
-      << "CreateWindow() failed!" << endl;
-    show_error_message();
-    return false;
-  }
-   
-  int chg_result = ChangeDisplaySettings(&_fullscreen_display_mode, 
-                                         CDS_FULLSCREEN);
-  if (chg_result != DISP_CHANGE_SUCCESSFUL) {
-    windisplay_cat.error()
-      << "ChangeDisplaySettings failed (error code: "
-      << chg_result << ") for specified res (" << dwWidth
-      << " x " << dwHeight << " x " << dwFullScreenBitDepth
-      << "), " << _fullscreen_display_mode.dmDisplayFrequency  << "Hz\n";
-    return false;
-  }
-
-  _properties.set_origin(0, 0);
-  _properties.set_size(dwWidth, dwHeight);
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: WinGraphicsWindow::open_regular_window
+//     Function: WinGraphicsWindow::open_graphic_window
 //       Access: Private
-//  Description: Creates a non-fullscreen window, on the desktop.
+//  Description: Creates a regular or fullscreen window.
 ////////////////////////////////////////////////////////////////////
 bool WinGraphicsWindow::
-open_regular_window() {
+open_graphic_window(bool fullscreen) {
   //  from MSDN:
   //  An OpenGL window has its own pixel format. Because of this, only
   //  device contexts retrieved for the client area of an OpenGL
@@ -837,7 +748,9 @@ open_regular_window() {
   DWORD window_style = 
     WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
 
-  if (!_properties.get_undecorated()) {
+  if (fullscreen){
+    window_style |= WS_SYSMENU;
+  } else if (!_properties.get_undecorated()) {
     window_style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
 
     if (!_properties.get_fixed_size()) {
@@ -846,44 +759,52 @@ open_regular_window() {
       window_style |= WS_BORDER;
     }
   }
+  
+  string title;
+  if (_properties.has_title()) {
+    title = _properties.get_title();
+  }
+
+  if (!_properties.has_size()) {
+    //Just pick a conservative default size if one isn't specified.
+    _properties.set_size(640, 480);
+  }
 
   int x_origin = 0;
   int y_origin = 0;
-  if (_properties.has_origin()) {
+  if (!fullscreen && _properties.has_origin()) {
     x_origin = _properties.get_x_origin();
     y_origin = _properties.get_y_origin();
   }
 
-  int x_size = 100;
-  int y_size = 100;
-  if (_properties.has_size()) {
-    x_size = _properties.get_x_size();
-    y_size = _properties.get_y_size();
-  }
+  int x_size = _properties.get_x_size();
+  int y_size = _properties.get_y_size();
 
-  RECT win_rect;
-  SetRect(&win_rect, x_origin, y_origin,
-          x_origin + x_size, y_origin + y_size);
-  
-  // compute window size based on desired client area size
-  if (!AdjustWindowRect(&win_rect, window_style, FALSE)) {
-    windisplay_cat.error()
-      << "AdjustWindowRect failed!" << endl;
-    return false;
-  }
+  int clientAreaWidth = x_size;
+  int clientAreaHeight = y_size;
 
-  string title;
-  if (_properties.has_title()) {
-    title = _properties.get_title();
-  }
+  if (!fullscreen){
+    RECT win_rect;
+    SetRect(&win_rect, x_origin, y_origin,
+            x_origin + x_size, y_origin + y_size);
+    
+    // compute window size based on desired client area size
+    if (!AdjustWindowRect(&win_rect, window_style, FALSE)) {
+      windisplay_cat.error()
+        << "AdjustWindowRect failed!" << endl;
+      return false;
+    }
 
-  if (_properties.has_origin()) {
-    x_origin = win_rect.left;
-    y_origin = win_rect.top;
+    if (_properties.has_origin()) {
+      x_origin = win_rect.left;
+      y_origin = win_rect.top;
 
-  } else {
-    x_origin = CW_USEDEFAULT;
-    y_origin = CW_USEDEFAULT;
+    } else {
+      x_origin = CW_USEDEFAULT;
+      y_origin = CW_USEDEFAULT;
+    }
+    clientAreaWidth = win_rect.right - win_rect.left;
+    clientAreaHeight = win_rect.bottom - win_rect.top;
   }
 
   const WindowClass &wclass = register_window_class(_properties);
@@ -891,38 +812,41 @@ open_regular_window() {
 
   _hparent = NULL;
   
-  WindowHandle *window_handle = _properties.get_parent_window();
-  if (window_handle != NULL) {
-    windisplay_cat.info()
-      << "Got parent_window " << *window_handle << "\n";
-    WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
-    if (os_handle != NULL) {
+  if (!fullscreen){
+    WindowHandle *window_handle = _properties.get_parent_window();
+    if (window_handle != NULL) {
       windisplay_cat.info()
-        << "os_handle type " << os_handle->get_type() << "\n";
-      
-      if (os_handle->is_of_type(NativeWindowHandle::WinHandle::get_class_type())) {
-        NativeWindowHandle::WinHandle *win_handle = DCAST(NativeWindowHandle::WinHandle, os_handle);
-        _hparent = win_handle->get_handle();
-        } else if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
-        NativeWindowHandle::IntHandle *int_handle = DCAST(NativeWindowHandle::IntHandle, os_handle);
-        _hparent = (HWND)int_handle->get_handle();
+        << "Got parent_window " << *window_handle << "\n";
+      WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
+      if (os_handle != NULL) {
+        windisplay_cat.info()
+          << "os_handle type " << os_handle->get_type() << "\n";
+        
+        if (os_handle->is_of_type(NativeWindowHandle::WinHandle::get_class_type())) {
+          NativeWindowHandle::WinHandle *win_handle = DCAST(NativeWindowHandle::WinHandle, os_handle);
+          _hparent = win_handle->get_handle();
+          } else if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
+          NativeWindowHandle::IntHandle *int_handle = DCAST(NativeWindowHandle::IntHandle, os_handle);
+          _hparent = (HWND)int_handle->get_handle();
+        }
       }
     }
+    _parent_window_handle = window_handle;
+  } else {
+    _parent_window_handle = NULL;
   }
-  _parent_window_handle = window_handle;
 
-  if (!_hparent) {
+  if (!_hparent) { // This can be a regular window or a fullscreen window
     _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style, 
                          x_origin, y_origin,
-                         win_rect.right - win_rect.left,
-                         win_rect.bottom - win_rect.top,
+                         clientAreaWidth,
+                         clientAreaHeight,
                          NULL, NULL, hinstance, 0);
-    
-  } else {
+  } else { // This is a regular window with a parent
     x_origin = 0;
     y_origin = 0;
     
-    if (_properties.has_origin()) {
+    if (!fullscreen && _properties.has_origin()) {
       x_origin = _properties.get_x_origin();
       y_origin = _properties.get_y_origin();
     }
@@ -954,6 +878,51 @@ open_regular_window() {
     return false;
   }
 
+  // I'd prefer to CreateWindow after DisplayChange in case it messes
+  // up GL somehow, but I need the window's black background to cover
+  // up the desktop during the mode change.
+
+  if (fullscreen){
+    HWND hDesktopWindow = GetDesktopWindow();
+    HDC scrnDC = GetDC(hDesktopWindow);
+    DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL);
+    //  DWORD drvr_ver = GetDeviceCaps(scrnDC, DRIVERVERSION);
+    //  DWORD cur_scrnwidth = GetDeviceCaps(scrnDC, HORZRES);
+    //  DWORD cur_scrnheight = GetDeviceCaps(scrnDC, VERTRES);
+    ReleaseDC(hDesktopWindow, scrnDC);
+    
+    DWORD dwWidth = _properties.get_x_size();
+    DWORD dwHeight = _properties.get_y_size();
+    DWORD dwFullScreenBitDepth = cur_bitdepth;
+
+    DEVMODE dm;
+    reconsider_fullscreen_size(dwWidth, dwHeight, dwFullScreenBitDepth);
+    if (!find_acceptable_display_mode(dwWidth, dwHeight, dwFullScreenBitDepth, dm)) {
+      windisplay_cat.error() 
+        << "Videocard has no supported display resolutions at specified res ("
+        << dwWidth << " x " << dwHeight << " x " << dwFullScreenBitDepth <<")\n";
+      return false;
+    }
+
+    dm.dmPelsWidth = dwWidth;
+    dm.dmPelsHeight = dwHeight;
+    dm.dmBitsPerPel = dwFullScreenBitDepth;
+    int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
+
+    if (chg_result != DISP_CHANGE_SUCCESSFUL) {
+      windisplay_cat.error()
+        << "ChangeDisplaySettings failed (error code: "
+        << chg_result << ") for specified res (" << dwWidth
+        << " x " << dwHeight << " x " << dwFullScreenBitDepth
+        << "), " << _fullscreen_display_mode.dmDisplayFrequency  << "Hz\n";
+      return false;
+    }
+
+    _properties.set_origin(0, 0);
+    _properties.set_size(dwWidth, dwHeight);
+
+  }
+
   return true;
 }
 
@@ -2165,7 +2134,21 @@ find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp,
     
     if ((dm.dmPelsWidth == dwWidth) && (dm.dmPelsHeight == dwHeight) &&
         (dm.dmBitsPerPel == bpp)) {
-      return true;
+          cout << "[FS FOUND] " << dwWidth << "x" << dwHeight << "@" << bpp << endl;
+      // We want to modify the current DEVMODE rather than using a fresh one in order
+      // to work around a Windows 7 bug.
+      ZeroMemory(&dm, sizeof(dm));
+      dm.dmSize = sizeof(dm);
+      if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)){
+        dm.dmPelsWidth = dwWidth;
+        dm.dmPelsHeight = dwHeight;
+        dm.dmBitsPerPel = bpp;
+        return true;
+      } else {
+        windisplay_cat.error() 
+          << "Couldn't retrieve active device mode.\n";
+        return false;
+      }
     }
     modenum++;
   }

+ 1 - 2
panda/src/windisplay/winGraphicsWindow.h

@@ -89,8 +89,7 @@ protected:
   virtual void support_overlay_window(bool flag);
 
 private:
-  bool open_fullscreen_window();
-  bool open_regular_window();
+  bool open_graphic_window(bool fullscreen);
   void adjust_z_order();
   void adjust_z_order(WindowProperties::ZOrder last_z_order,
                       WindowProperties::ZOrder this_z_order);