Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2019-03-10 20:49:52 +01:00
commit 8d1bdf0118
7 changed files with 321 additions and 58 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
// 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];
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];
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.

View File

@ -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();

View File

@ -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";
} else {
if (new_size_id != old_size_id) {
// Just go fullscreen at native resolution, then.
properties.set_origin(x, y);
properties.set_size(width, height);
} else {
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();