Ver Fonte

Merge branch 'release/1.10.x'

rdb há 6 anos atrás
pai
commit
8d1bdf0118

+ 9 - 7
direct/src/showutil/TexMemWatcher.py

@@ -786,8 +786,9 @@ class TexMemWatcher(DirectObject):
             # Look for a single rectangular hole to hold this piece.
             tp = self.findHole(tr.area, tr.w, tr.h)
             if tp:
-                texCmp = cmp(tr.w, tr.h)
-                holeCmp = cmp(tp.p[1] - tp.p[0], tp.p[3] - tp.p[2])
+                texCmp = (tr.w > tr.h) - (tr.w < tr.h)
+                holeCmp = ((tp.p[1] - tp.p[0]) > (tp.p[3] - tp.p[2])) \
+                        - ((tp.p[1] - tp.p[0]) < (tp.p[3] - tp.p[2]))
                 if texCmp != 0 and holeCmp != 0 and texCmp != holeCmp:
                     tp.rotated = True
                 tr.placements = [tp]
@@ -803,10 +804,11 @@ class TexMemWatcher(DirectObject):
             # in.
             tpList = self.findHolePieces(tr.area)
             if tpList:
-                texCmp = cmp(tr.w, tr.h)
+                texCmp = (tr.w > tr.h) - (tr.w < tr.h)
                 tr.placements = tpList
                 for tp in tpList:
-                    holeCmp = cmp(tp.p[1] - tp.p[0], tp.p[3] - tp.p[2])
+                    holeCmp = ((tp.p[1] - tp.p[0]) > (tp.p[3] - tp.p[2])) \
+                            - ((tp.p[1] - tp.p[0]) < (tp.p[3] - tp.p[2]))
                     if texCmp != 0 and holeCmp != 0 and texCmp != holeCmp:
                         tp.rotated = True
                     tp.setBitmasks(self.bitmasks)
@@ -858,11 +860,11 @@ class TexMemWatcher(DirectObject):
             # we have to squish it?
             if tw < w:
                 # We'd have to make it taller.
-                nh = min(area / tw, th)
+                nh = min(area // tw, th)
                 th = nh
             elif th < h:
                 # We'd have to make it narrower.
-                nw = min(area / th, tw)
+                nw = min(area // th, tw)
                 tw = nw
             else:
                 # Hey, we don't have to squish it after all!  Just
@@ -912,7 +914,7 @@ class TexMemWatcher(DirectObject):
             tpArea = (r - l) * (t - b)
             if tpArea >= area:
                 # we're done.
-                shorten = (tpArea - area) / (r - l)
+                shorten = (tpArea - area) // (r - l)
                 t -= shorten
                 tp.p = (l, r, b, t)
                 tp.area = (r - l) * (t - b)

+ 25 - 0
doc/ReleaseNotes

@@ -1,3 +1,28 @@
+------------------------  RELEASE 1.10.2  -----------------------
+
+This release fixes several more bugs, including a few regressions
+in 1.10.1.  Upgrading is highly recommended.
+
+* Fix regression on Windows causing freezes and instability
+* Fix a memory leak issue in Python applications
+* Fix crash reading unaligned float4 column in GeomVertexReader
+* Fixes for switching to fullscreen at runtime on Windows and Linux
+* Fix incorrect display mode listing in some Linux distributions
+* Fix threading crash on Linux when using get_keyboard_map()
+* Support "from __future__ import division" for Panda types
+* Support building with Visual Studio 2019 in makepanda
+* Work around Assimp crash when loading multiple .ply models
+* On Windows, a Python 3-compatible version of Pmw is included
+* Fix ParticlePanel spam when hovering over File menu items
+* TexMemWatcher has been fixed for Python 3
+* Prevent macOS window getting stuck after base.destroy()
+* Fix assertion setting mass before shape with Bullet debug build
+* Don't error if DirectScrolledFrame is destroyed twice
+* Fix reference count corruption accessing task.__dict__
+* Fix writing to SequenceNode frame_rate property
+* Fix collider sort not copied when copying CollisionNode
+* Add OpenCollective backer file
+
 ------------------------  RELEASE 1.10.1  -----------------------
 
 This is a bugfix release intended to fix several issues in 1.10.0.

+ 1 - 1
dtool/src/interrogate/interfaceMakerPythonNative.h

@@ -121,7 +121,7 @@ private:
   public:
     std::string _answer_location;
     WrapperType _wrapper_type;
-    int _min_version;
+    int _min_version = 0;
     std::string _wrapper_name;
     std::set<FunctionRemap*> _remaps;
     bool _keep_method;

+ 3 - 3
panda/src/windisplay/winGraphicsWindow.cxx

@@ -979,12 +979,12 @@ make_style(const WindowProperties &properties) {
 
   DWORD window_style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
 
-  if (_properties.get_fullscreen()) {
+  if (properties.get_fullscreen()) {
     window_style |= WS_SYSMENU;
-  } else if (!_properties.get_undecorated()) {
+  } else if (!properties.get_undecorated()) {
     window_style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
 
-    if (!_properties.get_fixed_size()) {
+    if (!properties.get_fixed_size()) {
       window_style |= (WS_SIZEBOX | WS_MAXIMIZEBOX);
     } else {
       window_style |= WS_BORDER;

+ 153 - 24
panda/src/x11display/x11GraphicsPipe.cxx

@@ -156,21 +156,55 @@ x11GraphicsPipe(const std::string &display) :
   void *xrandr = dlopen("libXrandr.so.2", RTLD_NOW | RTLD_LOCAL);
   if (xrandr != nullptr) {
     pfn_XRRQueryExtension _XRRQueryExtension = (pfn_XRRQueryExtension)dlsym(xrandr, "XRRQueryExtension");
+    pfn_XRRQueryVersion _XRRQueryVersion = (pfn_XRRQueryVersion)dlsym(xrandr, "XRRQueryVersion");
+
     _XRRSizes = (pfn_XRRSizes)dlsym(xrandr, "XRRSizes");
     _XRRRates = (pfn_XRRRates)dlsym(xrandr, "XRRRates");
     _XRRGetScreenInfo = (pfn_XRRGetScreenInfo)dlsym(xrandr, "XRRGetScreenInfo");
     _XRRConfigCurrentConfiguration = (pfn_XRRConfigCurrentConfiguration)dlsym(xrandr, "XRRConfigCurrentConfiguration");
     _XRRSetScreenConfig = (pfn_XRRSetScreenConfig)dlsym(xrandr, "XRRSetScreenConfig");
 
+    int event, error, major, minor;
     if (_XRRQueryExtension == nullptr || _XRRSizes == nullptr || _XRRRates == nullptr ||
         _XRRGetScreenInfo == nullptr || _XRRConfigCurrentConfiguration == nullptr ||
-        _XRRSetScreenConfig == nullptr) {
+        _XRRSetScreenConfig == nullptr || _XRRQueryVersion == nullptr) {
       _have_xrandr = false;
       x11display_cat.warning()
         << "libXrandr.so.2 does not provide required functions; resolution setting will not work.\n";
+    }
+    else if (_XRRQueryExtension(_display, &event, &error) &&
+             _XRRQueryVersion(_display, &major, &minor)) {
+      _have_xrandr = true;
+      if (x11display_cat.is_debug()) {
+        x11display_cat.debug()
+          << "Found RandR extension " << major << "." << minor << "\n";
+      }
+
+      if (major > 1 || (major == 1 && minor >= 2)) {
+        if (major > 1 || (major == 1 && minor >= 3)) {
+          _XRRGetScreenResourcesCurrent = (pfn_XRRGetScreenResources)
+            dlsym(xrandr, "XRRGetScreenResourcesCurrent");
+        } else {
+          // Fall back to this slower version.
+          _XRRGetScreenResourcesCurrent = (pfn_XRRGetScreenResources)
+            dlsym(xrandr, "XRRGetScreenResources");
+        }
+
+        _XRRFreeScreenResources = (pfn_XRRFreeScreenResources)dlsym(xrandr, "XRRFreeScreenResources");
+        _XRRGetCrtcInfo = (pfn_XRRGetCrtcInfo)dlsym(xrandr, "XRRGetCrtcInfo");
+        _XRRFreeCrtcInfo = (pfn_XRRFreeCrtcInfo)dlsym(xrandr, "XRRFreeCrtcInfo");
+      } else {
+        _XRRGetScreenResourcesCurrent = nullptr;
+        _XRRFreeScreenResources = nullptr;
+        _XRRGetCrtcInfo = nullptr;
+        _XRRFreeCrtcInfo = nullptr;
+      }
     } else {
-      int event, error;
-      _have_xrandr = _XRRQueryExtension(_display, &event, &error);
+      _have_xrandr = false;
+      if (x11display_cat.is_debug()) {
+        x11display_cat.debug()
+          << "RandR extension not supported; resolution setting will not work.\n";
+      }
     }
   } else {
     _have_xrandr = false;
@@ -182,29 +216,61 @@ x11GraphicsPipe(const std::string &display) :
 
   // Use Xrandr to fill in the supported resolution list.
   if (_have_xrandr) {
-    int num_sizes, num_rates;
-    XRRScreenSize *xrrs;
-    xrrs = _XRRSizes(_display, 0, &num_sizes);
-    _display_information->_total_display_modes = 0;
-    for (int i = 0; i < num_sizes; ++i) {
-      _XRRRates(_display, 0, i, &num_rates);
-      _display_information->_total_display_modes += num_rates;
-    }
-
-    short *rates;
-    short counter = 0;
-    _display_information->_display_mode_array = new DisplayMode[_display_information->_total_display_modes];
-    for (int i = 0; i < num_sizes; ++i) {
-      int num_rates;
-      rates = _XRRRates(_display, 0, i, &num_rates);
-      for (int j = 0; j < num_rates; ++j) {
-        DisplayMode* dm = _display_information->_display_mode_array + counter;
-        dm->width = xrrs[i].width;
-        dm->height = xrrs[i].height;
-        dm->refresh_rate = rates[j];
+    // If we have XRRGetScreenResources, we prefer that.  It seems to be more
+    // reliable than XRRSizes in multi-monitor set-ups.
+    if (auto res = get_screen_resources()) {
+      if (x11display_cat.is_debug()) {
+        x11display_cat.debug()
+          << "Using XRRScreenResources to obtain display modes\n";
+      }
+      _display_information->_total_display_modes = res->nmode;
+      _display_information->_display_mode_array = new DisplayMode[res->nmode];
+      for (int i = 0; i < res->nmode; ++i) {
+        XRRModeInfo &mode = res->modes[i];
+
+        DisplayMode *dm = _display_information->_display_mode_array + i;
+        dm->width = mode.width;
+        dm->height = mode.height;
         dm->bits_per_pixel = -1;
         dm->fullscreen_only = false;
-        ++counter;
+
+        if (mode.hTotal && mode.vTotal) {
+          dm->refresh_rate = (double)mode.dotClock /
+            ((double)mode.hTotal * (double)mode.vTotal);
+        } else {
+          dm->refresh_rate = 0;
+        }
+      }
+    } else {
+      if (x11display_cat.is_debug()) {
+        x11display_cat.debug()
+          << "Using XRRSizes and XRRRates to obtain display modes\n";
+      }
+
+      int num_sizes, num_rates;
+      XRRScreenSize *xrrs;
+      xrrs = _XRRSizes(_display, 0, &num_sizes);
+      _display_information->_total_display_modes = 0;
+      for (int i = 0; i < num_sizes; ++i) {
+        _XRRRates(_display, 0, i, &num_rates);
+        _display_information->_total_display_modes += num_rates;
+      }
+
+      short *rates;
+      short counter = 0;
+      _display_information->_display_mode_array = new DisplayMode[_display_information->_total_display_modes];
+      for (int i = 0; i < num_sizes; ++i) {
+        int num_rates;
+        rates = _XRRRates(_display, 0, i, &num_rates);
+        for (int j = 0; j < num_rates; ++j) {
+          DisplayMode* dm = _display_information->_display_mode_array + counter;
+          dm->width = xrrs[i].width;
+          dm->height = xrrs[i].height;
+          dm->refresh_rate = rates[j];
+          dm->bits_per_pixel = -1;
+          dm->fullscreen_only = false;
+          ++counter;
+        }
       }
     }
   }
@@ -258,6 +324,69 @@ x11GraphicsPipe::
   }
 }
 
+/**
+ * Returns an XRRScreenResources object, or null if RandR 1.2 is not supported.
+ */
+std::unique_ptr<XRRScreenResources, pfn_XRRFreeScreenResources> x11GraphicsPipe::
+get_screen_resources() const {
+  XRRScreenResources *res = nullptr;
+
+  if (_have_xrandr && _XRRGetScreenResourcesCurrent != nullptr) {
+    res = _XRRGetScreenResourcesCurrent(_display, _root);
+  }
+
+  return std::unique_ptr<XRRScreenResources, pfn_XRRFreeScreenResources>(res, _XRRFreeScreenResources);
+}
+
+/**
+ * Returns an XRRCrtcInfo object, or null if RandR 1.2 is not supported.
+ */
+std::unique_ptr<XRRCrtcInfo, pfn_XRRFreeCrtcInfo> x11GraphicsPipe::
+get_crtc_info(XRRScreenResources *res, RRCrtc crtc) const {
+  XRRCrtcInfo *info = nullptr;
+
+  if (_have_xrandr && _XRRGetCrtcInfo != nullptr) {
+    info = _XRRGetCrtcInfo(_display, res, crtc);
+  }
+
+  return std::unique_ptr<XRRCrtcInfo, pfn_XRRFreeCrtcInfo>(info, _XRRFreeCrtcInfo);
+}
+
+/**
+ * Finds a CRTC for going fullscreen to, at the given origin.  The new CRTC
+ * is returned, along with its x, y, width and height.
+ *
+ * If the required RandR extension is not supported, a value of None will be
+ * returned, but x, y, width and height will still be populated.
+ */
+RRCrtc x11GraphicsPipe::
+find_fullscreen_crtc(const LPoint2i &point,
+                     int &x, int &y, int &width, int &height) {
+  x = 0;
+  y = 0;
+  width = DisplayWidth(_display, _screen);
+  height = DisplayHeight(_display, _screen);
+
+  if (auto res = get_screen_resources()) {
+    for (int i = 0; i < res->ncrtc; ++i) {
+      RRCrtc crtc = res->crtcs[i];
+      if (auto info = get_crtc_info(res.get(), crtc)) {
+        if (point[0] >= info->x && point[0] < info->x + info->width &&
+            point[1] >= info->y && point[1] < info->y + info->height) {
+
+          x = info->x;
+          y = info->y;
+          width = info->width;
+          height = info->height;
+          return crtc;
+        }
+      }
+    }
+  }
+
+  return None;
+}
+
 /**
  * Returns an indication of the thread in which this GraphicsPipe requires its
  * window processing to be performed: typically either the app thread (e.g.

+ 64 - 0
panda/src/x11display/x11GraphicsPipe.h

@@ -32,12 +32,61 @@ typedef struct _XcursorImages XcursorImages;
 
 typedef unsigned short Rotation;
 typedef unsigned short SizeID;
+typedef unsigned long XRRModeFlags;
+typedef XID RROutput;
+typedef XID RRCrtc;
+typedef XID RRMode;
+
 typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
 typedef struct {
   int width, height;
   int mwidth, mheight;
 } XRRScreenSize;
 
+typedef struct _XRRModeInfo {
+  RRMode id;
+  unsigned int width;
+  unsigned int height;
+  unsigned long dotClock;
+  unsigned int hSyncStart;
+  unsigned int hSyncEnd;
+  unsigned int hTotal;
+  unsigned int hSkew;
+  unsigned int vSyncStart;
+  unsigned int vSyncEnd;
+  unsigned int vTotal;
+  char *name;
+  unsigned int nameLength;
+  XRRModeFlags modeFlags;
+} XRRModeInfo;
+
+typedef struct _XRRScreenResources {
+  Time timestamp;
+  Time configTimestamp;
+  int ncrtc;
+  RRCrtc *crtcs;
+  int noutput;
+  RROutput *outputs;
+  int nmode;
+  XRRModeInfo *modes;
+} XRRScreenResources;
+
+typedef struct _XRRCrtcInfo {
+  Time timestamp;
+  int x, y;
+  unsigned int width, height;
+  RRMode mode;
+  Rotation rotation;
+  int noutput;
+  RROutput *outputs;
+  Rotation rotations;
+  int npossible;
+  RROutput *possible;
+} XRRCrtcInfo;
+
+typedef void (*pfn_XRRFreeScreenResources)(XRRScreenResources *resources);
+typedef void (*pfn_XRRFreeCrtcInfo)(XRRCrtcInfo *crtcInfo);
+
 class FrameBufferProperties;
 
 /**
@@ -64,6 +113,12 @@ public:
   static INLINE int enable_x_error_messages();
   static INLINE int get_x_error_count();
 
+  std::unique_ptr<XRRScreenResources, pfn_XRRFreeScreenResources> get_screen_resources() const;
+  std::unique_ptr<XRRCrtcInfo, pfn_XRRFreeCrtcInfo> get_crtc_info(XRRScreenResources *res, RRCrtc crtc) const;
+
+  RRCrtc find_fullscreen_crtc(const LPoint2i &point,
+                              int &x, int &y, int &width, int &height);
+
 public:
   virtual PreferredWindowThread get_preferred_window_thread() const;
 
@@ -100,6 +155,7 @@ public:
   pfn_XcursorImageDestroy _XcursorImageDestroy;
 
   typedef Bool (*pfn_XRRQueryExtension)(X11_Display *, int*, int*);
+  typedef Status (*pfn_XRRQueryVersion)(X11_Display *, int*, int*);
   typedef XRRScreenSize *(*pfn_XRRSizes)(X11_Display*, int, int*);
   typedef short *(*pfn_XRRRates)(X11_Display*, int, int, int*);
   typedef XRRScreenConfiguration *(*pfn_XRRGetScreenInfo)(X11_Display*, X11_Window);
@@ -126,6 +182,14 @@ protected:
   typedef Status (*pfn_XF86DGADirectVideo)(X11_Display *, int, int);
   pfn_XF86DGADirectVideo _XF86DGADirectVideo;
 
+  typedef XRRScreenResources *(*pfn_XRRGetScreenResources)(X11_Display*, X11_Window);
+  typedef XRRCrtcInfo *(*pfn_XRRGetCrtcInfo)(X11_Display *dpy, XRRScreenResources *resources, RRCrtc crtc);
+
+  pfn_XRRGetScreenResources _XRRGetScreenResourcesCurrent;
+  pfn_XRRFreeScreenResources _XRRFreeScreenResources;
+  pfn_XRRGetCrtcInfo _XRRGetCrtcInfo;
+  pfn_XRRFreeCrtcInfo _XRRFreeCrtcInfo;
+
 private:
   void make_hidden_cursor();
   void release_hidden_cursor();

+ 66 - 23
panda/src/x11display/x11GraphicsWindow.cxx

@@ -579,20 +579,60 @@ set_properties_now(WindowProperties &properties) {
   bool is_fullscreen = _properties.has_fullscreen() && _properties.get_fullscreen();
   bool want_fullscreen = properties.has_fullscreen() ? properties.get_fullscreen() : is_fullscreen;
 
+  if (want_fullscreen && properties.has_origin()) {
+    // If we're fullscreen, reject changes to the origin.
+    properties.clear_origin();
+  }
+
   if (is_fullscreen != want_fullscreen || (is_fullscreen && properties.has_size())) {
     if (want_fullscreen) {
-      if (x11_pipe->_have_xrandr) {
-        XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root());
+      // OK, first figure out which CRTC the window is on.  It may be on more
+      // than one, actually, so grab a point in the center in order to figure
+      // out which one it's more-or-less mostly on.
+      LPoint2i center = _properties.get_origin() + _properties.get_size() / 2;
+      int x, y, width, height;
+      x11_pipe->find_fullscreen_crtc(center, x, y, width, height);
+
+      // Which size should we go fullscreen in?
+      int reqsizex, reqsizey;
+      if (properties.has_size()) {
+        reqsizex = properties.get_x_size();
+        reqsizey = properties.get_y_size();
+      } else if (_properties.has_size()) {
+        reqsizex = _properties.get_x_size();
+        reqsizey = _properties.get_y_size();
+      } else {
+        reqsizex = width;
+        reqsizey = height;
+      }
+
+      // Are we passing in pipe.display_width/height?  This is actually the
+      // size of the virtual desktop, which may not be a real resolution, so
+      // if that is passed in, we have to assume that the user means to just
+      // fullscreen without changing the screen resolution.
+      if ((reqsizex == x11_pipe->get_display_width() &&
+           reqsizey == x11_pipe->get_display_height())
+          || (width == reqsizex && height == reqsizey)
+          || !x11_pipe->_have_xrandr) {
+
+        // Cover the current CRTC.
+        properties.set_origin(x, y);
+        properties.set_size(width, height);
+
+        if (x11display_cat.is_debug()) {
+          x11display_cat.debug()
+            << "Setting window to fullscreen on CRTC "
+            << width << "x" << height << "+" << x << "+" << y << "\n";
+        }
+      } else {
+        // We may need to change the screen resolution.  The code below is
+        // suboptimal; in the future, we probably want to only touch the CRTC
+        // that the window is on.
+        XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, _xwindow);
         SizeID old_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation);
         SizeID new_size_id = (SizeID) -1;
-        int num_sizes = 0, reqsizex, reqsizey;
-        if (properties.has_size()) {
-          reqsizex = properties.get_x_size();
-          reqsizey = properties.get_y_size();
-        } else {
-          reqsizex = _properties.get_x_size();
-          reqsizey = _properties.get_y_size();
-        }
+        int num_sizes = 0;
+
         XRRScreenSize *xrrs;
         xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes);
         for (int i = 0; i < num_sizes; ++i) {
@@ -605,21 +645,29 @@ set_properties_now(WindowProperties &properties) {
           x11display_cat.error()
             << "Videocard has no supported display resolutions at specified res ("
             << reqsizex << " x " << reqsizey << ")\n";
+
+          // Just go fullscreen at native resolution, then.
+          properties.set_origin(x, y);
+          properties.set_size(width, height);
         } else {
-          if (new_size_id != old_size_id) {
+          if (x11display_cat.is_debug()) {
+            x11display_cat.debug()
+              << "Switching to fullscreen with resolution "
+              << reqsizex << "x" << reqsizey << "\n";
+          }
 
+          if (new_size_id != old_size_id) {
             _XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime);
             if (_orig_size_id == (SizeID) -1) {
               // Remember the original resolution so we can switch back to it.
               _orig_size_id = old_size_id;
             }
+
+            // Since the above changes the entire screen configuration, we
+            // have to set the origin to 0, 0.
+            properties.set_origin(0, 0);
           }
         }
-      } else {
-        // If we don't have Xrandr support, we fake the fullscreen support by
-        // setting the window size to the desktop size.
-        properties.set_size(x11_pipe->get_display_width(),
-                            x11_pipe->get_display_height());
       }
     } else {
       // Change the resolution back to what it was.  Don't remove the SizeID
@@ -1130,13 +1178,8 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
     size_hints_p = XAllocSizeHints();
     if (size_hints_p != nullptr) {
       if (properties.has_origin()) {
-        if (_properties.get_fullscreen()) {
-          size_hints_p->x = 0;
-          size_hints_p->y = 0;
-        } else {
-          size_hints_p->x = properties.get_x_origin();
-          size_hints_p->y = properties.get_y_origin();
-        }
+        size_hints_p->x = properties.get_x_origin();
+        size_hints_p->y = properties.get_y_origin();
         size_hints_p->flags |= USPosition;
       }
       LVecBase2i size = _properties.get_size();